aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/app.iml36
-rw-r--r--app/build.gradle13
-rw-r--r--app/src/androidTest/java/github/daneren2005/dsub/activity/DownloadActivityTest.java32
-rw-r--r--app/src/androidTest/java/github/daneren2005/dsub/domain/BookmarkTest.java2
-rw-r--r--app/src/main/AndroidManifest.xml2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/activity/DownloadActivity.java62
-rw-r--r--app/src/main/java/github/daneren2005/dsub/activity/EditPlayActionActivity.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/activity/SettingsActivity.java55
-rw-r--r--app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java430
-rw-r--r--app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java280
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/AlbumGridAdapter.java73
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java197
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/BasicListAdapter.java48
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/BookmarkAdapter.java53
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java37
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/DrawerAdapter.java126
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/EntryAdapter.java82
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java133
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java146
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java80
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java112
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/MergeAdapter.java290
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/PlaylistAdapter.java88
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java79
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/SackOfViewsAdapter.java181
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/SearchAdapter.java114
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java328
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java77
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/ShareAdapter.java75
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/UserAdapter.java34
-rw-r--r--app/src/main/java/github/daneren2005/dsub/domain/Playlist.java15
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java14
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java25
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java322
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java292
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java227
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java178
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java19
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java527
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectGenreFragment.java40
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java53
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java59
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java (renamed from app/src/main/java/github/daneren2005/dsub/fragments/SelectListFragment.java)78
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectShareFragment.java40
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java26
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectYearFragment.java36
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java38
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java350
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java99
-rw-r--r--app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java5
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadService.java7
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/parser/PlaylistsParser.java3
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Constants.java1
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java14
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Notifications.java3
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/UserUtil.java20
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Util.java40
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/AlbumCell.java108
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/AlbumListCountView.java130
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/AlbumView.java75
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/ArtistEntryView.java15
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/ArtistView.java13
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java40
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/BasicListView.java44
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/ChangeLog.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/ErrorDialog.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/GenreView.java5
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/GridSpacingDecoration.java99
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/HeaderGridView.java836
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/PlaylistSongView.java16
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/PlaylistView.java16
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/PodcastChannelView.java11
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/SettingView.java61
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/ShareView.java5
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/SongView.java156
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/UnscrollableGridView.java128
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/UpdateView.java89
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/UpdateView2.java47
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/UserView.java10
-rw-r--r--app/src/main/res/layout-large-land/abstract_fragment_container.xml4
-rw-r--r--app/src/main/res/layout/abstract_activity.xml19
-rw-r--r--app/src/main/res/layout/abstract_fragment_activity.xml201
-rw-r--r--app/src/main/res/layout/abstract_fragment_container.xml4
-rw-r--r--app/src/main/res/layout/abstract_recycler_fragment.xml (renamed from app/src/main/res/layout/abstract_list_fragment.xml)11
-rw-r--r--app/src/main/res/layout/actionbar_spinner.xml21
-rw-r--r--app/src/main/res/layout/album_cell_item.xml5
-rw-r--r--app/src/main/res/layout/album_list_header.xml29
-rw-r--r--app/src/main/res/layout/album_list_item.xml11
-rw-r--r--app/src/main/res/layout/basic_choice_item.xml27
-rw-r--r--app/src/main/res/layout/basic_count_item.xml6
-rw-r--r--app/src/main/res/layout/basic_header.xml13
-rw-r--r--app/src/main/res/layout/basic_list_item.xml5
-rw-r--r--app/src/main/res/layout/change_email.xml3
-rw-r--r--app/src/main/res/layout/change_password.xml3
-rw-r--r--app/src/main/res/layout/chat_item.xml11
-rw-r--r--app/src/main/res/layout/chat_item_reverse.xml11
-rw-r--r--app/src/main/res/layout/complex_list_item.xml14
-rw-r--r--app/src/main/res/layout/confirm_password.xml3
-rw-r--r--app/src/main/res/layout/create_bookmark.xml3
-rw-r--r--app/src/main/res/layout/create_podcast.xml3
-rw-r--r--app/src/main/res/layout/create_user.xml14
-rw-r--r--app/src/main/res/layout/download_activity.xml4
-rw-r--r--app/src/main/res/layout/download_playlist.xml34
-rw-r--r--app/src/main/res/layout/drawer_header.xml62
-rw-r--r--app/src/main/res/layout/drawer_list_item.xml26
-rw-r--r--app/src/main/res/layout/edit_play_action.xml15
-rw-r--r--app/src/main/res/layout/equalizer_bar.xml55
-rw-r--r--app/src/main/res/layout/genre_list_item.xml11
-rw-r--r--app/src/main/res/layout/grid_view.xml14
-rw-r--r--app/src/main/res/layout/home.xml2
-rw-r--r--app/src/main/res/layout/jukebox_volume.xml46
-rw-r--r--app/src/main/res/layout/lyrics.xml101
-rw-r--r--app/src/main/res/layout/main_buttons.xml157
-rw-r--r--app/src/main/res/layout/progress.xml30
-rw-r--r--app/src/main/res/layout/save_playlist.xml25
-rw-r--r--app/src/main/res/layout/search_buttons.xml73
-rw-r--r--app/src/main/res/layout/seekbar_preference.xml3
-rw-r--r--app/src/main/res/layout/select_album.xml7
-rw-r--r--app/src/main/res/layout/select_album_header.xml21
-rw-r--r--app/src/main/res/layout/select_artist_header.xml15
-rw-r--r--app/src/main/res/layout/settings_activity.xml21
-rw-r--r--app/src/main/res/layout/shuffle_dialog.xml9
-rw-r--r--app/src/main/res/layout/song_list_item.xml34
-rw-r--r--app/src/main/res/layout/start_timer.xml3
-rw-r--r--app/src/main/res/layout/sync_dialog.xml3
-rw-r--r--app/src/main/res/layout/tab_progress.xml3
-rw-r--r--app/src/main/res/layout/unscrollable_grid_view.xml11
-rw-r--r--app/src/main/res/layout/update_playlist.xml9
-rw-r--r--app/src/main/res/layout/update_share.xml9
-rw-r--r--app/src/main/res/layout/user_header.xml12
-rw-r--r--app/src/main/res/layout/user_list_item.xml5
-rw-r--r--app/src/main/res/menu/drawer_navigation.xml51
-rw-r--r--app/src/main/res/menu/select_album.xml2
-rw-r--r--app/src/main/res/menu/select_album_list.xml2
-rw-r--r--app/src/main/res/menu/select_song.xml2
-rw-r--r--app/src/main/res/menu/select_song_offline.xml2
-rw-r--r--app/src/main/res/menu/similar_artists.xml2
-rw-r--r--app/src/main/res/values-large/dimens.xml2
-rw-r--r--app/src/main/res/values-v16/themes.xml15
-rw-r--r--app/src/main/res/values-v21/themes.xml10
-rw-r--r--app/src/main/res/values/arrays.xml39
-rw-r--r--app/src/main/res/values/attrs.xml19
-rw-r--r--app/src/main/res/values/colors.xml17
-rw-r--r--app/src/main/res/values/dimens.xml2
-rw-r--r--app/src/main/res/values/strings.xml6
-rw-r--r--app/src/main/res/values/styles.xml57
-rw-r--r--app/src/main/res/values/themes.xml123
147 files changed, 4257 insertions, 5041 deletions
diff --git a/app/app.iml b/app/app.iml
index 28b7ee49..dce1b16c 100644
--- a/app/app.iml
+++ b/app/app.iml
@@ -69,11 +69,15 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
- <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.1.1/jars" />
- <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/mediarouter-v7/22.1.1/jars" />
- <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.1.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.0/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/22.2.0/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/mediarouter-v7/22.2.0/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/22.2.0/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.gms/play-services-base/7.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.gms/play-services-cast/7.0.0/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.sothree.slidinguppanel/library/3.0.0/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/de.hdodenhof/circleimageview/1.2.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
@@ -91,31 +95,35 @@
</content>
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" exported="" name="mediarouter-v7-22.1.1" level="project" />
+ <orderEntry type="library" exported="" name="mediarouter-v7-22.2.0" level="project" />
<orderEntry type="library" exported="" name="seamless-util-1.1.0" level="project" />
<orderEntry type="library" exported="" name="cling-core-2.0.1" level="project" />
+ <orderEntry type="library" exported="" name="recyclerview-v7-22.2.0" level="project" />
<orderEntry type="library" exported="" name="jetty-continuation-8.1.16.v20140903" level="project" />
- <orderEntry type="library" exported="" name="javax.servlet-3.0.0.v201112011016" level="project" />
- <orderEntry type="library" exported="" name="jetty-server-8.1.16.v20140903" level="project" />
- <orderEntry type="library" exported="" name="support-annotations-22.1.1" level="project" />
- <orderEntry type="library" exported="" name="support-v4-22.1.1" level="project" />
+ <orderEntry type="library" exported="" name="support-annotations-22.2.0" level="project" />
<orderEntry type="library" exported="" name="play-services-cast-7.0.0" level="project" />
- <orderEntry type="library" exported="" name="cling-support-2.0.1" level="project" />
<orderEntry type="library" exported="" name="seamless-http-1.1.0" level="project" />
<orderEntry type="library" exported="" name="jetty-util-8.1.16.v20140903" level="project" />
- <orderEntry type="library" exported="" name="appcompat-v7-22.1.1" level="project" />
+ <orderEntry type="library" exported="" name="appcompat-v7-22.2.0" level="project" />
<orderEntry type="library" exported="" name="seamless-swing-1.1.0" level="project" />
<orderEntry type="library" exported="" name="seamless-xml-1.1.0" level="project" />
+ <orderEntry type="library" exported="" name="kryo-2.21-all" level="project" />
+ <orderEntry type="library" exported="" name="play-services-base-7.0.0" level="project" />
+ <orderEntry type="library" exported="" name="jetty-http-8.1.16.v20140903" level="project" />
+ <orderEntry type="library" exported="" name="library-2.4.0" level="project" />
+ <orderEntry type="library" exported="" name="javax.servlet-3.0.0.v201112011016" level="project" />
+ <orderEntry type="library" exported="" name="jetty-server-8.1.16.v20140903" level="project" />
+ <orderEntry type="library" exported="" name="support-v4-22.2.0" level="project" />
+ <orderEntry type="library" exported="" name="cling-support-2.0.1" level="project" />
<orderEntry type="library" exported="" name="jetty-io-8.1.16.v20140903" level="project" />
<orderEntry type="library" exported="" name="CWAC-EndlessAdapter" level="project" />
+ <orderEntry type="library" exported="" name="circleimageview-1.2.1" level="project" />
<orderEntry type="library" exported="" name="jetty-security-8.1.16.v20140903" level="project" />
- <orderEntry type="library" exported="" name="kryo-2.21-all" level="project" />
- <orderEntry type="library" exported="" name="play-services-base-7.0.0" level="project" />
<orderEntry type="library" exported="" name="jetty-servlet-8.1.16.v20140903" level="project" />
<orderEntry type="library" exported="" name="CWAC-AdapterWrapper" level="project" />
+ <orderEntry type="library" exported="" name="library-3.0.0" level="project" />
+ <orderEntry type="library" exported="" name="design-22.2.0" level="project" />
<orderEntry type="library" exported="" name="jetty-client-8.1.16.v20140903" level="project" />
- <orderEntry type="library" exported="" name="jetty-http-8.1.16.v20140903" level="project" />
- <orderEntry type="module" module-name="DragSort ListView" exported="" />
<orderEntry type="module" module-name="Server Proxy" exported="" />
</component>
</module> \ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 0eeaec1d..c09f0f91 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,7 +6,7 @@ android {
defaultConfig {
applicationId "github.daneren2005.dsub"
- minSdkVersion 9
+ minSdkVersion 14
targetSdkVersion 19
}
buildTypes {
@@ -32,13 +32,16 @@ android {
}
dependencies {
- compile project(':DragSort ListView')
compile project(':Server Proxy')
compile fileTree(include: ['*.jar'], dir: 'libs')
- compile 'com.android.support:support-v4:22.1.1'
- compile 'com.android.support:appcompat-v7:22.1.1'
- compile 'com.android.support:mediarouter-v7:22.1.1'
+ compile 'com.android.support:support-v4:22.2.+'
+ compile 'com.android.support:appcompat-v7:22.2.+'
+ compile 'com.android.support:mediarouter-v7:22.2.+'
+ compile 'com.android.support:recyclerview-v7:22.2.+'
+ compile 'com.android.support:design:22.2.+'
compile 'com.google.android.gms:play-services-cast:7.0.0'
+ compile 'com.sothree.slidinguppanel:library:3.0.0'
+ compile 'de.hdodenhof:circleimageview:1.2.1'
compile group: 'org.fourthline.cling', name: 'cling-core', version:'2.0.1'
compile group: 'org.fourthline.cling', name: 'cling-support', version:'2.0.1'
compile group: 'org.eclipse.jetty', name: 'jetty-server', version:'8.1.16.v20140903'
diff --git a/app/src/androidTest/java/github/daneren2005/dsub/activity/DownloadActivityTest.java b/app/src/androidTest/java/github/daneren2005/dsub/activity/DownloadActivityTest.java
deleted file mode 100644
index ce859181..00000000
--- a/app/src/androidTest/java/github/daneren2005/dsub/activity/DownloadActivityTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package github.daneren2005.dsub.activity;
-
-import github.daneren2005.dsub.R;
-import android.test.*;
-import android.view.View;
-
-public class DownloadActivityTest extends
- ActivityInstrumentationTestCase2<DownloadActivity> {
-
- private DownloadActivity activity;
-
- public DownloadActivityTest() {
- super(DownloadActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- activity = getActivity();
- }
-
- /**
- * Test the main layout.
- */
- public void testLayout() {
- View view = activity.findViewById(R.layout.download_activity);
- assertNotNull(view);
- assertNotNull(view.findViewById(R.layout.download_activity));
- assertNotNull(activity.findViewById(R.id.fragment_container));
- }
-
-}
diff --git a/app/src/androidTest/java/github/daneren2005/dsub/domain/BookmarkTest.java b/app/src/androidTest/java/github/daneren2005/dsub/domain/BookmarkTest.java
index 814f658a..30663543 100644
--- a/app/src/androidTest/java/github/daneren2005/dsub/domain/BookmarkTest.java
+++ b/app/src/androidTest/java/github/daneren2005/dsub/domain/BookmarkTest.java
@@ -15,7 +15,7 @@ public class BookmarkTest extends TestCase {
*/
public void testSetCreated() throws ParseException {
Bookmark bookmark = new Bookmark();
- bookmark.setCreated(null);
+ bookmark.setCreated((String) null);
assertEquals(null, bookmark.getCreated());
bookmark.setCreated("");
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 38d80ae8..2b3a5fbc 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -31,7 +31,7 @@
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.wifi" android:required="false" />
- <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="19"/>
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19"/>
<supports-screens android:anyDensity="true" android:xlargeScreens="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
diff --git a/app/src/main/java/github/daneren2005/dsub/activity/DownloadActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/DownloadActivity.java
deleted file mode 100644
index e13a8b8c..00000000
--- a/app/src/main/java/github/daneren2005/dsub/activity/DownloadActivity.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package github.daneren2005.dsub.activity;
-
-import github.daneren2005.dsub.R;
-import android.os.Bundle;
-import android.view.MotionEvent;
-import github.daneren2005.dsub.fragments.NowPlayingFragment;
-
-import android.widget.EditText;
-
-import github.daneren2005.dsub.util.Constants;
-
-public class DownloadActivity extends SubsonicActivity {
- private static final String TAG = DownloadActivity.class.getSimpleName();
- private EditText playlistNameView;
-
- /**
- * Called when the activity is first created.
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.download_activity);
-
- if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
- currentFragment = new NowPlayingFragment();
- if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) {
- Bundle args = new Bundle();
- args.putBoolean(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true);
- currentFragment.setArguments(args);
- }
- currentFragment.setPrimaryFragment(true);
- getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent me) {
- if(currentFragment != null && currentFragment.getGestureDetector() != null) {
- return currentFragment.getGestureDetector().onTouchEvent(me);
- } else {
- return false;
- }
- }
-}
diff --git a/app/src/main/java/github/daneren2005/dsub/activity/EditPlayActionActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/EditPlayActionActivity.java
index e1f2cad3..0396f8a4 100644
--- a/app/src/main/java/github/daneren2005/dsub/activity/EditPlayActionActivity.java
+++ b/app/src/main/java/github/daneren2005/dsub/activity/EditPlayActionActivity.java
@@ -16,7 +16,7 @@
package github.daneren2005.dsub.activity;
import android.app.Activity;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
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 4651eb0b..f7e7251c 100644
--- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java
+++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java
@@ -25,17 +25,18 @@ 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;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -51,14 +52,13 @@ import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
-import android.widget.ListView;
+import android.widget.ImageView;
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;
@@ -68,20 +68,20 @@ import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.service.HeadphoneListenerService;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.ImageLoader;
+import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.util.Util;
-import github.daneren2005.dsub.adapter.DrawerAdapter;
import github.daneren2005.dsub.view.UpdateView;
import github.daneren2005.dsub.util.UserUtil;
-public class SubsonicActivity extends ActionBarActivity implements OnItemSelectedListener {
+public class SubsonicActivity extends AppCompatActivity implements OnItemSelectedListener {
private static final String TAG = SubsonicActivity.class.getSimpleName();
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>();
@@ -95,11 +95,15 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
ViewGroup rootView;
DrawerLayout drawer;
ActionBarDrawerToggle drawerToggle;
- DrawerAdapter drawerAdapter;
- ListView drawerList;
- TextView lastSelectedView = null;
+ NavigationView drawerList;
+ View drawerHeader;
+ ImageView drawerUserAvatar;
+ TextView drawerServerName;
+ TextView drawerUserName;
int lastSelectedPosition = 0;
+ boolean showingTabs = true;
boolean drawerOpen = false;
+ SharedPreferences.OnSharedPreferenceChangeListener preferencesListener;
@Override
protected void onCreate(Bundle bundle) {
@@ -118,26 +122,49 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
super.onCreate(bundle);
startService(new Intent(this, DownloadService.class));
setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- View actionbar = getLayoutInflater().inflate(R.layout.actionbar_spinner, null);
- actionBarSpinner = (Spinner)actionbar.findViewById(R.id.spinner);
- spinnerAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item);
- spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- actionBarSpinner.setOnItemSelectedListener(this);
- actionBarSpinner.setAdapter(spinnerAdapter);
-
- getSupportActionBar().setCustomView(actionbar);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setHomeButtonEnabled(true);
if(getIntent().hasExtra(Constants.FRAGMENT_POSITION)) {
lastSelectedPosition = getIntent().getIntExtra(Constants.FRAGMENT_POSITION, 0);
}
+
+ 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
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
+
+ if(spinnerAdapter == null) {
+ createCustomActionBarView();
+ }
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeButtonEnabled(true);
+
// Sync the toggle state after onRestoreInstanceState has occurred.
if(drawerToggle != null) {
drawerToggle.syncState();
@@ -150,6 +177,17 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
}
}
+ protected void createCustomActionBarView() {
+ View customActionbar = getLayoutInflater().inflate(R.layout.actionbar_spinner, null);
+ actionBarSpinner = (Spinner)customActionbar.findViewById(R.id.spinner);
+ spinnerAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item);
+ spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ actionBarSpinner.setOnItemSelectedListener(this);
+ actionBarSpinner.setAdapter(spinnerAdapter);
+
+ getSupportActionBar().setCustomView(customActionbar);
+ }
+
@Override
protected void onResume() {
super.onResume();
@@ -160,8 +198,8 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
restart();
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
-
- populateDrawer();
+
+ populateTabs();
UpdateView.addActiveActivity();
}
@@ -176,6 +214,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
protected void onDestroy() {
super.onDestroy();
destroyed = true;
+ Util.getPreferences(this).unregisterOnSharedPreferenceChangeListener(preferencesListener);
}
@Override
@@ -185,19 +224,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);
@@ -210,34 +236,100 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
LayoutInflater layoutInflater = getLayoutInflater();
layoutInflater.inflate(viewId, rootView);
}
-
- drawerList = (ListView) findViewById(R.id.left_drawer);
- drawerList.setOnItemClickListener(new ListView.OnItemClickListener() {
+
+ drawerList = (NavigationView) findViewById(R.id.left_drawer);
+ drawerList.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(final MenuItem menuItem) {
+ if(showingTabs) {
+ // Settings are on a different selectable track
+ if (menuItem.getItemId() != R.id.drawer_settings && menuItem.getItemId() != R.id.drawer_admin) {
+ 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");
+ menuItem.setChecked(true);
+ lastSelectedPosition = menuItem.getItemId();
+ }
+ });
+ } else {
+ drawerItemSelected("Admin");
+ menuItem.setChecked(true);
+ lastSelectedPosition = menuItem.getItemId();
+ }
+ 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 {
+ 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 onItemClick(AdapterView<?> parent, final View view, final int position, long id) {
- final int actualPosition = drawerAdapter.getActualPosition(position);
- 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 void onClick(View v) {
+ if(showingTabs) {
+ populateServers();
} else {
- drawerItemSelected(actualPosition, view);
+ populateTabs();
}
}
});
+ 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();
if(!isTv()) {
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
- drawerToggle = new ActionBarDrawerToggle(this, drawer, R.string.common_appname, R.string.common_appname) {
+ // Pass in toolbar if it exists
+ Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
+ drawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.common_appname, R.string.common_appname) {
@Override
public void onDrawerClosed(View view) {
setTitle(currentFragment.getTitle());
@@ -246,23 +338,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).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);
@@ -299,7 +387,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
primaryContainer = findViewById(R.id.fragment_container);
}
}
-
+
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
@@ -363,6 +451,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();
}
@@ -370,10 +464,11 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
-
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
+ SubsonicFragment currentFragment = getCurrentFragment();
if(drawerOpen) {
menuInflater.inflate(R.menu.drawer_menu, menu);
} else if(currentFragment != null) {
@@ -399,7 +494,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
return true;
}
- return currentFragment.onOptionsItemSelected(item);
+ return getCurrentFragment().onOptionsItemSelected(item);
}
@Override
@@ -415,7 +510,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
}
return super.onKeyDown(keyCode, event);
}
-
+
@Override
public void setTitle(CharSequence title) {
if(title != null && !title.equals(getSupportActionBar().getTitle())) {
@@ -426,7 +521,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
public void setSubtitle(CharSequence title) {
getSupportActionBar().setSubtitle(title);
}
-
+
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int top = spinnerAdapter.getCount() - 1;
@@ -439,97 +534,68 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
@Override
public void onNothingSelected(AdapterView<?> parent) {
-
+
}
-
- 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);
boolean sharedEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_SHARED_ENABLED, true) && !Util.isOffline(this);
boolean chatEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_CHAT_ENABLED, true) && !Util.isOffline(this);
boolean adminEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_ADMIN_ENABLED, true) && !Util.isOffline(this);
-
- if(drawerItems == null || !enabledItems[0] == podcastsEnabled || !enabledItems[1] == bookmarksEnabled || !enabledItems[2] == sharedEnabled || !enabledItems[3] == chatEnabled || !enabledItems[4] == adminEnabled) {
- drawerItems = getResources().getStringArray(R.array.drawerItems);
- drawerItemsDescriptions = getResources().getStringArray(R.array.drawerItemsDescriptions);
-
- 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) == null) {
- lastSelectedView = null;
- drawerAdapter.setSelectedPosition(lastSelectedPosition);
- } else {
- lastSelectedView = (TextView) drawerList.getChildAt(lastSelectedPosition).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 drawerItemSelected(int position, View view) {
- startFragmentActivity(drawerItemsDescriptions[position]);
-
- if(lastSelectedView != view) {
- if(lastSelectedView != null) {
- lastSelectedView.setTextAppearance(this, R.style.DSub_TextViewStyle);
+ private void populateServers() {
+ drawerList.getMenu().clear();
+
+ 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);
}
-
- lastSelectedView = (TextView) view.findViewById(R.id.drawer_name);
- lastSelectedView.setTextAppearance(this, R.style.DSub_TextViewStyle_Bold);
- lastSelectedPosition = position;
}
+ drawerList.getMenu().setGroupCheckable(MENU_GROUP_SERVER, true, true);
+
+ 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) {
@@ -539,6 +605,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();
}
@@ -575,6 +644,10 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
}
}
+ protected SubsonicFragment getCurrentFragment() {
+ return this.currentFragment;
+ }
+
public void replaceFragment(SubsonicFragment fragment, int tag) {
replaceFragment(fragment, tag, false);
}
@@ -628,11 +701,11 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
backStack.remove(backStack.size() - 1);
}
}
-
+
// Add fragment to the right container
trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
trans.add(R.id.fragment_second_container, fragment, tag + "");
-
+
// Commit it all
trans.commit();
}
@@ -656,7 +729,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
trans.commit();
} else {
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
-
+
// Remove old right fragment
trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
trans.remove(oldFrag);
@@ -682,7 +755,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
secondaryContainer.startAnimation(AnimationUtils.loadAnimation(this, R.anim.exit_to_right));
secondaryContainer.setVisibility(View.GONE);
}
-
+
trans.commit();
}
recreateSpinner();
@@ -695,16 +768,19 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
}
currentFragment.invalidate();
- populateDrawer();
+ populateTabs();
}
-
+
supportInvalidateOptionsMenu();
}
-
+
protected void recreateSpinner() {
if(currentFragment == null || currentFragment.getTitle() == null) {
return;
}
+ if(spinnerAdapter == null) {
+ createCustomActionBarView();
+ }
if(backStack.size() > 0) {
spinnerAdapter.clear();
@@ -727,6 +803,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
getSupportActionBar().setDisplayShowCustomEnabled(true);
}
} else if(!isTv()) {
+ getSupportActionBar().setTitle(currentFragment.getTitle());
getSupportActionBar().setDisplayShowCustomEnabled(false);
}
}
@@ -735,6 +812,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
Intent intent = new Intent(this, ((Object) this).getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtras(getIntent());
+ intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition);
Util.startActivityWithoutTransition(this, intent);
}
@@ -745,7 +823,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
theme = theme.substring(0, theme.indexOf("_fullscreen"));
Util.setTheme(this, theme);
}
-
+
Util.applyTheme(this, theme);
}
private void applyFullscreen() {
@@ -754,8 +832,8 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
// Hide additional elements on higher Android versions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_FULLSCREEN |
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ View.SYSTEM_UI_FLAG_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
getWindow().getDecorView().setSystemUiVisibility(flags);
} else if(Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
@@ -786,7 +864,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
if(finished) {
return null;
}
-
+
// If service is not available, request it to start and wait for it.
for (int i = 0; i < 5; i++) {
DownloadService downloadService = DownloadService.getInstance();
@@ -799,7 +877,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
}
return DownloadService.getInstance();
}
-
+
public static String getThemeName() {
return theme;
}
@@ -811,6 +889,38 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
return touchscreen;
}
+ public void openNowPlaying() {
+
+ }
+ public void closeNowPlaying() {
+
+ }
+
+ public void setActiveServer(int instance) {
+ if (Util.getActiveServer(this) != instance) {
+ final DownloadService service = getDownloadService();
+ if (service != null) {
+ new SilentBackgroundTask<Void>(this) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ service.clearIncomplete();
+ return null;
+ }
+ }.execute();
+
+ }
+ Util.setActiveServer(this, instance);
+ invalidate();
+ UserUtil.refreshCurrentUser(this, false, true);
+ updateDrawerHeader();
+ }
+ }
+ private void updateDrawerHeader() {
+ drawerServerName.setText(Util.getServerName(this));
+ drawerUserName.setText(UserUtil.getCurrentUsername(this));
+ getImageLoader().loadAvatar(this, drawerUserAvatar, UserUtil.getCurrentUsername(this));
+ }
+
private void setUncaughtExceptionHandler() {
Thread.UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
if (!(handler instanceof SubsonicActivity.SubsonicUncaughtExceptionHandler)) {
diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
index 6614e09d..c7661080 100644
--- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
+++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
@@ -30,15 +30,20 @@ import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
+import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
+import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.ImageButton;
+import android.widget.ImageView;
import android.widget.TextView;
+import com.sothree.slidinguppanel.SlidingUpPanelLayout;
+
import java.io.File;
-import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -53,6 +58,7 @@ import github.daneren2005.dsub.fragments.AdminFragment;
import github.daneren2005.dsub.fragments.ChatFragment;
import github.daneren2005.dsub.fragments.DownloadFragment;
import github.daneren2005.dsub.fragments.MainFragment;
+import github.daneren2005.dsub.fragments.NowPlayingFragment;
import github.daneren2005.dsub.fragments.SearchFragment;
import github.daneren2005.dsub.fragments.SelectArtistFragment;
import github.daneren2005.dsub.fragments.SelectBookmarkFragment;
@@ -66,7 +72,6 @@ import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
import github.daneren2005.dsub.updates.Updater;
-import github.daneren2005.dsub.util.BackgroundTask;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.FileUtil;
import github.daneren2005.dsub.util.SilentBackgroundTask;
@@ -83,9 +88,16 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
private static boolean sessionInitialized = false;
private static long ALLOWED_SKEW = 30000L;
+ private Handler handler = new Handler();
+ private SlidingUpPanelLayout slideUpPanel;
+ private NowPlayingFragment nowPlayingFragment;
+ private Toolbar mainToolbar;
+ private Toolbar nowPlayingToolbar;
+
private ScheduledExecutorService executorService;
+ private View slideUpFrame;
private View bottomBar;
- private View coverArtView;
+ private ImageView coverArtView;
private TextView trackView;
private TextView artistView;
private ImageButton startButton;
@@ -95,6 +107,24 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
+ if(savedInstanceState == null) {
+ String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
+ boolean firstRun = false;
+ if (fragmentType == null) {
+ fragmentType = Util.openToTab(this);
+ if (fragmentType != null) {
+ firstRun = true;
+ }
+ }
+
+ if ("".equals(fragmentType) || fragmentType == null || firstRun) {
+ // Initial startup stuff
+ if (!sessionInitialized) {
+ loadSession();
+ }
+ }
+ }
+
super.onCreate(savedInstanceState);
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) {
stopService(new Intent(this, DownloadService.class));
@@ -102,75 +132,151 @@ 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);
- }
- } else if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) {
- DownloadService service = getDownloadService();
- if((service != null && service.getCurrentPlaying() != null)) {
- getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD);
- Intent intent = new Intent();
- intent.setClass(this, DownloadActivity.class);
- startActivity(intent);
- }
+ lastSelectedPosition = R.id.drawer_downloading;
}
setContentView(R.layout.abstract_fragment_activity);
UserUtil.seedCurrentUser(this);
if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
- boolean firstRun = false;
if(fragmentType == null) {
fragmentType = Util.openToTab(this);
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;
}
- }
- currentFragment = getNewFragment(fragmentType);
-
- if("".equals(fragmentType) || fragmentType == null || firstRun) {
- // Initial startup stuff
- if(!sessionInitialized) {
- loadSession();
+
+ MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition);
+ if(item != null) {
+ item.setChecked(true);
}
}
-
+ currentFragment = getNewFragment(fragmentType);
currentFragment.setPrimaryFragment(true);
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
-
+
if(getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
SearchFragment fragment = new SearchFragment();
replaceFragment(fragment, fragment.getSupportTag());
}
-
+
// If a album type is set, switch to that album type view
String albumType = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
if(albumType != null) {
SubsonicFragment fragment = new SelectDirectoryFragment();
-
+
Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, albumType);
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
-
+
fragment.setArguments(args);
replaceFragment(fragment, fragment.getSupportTag());
}
}
- bottomBar = findViewById(R.id.bottom_bar);
- bottomBar.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- Intent intent = new Intent();
- intent.setClass(v.getContext(), DownloadActivity.class);
- startActivity(intent);
+ slideUpPanel = (SlidingUpPanelLayout) findViewById(R.id.slide_up_panel);
+ slideUpPanel.setPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() {
+ @Override
+ public void onPanelSlide(View panel, float slideOffset) {
+
+ }
+
+ @Override
+ public void onPanelCollapsed(View panel) {
+ bottomBar.setVisibility(View.VISIBLE);
+ nowPlayingToolbar.setVisibility(View.GONE);
+ nowPlayingFragment.setPrimaryFragment(false);
+ setSupportActionBar(mainToolbar);
+
+ if(getSupportActionBar().getCustomView() == null) {
+ createCustomActionBarView();
+ }
+ recreateSpinner();
+ if(drawerToggle != null && backStack.size() > 0) {
+ drawerToggle.setDrawerIndicatorEnabled(false);
+ } else {
+ drawerToggle.setDrawerIndicatorEnabled(true);
+ }
+ }
+
+ @Override
+ public void onPanelExpanded(View panel) {
+ // Disable custom view before switching
+ getSupportActionBar().setDisplayShowCustomEnabled(false);
+
+ bottomBar.setVisibility(View.GONE);
+ nowPlayingToolbar.setVisibility(View.VISIBLE);
+ setSupportActionBar(nowPlayingToolbar);
+ nowPlayingFragment.setPrimaryFragment(true);
+
+ drawerToggle.setDrawerIndicatorEnabled(false);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+
+ @Override
+ public void onPanelAnchored(View panel) {
+
+ }
+
+ @Override
+ public void onPanelHidden(View panel) {
+
}
});
- coverArtView = bottomBar.findViewById(R.id.album_art);
+
+ if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) {
+ // Post this later so it actually runs
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ openNowPlaying();
+ }
+ }, 200);
+ }
+
+ slideUpFrame = findViewById(R.id.slide_up_frame);
+ bottomBar = findViewById(R.id.bottom_bar);
+ mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
+ nowPlayingToolbar = (Toolbar) findViewById(R.id.now_playing_toolbar);
+ coverArtView = (ImageView) bottomBar.findViewById(R.id.album_art);
trackView = (TextView) bottomBar.findViewById(R.id.track_name);
artistView = (TextView) bottomBar.findViewById(R.id.artist_name);
+ setSupportActionBar(mainToolbar);
+
+ if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
+ nowPlayingFragment = new NowPlayingFragment();
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+ trans.add(R.id.now_playing_fragment_container, nowPlayingFragment, nowPlayingFragment.getTag() + "");
+ trans.commit();
+ }
+
ImageButton previousButton = (ImageButton) findViewById(R.id.download_previous);
previousButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -262,7 +368,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
}
}
}
-
+
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
@@ -276,7 +382,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
if (query != null) {
((SearchFragment)currentFragment).search(query, autoplay);
} else {
- ((SearchFragment)currentFragment).populateList();
if (requestsearch) {
onSearchRequested();
}
@@ -300,7 +405,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
public void onResume() {
super.onResume();
- final Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
@@ -329,9 +433,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();
@@ -347,8 +448,17 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
}
@Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ super.onSaveInstanceState(savedInstanceState);
+ savedInstanceState.putString(Constants.MAIN_NOW_PLAYING, nowPlayingFragment.getTag());
+ }
+ @Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
+
+ String id = savedInstanceState.getString(Constants.MAIN_NOW_PLAYING);
+ FragmentManager fm = getSupportFragmentManager();
+ nowPlayingFragment = (NowPlayingFragment) fm.findFragmentByTag(id);
if(drawerToggle != null && backStack.size() > 0) {
drawerToggle.setDrawerIndicatorEnabled(false);
}
@@ -369,7 +479,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
@Override
public void onBackPressed() {
- if(onBackPressedSupport()) {
+ if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
+ slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
+ } else if(onBackPressedSupport()) {
if(!Util.disableExitPrompt(this) && lastBackPressTime < (System.currentTimeMillis() - 4000)) {
lastBackPressTime = System.currentTimeMillis();
Util.toast(this, R.string.main_back_confirm);
@@ -380,6 +492,15 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
}
@Override
+ protected SubsonicFragment getCurrentFragment() {
+ if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
+ return nowPlayingFragment;
+ } else {
+ return super.getCurrentFragment();
+ }
+ }
+
+ @Override
public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) {
super.replaceFragment(fragment, tag, replaceCurrent);
if(drawerToggle != null) {
@@ -393,24 +514,33 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
drawerToggle.setDrawerIndicatorEnabled(true);
}
}
-
+
+ @Override
+ protected void drawerItemSelected(String fragmentType) {
+ super.drawerItemSelected(fragmentType);
+
+ if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
+ slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
+ }
+ }
+
@Override
public void startFragmentActivity(String fragmentType) {
// Create a transaction that does all of this
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
-
+
// Clear existing stack
for(int i = backStack.size() - 1; i >= 0; i--) {
trans.remove(backStack.get(i));
}
trans.remove(currentFragment);
backStack.clear();
-
+
// Create new stack
currentFragment = getNewFragment(fragmentType);
currentFragment.setPrimaryFragment(true);
trans.add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "");
-
+
// Done, cleanup
trans.commit();
supportInvalidateOptionsMenu();
@@ -426,7 +556,16 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
drawerToggle.setDrawerIndicatorEnabled(true);
}
}
-
+
+ @Override
+ public void openNowPlaying() {
+ slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
+ }
+ @Override
+ public void closeNowPlaying() {
+ slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
+ }
+
private SubsonicFragment getNewFragment(String fragmentType) {
if("Artist".equals(fragmentType)) {
return new SelectArtistFragment();
@@ -447,7 +586,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
} else {
return new MainFragment();
}
- }
+ }
private void update() {
DownloadService downloadService = getDownloadService();
@@ -465,20 +604,33 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
}
MusicDirectory.Entry song = null;
- if(current != null) {
- song = current.getSong();
- trackView.setText(song.getTitle());
- artistView.setText(song.getArtist());
- } else {
- trackView.setText("Title");
- artistView.setText("Artist");
- }
+ if(current != null || slideUpFrame.getVisibility() != View.GONE) {
+ slideUpFrame.setVisibility(View.VISIBLE);
+ if (current != null) {
+ song = current.getSong();
+ trackView.setText(song.getTitle());
+ artistView.setText(song.getArtist());
+ } else {
+ trackView.setText(R.string.main_title);
+ artistView.setText(R.string.main_artist);
+ }
+
+ 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);
+ }
- getImageLoader().loadImage(coverArtView, song, false, false);
- int[] attrs = new int[] {(state == PlayerState.STARTED) ? R.attr.media_button_pause : R.attr.media_button_start};
- TypedArray typedArray = this.obtainStyledAttributes(attrs);
- startButton.setImageResource(typedArray.getResourceId(0, 0));
- typedArray.recycle();
+ int[] attrs = new int[]{(state == PlayerState.STARTED) ? R.attr.actionbar_pause : R.attr.actionbar_start};
+ TypedArray typedArray = this.obtainStyledAttributes(attrs);
+ startButton.setImageResource(typedArray.getResourceId(0, 0));
+ typedArray.recycle();
+ }
}
public void checkUpdates() {
@@ -502,7 +654,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
if(ServerInfo.canSavePlayQueue(this) && !Util.isOffline(this)) {
loadRemotePlayQueue();
}
-
+
sessionInitialized = true;
}
private void loadSettings() {
@@ -551,7 +703,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
return true;
}
}
-
+
private void loadBookmarks() {
final Context context = this;
new SilentBackgroundTask<Void>(context) {
@@ -562,7 +714,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
return null;
}
-
+
@Override
public void error(Throwable error) {
Log.e(TAG, "Failed to get bookmarks", error);
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/AlbumGridAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/AlbumGridAdapter.java
deleted file mode 100644
index eb187569..00000000
--- a/app/src/main/java/github/daneren2005/dsub/adapter/AlbumGridAdapter.java
+++ /dev/null
@@ -1,73 +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 2014 (C) Scott Jackson
-*/
-
-package github.daneren2005.dsub.adapter;
-
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-
-import java.util.List;
-
-import github.daneren2005.dsub.domain.MusicDirectory;
-import github.daneren2005.dsub.util.ImageLoader;
-import github.daneren2005.dsub.view.AlbumCell;
-
-public class AlbumGridAdapter extends ArrayAdapter<MusicDirectory.Entry> {
- private final static String TAG = AlbumGridAdapter.class.getSimpleName();
- private final Context activity;
- private final ImageLoader imageLoader;
- private List<MusicDirectory.Entry> entries;
- private boolean showArtist;
-
- public AlbumGridAdapter(Context activity, ImageLoader imageLoader, List<MusicDirectory.Entry> entries, boolean showArtist) {
- super(activity, android.R.layout.simple_list_item_1, entries);
- this.entries = entries;
- this.activity = activity;
- this.imageLoader = imageLoader;
-
- // Always show artist if they aren't all the same
- if(!showArtist) {
- String artist = null;
- for(MusicDirectory.Entry entry: entries) {
- if(artist == null) {
- artist = entry.getArtist();
- }
-
- if(artist != null && !artist.equals(entry.getArtist())) {
- showArtist = true;
- }
- }
- }
- this.showArtist = showArtist;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- MusicDirectory.Entry entry = getItem(position);
-
- AlbumCell view;
- if(convertView instanceof AlbumCell) {
- view = (AlbumCell) convertView;
- } else {
- view = new AlbumCell(activity);
- }
-
- view.setShowArtist(showArtist);
- view.setObject(entry, imageLoader);
- return view;
- }
-}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java
index 4d469faf..7461af69 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java
@@ -1,97 +1,128 @@
/*
- This file is part of Subsonic.
+ 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
+*/
- 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 2010 (C) Sindre Mehus
- */
package github.daneren2005.dsub.adapter;
import android.content.Context;
-import github.daneren2005.dsub.R;
-import java.util.List;
+import android.support.v7.widget.PopupMenu;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.SectionIndexer;
+import android.widget.TextView;
+
+import java.util.List;
+
+import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.Artist;
+import github.daneren2005.dsub.domain.MusicFolder;
+import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.view.ArtistView;
+import github.daneren2005.dsub.view.UpdateView;
+
+public class ArtistAdapter extends SectionAdapter<Artist> {
+ public static int VIEW_TYPE_ARTIST = 4;
+
+ private List<MusicFolder> musicFolders;
+ private OnMusicFolderChanged onMusicFolderChanged;
+
+ public ArtistAdapter(Context context, List<Artist> artists, OnItemClickedListener listener) {
+ this(context, artists, null, listener, null);
+ }
+
+ public ArtistAdapter(Context context, List<Artist> artists, List<MusicFolder> musicFolders, OnItemClickedListener onItemClickedListener, OnMusicFolderChanged onMusicFolderChanged) {
+ super(context, artists);
+ this.musicFolders = musicFolders;
+ this.onItemClickedListener = onItemClickedListener;
+ this.onMusicFolderChanged = onMusicFolderChanged;
+
+ if(musicFolders != null) {
+ this.singleSectionHeader = true;
+ }
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
+ final View header = LayoutInflater.from(context).inflate(R.layout.select_artist_header, parent, false);
+ header.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ PopupMenu popup = new PopupMenu(context, header.findViewById(R.id.select_artist_folder_2));
+
+ popup.getMenu().add(R.string.select_artist_all_folders);
+ for (MusicFolder musicFolder : musicFolders) {
+ popup.getMenu().add(musicFolder.getName());
+ }
+
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ for (MusicFolder musicFolder : musicFolders) {
+ if(item.getTitle().equals(musicFolder.getName())) {
+ if(onMusicFolderChanged != null) {
+ onMusicFolderChanged.onMusicFolderChanged(musicFolder);
+ }
+ return true;
+ }
+ }
+
+ if(onMusicFolderChanged != null) {
+ onMusicFolderChanged.onMusicFolderChanged(null);
+ }
+ return true;
+ }
+ });
+ popup.show();
+ }
+ });
+
+ return new UpdateView.UpdateViewHolder(header, false);
+ }
+ @Override
+ public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header) {
+ TextView folderName = (TextView) holder.getView().findViewById(R.id.select_artist_folder_2);
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-/**
- * @author Sindre Mehus
- */
-public class ArtistAdapter extends ArrayAdapter<Artist> implements SectionIndexer {
-
- private final Context activity;
-
- // Both arrays are indexed by section ID.
- private final Object[] sections;
- private final Integer[] positions;
-
- public ArtistAdapter(Context activity, List<Artist> artists) {
- super(activity, R.layout.basic_list_item, artists);
- this.activity = activity;
-
- Set<String> sectionSet = new LinkedHashSet<String>(30);
- List<Integer> positionList = new ArrayList<Integer>(30);
- for (int i = 0; i < artists.size(); i++) {
- Artist artist = artists.get(i);
- String index = artist.getIndex();
- if (!sectionSet.contains(index)) {
- sectionSet.add(index);
- positionList.add(i);
- }
- }
- sections = sectionSet.toArray(new Object[sectionSet.size()]);
- positions = positionList.toArray(new Integer[positionList.size()]);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Artist entry = getItem(position);
- ArtistView view;
- if (convertView != null && convertView instanceof ArtistView) {
- view = (ArtistView) convertView;
+ String musicFolderId = Util.getSelectedMusicFolderId(context);
+ if(musicFolderId != null) {
+ for (MusicFolder musicFolder : musicFolders) {
+ if (musicFolder.getId().equals(musicFolderId)) {
+ folderName.setText(musicFolder.getName());
+ break;
+ }
+ }
} else {
- view = new ArtistView(activity);
+ folderName.setText(R.string.select_artist_all_folders);
}
- view.setObject(entry);
- return view;
- }
-
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new ArtistView(context));
+ }
+
@Override
- public Object[] getSections() {
- return sections;
- }
-
- @Override
- public int getPositionForSection(int section) {
- section = Math.min(section, positions.length - 1);
- return positions[section];
- }
-
- @Override
- public int getSectionForPosition(int pos) {
- for (int i = 0; i < sections.length - 1; i++) {
- if (pos < positions[i + 1]) {
- return i;
- }
- }
- return sections.length - 1;
- }
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Artist item, int viewType) {
+ holder.getUpdateView().setObject(item);
+ }
+
+ @Override
+ public int getItemViewType(Artist item) {
+ return VIEW_TYPE_ARTIST;
+ }
+
+ public interface OnMusicFolderChanged {
+ void onMusicFolderChanged(MusicFolder musicFolder);
+ }
}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/BasicListAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/BasicListAdapter.java
new file mode 100644
index 00000000..dfea91bf
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/BasicListAdapter.java
@@ -0,0 +1,48 @@
+/*
+ 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.ViewGroup;
+
+import java.util.List;
+
+import github.daneren2005.dsub.view.BasicListView;
+import github.daneren2005.dsub.view.UpdateView;
+
+public class BasicListAdapter extends SectionAdapter<String> {
+ public static int VIEW_TYPE_LINE = 1;
+
+ public BasicListAdapter(Context context, List<String> strings, OnItemClickedListener listener) {
+ super(context, strings);
+ this.onItemClickedListener = listener;
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new BasicListView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, String item, int viewType) {
+ holder.getUpdateView().setObject(item);
+ }
+
+ @Override
+ public int getItemViewType(String item) {
+ return VIEW_TYPE_LINE;
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/BookmarkAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/BookmarkAdapter.java
index 26d3e16a..8335966d 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/BookmarkAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/BookmarkAdapter.java
@@ -1,20 +1,16 @@
/*
- This file is part of Subsonic.
-
+ 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 2010 (C) Sindre Mehus
+ Copyright 2015 (C) Scott Jackson
*/
package github.daneren2005.dsub.adapter;
@@ -22,9 +18,7 @@ package github.daneren2005.dsub.adapter;
import android.content.Context;
import java.util.List;
-import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import android.widget.TextView;
import github.daneren2005.dsub.R;
@@ -32,33 +26,36 @@ import github.daneren2005.dsub.domain.Bookmark;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.view.SongView;
+import github.daneren2005.dsub.view.UpdateView;
-public class BookmarkAdapter extends ArrayAdapter<MusicDirectory.Entry> {
+public class BookmarkAdapter extends SectionAdapter<MusicDirectory.Entry> {
private final static String TAG = BookmarkAdapter.class.getSimpleName();
- private Context activity;
- public BookmarkAdapter(Context activity, List<MusicDirectory.Entry> bookmarks) {
- super(activity, android.R.layout.simple_list_item_1, bookmarks);
- this.activity = activity;
+ public BookmarkAdapter(Context activity, List<MusicDirectory.Entry> bookmarks, OnItemClickedListener listener) {
+ super(activity, bookmarks);
+ this.onItemClickedListener = listener;
}
-
- public View getView(int position, View convertView, ViewGroup parent) {
- MusicDirectory.Entry entry = getItem(position);
- Bookmark bookmark = entry.getBookmark();
- SongView view;
- if (convertView != null) {
- view = (SongView) convertView;
- } else {
- view = new SongView(activity);
- }
- view.setObject(entry, false);
-
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new SongView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, MusicDirectory.Entry item, int viewType) {
+ SongView songView = (SongView) holder.getUpdateView();
+ Bookmark bookmark = item.getBookmark();
+
+ songView.setObject(item, false);
+
// Add current position to duration
- TextView durationTextView = (TextView) view.findViewById(R.id.song_duration);
+ TextView durationTextView = (TextView) songView.findViewById(R.id.song_duration);
String duration = durationTextView.getText().toString();
durationTextView.setText(Util.formatDuration(bookmark.getPosition() / 1000) + " / " + duration);
-
- return view;
+ }
+
+ @Override
+ public int getItemViewType(MusicDirectory.Entry item) {
+ return EntryGridAdapter.VIEW_TYPE_SONG;
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java
index be9b4cb9..7e926d51 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java
@@ -24,26 +24,33 @@ import java.util.List;
import github.daneren2005.dsub.service.DownloadFile;
import github.daneren2005.dsub.view.SongView;
+import github.daneren2005.dsub.view.UpdateView;
-public class DownloadFileAdapter extends ArrayAdapter<DownloadFile> {
- Context context;
+public class DownloadFileAdapter extends SectionAdapter<DownloadFile> {
+ public static int VIEW_TYPE_DOWNLOAD_FILE = 1;
public DownloadFileAdapter(Context context, List<DownloadFile> entries) {
- super(context, android.R.layout.simple_list_item_1, entries);
- this.context = context;
+ super(context, entries);
+ }
+ public DownloadFileAdapter(Context context, List<DownloadFile> entries, OnItemClickedListener onItemClickedListener) {
+ super(context, entries);
+ this.onItemClickedListener = onItemClickedListener;
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new SongView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, DownloadFile item, int viewType) {
+ SongView songView = (SongView) holder.getUpdateView();
+ songView.setObject(item.getSong(), false);
+ songView.setDownloadFile(item);
}
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- SongView view;
- if (convertView != null && convertView instanceof SongView) {
- view = (SongView) convertView;
- } else {
- view = new SongView(context);
- }
- DownloadFile downloadFile = getItem(position);
- view.setObject(downloadFile.getSong(), false);
- view.setDownloadFile(downloadFile);
- return view;
+ public int getItemViewType(DownloadFile item) {
+ return VIEW_TYPE_DOWNLOAD_FILE;
}
}
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/EntryAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/EntryAdapter.java
deleted file mode 100644
index 9e506e5a..00000000
--- a/app/src/main/java/github/daneren2005/dsub/adapter/EntryAdapter.java
+++ /dev/null
@@ -1,82 +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 2010 (C) Sindre Mehus
- */
-package github.daneren2005.dsub.adapter;
-
-import android.content.Context;
-
-import java.util.List;
-
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import github.daneren2005.dsub.domain.MusicDirectory;
-import github.daneren2005.dsub.util.ImageLoader;
-import github.daneren2005.dsub.view.AlbumView;
-import github.daneren2005.dsub.view.ArtistEntryView;
-import github.daneren2005.dsub.view.SongView;
-
-/**
- * @author Sindre Mehus
- */
-public class EntryAdapter extends ArrayAdapter<MusicDirectory.Entry> {
- private final static String TAG = EntryAdapter.class.getSimpleName();
- private final Context activity;
- private final ImageLoader imageLoader;
- private final boolean checkable;
- private List<MusicDirectory.Entry> entries;
-
- public EntryAdapter(Context activity, ImageLoader imageLoader, List<MusicDirectory.Entry> entries, boolean checkable) {
- super(activity, android.R.layout.simple_list_item_1, entries);
- this.entries = entries;
- this.activity = activity;
- this.imageLoader = imageLoader;
- this.checkable = checkable;
- }
-
- public void removeAt(int position) {
- entries.remove(position);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- MusicDirectory.Entry entry = getItem(position);
-
- if (entry.isDirectory()) {
- if(entry.isAlbum()) {
- AlbumView view;
- view = new AlbumView(activity);
- view.setObject(entry, imageLoader);
- return view;
- } else {
- ArtistEntryView view = new ArtistEntryView(activity);
- view.setObject(entry);
- return view;
- }
- } else {
- SongView view;
- if (convertView != null && convertView instanceof SongView) {
- view = (SongView) convertView;
- } else {
- view = new SongView(activity);
- }
- view.setObject(entry, checkable);
- return view;
- }
- }
-}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java
new file mode 100644
index 00000000..48b278ec
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java
@@ -0,0 +1,133 @@
+/*
+ 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.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.domain.MusicDirectory.Entry;
+import github.daneren2005.dsub.util.ImageLoader;
+import github.daneren2005.dsub.view.AlbumView;
+import github.daneren2005.dsub.view.SongView;
+import github.daneren2005.dsub.view.UpdateView;
+import github.daneren2005.dsub.view.UpdateView.UpdateViewHolder;
+
+public class EntryGridAdapter extends SectionAdapter<Entry> {
+ private static String TAG = EntryGridAdapter.class.getSimpleName();
+
+ public static int VIEW_TYPE_ALBUM_CELL = 1;
+ public static int VIEW_TYPE_ALBUM_LINE = 2;
+ public static int VIEW_TYPE_SONG = 3;
+
+ private ImageLoader imageLoader;
+ private boolean largeAlbums;
+ private boolean showArtist = false;
+ private boolean checkable = true;
+ private View header;
+
+ public EntryGridAdapter(Context context, List<Entry> entries, ImageLoader imageLoader, boolean largeCell) {
+ super(context, entries);
+ this.imageLoader = imageLoader;
+ this.largeAlbums = largeCell;
+
+ // Always show artist if they aren't all the same
+ String artist = null;
+ for(MusicDirectory.Entry entry: entries) {
+ if(artist == null) {
+ artist = entry.getArtist();
+ }
+
+ if(artist != null && !artist.equals(entry.getArtist())) {
+ showArtist = true;
+ }
+ }
+ }
+
+ @Override
+ public UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ UpdateView updateView = null;
+ if(viewType == VIEW_TYPE_ALBUM_LINE || viewType == VIEW_TYPE_ALBUM_CELL) {
+ updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
+ } else if(viewType == VIEW_TYPE_SONG) {
+ updateView = new SongView(context);
+ }
+
+ return new UpdateViewHolder(updateView);
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateViewHolder holder, Entry entry, int viewType) {
+ UpdateView view = holder.getUpdateView();
+ if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
+ AlbumView albumView = (AlbumView) view;
+ albumView.setShowArtist(showArtist);
+ albumView.setObject(entry, imageLoader);
+ } else if(viewType == VIEW_TYPE_SONG) {
+ SongView songView = (SongView) view;
+ songView.setObject(entry, checkable && !entry.isVideo());
+ }
+ }
+
+ @Override
+ public void setChecked(UpdateView updateView, boolean checked) {
+ if(updateView instanceof SongView) {
+ ((SongView) updateView).setChecked(checked);
+ }
+ }
+
+ public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
+ return new UpdateViewHolder(header, false);
+ }
+ public void onBindHeaderHolder(UpdateViewHolder holder, String header) {
+
+ }
+
+ @Override
+ public int getItemViewType(Entry entry) {
+ if(entry.isDirectory()) {
+ if (largeAlbums) {
+ return VIEW_TYPE_ALBUM_CELL;
+ } else {
+ return VIEW_TYPE_ALBUM_LINE;
+ }
+ } else {
+ return VIEW_TYPE_SONG;
+ }
+ }
+
+ public void setHeader(View header) {
+ this.header = header;
+ this.singleSectionHeader = true;
+ }
+
+ public void setShowArtist(boolean showArtist) {
+ this.showArtist = showArtist;
+ }
+ public void setCheckable(boolean checkable) {
+ this.checkable = checkable;
+ }
+
+ public void removeAt(int index) {
+ sections.get(0).remove(index);
+ notifyItemRemoved(index);
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java
new file mode 100644
index 00000000..7b7dc6fc
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java
@@ -0,0 +1,146 @@
+/*
+ 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.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.List;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.domain.MusicDirectory.Entry;
+import github.daneren2005.dsub.domain.ServerInfo;
+import github.daneren2005.dsub.service.MusicService;
+import github.daneren2005.dsub.service.MusicServiceFactory;
+import github.daneren2005.dsub.util.ImageLoader;
+import github.daneren2005.dsub.util.SilentBackgroundTask;
+import github.daneren2005.dsub.view.UpdateView;
+
+public class EntryInfiniteGridAdapter extends EntryGridAdapter {
+ public static int VIEW_TYPE_LOADING = 4;
+
+ private String type;
+ private String extra;
+ private int size;
+
+ private boolean loading = false;
+ private boolean allLoaded = false;
+
+ public EntryInfiniteGridAdapter(Context context, List<Entry> entries, ImageLoader imageLoader, boolean largeCell) {
+ super(context, entries, imageLoader, largeCell);
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if(viewType == VIEW_TYPE_LOADING) {
+ View progress = LayoutInflater.from(context).inflate(R.layout.tab_progress, null);
+ progress.setVisibility(View.VISIBLE);
+ return new UpdateView.UpdateViewHolder(progress, false);
+ }
+
+ return super.onCreateViewHolder(parent, viewType);
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ if(isLoadingView(position)) {
+ return VIEW_TYPE_LOADING;
+ }
+
+ return super.getItemViewType(position);
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, int position) {
+ if(!isLoadingView(position)) {
+ super.onBindViewHolder(holder, position);
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ int size = super.getItemCount();
+
+ if(!allLoaded) {
+ size++;
+ }
+
+ return size;
+ }
+
+ public void setData(String type, String extra, int size) {
+ this.type = type;
+ this.extra = extra;
+ this.size = size;
+ }
+
+ public void loadMore() {
+ if(loading || allLoaded) {
+ return;
+ }
+ loading = true;
+
+ new SilentBackgroundTask<Void>(context) {
+ private List<Entry> newData;
+
+ @Override
+ protected Void doInBackground() throws Throwable {
+ newData = cacheInBackground();
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ appendCachedData(newData);
+ loading = false;
+
+ if(newData.isEmpty()) {
+ allLoaded = true;
+ notifyDataSetChanged();
+ }
+ }
+ }.execute();
+ }
+
+ protected List<Entry> cacheInBackground() throws Exception {
+ MusicService service = MusicServiceFactory.getMusicService(context);
+ MusicDirectory result;
+ int offset = sections.get(0).size();
+ if(("genres".equals(type) && ServerInfo.checkServerVersion(context, "1.10.0")) || "years".equals(type)) {
+ result = service.getAlbumList(type, extra, size, offset, context, null);
+ } else if("genres".equals(type) || "genres-songs".equals(type)) {
+ result = service.getSongsByGenre(extra, size, offset, context, null);
+ } else {
+ result = service.getAlbumList(type, size, offset, context, null);
+ }
+ return result.getChildren();
+ }
+
+ protected void appendCachedData(List<Entry> newData) {
+ if(newData.size() > 0) {
+ int start = sections.get(0).size();
+ sections.get(0).addAll(newData);
+ this.notifyItemRangeInserted(start, newData.size());
+ }
+ }
+
+ protected boolean isLoadingView(int position) {
+ return !allLoaded && position >= sections.get(0).size();
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java
index abb208c9..7e6954f9 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java
@@ -1,60 +1,48 @@
/*
- 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/>.
+ 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
+*/
- Copyright 2010 (C) Sindre Mehus
- */
package github.daneren2005.dsub.adapter;
-import android.widget.ArrayAdapter;
-import android.widget.SectionIndexer;
import android.content.Context;
-import android.view.View;
import android.view.ViewGroup;
-import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.Genre;
import github.daneren2005.dsub.view.GenreView;
+import github.daneren2005.dsub.view.UpdateView;
import java.util.List;
-import java.util.Set;
-import java.util.LinkedHashSet;
-import java.util.ArrayList;
-/**
- * @author Sindre Mehus
-*/
-public class GenreAdapter extends ArrayAdapter<Genre>{
- private Context activity;
- private List<Genre> genres;
-
- public GenreAdapter(Context context, List<Genre> genres) {
- super(context, android.R.layout.simple_list_item_1, genres);
- this.activity = context;
- this.genres = genres;
+public class GenreAdapter extends SectionAdapter<Genre>{
+ public static int VIEW_TYPE_GENRE = 1;
+
+ public GenreAdapter(Context context, List<Genre> genres, OnItemClickedListener listener) {
+ super(context, genres);
+ this.onItemClickedListener = listener;
}
-
+
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Genre genre = genres.get(position);
- GenreView view;
- if (convertView != null && convertView instanceof GenreView) {
- view = (GenreView) convertView;
- } else {
- view = new GenreView(activity);
- }
- view.setObject(genre);
- return view;
- }
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new GenreView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Genre item, int viewType) {
+ holder.getUpdateView().setObject(item);
+ }
+
+ @Override
+ public int getItemViewType(Genre item) {
+ return VIEW_TYPE_GENRE;
+ }
}
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..8f1f1c38
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java
@@ -0,0 +1,112 @@
+/*
+ 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 {
+ updateView.setObject(item);
+ }
+ }
+
+ @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/PlaylistAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/PlaylistAdapter.java
index d56a6b97..fa00c1dd 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/PlaylistAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/PlaylistAdapter.java
@@ -1,70 +1,54 @@
/*
- 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 2010 (C) Sindre Mehus
- */
+ 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 github.daneren2005.dsub.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import github.daneren2005.dsub.domain.Playlist;
import github.daneren2005.dsub.view.PlaylistView;
+import github.daneren2005.dsub.view.UpdateView;
-import java.util.Collections;
-import java.util.Comparator;
-
-/**
- * @author Sindre Mehus
- */
-public class PlaylistAdapter extends ArrayAdapter<Playlist> {
+public class PlaylistAdapter extends SectionAdapter<Playlist> {
+ public static int VIEW_TYPE_PLAYLIST = 1;
- private final Context activity;
-
- public PlaylistAdapter(Context activity, List<Playlist> Playlists) {
- super(activity, R.layout.basic_list_item, Playlists);
- this.activity = activity;
+ public PlaylistAdapter(Context context, List<Playlist> playlists, OnItemClickedListener listener) {
+ super(context, playlists);
+ this.onItemClickedListener = listener;
+ }
+ public PlaylistAdapter(Context context, List<String> headers, List<List<Playlist>> sections, OnItemClickedListener listener) {
+ super(context, headers, sections);
+ this.onItemClickedListener = listener;
}
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Playlist entry = getItem(position);
- PlaylistView view;
- if (convertView != null && convertView instanceof PlaylistView) {
- view = (PlaylistView) convertView;
- } else {
- view = new PlaylistView(activity);
- }
- view.setObject(entry);
- return view;
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new PlaylistView(context));
}
- public static class PlaylistComparator implements Comparator<Playlist> {
- @Override
- public int compare(Playlist playlist1, Playlist playlist2) {
- return playlist1.getName().compareToIgnoreCase(playlist2.getName());
- }
-
- public static List<Playlist> sort(List<Playlist> playlists) {
- Collections.sort(playlists, new PlaylistComparator());
- return playlists;
- }
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Playlist playlist, int viewType) {
+ holder.getUpdateView().setObject(playlist);
+ holder.setItem(playlist);
+ }
+ @Override
+ public int getItemViewType(Playlist playlist) {
+ return VIEW_TYPE_PLAYLIST;
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java
index 8ee39a10..dc94178d 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java
@@ -1,60 +1,47 @@
/*
- 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 2010 (C) Sindre Mehus
- */
+ 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.widget.ArrayAdapter;
-import android.widget.SectionIndexer;
import android.content.Context;
-import android.view.View;
import android.view.ViewGroup;
-import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.PodcastChannel;
import github.daneren2005.dsub.view.PodcastChannelView;
+import github.daneren2005.dsub.view.UpdateView;
import java.util.List;
-import java.util.Set;
-import java.util.LinkedHashSet;
-import java.util.ArrayList;
-/**
- * @author Sindre Mehus
-*/
-public class PodcastChannelAdapter extends ArrayAdapter<PodcastChannel>{
- private Context activity;
- private List<PodcastChannel> podcasts;
+public class PodcastChannelAdapter extends SectionAdapter<PodcastChannel>{
+ public static int VIEW_TYPE_PODCAST = 1;
- public PodcastChannelAdapter(Context context, List<PodcastChannel> podcasts) {
- super(context, android.R.layout.simple_list_item_1, podcasts);
- this.activity = context;
- this.podcasts = podcasts;
+ public PodcastChannelAdapter(Context context, List<PodcastChannel> podcasts, OnItemClickedListener listener) {
+ super(context, podcasts);
+ this.onItemClickedListener = listener;
}
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- PodcastChannel podcast = podcasts.get(position);
- PodcastChannelView view;
- if (convertView != null && convertView instanceof PodcastChannelView) {
- view = (PodcastChannelView) convertView;
- } else {
- view = new PodcastChannelView(activity);
- }
- view.setObject(podcast);
- return view;
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new PodcastChannelView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, PodcastChannel item, int viewType) {
+ holder.getUpdateView().setObject(item);
+ }
+
+ @Override
+ public int getItemViewType(PodcastChannel item) {
+ return VIEW_TYPE_PODCAST;
}
}
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/SearchAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SearchAdapter.java
new file mode 100644
index 00000000..c1185702
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/SearchAdapter.java
@@ -0,0 +1,114 @@
+/*
+ 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.content.res.Resources;
+import android.view.ViewGroup;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.MusicDirectory.Entry;
+import github.daneren2005.dsub.domain.SearchResult;
+import github.daneren2005.dsub.util.ImageLoader;
+import github.daneren2005.dsub.view.AlbumView;
+import github.daneren2005.dsub.view.ArtistView;
+import github.daneren2005.dsub.view.SongView;
+import github.daneren2005.dsub.view.UpdateView;
+
+import static github.daneren2005.dsub.adapter.ArtistAdapter.VIEW_TYPE_ARTIST;
+import static github.daneren2005.dsub.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_CELL;
+import static github.daneren2005.dsub.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_LINE;
+import static github.daneren2005.dsub.adapter.EntryGridAdapter.VIEW_TYPE_SONG;
+
+public class SearchAdapter extends SectionAdapter<Serializable> {
+ private SearchResult searchResult;
+ private ImageLoader imageLoader;
+ private boolean largeAlbums;
+
+ public SearchAdapter(Context context, SearchResult searchResult, ImageLoader imageLoader, boolean largeAlbums, OnItemClickedListener listener) {
+ this.context = context;
+ this.searchResult = searchResult;
+ this.imageLoader = imageLoader;
+ this.largeAlbums = largeAlbums;
+
+ this.sections = new ArrayList<>();
+ this.headers = new ArrayList<>();
+ Resources res = context.getResources();
+ if(!searchResult.getArtists().isEmpty()) {
+ this.sections.add((List<Serializable>) (List<?>) searchResult.getArtists());
+ this.headers.add(res.getString(R.string.search_artists));
+ }
+ if(!searchResult.getAlbums().isEmpty()) {
+ this.sections.add((List<Serializable>) (List<?>) searchResult.getAlbums());
+ this.headers.add(res.getString(R.string.search_albums));
+ }
+ if(!searchResult.getSongs().isEmpty()) {
+ this.sections.add((List<Serializable>) (List<?>) searchResult.getSongs());
+ this.headers.add(res.getString(R.string.search_songs));
+ }
+ this.onItemClickedListener = listener;
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ UpdateView updateView = null;
+ if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
+ updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
+ } else if(viewType == VIEW_TYPE_SONG) {
+ updateView = new SongView(context);
+ } else if(viewType == VIEW_TYPE_ARTIST) {
+ updateView = new ArtistView(context);
+ }
+
+ return new UpdateView.UpdateViewHolder(updateView);
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
+ UpdateView view = holder.getUpdateView();
+ if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
+ AlbumView albumView = (AlbumView) view;
+ albumView.setObject((Entry) item, imageLoader);
+ } else if(viewType == VIEW_TYPE_SONG) {
+ SongView songView = (SongView) view;
+ songView.setObject((Entry) item, false);
+ } else if(viewType == VIEW_TYPE_ARTIST) {
+ view.setObject(item);
+ }
+ }
+
+ @Override
+ public int getItemViewType(Serializable item) {
+ if(item instanceof Entry) {
+ Entry entry = (Entry) item;
+ if (entry.isDirectory()) {
+ if (largeAlbums) {
+ return VIEW_TYPE_ALBUM_CELL;
+ } else {
+ return VIEW_TYPE_ALBUM_LINE;
+ }
+ } else {
+ return VIEW_TYPE_SONG;
+ }
+ } else {
+ return VIEW_TYPE_ARTIST;
+ }
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java
new file mode 100644
index 00000000..f57012b5
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java
@@ -0,0 +1,328 @@
+/*
+ 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.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.view.BasicHeaderView;
+import github.daneren2005.dsub.view.UpdateView;
+import github.daneren2005.dsub.view.UpdateView.UpdateViewHolder;
+
+public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewHolder<T>> {
+ private static String TAG = SectionAdapter.class.getSimpleName();
+ public static int VIEW_TYPE_HEADER = 0;
+
+ protected Context context;
+ protected List<String> headers;
+ protected List<List<T>> sections;
+ protected boolean singleSectionHeader;
+ protected OnItemClickedListener<T> onItemClickedListener;
+ protected UpdateView contextView;
+ protected T contextItem;
+ private List<T> selected = new ArrayList<>();
+
+ protected SectionAdapter() {}
+ public SectionAdapter(Context context, List<T> section) {
+ this(context, section, false);
+ }
+ public SectionAdapter(Context context, List<T> section, boolean singleSectionHeader) {
+ this.context = context;
+ this.headers = Arrays.asList("Section");
+ this.sections = new ArrayList<>();
+ this.sections.add(section);
+ this.singleSectionHeader = singleSectionHeader;
+ }
+ public SectionAdapter(Context context, List<String> headers, List<List<T>> sections) {
+ this(context, headers, sections, true);
+ }
+ public SectionAdapter(Context context, List<String> headers, List<List<T>> sections, boolean singleSectionHeader){
+ this.context = context;
+ this.headers = headers;
+ this.sections = sections;
+ this.singleSectionHeader = singleSectionHeader;
+ }
+
+ @Override
+ public UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if(viewType == VIEW_TYPE_HEADER) {
+ return onCreateHeaderHolder(parent);
+ } else {
+ final UpdateViewHolder<T> holder = onCreateSectionViewHolder(parent, viewType);
+ final UpdateView updateView = holder.getUpdateView();
+
+ if(updateView != null) {
+ updateView.getChildAt(0).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ T item = holder.getItem();
+ updateView.onClick();
+ if (updateView.isCheckable()) {
+ if (selected.contains(item)) {
+ selected.remove(item);
+ setChecked(updateView, false);
+ } else {
+ selected.add(item);
+ setChecked(updateView, true);
+ }
+ } else if (onItemClickedListener != null) {
+ onItemClickedListener.onItemClicked(item);
+ }
+ }
+ });
+
+ View moreButton = updateView.findViewById(R.id.more_button);
+ if(moreButton == null) {
+ moreButton = updateView.findViewById(R.id.item_more);
+ }
+ if (moreButton != null) {
+ moreButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ T item = holder.getItem();
+ setContextItem(updateView, item);
+ v.showContextMenu();
+ }
+ });
+
+ /*updateView.getChildAt(0).setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ T item = holder.getItem();
+ setContextItem(updateView, item);
+ v.showContextMenu();
+ return false;
+ }
+ });*/
+ }
+ }
+
+ return holder;
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateViewHolder holder, int position) {
+ UpdateView updateView = holder.getUpdateView();
+
+ if(sections.size() == 1 && !singleSectionHeader) {
+ T item = sections.get(0).get(position);
+ onBindViewHolder(holder, item, getItemViewType(position));
+ if(updateView.isCheckable()) {
+ setChecked(updateView, selected.contains(item));
+ }
+ holder.setItem(item);
+ return;
+ }
+
+ int subPosition = 0;
+ int subHeader = 0;
+ for(List<T> section: sections) {
+ boolean validHeader = headers.get(subHeader) != null;
+ if(position == subPosition && validHeader) {
+ onBindHeaderHolder(holder, headers.get(subHeader));
+ return;
+ }
+
+ 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()) {
+ setChecked(updateView, selected.contains(item));
+ }
+ holder.setItem(item);
+ return;
+ }
+
+ subPosition += section.size();
+ if(validHeader) {
+ subPosition += 1;
+ }
+ subHeader++;
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ if(sections.size() == 1 && !singleSectionHeader) {
+ return sections.get(0).size();
+ }
+
+ int count = 0;
+ for(String header: headers) {
+ if(header != null) {
+ count++;
+ }
+ }
+ for(List<T> section: sections) {
+ count += section.size();
+ }
+
+ return count;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ if(sections.size() == 1 && !singleSectionHeader) {
+ return getItemViewType(sections.get(0).get(position));
+ }
+
+ int subPosition = 0;
+ int subHeader = 0;
+ for(List<T> section: sections) {
+ boolean validHeader = headers.get(subHeader) != null;
+ if(position == subPosition && validHeader) {
+ return VIEW_TYPE_HEADER;
+ }
+
+ int headerOffset = validHeader ? 1 : 0;
+ if(position < (subPosition + section.size() + headerOffset)) {
+ return getItemViewType(section.get(position - subPosition - headerOffset));
+ }
+
+ subPosition += section.size();
+ if(validHeader) {
+ subPosition += 1;
+ }
+ subHeader++;
+ }
+
+ return -1;
+ }
+
+ public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
+ return new UpdateViewHolder(new BasicHeaderView(context));
+ }
+ public void onBindHeaderHolder(UpdateViewHolder holder, String header) {
+ UpdateView view = holder.getUpdateView();
+ if(view != null) {
+ view.setObject(header);
+ }
+ }
+
+ public T getItemForPosition(int position) {
+ if(sections.size() == 1 && !singleSectionHeader) {
+ return sections.get(0).get(position);
+ }
+
+ int subPosition = 0;
+ for(List<T> section: sections) {
+ if(position == subPosition) {
+ return null;
+ }
+
+ if(position <= (subPosition + section.size())) {
+ return section.get(position - subPosition - 1);
+ }
+
+ subPosition += section.size() + 1;
+ }
+
+ return null;
+ }
+ public int getItemPosition(T item) {
+ if(sections.size() == 1 && !singleSectionHeader) {
+ return sections.get(0).indexOf(item);
+ }
+
+ int subPosition = 0;
+ for(List<T> section: sections) {
+ subPosition += section.size() + 1;
+
+ int position = section.indexOf(item);
+ if(position != -1) {
+ return position + subPosition;
+ }
+ }
+
+ return -1;
+ }
+
+ public void setContextItem(UpdateView updateView, T item) {
+ contextView = updateView;
+ contextItem = item;
+ }
+ public UpdateView getContextView() {
+ return contextView;
+ }
+ public T getContextItem() {
+ return contextItem;
+ }
+
+ public void setOnItemClickedListener(OnItemClickedListener<T> onItemClickedListener) {
+ this.onItemClickedListener = onItemClickedListener;
+ }
+
+ public void addSelected(T item) {
+ selected.add(item);
+ }
+ public List<T> getSelected() {
+ List<T> selected = new ArrayList<>();
+ selected.addAll(this.selected);
+ return selected;
+ }
+
+ public void clearSelected() {
+ // TODO: This needs to work with multiple sections
+ for(T item: selected) {
+ int index = sections.get(0).indexOf(item);
+
+ if(singleSectionHeader) {
+ index++;
+ }
+
+ this.notifyItemChanged(index);
+ }
+ selected.clear();
+ }
+
+ public void removeItem(T item) {
+ int subPosition = 0;
+ for(List<T> section: sections) {
+ if(sections.size() > 1 || singleSectionHeader) {
+ subPosition++;
+ }
+
+ int index = section.indexOf(item);
+ if (index != -1) {
+ section.remove(item);
+ notifyItemRemoved(subPosition + index);
+ break;
+ }
+
+ subPosition += section.size();
+ }
+ }
+
+ public abstract UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType);
+ public abstract void onBindViewHolder(UpdateViewHolder holder, T item, int viewType);
+ public abstract int getItemViewType(T item);
+ public void setChecked(UpdateView updateView, boolean checked) {}
+
+ public interface OnItemClickedListener<T> {
+ void onItemClicked(T item);
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java
index 45c3ead1..d99b294b 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java
@@ -16,44 +16,83 @@
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;
import github.daneren2005.dsub.domain.User;
+import github.daneren2005.dsub.util.ImageLoader;
import github.daneren2005.dsub.view.SettingView;
+import github.daneren2005.dsub.view.UpdateView;
import static github.daneren2005.dsub.domain.User.Setting;
-public class SettingsAdapter extends ArrayAdapter<Setting> {
- private final Context context;
+public class SettingsAdapter extends SectionAdapter<Setting> {
+ public final int VIEW_TYPE_SETTING = 1;
+
+ private final User user;
private final boolean editable;
+ private final ImageLoader imageLoader;
- public SettingsAdapter(Context context, User user, boolean editable) {
- super(context, R.layout.basic_list_item, user.getSettings());
- this.context = context;
+ public SettingsAdapter(Context context, User user, ImageLoader imageLoader, boolean editable) {
+ super(context, user.getSettings(), imageLoader != null);
+ this.user = user;
+ this.imageLoader = imageLoader;
this.editable = editable;
+
+ List<Setting> settings = sections.get(0);
+ for(Setting setting: settings) {
+ if(setting.getValue()) {
+ addSelected(setting);
+ }
+ }
}
- public SettingsAdapter(Context context, List<Setting> settings, boolean editable) {
- super(context, R.layout.basic_list_item, settings);
- this.context = context;
- this.editable = editable;
+ public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
+ View header = LayoutInflater.from(context).inflate(R.layout.user_header, parent, false);
+ return new UpdateView.UpdateViewHolder(header, false);
}
+ public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String description) {
+ View header = holder.getView();
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Setting entry = getItem(position);
- SettingView view;
- if (convertView != null && convertView instanceof SettingView) {
- view = (SettingView) convertView;
+ ImageView coverArtView = (ImageView) header.findViewById(R.id.user_avatar);
+ imageLoader.loadAvatar(context, coverArtView, user.getUsername());
+
+ TextView usernameView = (TextView) header.findViewById(R.id.user_username);
+ usernameView.setText(user.getUsername());
+
+ final TextView emailView = (TextView) header.findViewById(R.id.user_email);
+ if(user.getEmail() != null) {
+ emailView.setText(user.getEmail());
} else {
- view = new SettingView(context);
+ emailView.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new SettingView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Setting item, int viewType) {
+ holder.getUpdateView().setObject(item, editable);
+ }
+
+ @Override
+ public int getItemViewType(Setting item) {
+ return VIEW_TYPE_SETTING;
+ }
+
+ @Override
+ public void setChecked(UpdateView updateView, boolean checked) {
+ if(updateView instanceof SettingView) {
+ ((SettingView) updateView).setChecked(checked);
}
- view.setObject(entry, editable);
- return view;
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/ShareAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/ShareAdapter.java
index 4121a85a..6db3d927 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/ShareAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/ShareAdapter.java
@@ -1,56 +1,49 @@
/*
- 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/>.
+ 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
+*/
- Copyright 2010 (C) Sindre Mehus
- */
package github.daneren2005.dsub.adapter;
import android.content.Context;
-import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import java.util.List;
import github.daneren2005.dsub.domain.Share;
import github.daneren2005.dsub.view.ShareView;
+import github.daneren2005.dsub.view.UpdateView;
-/**
- * @author Sindre Mehus
-*/
-public class ShareAdapter extends ArrayAdapter<Share>{
- private Context activity;
- private List<Share> shares;
-
- public ShareAdapter(Context context, List<Share> shares) {
- super(context, android.R.layout.simple_list_item_1, shares);
- this.activity = context;
- this.shares = shares;
+public class ShareAdapter extends SectionAdapter<Share>{
+ public static int VIEW_TYPE_SHARE = 1;
+
+ public ShareAdapter(Context context, List<Share> shares, OnItemClickedListener listener) {
+ super(context, shares);
+ this.onItemClickedListener = listener;
}
-
+
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Share share = shares.get(position);
- ShareView view;
- if (convertView != null && convertView instanceof ShareView) {
- view = (ShareView) convertView;
- } else {
- view = new ShareView(activity);
- }
- view.setObject(share);
- return view;
- }
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new ShareView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Share item, int viewType) {
+ holder.getUpdateView().setObject(item);
+ }
+
+ @Override
+ public int getItemViewType(Share item) {
+ return VIEW_TYPE_SHARE;
+ }
}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/UserAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/UserAdapter.java
index f0f78d97..95809e48 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/UserAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/UserAdapter.java
@@ -25,28 +25,32 @@ import java.util.List;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.User;
import github.daneren2005.dsub.util.ImageLoader;
+import github.daneren2005.dsub.view.UpdateView;
import github.daneren2005.dsub.view.UserView;
-public class UserAdapter extends ArrayAdapter<User> {
- private final Context activity;
+public class UserAdapter extends SectionAdapter<User> {
+ public static int VIEW_TYPE_USER = 1;
+
private final ImageLoader imageLoader;
- public UserAdapter(Context activity, List<User> users, ImageLoader imageLoader) {
- super(activity, R.layout.basic_list_item, users);
- this.activity = activity;
+ public UserAdapter(Context context, List<User> users, ImageLoader imageLoader, OnItemClickedListener listener) {
+ super(context, users);
this.imageLoader = imageLoader;
+ this.onItemClickedListener = listener;
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new UserView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, User item, int viewType) {
+ holder.getUpdateView().setObject(item, imageLoader);
}
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- User entry = getItem(position);
- UserView view;
- if (convertView != null && convertView instanceof UserView) {
- view = (UserView) convertView;
- } else {
- view = new UserView(activity);
- }
- view.setObject(entry, imageLoader);
- return view;
+ public int getItemViewType(User item) {
+ return VIEW_TYPE_USER;
}
} \ No newline at end of file
diff --git a/app/src/main/java/github/daneren2005/dsub/domain/Playlist.java b/app/src/main/java/github/daneren2005/dsub/domain/Playlist.java
index 7cd820c0..99b85ce9 100644
--- a/app/src/main/java/github/daneren2005/dsub/domain/Playlist.java
+++ b/app/src/main/java/github/daneren2005/dsub/domain/Playlist.java
@@ -19,6 +19,9 @@
package github.daneren2005.dsub.domain;
import java.io.Serializable;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
/**
* @author Sindre Mehus
@@ -125,4 +128,16 @@ public class Playlist implements Serializable {
Playlist playlist = (Playlist) o;
return playlist.id.equals(this.id);
}
+
+ public static class PlaylistComparator implements Comparator<Playlist> {
+ @Override
+ public int compare(Playlist playlist1, Playlist playlist2) {
+ return playlist1.getName().compareToIgnoreCase(playlist2.getName());
+ }
+
+ public static List<Playlist> sort(List<Playlist> playlists) {
+ Collections.sort(playlists, new PlaylistComparator());
+ return playlists;
+ }
+ }
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java
index 66ce5f15..f3f9eb64 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.List;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.User;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.parser.SubsonicRESTException;
@@ -37,7 +38,7 @@ import github.daneren2005.dsub.util.UserUtil;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.adapter.UserAdapter;
-public class AdminFragment extends SelectListFragment<User> {
+public class AdminFragment extends SelectRecyclerFragment<User> {
private static String TAG = AdminFragment.class.getSimpleName();
@Override
@@ -69,8 +70,7 @@ public class AdminFragment extends SelectListFragment<User> {
@Override
public boolean onContextItemSelected(MenuItem menuItem) {
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- User user = objects.get(info.position);
+ User user = adapter.getContextItem();
switch(menuItem.getItemId()) {
case R.id.admin_change_email:
@@ -97,8 +97,8 @@ public class AdminFragment extends SelectListFragment<User> {
}
@Override
- public ArrayAdapter getAdapter(List<User> objs) {
- return new UserAdapter(context, objs, getImageLoader());
+ public SectionAdapter getAdapter(List<User> objs) {
+ return new UserAdapter(context, objs, getImageLoader(), this);
}
@Override
@@ -134,9 +134,7 @@ public class AdminFragment extends SelectListFragment<User> {
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- User user = (User) parent.getItemAtPosition(position);
-
+ public void onItemClicked(User user) {
SubsonicFragment fragment = new UserFragment();
Bundle args = new Bundle();
args.putSerializable(Constants.INTENT_EXTRA_NAME_ID, user);
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java
index 59229c3f..5a3d63ad 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java
@@ -30,6 +30,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.service.DownloadFile;
import github.daneren2005.dsub.service.DownloadService;
@@ -38,13 +39,15 @@ import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.adapter.DownloadFileAdapter;
+import github.daneren2005.dsub.view.UpdateView;
-public class DownloadFragment extends SelectListFragment<DownloadFile> {
+public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> {
private long currentRevision;
private ScheduledExecutorService executorService;
public DownloadFragment() {
serialize = false;
+ pullToRefresh = false;
}
@Override
@@ -80,7 +83,7 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> {
}
@Override
- public ArrayAdapter getAdapter(List<DownloadFile> objs) {
+ public SectionAdapter getAdapter(List<DownloadFile> objs) {
return new DownloadFileAdapter(context, objs);
}
@@ -91,9 +94,6 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> {
return new ArrayList<DownloadFile>();
}
- listView.setOnScrollListener(null);
- refreshLayout.setEnabled(false);
-
List<DownloadFile> songList = new ArrayList<DownloadFile>();
songList.addAll(downloadService.getBackgroundDownloads());
currentRevision = downloadService.getDownloadListUpdateRevision();
@@ -106,7 +106,7 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> {
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ public void onItemClicked(DownloadFile item) {
}
@@ -144,11 +144,13 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> {
@Override
public void onCreateContextMenu(android.view.ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ UpdateView targetView = adapter.getContextView();
+ menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0);
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Object selectedItem = ((DownloadFile) listView.getItemAtPosition(info.position)).getSong();
+ DownloadFile downloadFile = adapter.getContextItem();
+ MusicDirectory.Entry selectedItem = downloadFile.getSong();
onCreateContextMenu(menu, view, menuInfo, selectedItem);
- if(selectedItem instanceof MusicDirectory.Entry && !((MusicDirectory.Entry) selectedItem).isVideo() && !Util.isOffline(context)) {
+ if(!selectedItem.isVideo() && !Util.isOffline(context)) {
menu.removeItem(R.id.song_menu_remove_playlist);
}
@@ -161,9 +163,8 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> {
return false;
}
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Object selectedItem = ((DownloadFile) listView.getItemAtPosition(info.position)).getSong();
-
+ DownloadFile downloadFile = adapter.getContextItem();
+ MusicDirectory.Entry selectedItem = downloadFile.getSong();
if(onContextItemSelected(menuItem, selectedItem)) {
return true;
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
index ae38534a..96e1d326 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
@@ -1,6 +1,6 @@
package github.daneren2005.dsub.fragments;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -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,159 +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);
+ public int getOptionsMenu() {
+ return 0;
}
@Override
- public boolean onContextItemSelected(android.view.MenuItem menuItem) {
- if(menuItem.getGroupId() != getSupportTag()) {
- return false;
- }
-
- int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE;
- setActiveServer(activeServer);
- return true;
- }
-
- @Override
- protected void refresh(boolean refresh) {
- createLayout();
- }
-
- private void createLayout() {
- View buttons = inflater.inflate(R.layout.main_buttons, null);
-
- final View serverButton = buttons.findViewById(R.id.main_select_server);
- final TextView serverTextView = (TextView) serverButton.findViewById(R.id.main_select_server_2);
- final TextView offlineButton = (TextView) buttons.findViewById(R.id.main_offline);
- offlineButton.setText(Util.isOffline(context) ? R.string.main_online : R.string.main_offline);
-
- final View albumsTitle = buttons.findViewById(R.id.main_albums);
- final View videoTitle = buttons.findViewById(R.id.main_video_section);
- final View albumsNewestButton = buttons.findViewById(R.id.main_albums_newest);
- countView = (TextView) buttons.findViewById(R.id.main_albums_recent_count);
- final View albumsRandomButton = buttons.findViewById(R.id.main_albums_random);
- final View albumsHighestButton = buttons.findViewById(R.id.main_albums_highest);
- final View albumsRecentButton = buttons.findViewById(R.id.main_albums_recent);
- final View albumsFrequentButton = buttons.findViewById(R.id.main_albums_frequent);
- final View albumsStarredButton = buttons.findViewById(R.id.main_albums_starred);
- final View albumsGenresButton = buttons.findViewById(R.id.main_albums_genres);
- final View albumsYearButton = buttons.findViewById(R.id.main_albums_year);
- final View albumsAlphabeticalButton = buttons.findViewById(R.id.main_albums_alphabetical);
- final View videosButton = buttons.findViewById(R.id.main_videos);
-
- final View dummyView = rootView.findViewById(R.id.main_dummy);
-
- final CheckBox albumsPerFolderCheckbox = (CheckBox) buttons.findViewById(R.id.main_albums_per_folder);
- if(!Util.isOffline(context) && ServerInfo.canAlbumListPerFolder(context)) {
- albumsPerFolderCheckbox.setChecked(Util.getAlbumListsPerFolder(context));
- albumsPerFolderCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- Util.setAlbumListsPerFolder(context, isChecked);
- }
- });
- } else {
- albumsPerFolderCheckbox.setVisibility(View.GONE);
- }
+ public SectionAdapter getAdapter(List objs) {
+ List<List<Integer>> sections = new ArrayList<>();
+ List<String> headers = new ArrayList<>();
- int instance = Util.getActiveServer(context);
- String name = Util.getServerName(context, instance);
- serverTextView.setText(name);
+ List<Integer> offline = Arrays.asList(R.string.main_offline);
+ sections.add(offline);
+ headers.add(null);
- 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);
- if(!Util.isOffline(context)) {
- getMostRecentCount();
- }
+ return new MainAdapter(context, headers, sections, this);
}
- private void setActiveServer(int instance) {
- if (Util.getActiveServer(context) != instance) {
- final DownloadService service = getDownloadService();
- if (service != null) {
- new SilentBackgroundTask<Void>(context) {
- @Override
- protected Void doInBackground() throws Throwable {
- service.clearIncomplete();
- return null;
- }
- }.execute();
+ @Override
+ public List<Integer> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
+ return Arrays.asList(0);
+ }
- }
- Util.setActiveServer(context, instance);
- context.invalidate();
- UserUtil.refreshCurrentUser(context, false, true);
- }
+ @Override
+ public int getTitleResource() {
+ return R.string.common_appname;
}
private void toggleOffline() {
@@ -306,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();
@@ -506,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/fragments/NowPlayingFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
index 3e30af50..0f9d9f68 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
@@ -20,7 +20,8 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import android.app.AlertDialog;
+import android.annotation.TargetApi;
+import android.support.v7.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -30,6 +31,9 @@ import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.MediaRouteButton;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Display;
@@ -54,6 +58,7 @@ import android.widget.TextView;
import android.widget.ViewFlipper;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.activity.SubsonicFragmentActivity;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.audiofx.EqualizerController;
import github.daneren2005.dsub.domain.Bookmark;
import github.daneren2005.dsub.domain.PlayerState;
@@ -69,6 +74,7 @@ import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.adapter.DownloadFileAdapter;
import github.daneren2005.dsub.view.FadeOutAnimation;
+import github.daneren2005.dsub.view.SongView;
import github.daneren2005.dsub.view.UpdateView;
import github.daneren2005.dsub.util.Util;
@@ -78,10 +84,9 @@ import github.daneren2005.dsub.util.*;
import github.daneren2005.dsub.view.AutoRepeatButton;
import java.util.ArrayList;
import java.util.concurrent.ScheduledFuture;
-import com.mobeta.android.dslv.*;
import github.daneren2005.dsub.activity.SubsonicActivity;
-public class NowPlayingFragment extends SubsonicFragment implements OnGestureListener {
+public class NowPlayingFragment extends SubsonicFragment implements OnGestureListener, SectionAdapter.OnItemClickedListener<DownloadFile> {
private static final String TAG = NowPlayingFragment.class.getSimpleName();
private static final int PERCENTAGE_OF_SCREEN_FOR_SWIPE = 10;
private static final int INCREMENT_TIME = 5000;
@@ -96,7 +101,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
private TextView emptyTextView;
private TextView songTitleTextView;
private ImageView albumArtImageView;
- private DragSortListView playlistView;
+ private RecyclerView playlistView;
private TextView positionTextView;
private TextView durationTextView;
private TextView statusTextView;
@@ -141,6 +146,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
startFlipped = true;
}
}
+ primaryFragment = false;
}
@Override
@@ -153,11 +159,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
rootView = inflater.inflate(R.layout.download, container, false);
setTitle(R.string.button_bar_now_playing);
-
+
mainLayout = rootView.findViewById(R.id.download_layout);
- if(!primaryFragment) {
- mainLayout.setVisibility(View.GONE);
- }
WindowManager w = context.getWindowManager();
Display d = w.getDefaultDisplay();
@@ -173,7 +176,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
durationTextView = (TextView)rootView.findViewById(R.id.download_duration);
statusTextView = (TextView)rootView.findViewById(R.id.download_status);
progressBar = (SeekBar)rootView.findViewById(R.id.download_progress_bar);
- playlistView = (DragSortListView)rootView.findViewById(R.id.download_list);
previousButton = (AutoRepeatButton)rootView.findViewById(R.id.download_previous);
nextButton = (AutoRepeatButton)rootView.findViewById(R.id.download_next);
pauseButton =rootView.findViewById(R.id.download_pause);
@@ -185,6 +187,45 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
rateGoodButton = (ImageButton) rootView.findViewById(R.id.download_rating_good);
toggleListButton =rootView.findViewById(R.id.download_toggle_list);
+ playlistView = (RecyclerView)rootView.findViewById(R.id.download_list);
+ setupLayoutManager(playlistView, false);
+ ItemTouchHelper touchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT) {
+ @Override
+ public boolean onMove(RecyclerView recyclerView, final RecyclerView.ViewHolder fromHolder, final RecyclerView.ViewHolder toHolder) {
+ new SilentBackgroundTask<Void>(context) {
+ private int from;
+ private int to;
+
+ @Override
+ protected Void doInBackground() throws Throwable {
+ from = fromHolder.getAdapterPosition();
+ to = toHolder.getAdapterPosition();
+ getDownloadService().swap(true, from, to);
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ songListAdapter.notifyItemMoved(from, to);
+ }
+ }.execute();
+
+ return true;
+ }
+
+ @Override
+ public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
+ SongView songView = (SongView) ((UpdateView.UpdateViewHolder) viewHolder).getUpdateView();
+ DownloadFile downloadFile = songView.getDownloadFile();
+
+ DownloadService downloadService = getDownloadService();
+ downloadService.remove(downloadFile);
+ songListAdapter.removeItem(downloadFile);
+ currentRevision = downloadService.getDownloadListUpdateRevision();
+ }
+ });
+ touchHelper.attachToRecyclerView(playlistView);
+
starButton = (ImageButton)rootView.findViewById(R.id.download_star);
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_STAR, true)) {
starButton.setOnClickListener(new OnClickListener() {
@@ -397,7 +438,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
} else {
// Immediately skip to the next song
downloadService.next(true);
-
+
// Otherwise set rating to 1
setRating(entry, 1);
rateBadButton.setImageResource(R.drawable.ic_action_rating_bad_selected);
@@ -500,56 +541,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
}
});
- playlistView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
- warnIfStorageUnavailable();
- new SilentBackgroundTask<Void>(context) {
- @Override
- protected Void doInBackground() throws Throwable {
- getDownloadService().play(position);
- return null;
- }
-
- @Override
- protected void done(Void result) {
- onCurrentChanged();
- onProgressChanged();
- }
- }.execute();
- }
- });
- playlistView.setDropListener(new DragSortListView.DropListener() {
- @Override
- public void drop(final int from, final int to) {
- new SilentBackgroundTask<Void>(context) {
- @Override
- protected Void doInBackground() throws Throwable {
- getDownloadService().swap(true, from, to);
- onDownloadListChanged();
-
- return null;
- }
- }.execute();
- }
- });
- playlistView.setRemoveListener(new DragSortListView.RemoveListener() {
- @Override
- public void remove(int which) {
- getDownloadService().remove(which);
- onDownloadListChanged();
- }
- });
-
registerForContextMenu(playlistView);
- DownloadService downloadService = getDownloadService();
- if (downloadService != null && context.getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false)) {
- context.getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE);
- warnIfStorageUnavailable();
- downloadService.setShufflePlayEnabled(true);
- }
-
if(Build.MODEL.equals("Nexus 4") || Build.MODEL.equals("GT-I9100")) {
View slider = rootView.findViewById(R.id.download_slider);
slider.setPadding(0, 0, 0, 0);
@@ -604,7 +597,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if(menuItemSelected(menuItem.getItemId(), null)) {
return true;
}
-
+
return super.onOptionsItemSelected(menuItem);
}
@@ -614,10 +607,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if(!primaryFragment) {
return;
}
+ UpdateView targetView = songListAdapter.getContextView();
+ menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0);
if (view == playlistView) {
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- DownloadFile downloadFile = (DownloadFile) playlistView.getItemAtPosition(info.position);
+ DownloadFile downloadFile = songListAdapter.getContextItem();
android.view.MenuInflater inflater = context.getMenuInflater();
if(Util.isOffline(context)) {
@@ -641,9 +635,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if(!primaryFragment) {
return false;
}
-
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- DownloadFile downloadFile = (DownloadFile) playlistView.getItemAtPosition(info.position);
+
+ DownloadFile downloadFile = songListAdapter.getContextItem();
return menuItemSelected(menuItem.getItemId(), downloadFile) || super.onContextItemSelected(menuItem);
}
@@ -745,7 +738,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
@Override
protected void done(Void result) {
- onDownloadListChanged();
+ context.closeNowPlaying();
}
}.execute();
}
@@ -841,7 +834,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
@Override
public void onResume() {
super.onResume();
-
+ if(this.primaryFragment) {
+ onResumeHandlers();
+ } else {
+ update();
+ }
+ }
+ private void onResumeHandlers() {
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
@@ -898,25 +897,46 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
@Override
public void onPause() {
super.onPause();
- executorService.shutdown();
- if(getDownloadService() != null) {
- getDownloadService().stopRemoteScan();
+ onPauseHandlers();
+ }
+ private void onPauseHandlers() {
+ if(executorService != null) {
+ executorService.shutdown();
+ if (getDownloadService() != null) {
+ getDownloadService().stopRemoteScan();
+ }
+ executorService = null;
+ playlistFlipper.setDisplayedChild(0);
}
}
-
+
@Override
public void setPrimaryFragment(boolean primary) {
super.setPrimaryFragment(primary);
if(rootView != null) {
if(primary) {
- mainLayout.setVisibility(View.VISIBLE);
- updateButtons();
+ onResumeHandlers();
} else {
- mainLayout.setVisibility(View.GONE);
+ onPauseHandlers();
}
}
}
+ @Override
+ public void setTitle(int title) {
+ this.title = context.getResources().getString(title);
+ if(this.primaryFragment) {
+ context.setTitle(this.title);
+ }
+ }
+ @Override
+ public void setSubtitle(CharSequence title) {
+ this.subtitle = title;
+ if(this.primaryFragment) {
+ context.setSubtitle(title);
+ }
+ }
+
private void scheduleHideControls() {
if (hideControlsFuture != null) {
hideControlsFuture.cancel(false);
@@ -954,7 +974,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if(context == null) {
return;
}
-
+
if(Util.isOffline(context)) {
bookmarkButton.setVisibility(View.GONE);
rateBadButton.setVisibility(View.GONE);
@@ -971,24 +991,25 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
// Scroll to current playing/downloading.
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void scrollToCurrent() {
if (getDownloadService() == null || songListAdapter == null) {
scrollWhenLoaded = true;
return;
}
- for (int i = 0; i < songListAdapter.getCount(); i++) {
- if (currentPlaying == playlistView.getItemAtPosition(i)) {
- playlistView.setSelectionFromTop(i, 40);
- return;
- }
+ // Try to get position of current playing/downloading
+ int position = songListAdapter.getItemPosition(currentPlaying);
+ if(position == -1) {
+ DownloadFile currentDownloading = getDownloadService().getCurrentDownloading();
+ position = songListAdapter.getItemPosition(currentDownloading);
}
- DownloadFile currentDownloading = getDownloadService().getCurrentDownloading();
- for (int i = 0; i < songListAdapter.getCount(); i++) {
- if (currentDownloading == playlistView.getItemAtPosition(i)) {
- playlistView.setSelectionFromTop(i, 40);
- return;
- }
+
+ // If found, scroll to it
+ if(position != -1) {
+ // RecyclerView.scrollToPosition just puts it on the screen (ie: bottom if scrolled below it)
+ LinearLayoutManager layoutManager = (LinearLayoutManager) playlistView.getLayoutManager();
+ layoutManager.scrollToPositionWithOffset(position, 0);
}
}
@@ -1043,26 +1064,26 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
- lengthBar.setProgress(length - 1);
+ lengthBar.setProgress(length - 1);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.menu_set_timer)
- .setView(dialogView)
- .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- int length = getMinutes(lengthBar.getProgress());
+ .setView(dialogView)
+ .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ int length = getMinutes(lengthBar.getProgress());
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(Constants.PREFERENCES_KEY_SLEEP_TIMER_DURATION, Integer.toString(length));
- editor.commit();
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(Constants.PREFERENCES_KEY_SLEEP_TIMER_DURATION, Integer.toString(length));
+ editor.commit();
- getDownloadService().setSleepTimerDuration(length);
- getDownloadService().startSleepTimer();
- context.supportInvalidateOptionsMenu();
- }
- })
- .setNegativeButton(R.string.common_cancel, null);
+ getDownloadService().setSleepTimerDuration(length);
+ getDownloadService().startSleepTimer();
+ context.supportInvalidateOptionsMenu();
+ }
+ })
+ .setNegativeButton(R.string.common_cancel, null);
AlertDialog dialog = builder.create();
dialog.show();
}
@@ -1087,7 +1108,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
playlistFlipper.setInAnimation(AnimationUtils.loadAnimation(context, R.anim.push_up_in));
playlistFlipper.setOutAnimation(AnimationUtils.loadAnimation(context, R.anim.push_up_out));
playlistFlipper.setDisplayedChild(1);
-
+
UpdateView.triggerUpdate();
}
}
@@ -1125,7 +1146,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
protected Void doInBackground() throws Throwable {
currentPlayingIndex = downloadService.getCurrentPlayingIndex() + 1;
size = downloadService.size();
-
+
return null;
}
@@ -1133,24 +1154,24 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
protected void done(Void result) {
List<DownloadFile> list;
list = downloadService.getSongs();
-
+
if(downloadService.isShufflePlayEnabled()) {
emptyTextView.setText(R.string.download_shuffle_loading);
}
else {
emptyTextView.setText(R.string.download_empty);
}
-
+
if(songListAdapter == null || refresh) {
- songList = new ArrayList<DownloadFile>();
+ songList = new ArrayList<>();
songList.addAll(list);
- playlistView.setAdapter(songListAdapter = new DownloadFileAdapter(context, songList));
+ playlistView.setAdapter(songListAdapter = new DownloadFileAdapter(context, songList, NowPlayingFragment.this));
} else {
songList.clear();
songList.addAll(list);
songListAdapter.notifyDataSetChanged();
}
-
+
emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE);
currentRevision = downloadService.getDownloadListUpdateRevision();
@@ -1171,7 +1192,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
default:
break;
}
-
+
if(scrollWhenLoaded) {
scrollToCurrent();
scrollWhenLoaded = false;
@@ -1194,7 +1215,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if (downloadService == null || onCurrentChangedTask != null) {
return;
}
-
+
onCurrentChangedTask = new SilentBackgroundTask<Void>(context) {
int currentPlayingIndex;
int currentPlayingSize;
@@ -1255,7 +1276,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
}
};
-
+
if(onDownloadListChangedTask == null) {
onCurrentChangedTask.execute();
}
@@ -1395,33 +1416,33 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
}.execute();
}
-
+
private void createBookmark() {
DownloadService downloadService = getDownloadService();
if(downloadService == null) {
return;
}
-
+
final DownloadFile currentDownload = downloadService.getCurrentPlaying();
if(currentDownload == null) {
return;
}
-
+
View dialogView = context.getLayoutInflater().inflate(R.layout.create_bookmark, null);
final EditText commentBox = (EditText)dialogView.findViewById(R.id.comment_text);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.download_save_bookmark_title)
- .setView(dialogView)
- .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- String comment = commentBox.getText().toString();
+ .setView(dialogView)
+ .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ String comment = commentBox.getText().toString();
- createBookmark(currentDownload, comment);
- }
- })
- .setNegativeButton(R.string.common_cancel, null);
+ createBookmark(currentDownload, comment);
+ }
+ })
+ .setNegativeButton(R.string.common_cancel, null);
AlertDialog dialog = builder.create();
dialog.show();
}
@@ -1430,13 +1451,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if(downloadService == null) {
return;
}
-
+
final Entry currentSong = currentDownload.getSong();
final int position = downloadService.getPlayerPosition();
final Bookmark oldBookmark = currentSong.getBookmark();
currentSong.setBookmark(new Bookmark(position));
bookmarkButton.setImageResource(R.drawable.ic_menu_bookmark_selected);
-
+
new SilentBackgroundTask<Void>(context) {
@Override
protected Void doInBackground() throws Throwable {
@@ -1458,12 +1479,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
Util.toast(context, R.string.download_save_bookmark);
setControlsVisible(true);
}
-
+
@Override
protected void error(Throwable error) {
Log.w(TAG, "Failed to create bookmark", error);
currentSong.setBookmark(oldBookmark);
-
+
// If no bookmark at start, then return to no bookmark
if(oldBookmark == null) {
int bookmark;
@@ -1474,14 +1495,14 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
bookmarkButton.setImageResource(bookmark);
}
-
+
String msg;
if(error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
} else {
msg = context.getResources().getString(R.string.download_save_bookmark_failed) + getErrorMessage(error);
}
-
+
Util.toast(context, msg, false);
}
}.execute();
@@ -1570,4 +1591,19 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
+
+ @Override
+ public void onItemClicked(final DownloadFile item) {
+ warnIfStorageUnavailable();
+ new SilentBackgroundTask<Void>(context) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ getDownloadService().play(item);
+
+ onCurrentChanged();
+ onProgressChanged();
+ return null;
+ }
+ }.execute();
+ }
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
index 0f1598dd..20a87e7d 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
@@ -1,12 +1,14 @@
package github.daneren2005.dsub.fragments;
-import java.util.ArrayList;
-import java.util.List;
+import java.io.Serializable;
import java.util.Arrays;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -14,11 +16,13 @@ import android.view.MenuInflater;
import android.view.View;
import android.view.MenuItem;
import android.widget.AdapterView;
-import android.widget.ListAdapter;
-import android.widget.ListView;
import android.net.Uri;
import android.view.ViewGroup;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.ArtistAdapter;
+import github.daneren2005.dsub.adapter.EntryGridAdapter;
+import github.daneren2005.dsub.adapter.SearchAdapter;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.SearchCritera;
@@ -26,40 +30,24 @@ import github.daneren2005.dsub.domain.SearchResult;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
import github.daneren2005.dsub.service.DownloadService;
-import github.daneren2005.dsub.adapter.ArtistAdapter;
import github.daneren2005.dsub.util.BackgroundTask;
import github.daneren2005.dsub.util.Constants;
-import github.daneren2005.dsub.adapter.EntryAdapter;
-import github.daneren2005.dsub.adapter.MergeAdapter;
import github.daneren2005.dsub.util.TabBackgroundTask;
import github.daneren2005.dsub.util.Util;
+import github.daneren2005.dsub.view.UpdateView;
-public class SearchFragment extends SubsonicFragment {
+public class SearchFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Serializable> {
private static final String TAG = SearchFragment.class.getSimpleName();
- private static final int DEFAULT_ARTISTS = 3;
- private static final int DEFAULT_ALBUMS = 5;
- private static final int DEFAULT_SONGS = 10;
-
private static final int MAX_ARTISTS = 10;
- private static final int MAX_ALBUMS = 20;
+ private static final int MAX_ALBUMS = 10;
private static final int MAX_SONGS = 25;
- private ListView list;
-
- private View artistsHeading;
- private View albumsHeading;
- private View songsHeading;
- private View moreArtistsButton;
- private View moreAlbumsButton;
- private View moreSongsButton;
+
+ protected RecyclerView recyclerView;
+ protected SearchAdapter adapter;
+ protected boolean largeAlbums = false;
+
private SearchResult searchResult;
- private MergeAdapter mergeAdapter;
- private ArtistAdapter artistAdapter;
- private ListAdapter moreArtistsAdapter;
- private EntryAdapter albumAdapter;
- private ListAdapter moreAlbumsAdapter;
- private ListAdapter moreSongsAdapter;
- private EntryAdapter songAdapter;
private boolean skipSearch = false;
private String currentQuery;
@@ -70,6 +58,7 @@ public class SearchFragment extends SubsonicFragment {
if(savedInstanceState != null) {
searchResult = (SearchResult) savedInstanceState.getSerializable(Constants.FRAGMENT_LIST);
}
+ largeAlbums = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true);
}
@Override
@@ -80,63 +69,43 @@ public class SearchFragment extends SubsonicFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false);
+ rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
setTitle(R.string.search_title);
- View buttons = inflater.inflate(R.layout.search_buttons, null);
-
- artistsHeading = buttons.findViewById(R.id.search_artists);
- albumsHeading = buttons.findViewById(R.id.search_albums);
- songsHeading = buttons.findViewById(R.id.search_songs);
-
- moreArtistsButton = buttons.findViewById(R.id.search_more_artists);
- moreAlbumsButton = buttons.findViewById(R.id.search_more_albums);
- moreSongsButton = buttons.findViewById(R.id.search_more_songs);
-
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
refreshLayout.setEnabled(false);
- list = (ListView) rootView.findViewById(R.id.fragment_list);
+ recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
+ setupLayoutManager(recyclerView, largeAlbums);
- list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (view == moreArtistsButton) {
- expandArtists();
- } else if (view == moreAlbumsButton) {
- expandAlbums();
- } else if (view == moreSongsButton) {
- expandSongs();
- } else {
- Object item = parent.getItemAtPosition(position);
- if (item instanceof Artist) {
- onArtistSelected((Artist) item, false);
- } else if (item instanceof MusicDirectory.Entry) {
- MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
- if (entry.isDirectory()) {
- onAlbumSelected(entry, false);
- } else if (entry.isVideo()) {
- onVideoSelected(entry);
- } else {
- onSongSelected(entry, false, true, true, false);
- }
-
- }
- }
- }
- });
- registerForContextMenu(list);
+ registerForContextMenu(recyclerView);
context.onNewIntent(context.getIntent());
if(searchResult != null) {
skipSearch = true;
- populateList();
+ recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, this));
}
return rootView;
}
@Override
+ public GridLayoutManager.SpanSizeLookup getSpanSizeLookup() {
+ final int columns = getRecyclerColumnCount();
+ return new GridLayoutManager.SpanSizeLookup() {
+ @Override
+ public int getSpanSize(int position) {
+ int viewType = adapter.getItemViewType(position);
+ if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == ArtistAdapter.VIEW_TYPE_ARTIST) {
+ return columns;
+ } else {
+ return 1;
+ }
+ }
+ };
+ }
+
+ @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.search, menu);
}
@@ -156,11 +125,12 @@ public class SearchFragment extends SubsonicFragment {
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ UpdateView targetView = adapter.getContextView();
+ menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0);
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Object selectedItem = list.getItemAtPosition(info.position);
- onCreateContextMenu(menu, view, menuInfo, selectedItem);
- if(selectedItem instanceof MusicDirectory.Entry && !((MusicDirectory.Entry) selectedItem).isVideo() && !Util.isOffline(context)) {
+ Serializable item = adapter.getContextItem();
+ onCreateContextMenu(menu, view, menuInfo, item);
+ if(item instanceof MusicDirectory.Entry && !((MusicDirectory.Entry) item).isVideo() && !Util.isOffline(context)) {
menu.removeItem(R.id.song_menu_remove_playlist);
}
@@ -172,27 +142,37 @@ public class SearchFragment extends SubsonicFragment {
if(menuItem.getGroupId() != getSupportTag()) {
return false;
}
-
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Object selectedItem = list.getItemAtPosition(info.position);
-
- if(onContextItemSelected(menuItem, selectedItem)) {
+
+ Serializable item = adapter.getContextItem();
+ if(onContextItemSelected(menuItem, item)) {
return true;
}
return true;
}
-
- @Override
- public void setPrimaryFragment(boolean primary) {
- super.setPrimaryFragment(primary);
- }
@Override
public void refresh(boolean refresh) {
context.onNewIntent(context.getIntent());
}
+ @Override
+ public void onItemClicked(Serializable item) {
+ Log.d(TAG, item.getClass().getSimpleName());
+ if (item instanceof Artist) {
+ onArtistSelected((Artist) item, false);
+ } else if (item instanceof MusicDirectory.Entry) {
+ MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
+ if (entry.isDirectory()) {
+ onAlbumSelected(entry, false);
+ } else if (entry.isVideo()) {
+ onVideoSelected(entry);
+ } else {
+ onSongSelected(entry, false, true, true, false);
+ }
+ }
+ }
+
public void search(final String query, final boolean autoplay) {
if(skipSearch) {
skipSearch = false;
@@ -200,9 +180,6 @@ public class SearchFragment extends SubsonicFragment {
}
currentQuery = query;
- mergeAdapter = new MergeAdapter();
- list.setAdapter(mergeAdapter);
-
BackgroundTask<SearchResult> task = new TabBackgroundTask<SearchResult>(this) {
@Override
protected SearchResult doInBackground() throws Throwable {
@@ -214,7 +191,7 @@ public class SearchFragment extends SubsonicFragment {
@Override
protected void done(SearchResult result) {
searchResult = result;
- populateList();
+ recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, SearchFragment.this));
if (autoplay) {
autoplay(query);
}
@@ -224,82 +201,6 @@ public class SearchFragment extends SubsonicFragment {
task.execute();
}
- public void populateList() {
- mergeAdapter = new MergeAdapter();
-
- if (searchResult != null) {
- List<Artist> artists = searchResult.getArtists();
- if (!artists.isEmpty()) {
- mergeAdapter.addView(artistsHeading);
- List<Artist> displayedArtists = new ArrayList<Artist>(artists.subList(0, Math.min(DEFAULT_ARTISTS, artists.size())));
- artistAdapter = new ArtistAdapter(context, displayedArtists);
- mergeAdapter.addAdapter(artistAdapter);
- if (artists.size() > DEFAULT_ARTISTS) {
- moreArtistsAdapter = mergeAdapter.addView(moreArtistsButton, true);
- }
- }
-
- List<MusicDirectory.Entry> albums = searchResult.getAlbums();
- if (!albums.isEmpty()) {
- mergeAdapter.addView(albumsHeading);
- List<MusicDirectory.Entry> displayedAlbums = new ArrayList<MusicDirectory.Entry>(albums.subList(0, Math.min(DEFAULT_ALBUMS, albums.size())));
- albumAdapter = new EntryAdapter(context, getImageLoader(), displayedAlbums, false);
- mergeAdapter.addAdapter(albumAdapter);
- if (albums.size() > DEFAULT_ALBUMS) {
- moreAlbumsAdapter = mergeAdapter.addView(moreAlbumsButton, true);
- }
- }
-
- List<MusicDirectory.Entry> songs = searchResult.getSongs();
- if (!songs.isEmpty()) {
- mergeAdapter.addView(songsHeading);
- List<MusicDirectory.Entry> displayedSongs = new ArrayList<MusicDirectory.Entry>(songs.subList(0, Math.min(DEFAULT_SONGS, songs.size())));
- songAdapter = new EntryAdapter(context, getImageLoader(), displayedSongs, false);
- mergeAdapter.addAdapter(songAdapter);
- if (songs.size() > DEFAULT_SONGS) {
- moreSongsAdapter = mergeAdapter.addView(moreSongsButton, true);
- }
- }
-
- boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty();
- if(empty) {
- setEmpty(true);
- }
- }
-
- list.setAdapter(mergeAdapter);
- }
-
- private void expandArtists() {
- artistAdapter.clear();
- for (Artist artist : searchResult.getArtists()) {
- artistAdapter.add(artist);
- }
- artistAdapter.notifyDataSetChanged();
- mergeAdapter.removeAdapter(moreArtistsAdapter);
- mergeAdapter.notifyDataSetChanged();
- }
-
- private void expandAlbums() {
- albumAdapter.clear();
- for (MusicDirectory.Entry album : searchResult.getAlbums()) {
- albumAdapter.add(album);
- }
- albumAdapter.notifyDataSetChanged();
- mergeAdapter.removeAdapter(moreAlbumsAdapter);
- mergeAdapter.notifyDataSetChanged();
- }
-
- private void expandSongs() {
- songAdapter.clear();
- for (MusicDirectory.Entry song : searchResult.getSongs()) {
- songAdapter.add(song);
- }
- songAdapter.notifyDataSetChanged();
- mergeAdapter.removeAdapter(moreSongsAdapter);
- mergeAdapter.notifyDataSetChanged();
- }
-
private void onArtistSelected(Artist artist, boolean autoplay) {
SubsonicFragment fragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java
index 5488c95b..8a2b7153 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java
@@ -11,10 +11,11 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
-import android.widget.TextView;
+
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.ArtistAdapter;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.Indexes;
import github.daneren2005.dsub.domain.MusicDirectory;
@@ -23,19 +24,16 @@ import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.Util;
-import github.daneren2005.dsub.adapter.ArtistAdapter;
+import github.daneren2005.dsub.view.UpdateView;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-public class SelectArtistFragment extends SelectListFragment<Artist> {
+public class SelectArtistFragment extends SelectRecyclerFragment<Artist> implements ArtistAdapter.OnMusicFolderChanged {
private static final String TAG = SelectArtistFragment.class.getSimpleName();
private static final int MENU_GROUP_MUSIC_FOLDER = 10;
- private View folderButtonParent;
- private View folderButton;
- private TextView folderName;
private List<MusicFolder> musicFolders = null;
private List<MusicDirectory.Entry> entries;
private String groupId;
@@ -75,19 +73,7 @@ public class SelectArtistFragment extends SelectListFragment<Artist> {
}
}
- folderButton = null;
super.onCreateView(inflater, container, bundle);
-
- if("4.4.2".equals(Build.VERSION.RELEASE)) {
- listView.setFastScrollAlwaysVisible(true);
- }
-
- if(objects != null && currentTask == null) {
- if (Util.isOffline(context) || Util.isTagBrowsing(context) || groupId != null) {
- folderButton.setVisibility(View.GONE);
- }
- setMusicFolders();
- }
return rootView;
}
@@ -95,30 +81,12 @@ public class SelectArtistFragment extends SelectListFragment<Artist> {
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ UpdateView targetView = adapter.getContextView();
+ menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0);
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Object entry = listView.getItemAtPosition(info.position);
-
- if (entry instanceof Artist) {
- onCreateContextMenu(menu, view, menuInfo, entry);
- } else if (info.position == 0) {
- String musicFolderId = Util.getSelectedMusicFolderId(context);
- MenuItem menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders);
- if (musicFolderId == null) {
- menuItem.setChecked(true);
- }
- if (musicFolders != null) {
- for (int i = 0; i < musicFolders.size(); i++) {
- MusicFolder musicFolder = musicFolders.get(i);
- menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, i, i + 1, musicFolder.getName());
- if (musicFolder.getId().equals(musicFolderId)) {
- menuItem.setChecked(true);
- }
- }
- }
- menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true);
- }
+ Artist artist = adapter.getContextItem();
+ onCreateContextMenu(menu, view, menuInfo, artist);
recreateContextMenu(menu);
}
@@ -129,56 +97,33 @@ public class SelectArtistFragment extends SelectListFragment<Artist> {
}
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Artist artist = (Artist) listView.getItemAtPosition(info.position);
-
- if (artist != null) {
- return onContextItemSelected(menuItem, artist);
- } else if (info.position == 0) {
- MusicFolder selectedFolder = menuItem.getItemId() == -1 ? null : musicFolders.get(menuItem.getItemId());
- String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
- String musicFolderName = selectedFolder == null ? context.getString(R.string.select_artist_all_folders)
- : selectedFolder.getName();
- Util.setSelectedMusicFolderId(context, musicFolderId);
- folderName.setText(musicFolderName);
- context.invalidate();
- }
+ Artist artist = adapter.getContextItem();
- return true;
+ return onContextItemSelected(menuItem, artist);
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (view == folderButtonParent) {
- selectFolder();
- } else {
- Artist artist = (Artist) parent.getItemAtPosition(position);
-
- SubsonicFragment fragment;
- if((Util.isFirstLevelArtist(context) || Util.isOffline(context) || Util.isTagBrowsing(context)) || "root".equals(artist.getId()) || groupId != null) {
- fragment = new SelectDirectoryFragment();
- Bundle args = new Bundle();
- args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
- args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
- if ("root".equals(artist.getId())) {
- args.putSerializable(Constants.FRAGMENT_LIST, (Serializable) entries);
- }
- args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
- fragment.setArguments(args);
- } else {
- fragment = new SelectArtistFragment();
- Bundle args = new Bundle();
- args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
- args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
- fragment.setArguments(args);
+ public void onItemClicked(Artist artist) {
+ SubsonicFragment fragment;
+ if((Util.isFirstLevelArtist(context) || Util.isOffline(context) || Util.isTagBrowsing(context)) || "root".equals(artist.getId()) || groupId != null) {
+ fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+ if ("root".equals(artist.getId())) {
+ args.putSerializable(Constants.FRAGMENT_LIST, (Serializable) entries);
}
-
- replaceFragment(fragment);
+ args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
+ fragment.setArguments(args);
+ } else {
+ fragment = new SelectArtistFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+ fragment.setArguments(args);
}
- }
- @Override
- public void onFinishRefresh() {
- setMusicFolders();
+ replaceFragment(fragment);
}
@Override
@@ -215,9 +160,8 @@ public class SelectArtistFragment extends SelectListFragment<Artist> {
}
@Override
- public ArrayAdapter getAdapter(List<Artist> objects) {
- createMusicFolderButton();
- return new ArtistAdapter(context, objects);
+ public SectionAdapter getAdapter(List<Artist> objects) {
+ return new ArtistAdapter(context, objects, musicFolders, this, this);
}
@Override
@@ -236,12 +180,12 @@ public class SelectArtistFragment extends SelectListFragment<Artist> {
String musicFolderId = Util.getSelectedMusicFolderId(context);
Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener);
- artists = new ArrayList<Artist>(indexes.getShortcuts().size() + indexes.getArtists().size());
+ artists = new ArrayList<>(indexes.getShortcuts().size() + indexes.getArtists().size());
artists.addAll(indexes.getShortcuts());
artists.addAll(indexes.getArtists());
entries = indexes.getEntries();
} else {
- artists = new ArrayList<Artist>();
+ artists = new ArrayList<>();
MusicDirectory dir = musicService.getMusicDirectory(groupId, groupName, refresh, context, listener);
for(MusicDirectory.Entry entry: dir.getChildren(true, false)) {
Artist artist = new Artist();
@@ -251,7 +195,7 @@ public class SelectArtistFragment extends SelectListFragment<Artist> {
artists.add(artist);
}
- entries = new ArrayList<MusicDirectory.Entry>();
+ entries = new ArrayList<>();
entries.addAll(dir.getChildren(false, true));
if(!entries.isEmpty()) {
Artist root = new Artist();
@@ -270,32 +214,14 @@ public class SelectArtistFragment extends SelectListFragment<Artist> {
return groupId == null ? R.string.button_bar_browse : 0;
}
- private void createMusicFolderButton() {
- if(folderButton == null) {
- folderButtonParent = context.getLayoutInflater().inflate(R.layout.select_artist_header, listView, false);
- folderName = (TextView) folderButtonParent.findViewById(R.id.select_artist_folder_2);
- listView.addHeaderView(folderButtonParent);
- folderButton = folderButtonParent.findViewById(R.id.select_artist_folder);
- }
-
- if (Util.isOffline(context) || Util.isTagBrowsing(context) || musicFolders == null) {
- folderButton.setVisibility(View.GONE);
- } else {
- folderButton.setVisibility(View.VISIBLE);
- }
- }
-
@Override
public void setEmpty(boolean empty) {
super.setEmpty(empty);
if(empty && !Util.isOffline(context)) {
- createMusicFolderButton();
- setMusicFolders();
-
objects.clear();
- listView.setAdapter(new ArtistAdapter(context, objects));
- listView.setVisibility(View.VISIBLE);
+ recyclerView.setAdapter(new ArtistAdapter(context, objects, musicFolders, this, this));
+ recyclerView.setVisibility(View.VISIBLE);
View view = rootView.findViewById(R.id.tab_progress);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
@@ -305,29 +231,19 @@ public class SelectArtistFragment extends SelectListFragment<Artist> {
}
}
- private void setMusicFolders() {
- // Display selected music folder
- if (musicFolders != null) {
- String musicFolderId = Util.getSelectedMusicFolderId(context);
- if (musicFolderId == null) {
- folderName.setText(R.string.select_artist_all_folders);
- } else {
- for (MusicFolder musicFolder : musicFolders) {
- if (musicFolder.getId().equals(musicFolderId)) {
- folderName.setText(musicFolder.getName());
- break;
- }
- }
- }
- }
- }
-
- private void selectFolder() {
- folderButton.showContextMenu();
- }
-
private void toggleFirstLevelArtist() {
Util.toggleFirstLevelArtist(context);
context.invalidateOptionsMenu();
}
+
+ @Override
+ public void onMusicFolderChanged(MusicFolder selectedFolder) {
+ String startMusicFolderId = Util.getSelectedMusicFolderId(context);
+ String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
+
+ if(!Util.equals(startMusicFolderId, musicFolderId)) {
+ Util.setSelectedMusicFolderId(context, musicFolderId);
+ context.invalidate();
+ }
+ }
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java
index c71d99f6..a774a287 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java
@@ -25,7 +25,7 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.activity.DownloadActivity;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.Bookmark;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.service.DownloadService;
@@ -34,16 +34,19 @@ import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.adapter.BookmarkAdapter;
+import github.daneren2005.dsub.view.UpdateView;
import java.util.Arrays;
import java.util.List;
-public class SelectBookmarkFragment extends SelectListFragment<MusicDirectory.Entry> {
+public class SelectBookmarkFragment extends SelectRecyclerFragment<MusicDirectory.Entry> {
private static final String TAG = SelectBookmarkFragment.class.getSimpleName();
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ UpdateView targetView = adapter.getContextView();
+ menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0);
MenuInflater inflater = context.getMenuInflater();
inflater.inflate(R.menu.select_bookmark_context, menu);
@@ -53,8 +56,7 @@ public class SelectBookmarkFragment extends SelectListFragment<MusicDirectory.En
@Override
public boolean onContextItemSelected(MenuItem menuItem) {
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- MusicDirectory.Entry bookmark = objects.get(info.position);
+ MusicDirectory.Entry bookmark = adapter.getContextItem();
switch(menuItem.getItemId()) {
case R.id.bookmark_menu_info:
@@ -78,8 +80,8 @@ public class SelectBookmarkFragment extends SelectListFragment<MusicDirectory.En
}
@Override
- public ArrayAdapter getAdapter(List<MusicDirectory.Entry> bookmarks) {
- return new BookmarkAdapter(context, bookmarks);
+ public SectionAdapter getAdapter(List<MusicDirectory.Entry> bookmarks) {
+ return new BookmarkAdapter(context, bookmarks, this);
}
@Override
@@ -93,13 +95,12 @@ public class SelectBookmarkFragment extends SelectListFragment<MusicDirectory.En
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ public void onItemClicked(final MusicDirectory.Entry bookmark) {
final DownloadService downloadService = getDownloadService();
if(downloadService == null) {
return;
}
- final MusicDirectory.Entry bookmark = (MusicDirectory.Entry) parent.getItemAtPosition(position);
new SilentBackgroundTask<Void>(context) {
@Override
protected Void doInBackground() throws Throwable {
@@ -110,7 +111,7 @@ public class SelectBookmarkFragment extends SelectListFragment<MusicDirectory.En
@Override
protected void done(Void result) {
- Util.startActivityWithoutTransition(context, DownloadActivity.class);
+ context.openNowPlaying();
}
}.execute();
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
index 841a6369..08a051cf 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
@@ -1,7 +1,7 @@
package github.daneren2005.dsub.fragments;
import android.annotation.TargetApi;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -9,6 +9,9 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;
@@ -23,30 +26,26 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.EntryInfiniteGridAdapter;
+import github.daneren2005.dsub.adapter.EntryGridAdapter;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.ArtistInfo;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.ServerInfo;
import github.daneren2005.dsub.domain.Share;
import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.util.ImageLoader;
-import github.daneren2005.dsub.adapter.AlbumGridAdapter;
-import github.daneren2005.dsub.adapter.EntryAdapter;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
-import github.daneren2005.dsub.activity.DownloadActivity;
import github.daneren2005.dsub.domain.PodcastEpisode;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
@@ -59,9 +58,9 @@ import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.util.TabBackgroundTask;
import github.daneren2005.dsub.util.UserUtil;
import github.daneren2005.dsub.util.Util;
-import github.daneren2005.dsub.adapter.AlbumListAdapter;
-import github.daneren2005.dsub.view.HeaderGridView;
+import github.daneren2005.dsub.view.GridSpacingDecoration;
import github.daneren2005.dsub.view.MyLeadingMarginSpan2;
+import github.daneren2005.dsub.view.UpdateView;
import java.util.ArrayList;
import java.util.Arrays;
@@ -70,17 +69,14 @@ import java.util.Set;
import static github.daneren2005.dsub.domain.MusicDirectory.Entry;
-public class SelectDirectoryFragment extends SubsonicFragment implements AdapterView.OnItemClickListener {
+public class SelectDirectoryFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Entry> {
private static final String TAG = SelectDirectoryFragment.class.getSimpleName();
- private GridView albumList;
- private ListView entryList;
+ private RecyclerView recyclerView;
+ private EntryGridAdapter entryGridAdapter;
private Boolean licenseValid;
- private EntryAdapter entryAdapter;
private List<Entry> albums;
private List<Entry> entries;
- private boolean albumContext = false;
- private boolean addAlbumHeader = false;
private LoadTask currentTask;
private ArtistInfo artistInfo;
private String artistInfoDelayed;
@@ -114,7 +110,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
super.onCreate(bundle);
if(bundle != null) {
entries = (List<Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST);
- albums = (List<Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST2);
artistInfo = (ArtistInfo) bundle.getSerializable(Constants.FRAGMENT_EXTRA);
restoredInstance = true;
}
@@ -172,28 +167,37 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
refreshLayout.setOnRefreshListener(this);
- entryList = (ListView) rootView.findViewById(R.id.select_album_entries);
- entryList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
- entryList.setOnItemClickListener(this);
- setupScrollList(entryList);
-
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true)) {
largeAlbums = true;
}
- if(albumListType == null || "starred".equals(albumListType) || !largeAlbums) {
- albumList = (GridView) inflater.inflate(R.layout.unscrollable_grid_view, entryList, false);
- addAlbumHeader = true;
- } else {
- ViewGroup rootGroup = (ViewGroup) rootView.findViewById(R.id.select_album_layout);
- albumList = (GridView) inflater.inflate(R.layout.grid_view, rootGroup, false);
- rootGroup.removeView(entryList);
- rootGroup.addView(albumList);
+ recyclerView = (RecyclerView) rootView.findViewById(R.id.select_album_entries);
+ recyclerView.setHasFixedSize(true);
+ setupScrollList(recyclerView);
- setupScrollList(albumList);
+ if(largeAlbums) {
+ final int columns = context.getResources().getInteger(R.integer.Grid_Columns);
+ GridLayoutManager gridLayoutManager = new GridLayoutManager(context, columns);
+ gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
+ @Override
+ public int getSpanSize(int position) {
+ int viewType = entryGridAdapter.getItemViewType(position);
+ if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == EntryInfiniteGridAdapter.VIEW_TYPE_LOADING) {
+ return columns;
+ } else {
+ return 1;
+ }
+ }
+ });
+ recyclerView.addItemDecoration(new GridSpacingDecoration());
+ recyclerView.setLayoutManager(gridLayoutManager);
+ } else {
+ LinearLayoutManager layoutManager = new LinearLayoutManager(context);
+ layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
+ recyclerView.setLayoutManager(layoutManager);
}
- registerForContextMenu(entryList);
- setupAlbumList();
+
+ registerForContextMenu(recyclerView);
if(entries == null) {
if(primaryFragment || secondaryFragment) {
@@ -287,21 +291,22 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
return true;
case R.id.menu_download:
downloadBackground(false);
- selectAll(false, false);
+ entryGridAdapter.clearSelected();
return true;
case R.id.menu_cache:
downloadBackground(true);
- selectAll(false, false);
+ entryGridAdapter.clearSelected();
return true;
case R.id.menu_delete:
delete();
- selectAll(false, false);
+ entryGridAdapter.clearSelected();
return true;
case R.id.menu_add_playlist:
- if(getSelectedSongs().isEmpty()) {
- selectAll(true, false);
+ List<Entry> songs = getSelectedSongs();
+ if(songs.isEmpty()) {
+ songs = entries;
}
- addToPlaylist(getSelectedSongs());
+ addToPlaylist(songs);
return true;
case R.id.menu_remove_playlist:
removeFromPlaylist(playlistId, playlistName, getSelectedIndexes());
@@ -333,23 +338,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
-
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
-
- Entry entry;
- if(view.getId() == R.id.select_album_entries) {
- if(info.position == 0) {
- return;
- }
- entry = (Entry) entryList.getItemAtPosition(info.position);
- // When List has Grid embedded in header, this is called against the header as well
- if(entry != null) {
- albumContext = false;
- }
- } else {
- entry = (Entry) albumList.getItemAtPosition(info.position);
- albumContext = true;
- }
+ Entry entry = entryGridAdapter.getContextItem();
+ UpdateView targetView = entryGridAdapter.getContextView();
+ menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0);
// Don't try to display a context menu if error here
if(entry == null) {
@@ -384,22 +375,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
if(menuItem.getGroupId() != getSupportTag()) {
return false;
}
-
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Object selectedItem;
- int headers = entryList.getHeaderViewsCount();
- if(albumContext) {
- selectedItem = albumList.getItemAtPosition(info.position);
- } else {
- if(info.position == 0) {
- return false;
- }
- selectedItem = entries.get(info.position - headers);
- }
+ Entry entry = entryGridAdapter.getContextItem();
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PLAY_NOW_AFTER, false) && menuItem.getItemId() == R.id.song_menu_play_now) {
List<Entry> songs = new ArrayList<Entry>();
- Iterator it = entries.listIterator(info.position - headers);
+ songs.add(entry);
+ Iterator it = entries.listIterator(entries.indexOf(entry));
while(it.hasNext()) {
songs.add((Entry) it.next());
}
@@ -408,19 +389,19 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
return true;
}
- if(onContextItemSelected(menuItem, selectedItem)) {
+ if(onContextItemSelected(menuItem, entry)) {
return true;
}
switch (menuItem.getItemId()) {
case R.id.song_menu_remove_playlist:
- removeFromPlaylist(playlistId, playlistName, Arrays.<Integer>asList(info.position - headers));
+ removeFromPlaylist(playlistId, playlistName, Arrays.<Integer>asList(entries.indexOf(entry)));
break;
case R.id.song_menu_server_download:
- downloadPodcastEpisode((PodcastEpisode)selectedItem);
+ downloadPodcastEpisode((PodcastEpisode) entry);
break;
case R.id.song_menu_server_delete:
- deletePodcastEpisode((PodcastEpisode)selectedItem);
+ deletePodcastEpisode((PodcastEpisode) entry);
break;
}
@@ -428,38 +409,35 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (position >= 0) {
- Entry entry = (Entry) parent.getItemAtPosition(position);
- if (entry.isDirectory()) {
- SubsonicFragment fragment = new SelectDirectoryFragment();
- Bundle args = new Bundle();
- args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getId());
- args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle());
- args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, entry);
- if ("newest".equals(albumListType)) {
- args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true);
- }
- if(entry.getArtist() == null && entry.getParent() == null) {
- args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
- }
- fragment.setArguments(args);
-
- replaceFragment(fragment, true);
- } else if (entry.isVideo()) {
- playVideo(entry);
- } else if(entry instanceof PodcastEpisode) {
- String status = ((PodcastEpisode)entry).getStatus();
- if("error".equals(status)) {
- Util.toast(context, R.string.select_podcasts_error);
- return;
- } else if(!"completed".equals(status)) {
- Util.toast(context, R.string.select_podcasts_skipped);
- return;
- }
-
- playNow(Arrays.asList(entry));
+ public void onItemClicked(Entry entry) {
+ if (entry.isDirectory()) {
+ SubsonicFragment fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getId());
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle());
+ args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, entry);
+ if ("newest".equals(albumListType)) {
+ args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true);
+ }
+ if(!entry.isAlbum()) {
+ args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
+ }
+ fragment.setArguments(args);
+
+ replaceFragment(fragment, true);
+ } else if (entry.isVideo()) {
+ playVideo(entry);
+ } else if(entry instanceof PodcastEpisode) {
+ String status = ((PodcastEpisode)entry).getStatus();
+ if("error".equals(status)) {
+ Util.toast(context, R.string.select_podcasts_error);
+ return;
+ } else if(!"completed".equals(status)) {
+ Util.toast(context, R.string.select_podcasts_skipped);
+ return;
}
+
+ playNow(Arrays.asList(entry));
}
}
@@ -478,8 +456,8 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
if(currentTask != null) {
currentTask.cancel();
}
-
- entryList.setVisibility(View.INVISIBLE);
+
+ recyclerView.setVisibility(View.INVISIBLE);
if (playlistId != null) {
getPlaylist(playlistId, playlistName, refresh);
} else if(podcastId != null) {
@@ -686,11 +664,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
licenseValid = musicService.isLicenseValid(context, this);
albums = dir.getChildren(true, false);
- if(largeAlbums) {
- entries = dir.getChildren(false, true);
- } else {
- entries = dir.getChildren();
- }
+ entries = dir.getChildren();
// This isn't really an artist if no albums on it!
if(albums.size() == 0) {
@@ -728,120 +702,120 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
}
private void finishLoading() {
- // Show header if not album list type and not root and not artist
- // For Subsonic 5.1+ display a header for artists with getArtistInfo data if it exists
- View header = null;
- if(albumListType == null && !"root".equals(id) && (!artist || artistInfo != null || artistInfoDelayed != null)) {
- header = createHeader();
+ boolean validData = !entries.isEmpty() || !albums.isEmpty();
+ if(!validData) {
+ setEmpty(true);
+ }
- if(header != null && artistInfoDelayed != null) {
- final View finalHeader = header.findViewById(R.id.select_album_header);
- final View headerProgress = header.findViewById(R.id.header_progress);
+ if(validData) {
+ recyclerView.setVisibility(View.VISIBLE);
+ }
- finalHeader.setVisibility(View.INVISIBLE);
- headerProgress.setVisibility(View.VISIBLE);
+ if(albumListType == null || "starred".equals(albumListType)) {
+ entryGridAdapter = new EntryGridAdapter(context, entries, getImageLoader(), largeAlbums);
+ } else {
+ entryGridAdapter = new EntryInfiniteGridAdapter(context, entries, getImageLoader(), largeAlbums);
- new SilentBackgroundTask<Void>(context) {
- @Override
- protected Void doInBackground() throws Throwable {
- MusicService musicService = MusicServiceFactory.getMusicService(context);
- artistInfo = musicService.getArtistInfo(artistInfoDelayed, false, true, context, this);
+ // Setup infinite loading based on scrolling
+ final EntryInfiniteGridAdapter infiniteGridAdapter = (EntryInfiniteGridAdapter) entryGridAdapter;
+ infiniteGridAdapter.setData(albumListType, albumListExtra, albumListSize);
- return null;
- }
+ recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ }
- @Override
- protected void done(Void result) {
- /*if(albumList instanceof HeaderGridView) {
- HeaderGridView headerGridView = (HeaderGridView) albumList;
- headerGridView.invalidateRowHeight();
- ((BaseAdapter) headerGridView.getAdapter()).notifyDataSetChanged();
- }*/
-
- setupCoverArt(finalHeader);
- setupTextDisplay(finalHeader);
- setupButtonEvents(finalHeader);
-
- finalHeader.setVisibility(View.VISIBLE);
- headerProgress.setVisibility(View.GONE);
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+
+ RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
+ int totalItemCount = layoutManager.getItemCount();
+ int lastVisibleItem;
+ if(layoutManager instanceof GridLayoutManager) {
+ lastVisibleItem = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
+ } else if(layoutManager instanceof LinearLayoutManager) {
+ lastVisibleItem = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
+ } else {
+ return;
}
- }.execute();
- }
-
- // Only add header to entry list if we aren't going recreate album grid as root anyways
- if(header != null && entryList != null && (!addAlbumHeader || entries.size() > 0)) {
- entryList.addHeaderView(header, null, false);
- header = null;
- }
- }
- // Needs to be added here, GB crashes if you to try to remove the header view before adapter is set
- if(addAlbumHeader) {
- if(entries.size() > 0 || playlistId != null || podcastId != null) {
- entryList.addHeaderView(albumList);
- } else {
- ViewGroup rootGroup = (ViewGroup) rootView.findViewById(R.id.select_album_layout);
- albumList = (GridView) context.getLayoutInflater().inflate(R.layout.grid_view, rootGroup, false);
- rootGroup.removeView(entryList);
- rootGroup.addView(albumList);
-
- setupScrollList(albumList);
- setupAlbumList();
-
- // This should only not be null for a artist with only albums
- if(header != null) {
- HeaderGridView headerGridView = (HeaderGridView) albumList;
- headerGridView.addHeaderView(header);
+ if(totalItemCount > 0 && lastVisibleItem >= totalItemCount - 2) {
+ infiniteGridAdapter.loadMore();
+ }
}
- }
- addAlbumHeader = false;
+ });
}
-
- boolean validData = !entries.isEmpty() || !albums.isEmpty();
- if(!validData) {
- setEmpty(true);
+ entryGridAdapter.setOnItemClickedListener(this);
+ // Always show artist if this is not a artist we are viewing
+ if(!artist) {
+ entryGridAdapter.setShowArtist(true);
+ }
+ // Podcasts are not checkable
+ if(podcastId != null) {
+ entryGridAdapter.setCheckable(false);
}
- // Always going to have entries in entryAdapter
- entryAdapter = new EntryAdapter(context, getImageLoader(), entries, (podcastId == null));
- ListAdapter listAdapter = entryAdapter;
- // Song-only genre needs to always be entry list + infinite adapter
- if("genres-songs".equals(albumListType)) {
- ViewGroup rootGroup = (ViewGroup) rootView.findViewById(R.id.select_album_layout);
- if(rootGroup.findViewById(R.id.gridview) != null && largeAlbums) {
- rootGroup.removeView(albumList);
- rootGroup.addView(entryList);
- }
- listAdapter = new AlbumListAdapter(context, entryAdapter, albumListType, albumListExtra, albumListSize);
- } else if(albumListType == null || "starred".equals(albumListType)) {
- // Only set standard album adapter if not album list and largeAlbums is true
- if(largeAlbums) {
- albumList.setAdapter(new AlbumGridAdapter(context, getImageLoader(), albums, !artist));
- }
- } else {
- // If album list, use infinite adapters for either depending on whether or not largeAlbums is true
- if(largeAlbums) {
- albumList.setAdapter(new AlbumListAdapter(context, new AlbumGridAdapter(context, getImageLoader(), albums, true), albumListType, albumListExtra, albumListSize));
- } else {
- listAdapter = new AlbumListAdapter(context, entryAdapter, albumListType, albumListExtra, albumListSize);
+ // Show header if not album list type and not root and not artist
+ // For Subsonic 5.1+ display a header for artists with getArtistInfo data if it exists
+ boolean addedHeader = false;
+ if(albumListType == null && !"root".equals(id) && (!artist || artistInfo != null || artistInfoDelayed != null)) {
+ View header = createHeader();
+
+ if(header != null) {
+ if (artistInfoDelayed != null) {
+ final View finalHeader = header.findViewById(R.id.select_album_header);
+ final View headerProgress = header.findViewById(R.id.header_progress);
+
+ finalHeader.setVisibility(View.INVISIBLE);
+ headerProgress.setVisibility(View.VISIBLE);
+
+ new SilentBackgroundTask<Void>(context) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ artistInfo = musicService.getArtistInfo(artistInfoDelayed, false, true, context, this);
+
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ setupCoverArt(finalHeader);
+ setupTextDisplay(finalHeader);
+ setupButtonEvents(finalHeader);
+
+ finalHeader.setVisibility(View.VISIBLE);
+ headerProgress.setVisibility(View.GONE);
+ }
+ }.execute();
+ }
+
+ entryGridAdapter.setHeader(header);
+ addedHeader = true;
}
}
- entryList.setAdapter(listAdapter);
- if(validData) {
- entryList.setVisibility(View.VISIBLE);
- }
- context.supportInvalidateOptionsMenu();
+ int scrollToPosition = -1;
if(lookupEntry != null) {
for(int i = 0; i < entries.size(); i++) {
if(lookupEntry.equals(entries.get(i).getTitle())) {
- entryList.setSelection(i + entryList.getHeaderViewsCount());
+ scrollToPosition = i;
+ entryGridAdapter.addSelected(entries.get(i));
lookupEntry = null;
break;
}
}
}
+ recyclerView.setAdapter(entryGridAdapter);
+ context.supportInvalidateOptionsMenu();
+
+ if(scrollToPosition != -1) {
+ recyclerView.scrollToPosition(scrollToPosition + (addedHeader ? 1 : 0));
+ }
+
Bundle args = getArguments();
boolean playAll = args.getBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
if (playAll && !restoredInstance) {
@@ -849,122 +823,51 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
}
}
- private void setupAlbumList() {
- albumList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Entry entry = (Entry) parent.getItemAtPosition(position);
- SubsonicFragment fragment = new SelectDirectoryFragment();
- Bundle args = new Bundle();
- args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getId());
- args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle());
- args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, entry);
- if ("newest".equals(albumListType)) {
- args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true);
- }
- if(entry.getArtist() == null && entry.getParent() == null) {
- args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
- }
- fragment.setArguments(args);
-
- replaceFragment(fragment, true);
- }
- });
-
- registerForContextMenu(entryList);
- registerForContextMenu(albumList);
- }
-
private void playNow(final boolean shuffle, final boolean append) {
playNow(shuffle, append, false);
}
private void playNow(final boolean shuffle, final boolean append, final boolean playNext) {
- if(getSelectedSongs().size() > 0) {
- download(append, false, !append, playNext, shuffle);
- selectAll(false, false);
+ List<Entry> songs = getSelectedSongs();
+ if(!songs.isEmpty()) {
+ download(songs, append, false, !append, playNext, shuffle);
+ entryGridAdapter.clearSelected();
}
else {
playAll(shuffle, append);
}
}
private void playAll(final boolean shuffle, final boolean append) {
- boolean hasSubFolders = false;
- for (int i = 0; i < entryList.getCount(); i++) {
- Entry entry = (Entry) entryList.getItemAtPosition(i);
- if (entry != null && entry.isDirectory()) {
- hasSubFolders = true;
- break;
- }
- }
- if(albums.size() > 0) {
- hasSubFolders = true;
- }
+ boolean hasSubFolders = !albums.isEmpty();
if (hasSubFolders && (id != null || share != null || "starred".equals(albumListType))) {
downloadRecursively(id, false, append, !append, shuffle, false);
} else if(hasSubFolders && albumListType != null) {
downloadRecursively(albums, shuffle, append);
} else {
- selectAll(true, false);
- download(append, false, !append, false, shuffle);
- selectAll(false, false);
- }
- }
-
- private void selectAll(boolean selected, boolean toast) {
- int count = entryList.getCount();
- int selectedCount = 0;
- for (int i = 0; i < count; i++) {
- Entry entry = (Entry) entryList.getItemAtPosition(i);
- if (entry != null && !entry.isDirectory() && !entry.isVideo()) {
- entryList.setItemChecked(i, selected);
- selectedCount++;
- }
- }
-
- // Display toast: N tracks selected / N tracks unselected
- if (toast) {
- int toastResId = selected ? R.string.select_album_n_selected
- : R.string.select_album_n_unselected;
- Util.toast(context, context.getString(toastResId, selectedCount));
+ download(entries, append, false, !append, false, shuffle);
}
}
private List<Entry> getSelectedSongs() {
- List<Entry> songs = new ArrayList<Entry>(10);
- int count = entryList.getCount();
- for (int i = 0; i < count; i++) {
- if (entryList.isItemChecked(i)) {
- Entry entry = (Entry) entryList.getItemAtPosition(i);
- // Don't try to add directories or 1-starred songs
- if(!entry.isDirectory() && entry.getRating() != 1) {
- songs.add(entry);
- }
- }
- }
- return songs;
+ return entryGridAdapter.getSelected();
}
private List<Integer> getSelectedIndexes() {
+ List<Entry> selected = entryGridAdapter.getSelected();
List<Integer> indexes = new ArrayList<Integer>();
- int count = entryList.getCount();
- int headers = entryList.getHeaderViewsCount();
- for (int i = 0; i < count; i++) {
- if (entryList.isItemChecked(i)) {
- indexes.add(i - headers);
- }
+ for(Entry entry: selected) {
+ indexes.add(entries.indexOf(entry));
}
return indexes;
}
- private void download(final boolean append, final boolean save, final boolean autoplay, final boolean playNext, final boolean shuffle) {
+ private void download(final List<Entry> songs, final boolean append, final boolean save, final boolean autoplay, final boolean playNext, final boolean shuffle) {
if (getDownloadService() == null) {
return;
}
- final List<Entry> songs = getSelectedSongs();
warnIfStorageUnavailable();
// Conditions for using play now button
@@ -993,7 +896,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
@Override
protected void done(Void result) {
if (autoplay) {
- Util.startActivityWithoutTransition(context, DownloadActivity.class);
+ context.openNowPlaying();
} else if (save) {
Util.toast(context,
context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size()));
@@ -1007,11 +910,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
checkLicenseAndTrialPeriod(onValid);
}
private void downloadBackground(final boolean save) {
+ List<Entry> songs = getSelectedSongs();
if(playlistId != null) {
- selectAll(true, false);
+ songs = entries;
}
- List<Entry> songs = getSelectedSongs();
if(songs.isEmpty()) {
// Get both songs and albums
downloadRecursively(id, save, false, false, false, true);
@@ -1044,12 +947,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
private void delete() {
List<Entry> songs = getSelectedSongs();
if(songs.isEmpty()) {
- selectAll(true, false);
- songs = getSelectedSongs();
-
- // Also delete all directories
- for(Entry album: albums) {
- deleteRecursively(album);
+ for(Entry entry: entries) {
+ if(entry.isDirectory()) {
+ deleteRecursively(entry);
+ } else {
+ songs.add(entry);
+ }
}
}
if (getDownloadService() != null) {
@@ -1068,11 +971,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
@Override
protected void done(Void result) {
- for(int i = indexes.size() - 1; i >= 0; i--) {
- entryList.setItemChecked(indexes.get(i) + 1, false);
- entryAdapter.removeAt(indexes.get(i));
+ for(Integer index: indexes) {
+ entryGridAdapter.removeAt(index);
}
- entryAdapter.notifyDataSetChanged();
Util.toast(context, context.getResources().getString(R.string.removed_playlist, indexes.size(), name));
}
@@ -1157,8 +1058,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
@Override
protected void done(Void result) {
- entries.remove(episode);
- entryAdapter.notifyDataSetChanged();
+ entryGridAdapter.removeItem(episode);
}
@Override
@@ -1219,10 +1119,8 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
Util.toast(context, context.getResources().getString(R.string.starring_content_unstarred, Integer.toString(unstar.size())));
for(Entry entry: unstar) {
- entries.remove(entry);
+ entryGridAdapter.removeItem(entry);
}
- entryAdapter.notifyDataSetChanged();
- selectAll(false, false);
}
@Override
@@ -1335,31 +1233,19 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
@Override
protected void done(Void result) {
- Util.startActivityWithoutTransition(context, DownloadActivity.class);
+ context.openNowPlaying();
}
}.execute();
}
private View createHeader() {
- View header = entryList.findViewById(R.id.select_album_header_wrapper);
- boolean add = false;
- if(header == null) {
- header = LayoutInflater.from(context).inflate(R.layout.select_album_header, entryList, false);
- add = true;
- }
+ View header = LayoutInflater.from(context).inflate(R.layout.select_album_header, null, false);
setupCoverArt(header);
setupTextDisplay(header);
+ setupButtonEvents(header);
- if(add) {
- setupButtonEvents(header);
- }
-
- if(add) {
- return header;
- } else {
- return null;
- }
+ return header;
}
private void setupCoverArt(View header) {
@@ -1508,11 +1394,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
} else {
artistView.setMaxLines(minLines);
}
-
- if(albumList instanceof HeaderGridView) {
- HeaderGridView headerGridView = (HeaderGridView) albumList;
- ((BaseAdapter) headerGridView.getAdapter()).notifyDataSetChanged();
- }
}
});
artistView.setMovementMethod(LinkMovementMethod.getInstance());
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectGenreFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectGenreFragment.java
index 2d310172..fe012f62 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectGenreFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectGenreFragment.java
@@ -1,21 +1,18 @@
/*
- This file is part of Subsonic.
+ 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
+*/
- 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 2010 (C) Sindre Mehus
- */
package github.daneren2005.dsub.fragments;
import android.os.Bundle;
@@ -23,6 +20,7 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.Genre;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.util.Constants;
@@ -31,7 +29,7 @@ import github.daneren2005.dsub.adapter.GenreAdapter;
import java.util.List;
-public class SelectGenreFragment extends SelectListFragment<Genre> {
+public class SelectGenreFragment extends SelectRecyclerFragment<Genre> {
private static final String TAG = SelectGenreFragment.class.getSimpleName();
@Override
@@ -40,8 +38,8 @@ public class SelectGenreFragment extends SelectListFragment<Genre> {
}
@Override
- public ArrayAdapter getAdapter(List<Genre> objs) {
- return new GenreAdapter(context, objs);
+ public SectionAdapter getAdapter(List<Genre> objs) {
+ return new GenreAdapter(context, objs, this);
}
@Override
@@ -55,9 +53,7 @@ public class SelectGenreFragment extends SelectListFragment<Genre> {
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Genre genre = (Genre) parent.getItemAtPosition(position);
-
+ public void onItemClicked(Genre genre) {
SubsonicFragment fragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, "genres");
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java
index 3d7e664f..49589971 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java
@@ -1,19 +1,20 @@
package github.daneren2005.dsub.fragments;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.DialogInterface;
+import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
+import android.support.v7.widget.RecyclerView;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.Playlist;
import github.daneren2005.dsub.domain.ServerInfo;
@@ -31,9 +32,11 @@ import github.daneren2005.dsub.util.UserUtil;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.adapter.PlaylistAdapter;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-public class SelectPlaylistFragment extends SelectListFragment<Playlist> {
+public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
private static final String TAG = SelectPlaylistFragment.class.getSimpleName();
@Override
@@ -47,8 +50,7 @@ public class SelectPlaylistFragment extends SelectListFragment<Playlist> {
else {
inflater.inflate(R.menu.select_playlist_context, menu);
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Playlist playlist = (Playlist) listView.getItemAtPosition(info.position);
+ Playlist playlist = adapter.getContextItem();
if(SyncUtil.isSyncedPlaylist(context, playlist.getId())) {
menu.removeItem(R.id.playlist_menu_sync);
} else {
@@ -71,9 +73,8 @@ public class SelectPlaylistFragment extends SelectListFragment<Playlist> {
if(menuItem.getGroupId() != getSupportTag()) {
return false;
}
-
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Playlist playlist = (Playlist) listView.getItemAtPosition(info.position);
+
+ Playlist playlist = adapter.getContextItem();
SubsonicFragment fragment;
Bundle args;
@@ -130,8 +131,31 @@ public class SelectPlaylistFragment extends SelectListFragment<Playlist> {
}
@Override
- public ArrayAdapter getAdapter(List<Playlist> playlists) {
- return new PlaylistAdapter(context, playlists);
+ public SectionAdapter<Playlist> getAdapter(List<Playlist> playlists) {
+ List<Playlist> mine = new ArrayList<>();
+ List<Playlist> shared = new ArrayList<>();
+
+ String currentUsername = UserUtil.getCurrentUsername(context);
+ for(Playlist playlist: playlists) {
+ if(playlist.getOwner() == null || playlist.getOwner().equals(currentUsername)) {
+ mine.add(playlist);
+ } else {
+ shared.add(playlist);
+ }
+ }
+
+ if(shared.isEmpty()) {
+ return new PlaylistAdapter(context, playlists, this);
+ } else {
+ Resources res = context.getResources();
+ List<String> headers = Arrays.asList(res.getString(R.string.playlist_mine), res.getString(R.string.playlist_shared));
+
+ List<List<Playlist>> sections = new ArrayList<>();
+ sections.add(mine);
+ sections.add(shared);
+
+ return new PlaylistAdapter(context, headers, sections, this);
+ }
}
@Override
@@ -149,9 +173,7 @@ public class SelectPlaylistFragment extends SelectListFragment<Playlist> {
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Playlist playlist = (Playlist) parent.getItemAtPosition(position);
-
+ public void onItemClicked(Playlist playlist) {
SubsonicFragment fragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
@@ -179,8 +201,7 @@ public class SelectPlaylistFragment extends SelectListFragment<Playlist> {
@Override
protected void done(Void result) {
- adapter.remove(playlist);
- adapter.notifyDataSetChanged();
+ adapter.removeItem(playlist);
Util.toast(context, context.getResources().getString(R.string.menu_deleted_playlist, playlist.getName()));
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java
index 3a564f1c..520d0414 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java
@@ -1,33 +1,28 @@
/*
- 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 2010 (C) Sindre Mehus
- */
+ 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.fragments;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.TextView;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.PodcastChannel;
import github.daneren2005.dsub.service.MusicService;
@@ -46,11 +41,7 @@ import github.daneren2005.dsub.adapter.PodcastChannelAdapter;
import java.util.ArrayList;
import java.util.List;
-/**
- *
- * @author Scott
- */
-public class SelectPodcastsFragment extends SelectListFragment<PodcastChannel> {
+public class SelectPodcastsFragment extends SelectRecyclerFragment<PodcastChannel> {
private static final String TAG = SelectPodcastsFragment.class.getSimpleName();
@Override
@@ -79,8 +70,7 @@ public class SelectPodcastsFragment extends SelectListFragment<PodcastChannel> {
if(!Util.isOffline(context) && UserUtil.canPodcast()) {
inflater.inflate(R.menu.select_podcasts_context, menu);
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- PodcastChannel podcast = (PodcastChannel) listView.getItemAtPosition(info.position);
+ PodcastChannel podcast = adapter.getContextItem();
if(SyncUtil.isSyncedPodcast(context, podcast.getId())) {
menu.removeItem(R.id.podcast_menu_sync);
} else {
@@ -98,10 +88,8 @@ public class SelectPodcastsFragment extends SelectListFragment<PodcastChannel> {
if(menuItem.getGroupId() != getSupportTag()) {
return false;
}
-
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- PodcastChannel channel = (PodcastChannel) listView.getItemAtPosition(info.position);
+ PodcastChannel channel = adapter.getContextItem();
switch (menuItem.getItemId()) {
case R.id.podcast_menu_sync:
syncPodcast(channel);
@@ -126,8 +114,8 @@ public class SelectPodcastsFragment extends SelectListFragment<PodcastChannel> {
}
@Override
- public ArrayAdapter getAdapter(List<PodcastChannel> channels) {
- return new PodcastChannelAdapter(context, channels);
+ public SectionAdapter getAdapter(List<PodcastChannel> channels) {
+ return new PodcastChannelAdapter(context, channels, this);
}
@Override
@@ -141,9 +129,7 @@ public class SelectPodcastsFragment extends SelectListFragment<PodcastChannel> {
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- PodcastChannel channel = (PodcastChannel) parent.getItemAtPosition(position);
-
+ public void onItemClicked(PodcastChannel channel) {
if("error".equals(channel.getStatus())) {
Util.toast(context, context.getResources().getString(R.string.select_podcasts_invalid_podcast_channel, channel.getErrorMessage() == null ? "error" : channel.getErrorMessage()));
} else if("downloading".equals(channel.getStatus())) {
@@ -258,8 +244,7 @@ public class SelectPodcastsFragment extends SelectListFragment<PodcastChannel> {
@Override
protected void done(Void result) {
- adapter.remove(channel);
- adapter.notifyDataSetChanged();
+ adapter.removeItem(channel);
Util.toast(context, context.getResources().getString(R.string.select_podcasts_deleted, channel.getName()));
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectListFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java
index 6f73f6e8..526a4312 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectListFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java
@@ -1,25 +1,23 @@
/*
- This file is part of Subsonic.
+ 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
+*/
- 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 2010 (C) Sindre Mehus
- */
package github.daneren2005.dsub.fragments;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -27,15 +25,13 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
import github.daneren2005.dsub.util.BackgroundTask;
@@ -43,13 +39,16 @@ import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.TabBackgroundTask;
-public abstract class SelectListFragment<T> extends SubsonicFragment implements AdapterView.OnItemClickListener {
- private static final String TAG = SelectListFragment.class.getSimpleName();
- protected ListView listView;
- protected ArrayAdapter adapter;
+public abstract class SelectRecyclerFragment<T> extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<T> {
+ private static final String TAG = SelectRecyclerFragment.class.getSimpleName();
+ protected RecyclerView recyclerView;
+ protected SectionAdapter<T> adapter;
protected BackgroundTask<List<T>> currentTask;
protected List<T> objects;
protected boolean serialize = true;
+ protected boolean largeAlbums = false;
+ protected int columns;
+ protected boolean pullToRefresh = true;
@Override
public void onCreate(Bundle bundle) {
@@ -58,6 +57,7 @@ public abstract class SelectListFragment<T> extends SubsonicFragment implements
if(bundle != null && serialize) {
objects = (List<T>) bundle.getSerializable(Constants.FRAGMENT_LIST);
}
+ columns = context.getResources().getInteger(R.integer.Grid_Columns);
}
@Override
@@ -70,21 +70,26 @@ public abstract class SelectListFragment<T> extends SubsonicFragment implements
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false);
+ rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
refreshLayout.setOnRefreshListener(this);
- listView = (ListView)rootView.findViewById(R.id.fragment_list);
- listView.setOnItemClickListener(this);
- setupScrollList(listView);
- registerForContextMenu(listView);
+ recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
+ setupLayoutManager();
+
+ if(pullToRefresh) {
+ setupScrollList(recyclerView);
+ } else {
+ refreshLayout.setEnabled(false);
+ }
if(objects == null) {
refresh(false);
} else {
- listView.setAdapter(adapter = getAdapter(objects));
+ recyclerView.setAdapter(adapter = getAdapter(objects));
}
+ registerForContextMenu(recyclerView);
return rootView;
}
@@ -109,7 +114,7 @@ public abstract class SelectListFragment<T> extends SubsonicFragment implements
if(titleRes != 0) {
setTitle(getTitleResource());
}
- listView.setVisibility(View.GONE);
+ recyclerView.setVisibility(View.GONE);
// Cancel current running task before starting another one
if(currentTask != null) {
@@ -135,13 +140,10 @@ public abstract class SelectListFragment<T> extends SubsonicFragment implements
@Override
protected void done(List<T> result) {
if (result != null && !result.isEmpty()) {
- // Toggle fast scroll to get around issue when length of list changes
- listView.setFastScrollEnabled(false);
- listView.setAdapter(adapter = getAdapter(result));
- listView.setFastScrollEnabled(true);
+ recyclerView.setAdapter(adapter = getAdapter(result));
onFinishRefresh();
- listView.setVisibility(View.VISIBLE);
+ recyclerView.setVisibility(View.VISIBLE);
} else {
setEmpty(true);
}
@@ -152,8 +154,12 @@ public abstract class SelectListFragment<T> extends SubsonicFragment implements
currentTask.execute();
}
+ private void setupLayoutManager() {
+ setupLayoutManager(recyclerView, largeAlbums);
+ }
+
public abstract int getOptionsMenu();
- public abstract ArrayAdapter getAdapter(List<T> objs);
+ public abstract SectionAdapter<T> getAdapter(List<T> objs);
public abstract List<T> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception;
public abstract int getTitleResource();
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectShareFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectShareFragment.java
index 07cd3bef..3d79b7b9 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectShareFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectShareFragment.java
@@ -1,13 +1,26 @@
+/*
+ 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.fragments;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.DatePicker;
@@ -17,6 +30,7 @@ import java.util.Date;
import java.util.List;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.Share;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
@@ -28,10 +42,7 @@ import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.adapter.ShareAdapter;
-/**
- * Created by Scott on 12/28/13.
- */
-public class SelectShareFragment extends SelectListFragment<Share> {
+public class SelectShareFragment extends SelectRecyclerFragment<Share> {
private static final String TAG = SelectShareFragment.class.getSimpleName();
@Override
@@ -48,9 +59,7 @@ public class SelectShareFragment extends SelectListFragment<Share> {
return false;
}
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Share share = (Share) listView.getItemAtPosition(info.position);
-
+ Share share = adapter.getContextItem();
switch (menuItem.getItemId()) {
case R.id.share_menu_share:
shareExternal(share);
@@ -75,8 +84,8 @@ public class SelectShareFragment extends SelectListFragment<Share> {
}
@Override
- public ArrayAdapter getAdapter(List<Share> objs) {
- return new ShareAdapter(context, objs);
+ public SectionAdapter getAdapter(List<Share> objs) {
+ return new ShareAdapter(context, objs, this);
}
@Override
@@ -90,9 +99,7 @@ public class SelectShareFragment extends SelectListFragment<Share> {
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Share share = (Share) parent.getItemAtPosition(position);
-
+ public void onItemClicked(Share share) {
SubsonicFragment fragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
args.putSerializable(Constants.INTENT_EXTRA_NAME_SHARE, share);
@@ -193,8 +200,7 @@ public class SelectShareFragment extends SelectListFragment<Share> {
@Override
protected void done(Void result) {
- adapter.remove(share);
- adapter.notifyDataSetChanged();
+ adapter.removeItem(share);
Util.toast(context, context.getResources().getString(R.string.share_deleted, share.getName()));
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java
index b4d34ff9..bf25db77 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java
@@ -19,25 +19,28 @@ import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import java.util.List;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.EntryGridAdapter;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.util.ProgressListener;
-import github.daneren2005.dsub.adapter.EntryAdapter;
+import github.daneren2005.dsub.view.UpdateView;
-public class SelectVideoFragment extends SelectListFragment<MusicDirectory.Entry> {
+public class SelectVideoFragment extends SelectRecyclerFragment<MusicDirectory.Entry> {
@Override
public int getOptionsMenu() {
return R.menu.empty;
}
@Override
- public ArrayAdapter getAdapter(List<MusicDirectory.Entry> objs) {
- return new EntryAdapter(context, null, objs, false);
+ public SectionAdapter getAdapter(List<MusicDirectory.Entry> objs) {
+ SectionAdapter adapter = new EntryGridAdapter(context, objs, null, false);
+ adapter.setOnItemClickedListener(this);
+ return adapter;
}
@Override
@@ -52,18 +55,17 @@ public class SelectVideoFragment extends SelectListFragment<MusicDirectory.Entry
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- MusicDirectory.Entry entry = (MusicDirectory.Entry) parent.getItemAtPosition(position);
+ public void onItemClicked(MusicDirectory.Entry entry) {
playVideo(entry);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ UpdateView targetView = adapter.getContextView();
+ menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0);
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Object entry = listView.getItemAtPosition(info.position);
-
+ MusicDirectory.Entry entry = adapter.getContextItem();
onCreateContextMenu(menu, view, menuInfo, entry);
recreateContextMenu(menu);
}
@@ -74,9 +76,7 @@ public class SelectVideoFragment extends SelectListFragment<MusicDirectory.Entry
return false;
}
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Object entry = listView.getItemAtPosition(info.position);
-
+ MusicDirectory.Entry entry = adapter.getContextItem();
return onContextItemSelected(menuItem, entry);
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectYearFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectYearFragment.java
index dc19acad..a89bc280 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectYearFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectYearFragment.java
@@ -1,21 +1,18 @@
/*
- This file is part of Subsonic.
-
+ 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
+ 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 2010 (C) Sindre Mehus
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+ Copyright 2015 (C) Scott Jackson
*/
+
package github.daneren2005.dsub.fragments;
import android.os.Bundle;
@@ -27,14 +24,13 @@ import java.util.ArrayList;
import java.util.List;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.BasicListAdapter;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.ProgressListener;
-/**
- * Created by Scott on 12/23/13.
- */
-public class SelectYearFragment extends SelectListFragment<Integer> {
+public class SelectYearFragment extends SelectRecyclerFragment<String> {
@Override
public int getOptionsMenu() {
@@ -42,15 +38,15 @@ public class SelectYearFragment extends SelectListFragment<Integer> {
}
@Override
- public ArrayAdapter getAdapter(List<Integer> objs) {
- return new ArrayAdapter<Integer>(context, android.R.layout.simple_list_item_1, objs);
+ public SectionAdapter getAdapter(List<String> objs) {
+ return new BasicListAdapter(context, objs, this);
}
@Override
- public List<Integer> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
- List<Integer> decades = new ArrayList<Integer>();
+ public List<String> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
+ List<String> decades = new ArrayList<>();
for(int i = 2010; i >= 1920; i -= 10) {
- decades.add(i);
+ decades.add(String.valueOf(i));
}
return decades;
@@ -62,15 +58,13 @@ public class SelectYearFragment extends SelectListFragment<Integer> {
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Integer decade = (Integer) parent.getItemAtPosition(position);
-
+ public void onItemClicked(String decade) {
SubsonicFragment fragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, "years");
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
- args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA, Integer.toString(decade));
+ args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA, decade);
fragment.setArguments(args);
replaceFragment(fragment);
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java
index 79e759cc..088b6d00 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java
@@ -17,12 +17,15 @@ package github.daneren2005.dsub.fragments;
import android.os.Bundle;
import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.ArtistAdapter;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.ArtistInfo;
import github.daneren2005.dsub.domain.MusicDirectory;
@@ -32,13 +35,13 @@ import github.daneren2005.dsub.service.MusicServiceFactory;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.Util;
-import github.daneren2005.dsub.adapter.ArtistAdapter;
+import github.daneren2005.dsub.view.UpdateView;
import java.net.URLEncoder;
import java.util.LinkedList;
import java.util.List;
-public class SimilarArtistFragment extends SelectListFragment<Artist> {
+public class SimilarArtistFragment extends SelectRecyclerFragment<Artist> {
private static final String TAG = SimilarArtistFragment.class.getSimpleName();
private ArtistInfo info;
private String artistId;
@@ -52,6 +55,18 @@ public class SimilarArtistFragment extends SelectListFragment<Artist> {
}
@Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
+ super.onCreateOptionsMenu(menu, menuInflater);
+ if(!primaryFragment) {
+ return;
+ }
+
+ if(info.getMissingArtists().isEmpty()) {
+ menu.removeItem(R.id.menu_show_missing);
+ }
+ }
+
+ @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_play_now:
@@ -71,10 +86,11 @@ public class SimilarArtistFragment extends SelectListFragment<Artist> {
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ UpdateView targetView = adapter.getContextView();
+ menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0);
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Object entry = listView.getItemAtPosition(info.position);
- onCreateContextMenu(menu, view, menuInfo, entry);
+ Artist artist = adapter.getContextItem();
+ onCreateContextMenu(menu, view, menuInfo, artist);
recreateContextMenu(menu);
}
@@ -85,14 +101,12 @@ public class SimilarArtistFragment extends SelectListFragment<Artist> {
return false;
}
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Artist artist = (Artist) listView.getItemAtPosition(info.position);
+ Artist artist = adapter.getContextItem();
return onContextItemSelected(menuItem, artist);
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Artist artist = (Artist) parent.getItemAtPosition(position);
+ public void onItemClicked(Artist artist) {
SubsonicFragment fragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
@@ -109,8 +123,8 @@ public class SimilarArtistFragment extends SelectListFragment<Artist> {
}
@Override
- public ArrayAdapter getAdapter(List<Artist> objects) {
- return new ArtistAdapter(context, objects);
+ public SectionAdapter getAdapter(List<Artist> objects) {
+ return new ArtistAdapter(context, objects, this);
}
@Override
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
index 109983ba..a155e807 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
@@ -18,8 +18,9 @@
*/
package github.daneren2005.dsub.fragments;
+import android.annotation.TargetApi;
import android.app.Activity;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -28,13 +29,19 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.StatFs;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.internal.view.ContextThemeWrapper;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.ContextMenu;
import android.view.GestureDetector;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -49,9 +56,9 @@ import android.widget.EditText;
import android.widget.RatingBar;
import android.widget.TextView;
import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.activity.DownloadActivity;
import github.daneren2005.dsub.activity.SubsonicActivity;
import github.daneren2005.dsub.activity.SubsonicFragmentActivity;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.Bookmark;
import github.daneren2005.dsub.domain.Genre;
@@ -75,10 +82,10 @@ import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.util.LoadingTask;
import github.daneren2005.dsub.util.UserUtil;
import github.daneren2005.dsub.util.Util;
-import github.daneren2005.dsub.view.AlbumCell;
import github.daneren2005.dsub.view.AlbumView;
import github.daneren2005.dsub.view.ArtistEntryView;
import github.daneren2005.dsub.view.ArtistView;
+import github.daneren2005.dsub.view.GridSpacingDecoration;
import github.daneren2005.dsub.view.PlaylistSongView;
import github.daneren2005.dsub.view.SongView;
import github.daneren2005.dsub.view.UpdateView;
@@ -101,7 +108,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
private static final String TAG = SubsonicFragment.class.getSimpleName();
private static int TAG_INC = 10;
private int tag;
-
+
protected SubsonicActivity context;
protected CharSequence title = null;
protected CharSequence subtitle = null;
@@ -116,7 +123,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
protected boolean artistOverride = false;
protected SwipeRefreshLayout refreshLayout;
protected boolean firstRun;
-
+
public SubsonicFragment() {
super();
tag = TAG_INC++;
@@ -187,7 +194,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
return false;
}
-
+
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo, Object selected) {
MenuInflater inflater = context.getMenuInflater();
@@ -199,7 +206,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
else {
inflater.inflate(R.menu.select_podcast_episode_context, menu);
-
+
if(entry.getBookmark() == null) {
menu.removeItem(R.id.bookmark_menu_delete);
}
@@ -223,7 +230,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
else {
inflater.inflate(R.menu.select_song_context, menu);
-
+
if(entry.getBookmark() == null) {
menu.removeItem(R.id.bookmark_menu_delete);
}
@@ -286,7 +293,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
if(info.targetView instanceof SongView) {
SongView songView = (SongView) info.targetView;
DownloadFile downloadFile = songView.getDownloadFile();
-
+
try {
if(downloadFile != null) {
if(downloadFile.isWorkDone()) {
@@ -294,7 +301,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
if(downloadFile.isSaved()) {
menu.removeItem(R.id.song_menu_pin);
}
-
+
// Remove cache option no matter what if already downloaded
menu.removeItem(R.id.song_menu_download);
} else {
@@ -307,14 +314,10 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
}
// Apply similar logic to album views
- else if(info.targetView instanceof AlbumCell || info.targetView instanceof AlbumView
- || info.targetView instanceof ArtistView || info.targetView instanceof ArtistEntryView) {
+ else if(info.targetView instanceof AlbumView || info.targetView instanceof ArtistView || info.targetView instanceof ArtistEntryView) {
File folder = null;
int id = 0;
- if(info.targetView instanceof AlbumCell) {
- folder = ((AlbumCell) info.targetView).getFile();
- id = R.id.album_menu_delete;
- } else if(info.targetView instanceof AlbumView) {
+ if(info.targetView instanceof AlbumView) {
folder = ((AlbumView) info.targetView).getFile();
id = R.id.album_menu_delete;
} else if(info.targetView instanceof ArtistView) {
@@ -324,7 +327,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
folder = ((ArtistEntryView) info.targetView).getFile();
id = R.id.artist_menu_delete;
}
-
+
try {
if(folder != null && !folder.exists()) {
menu.removeItem(id);
@@ -475,7 +478,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
return true;
}
-
+
public void replaceFragment(SubsonicFragment fragment) {
replaceFragment(fragment, true);
}
@@ -492,7 +495,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
public int getSupportTag() {
return tag;
}
-
+
public void setPrimaryFragment(boolean primary) {
primaryFragment = primary;
if(primary) {
@@ -631,6 +634,68 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
R.color.holo_red_light);
}
}
+ protected void setupScrollList(final RecyclerView recyclerView) {
+ if(!context.isTouchscreen()) {
+ refreshLayout.setEnabled(false);
+ } else {
+ recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ }
+
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ refreshLayout.setEnabled(!recyclerView.canScrollVertically(-1));
+ }
+ });
+
+ refreshLayout.setColorScheme(
+ R.color.holo_blue_light,
+ R.color.holo_orange_light,
+ R.color.holo_green_light,
+ R.color.holo_red_light);
+ }
+ }
+
+ public void setupLayoutManager(RecyclerView recyclerView, boolean largeAlbums) {
+ recyclerView.setLayoutManager(getLayoutManager(recyclerView, largeAlbums));
+ }
+ public RecyclerView.LayoutManager getLayoutManager(RecyclerView recyclerView, boolean largeCells) {
+ if(largeCells) {
+ return getGridLayoutManager(recyclerView);
+ } else {
+ return getLinearLayoutManager();
+ }
+ }
+ public GridLayoutManager getGridLayoutManager(RecyclerView recyclerView) {
+ final int columns = getRecyclerColumnCount();
+ GridLayoutManager gridLayoutManager = new GridLayoutManager(context, columns);
+
+ GridLayoutManager.SpanSizeLookup spanSizeLookup = getSpanSizeLookup();
+ if(spanSizeLookup != null) {
+ gridLayoutManager.setSpanSizeLookup(spanSizeLookup);
+ }
+ RecyclerView.ItemDecoration itemDecoration = getItemDecoration();
+ if(itemDecoration != null) {
+ recyclerView.addItemDecoration(itemDecoration);
+ }
+ return gridLayoutManager;
+ }
+ public LinearLayoutManager getLinearLayoutManager() {
+ LinearLayoutManager layoutManager = new LinearLayoutManager(context);
+ layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
+ return layoutManager;
+ }
+ public GridLayoutManager.SpanSizeLookup getSpanSizeLookup() {
+ return null;
+ }
+ public RecyclerView.ItemDecoration getItemDecoration() {
+ return new GridSpacingDecoration();
+ }
+ public int getRecyclerColumnCount() {
+ return context.getResources().getInteger(R.integer.Grid_Columns);
+ }
protected void warnIfStorageUnavailable() {
if (!Util.isExternalStoragePresent()) {
@@ -650,9 +715,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
protected void onShuffleRequested() {
if(Util.isOffline(context)) {
- Intent intent = new Intent(context, DownloadActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
- Util.startActivityWithoutTransition(context, intent);
+ DownloadService downloadService = getDownloadService();
+ if(downloadService == null) {
+ return;
+ }
+ downloadService.setShufflePlayEnabled(true);
+ context.openNowPlaying();
return;
}
@@ -691,21 +759,21 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.shuffle_pick_genre)
- .setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- if(which == 0) {
- genreCombo.setText("");
- } else {
- genreCombo.setText(finalNames.get(which));
- }
- }
- });
+ .setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ if(which == 0) {
+ genreCombo.setText("");
+ } else {
+ genreCombo.setText(finalNames.get(which));
+ }
+ }
+ });
AlertDialog dialog = builder.create();
dialog.show();
}
@Override
- protected void error(Throwable error) {
+ protected void error(Throwable error) {
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
@@ -731,31 +799,34 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.shuffle_title)
- .setView(dialogView)
- .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- Intent intent = new Intent(context, DownloadActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
- String genre;
- if(useCombo) {
- genre = genreCombo.getText().toString();
- } else {
- genre = genreBox.getText().toString();
+ .setView(dialogView)
+ .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ String genre;
+ if (useCombo) {
+ genre = genreCombo.getText().toString();
+ } else {
+ genre = genreBox.getText().toString();
+ }
+ String startYear = startYearBox.getText().toString();
+ String endYear = endYearBox.getText().toString();
+
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear);
+ editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear);
+ editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
+ editor.commit();
+
+ DownloadService downloadService = getDownloadService();
+ if (downloadService == null) {
+ return;
+ }
+ downloadService.setShufflePlayEnabled(true);
+ context.openNowPlaying();
}
- String startYear = startYearBox.getText().toString();
- String endYear = endYearBox.getText().toString();
-
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear);
- editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear);
- editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
- editor.commit();
-
- Util.startActivityWithoutTransition(context, intent);
- }
- })
- .setNegativeButton(R.string.common_cancel, null);
+ })
+ .setNegativeButton(R.string.common_cancel, null);
AlertDialog dialog = builder.create();
dialog.show();
}
@@ -906,7 +977,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
playNowOverride = true;
return false;
}
-
+
if (!append && !background) {
downloadService.clear();
}
@@ -994,7 +1065,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
MusicService musicService = MusicServiceFactory.getMusicService(context);
List<Playlist> playlists = new ArrayList<Playlist>();
playlists.addAll(musicService.getPlaylists(false, context, this));
-
+
// Iterate through and remove all non owned public playlists
Iterator<Playlist> it = playlists.iterator();
while(it.hasNext()) {
@@ -1003,7 +1074,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
it.remove();
}
}
-
+
return playlists;
}
@@ -1016,7 +1087,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Playlist playlist = getItem(position);
-
+
// Create new if not getting a convert view to use
PlaylistSongView view;
if(convertView instanceof PlaylistSongView) {
@@ -1033,21 +1104,21 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.playlist_add_to)
- .setAdapter(playlistAdapter, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- if (which > 0) {
- addToPlaylist(playlists.get(which), songs);
- } else {
- createNewPlaylist(songs, false);
+ .setAdapter(playlistAdapter, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ if (which > 0) {
+ addToPlaylist(playlists.get(which), songs);
+ } else {
+ createNewPlaylist(songs, false);
+ }
}
- }
- });
+ });
AlertDialog dialog = builder.create();
dialog.show();
}
@Override
- protected void error(Throwable error) {
+ protected void error(Throwable error) {
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
@@ -1075,7 +1146,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
@Override
- protected void error(Throwable error) {
+ protected void error(Throwable error) {
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
@@ -1087,7 +1158,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
}.execute();
}
-
+
protected void createNewPlaylist(final List<Entry> songs, final boolean getSuggestion) {
View layout = context.getLayoutInflater().inflate(R.layout.save_playlist, null);
final EditText playlistNameView = (EditText) layout.findViewById(R.id.save_playlist_name);
@@ -1115,34 +1186,34 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.download_playlist_title)
- .setMessage(R.string.download_playlist_name)
- .setView(layout)
- .setPositiveButton(R.string.common_save, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- String playlistName = String.valueOf(playlistNameView.getText());
- if(overwriteCheckBox.isChecked()) {
- overwritePlaylist(songs, playlistName, getDownloadService().getSuggestedPlaylistId());
- } else {
- createNewPlaylist(songs, playlistName);
-
- if(getSuggestion) {
- DownloadService downloadService = getDownloadService();
- if(downloadService != null) {
- downloadService.setSuggestedPlaylistName(playlistName, null);
+ .setMessage(R.string.download_playlist_name)
+ .setView(layout)
+ .setPositiveButton(R.string.common_save, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ String playlistName = String.valueOf(playlistNameView.getText());
+ if(overwriteCheckBox.isChecked()) {
+ overwritePlaylist(songs, playlistName, getDownloadService().getSuggestedPlaylistId());
+ } else {
+ createNewPlaylist(songs, playlistName);
+
+ if(getSuggestion) {
+ DownloadService downloadService = getDownloadService();
+ if(downloadService != null) {
+ downloadService.setSuggestedPlaylistName(playlistName, null);
+ }
}
}
}
- }
- })
- .setNegativeButton(R.string.common_cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- })
- .setCancelable(true);
-
+ })
+ .setNegativeButton(R.string.common_cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ })
+ .setCancelable(true);
+
AlertDialog dialog = builder.create();
dialog.show();
}
@@ -1184,7 +1255,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
@Override
- protected void error(Throwable error) {
+ protected void error(Throwable error) {
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
@@ -1197,6 +1268,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}.execute();
}
+ @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
public void displaySongInfo(final Entry song) {
Integer duration = null;
Integer bitrate = null;
@@ -1209,12 +1281,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
if(file.exists()) {
MediaMetadataRetriever metadata = new MediaMetadataRetriever();
metadata.setDataSource(file.getAbsolutePath());
-
+
String tmp = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
duration = Integer.parseInt((tmp != null) ? tmp : "0") / 1000;
format = FileUtil.getExtension(file.getName());
size = file.length();
-
+
// If no duration try to read bitrate tag
if(duration == null) {
tmp = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE);
@@ -1224,7 +1296,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
// Divide by 1000 so in kbps
bitrate = (int) (size / duration) / 1000 * 8;
}
-
+
if(Util.isOffline(context)) {
song.setGenre(metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE));
String year = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR);
@@ -1286,7 +1358,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
Util.info(context, song.getTitle(), msg);
}
-
+
protected void playVideo(Entry entry) {
if(entryExists(entry)) {
playExternalPlayer(entry);
@@ -1315,7 +1387,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
intent.putExtra(Intent.EXTRA_TITLE, entry.getTitle());
List<ResolveInfo> intents = context.getPackageManager()
- .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if(intents != null && intents.size() > 0) {
startActivity(intent);
}else {
@@ -1373,7 +1445,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
public void deleteRecursively(Artist artist) {
deleteRecursively(FileUtil.getArtistDirectory(context, artist));
}
-
+
public void deleteRecursively(Entry album) {
deleteRecursively(FileUtil.getAlbumDirectory(context, album));
@@ -1490,7 +1562,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
intent.putExtra(Intent.EXTRA_TEXT, share.getUrl());
context.startActivity(Intent.createChooser(intent, context.getResources().getString(R.string.share_via)));
}
-
+
public GestureDetector getGestureDetector() {
return gestureScanner;
}
@@ -1515,7 +1587,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
public void onClick(DialogInterface dialog, int id) {
final Bookmark oldBookmark = song.getBookmark();
song.setBookmark(null);
-
+
new SilentBackgroundTask<Void>(context) {
@Override
protected Void doInBackground() throws Throwable {
@@ -1528,7 +1600,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
@Override
protected void error(Throwable error) {
song.setBookmark(oldBookmark);
-
+
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
@@ -1546,7 +1618,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
AlertDialog dialog = builder.create();
dialog.show();
}
-
+
protected void playNow(List<Entry> entries) {
playNow(entries, null, null);
}
@@ -1558,7 +1630,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
break;
}
}
-
+
// If no bookmark found, just play from start
if(bookmark == null) {
playNow(entries, 0, playlistName, playlistId);
@@ -1585,22 +1657,22 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
if(downloadService == null) {
return null;
}
-
+
downloadService.clear();
downloadService.download(entries, false, true, true, false, entries.indexOf(song), position);
downloadService.setSuggestedPlaylistName(playlistName, playlistId);
return null;
}
-
+
@Override
protected void done(Void result) {
- Util.startActivityWithoutTransition(context, DownloadActivity.class);
+ context.openNowPlaying();
}
}.execute();
}
- protected void deleteBookmark(final MusicDirectory.Entry entry, final ArrayAdapter adapter) {
+ protected void deleteBookmark(final MusicDirectory.Entry entry, final SectionAdapter adapter) {
Util.confirmDialog(context, R.string.bookmark_delete_title, entry.getTitle(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
@@ -1626,8 +1698,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
@Override
protected void done(Void result) {
if (adapter != null) {
- adapter.remove(entry);
- adapter.notifyDataSetChanged();
+ adapter.removeItem(entry);
}
Util.toast(context, context.getResources().getString(R.string.bookmark_deleted, entry.getTitle()));
}
@@ -1657,19 +1728,19 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
View layout = context.getLayoutInflater().inflate(R.layout.rating, null);
final RatingBar ratingBar = (RatingBar) layout.findViewById(R.id.rating_bar);
ratingBar.setRating((float) entry.getRating());
-
+
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getResources().getString(R.string.rating_title, entry.getTitle()))
- .setView(layout)
- .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- int rating = (int) ratingBar.getRating();
- setRating(entry, rating, onRatingChange);
- }
- })
- .setNegativeButton(R.string.common_cancel, null);
-
+ .setView(layout)
+ .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ int rating = (int) ratingBar.getRating();
+ setRating(entry, rating, onRatingChange);
+ }
+ })
+ .setNegativeButton(R.string.common_cancel, null);
+
AlertDialog dialog = builder.create();
dialog.show();
}
@@ -1684,7 +1755,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
if(onRatingChange != null) {
onRatingChange.ratingChange(rating);
}
-
+
new SilentBackgroundTask<Void>(context) {
@Override
protected Void doInBackground() throws Throwable {
@@ -1711,7 +1782,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
if(onRatingChange != null) {
onRatingChange.ratingChange(oldRating);
}
-
+
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
@@ -1723,16 +1794,16 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
}.execute();
}
-
+
protected abstract class EntryInstanceUpdater {
private Entry entry;
-
+
public EntryInstanceUpdater(Entry entry) {
this.entry = entry;
}
-
+
public abstract void update(Entry found);
-
+
public void execute() {
DownloadService downloadService = getDownloadService();
if(downloadService != null && !entry.isDirectory()) {
@@ -1745,12 +1816,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
serializeChanges = true;
}
}
-
+
if(serializeChanges) {
downloadService.serializeQueue();
}
}
-
+
Entry find = UpdateView.findEntry(entry);
if(find != null) {
update(find);
@@ -1780,11 +1851,6 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
return;
}
- for (Entry song : parent.getChildren(false, true)) {
- if (!song.isVideo() && song.getRating() != 1) {
- songs.add(song);
- }
- }
for (Entry dir : parent.getChildren(true, false)) {
if(dir.getRating() == 1) {
continue;
@@ -1798,6 +1864,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
getSongsRecursively(musicDirectory, songs);
}
+
+ for (Entry song : parent.getChildren(false, true)) {
+ if (!song.isVideo() && song.getRating() != 1) {
+ songs.add(song);
+ }
+ }
}
@Override
@@ -1810,7 +1882,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
if(result) {
- Util.startActivityWithoutTransition(context, DownloadActivity.class);
+ context.openNowPlaying();
}
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java
index 00c7c603..25196d66 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java
@@ -15,71 +15,30 @@
package github.daneren2005.dsub.fragments;
-import android.app.Activity;
import android.os.Bundle;
-import android.support.v4.widget.SwipeRefreshLayout;
-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.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
+
+import java.util.List;
import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.activity.SubsonicActivity;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.ServerInfo;
import github.daneren2005.dsub.domain.User;
+import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.util.Constants;
-import github.daneren2005.dsub.util.ImageLoader;
+import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.UserUtil;
import github.daneren2005.dsub.adapter.SettingsAdapter;
-public class UserFragment extends SubsonicFragment{
- private ListView listView;
+public class UserFragment extends SelectRecyclerFragment<User.Setting>{
private User user;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false);
-
- refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
- refreshLayout.setEnabled(false);
-
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
Bundle args = getArguments();
user = (User) args.getSerializable(Constants.INTENT_EXTRA_NAME_ID);
-
- listView = (ListView)rootView.findViewById(R.id.fragment_list);
- createHeader();
- listView.setAdapter(new SettingsAdapter(context, user.getSettings(), UserUtil.isCurrentAdmin() && ServerInfo.checkServerVersion(context, "1.10")));
-
- setTitle(user.getUsername());
-
- return rootView;
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- ((SubsonicActivity) activity).supportInvalidateOptionsMenu();
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
- // For some reason this is called before onAttach
- if(!primaryFragment || context == null) {
- return;
- }
-
- if(UserUtil.isCurrentAdmin() && ServerInfo.checkServerVersion(context, "1.10")) {
- menuInflater.inflate(R.menu.user, menu);
- } else if(UserUtil.isCurrentRole(User.SETTINGS)) {
- menuInflater.inflate(R.menu.user_user, menu);
- } else {
- menuInflater.inflate(R.menu.empty, menu);
- }
+ pullToRefresh = false;
}
@Override
@@ -103,23 +62,35 @@ public class UserFragment extends SubsonicFragment{
return false;
}
- private void createHeader() {
- View header = LayoutInflater.from(context).inflate(R.layout.user_header, listView, false);
+ @Override
+ public int getOptionsMenu() {
+ if(UserUtil.isCurrentAdmin() && ServerInfo.checkServerVersion(context, "1.10")) {
+ return R.menu.user;
+ } else if(UserUtil.isCurrentRole(User.SETTINGS)) {
+ return R.menu.user_user;
+ } else {
+ return R.menu.empty;
+ }
+ }
+
+ @Override
+ public SectionAdapter<User.Setting> getAdapter(List<User.Setting> objs) {
+ return new SettingsAdapter(context, user, getImageLoader(), UserUtil.isCurrentAdmin() && ServerInfo.checkServerVersion(context, "1.10"));
+ }
- final ImageLoader imageLoader = getImageLoader();
- ImageView coverArtView = (ImageView) header.findViewById(R.id.user_avatar);
- imageLoader.loadAvatar(context, coverArtView, user.getUsername());
+ @Override
+ public List<User.Setting> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
+ return user.getSettings();
+ }
- TextView usernameView = (TextView) header.findViewById(R.id.user_username);
- usernameView.setText(user.getUsername());
+ @Override
+ public int getTitleResource() {
+ setTitle(user.getUsername());
+ return 0;
+ }
- final TextView emailView = (TextView) header.findViewById(R.id.user_email);
- if(user.getEmail() != null) {
- emailView.setText(user.getEmail());
- } else {
- emailView.setVisibility(View.GONE);
- }
+ @Override
+ public void onItemClicked(User.Setting item) {
- listView.addHeaderView(header);
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java b/app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java
index 444b6cff..7cb3ce8b 100644
--- a/app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java
+++ b/app/src/main/java/github/daneren2005/dsub/provider/DSubWidgetProvider.java
@@ -39,7 +39,6 @@ import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.activity.DownloadActivity;
import github.daneren2005.dsub.activity.SubsonicActivity;
import github.daneren2005.dsub.activity.SubsonicFragmentActivity;
import github.daneren2005.dsub.domain.MusicDirectory;
@@ -270,9 +269,7 @@ public class DSubWidgetProvider extends AppWidgetProvider {
/**
* Link up various button actions using {@link PendingIntent}.
*
- * @param playerActive True if player is active in background, which means
- * widget click will launch {@link DownloadActivity},
- * otherwise we launch {@link github.daneren2005.dsub.activity.SubsonicFragmentActivity}.
+ * @param playerActive @param playerActive True if player is active in background. Launch {@link github.daneren2005.dsub.activity.SubsonicFragmentActivity}.
*/
private void linkButtons(Context context, RemoteViews views, boolean playerActive) {
Intent intent = new Intent(context, SubsonicFragmentActivity.class);
diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
index 9e57f5b0..bf68c450 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
@@ -886,6 +886,9 @@ public class DownloadService extends Service {
public synchronized void play(int index) {
play(index, true);
}
+ public synchronized void play(DownloadFile downloadFile) {
+ play(downloadList.indexOf(downloadFile));
+ }
private synchronized void play(int index, boolean start) {
play(index, start, 0);
}
@@ -1818,6 +1821,10 @@ public class DownloadService extends Service {
applyReplayGain(mediaPlayer, currentPlaying);
}
+ public synchronized void swap(boolean mainList, DownloadFile from, DownloadFile to) {
+ List<DownloadFile> list = mainList ? downloadList : backgroundDownloadList;
+ swap(mainList, list.indexOf(from), list.indexOf(to));
+ }
public synchronized void swap(boolean mainList, int from, int to) {
List<DownloadFile> list = mainList ? downloadList : backgroundDownloadList;
int max = list.size();
diff --git a/app/src/main/java/github/daneren2005/dsub/service/parser/PlaylistsParser.java b/app/src/main/java/github/daneren2005/dsub/service/parser/PlaylistsParser.java
index 6f01d510..69e5af64 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/parser/PlaylistsParser.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/parser/PlaylistsParser.java
@@ -22,7 +22,6 @@ import android.content.Context;
import github.daneren2005.dsub.domain.Playlist;
import github.daneren2005.dsub.util.ProgressListener;
-import github.daneren2005.dsub.adapter.PlaylistAdapter;
import org.xmlpull.v1.XmlPullParser;
import java.io.Reader;
@@ -64,7 +63,7 @@ public class PlaylistsParser extends AbstractParser {
validate();
- return PlaylistAdapter.PlaylistComparator.sort(result);
+ return Playlist.PlaylistComparator.sort(result);
}
} \ No newline at end of file
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Constants.java b/app/src/main/java/github/daneren2005/dsub/util/Constants.java
index 05481bf0..6252d0e4 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Constants.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Constants.java
@@ -172,6 +172,7 @@ public final class Constants {
public static final String MAIN_BACK_STACK = "backStackIds";
public static final String MAIN_BACK_STACK_SIZE = "backStackIdsSize";
+ public static final String MAIN_NOW_PLAYING = "nowPlayingId";
public static final String FRAGMENT_LIST = "fragmentList";
public static final String FRAGMENT_LIST2 = "fragmentList2";
public static final String FRAGMENT_EXTRA = "fragmentExtra";
diff --git a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java
index 7ba2064b..a770fbb1 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java
@@ -190,8 +190,11 @@ public class ImageLoader {
}
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, boolean crossfade) {
- // TODO: If we know this a artist, try to load artist info instead
int size = large ? imageSizeLarge : imageSizeDefault;
+ return loadImage(view, entry, large, size, crossfade);
+ }
+ public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) {
+ // TODO: If we know this a artist, try to load artist info instead
if(entry != null && !entry.isAlbum() && ServerInfo.checkServerVersion(context, "1.11") && !Util.isOffline(context)) {
SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade);
task.execute();
@@ -274,12 +277,18 @@ 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);
view.setImageDrawable(drawable);
return null;
}
+ view.setImageDrawable(null);
SilentBackgroundTask<Void> task = new AvatarTask(context, view, username);
task.execute();
@@ -582,7 +591,6 @@ public class ImageLoader {
}
} catch (Throwable x) {
Log.e(TAG, "Failed to download album art.", x);
- cancelled.set(true);
}
return null;
@@ -592,6 +600,8 @@ public class ImageLoader {
protected void done(Void result) {
if(mDrawable != null) {
mView.setImageDrawable(mDrawable);
+ } else {
+ mView.setImageResource(R.drawable.ic_social_person);
}
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/util/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/UserUtil.java b/app/src/main/java/github/daneren2005/dsub/util/UserUtil.java
index 29618424..d758c4c9 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/UserUtil.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/UserUtil.java
@@ -16,18 +16,22 @@
package github.daneren2005.dsub.util;
import android.app.Activity;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.support.v7.app.ActionBarActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
+import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.User;
import github.daneren2005.dsub.fragments.SubsonicFragment;
import github.daneren2005.dsub.service.DownloadService;
@@ -182,6 +186,7 @@ public final class UserUtil {
.setCancelable(true);
AlertDialog dialog = builder.create();
+ dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
dialog.show();
}
}
@@ -247,7 +252,6 @@ public final class UserUtil {
protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(context);
musicService.updateUser(user, context, null);
- user.setSettings(user.getSettings());
return null;
}
@@ -326,7 +330,7 @@ public final class UserUtil {
});
}
- public static void deleteUser(final Context context, final User user, final ArrayAdapter adapter) {
+ public static void deleteUser(final Context context, final User user, final SectionAdapter adapter) {
Util.confirmDialog(context, R.string.common_delete, user.getUsername(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
@@ -341,8 +345,7 @@ public final class UserUtil {
@Override
protected void done(Void v) {
if(adapter != null) {
- adapter.remove(user);
- adapter.notifyDataSetChanged();
+ adapter.removeItem(user);
}
Util.toast(context, context.getResources().getString(R.string.admin_delete_user_success, user.getUsername()));
@@ -378,8 +381,11 @@ public final class UserUtil {
final TextView usernameView = (TextView) layout.findViewById(R.id.username);
final TextView emailView = (TextView) layout.findViewById(R.id.email);
final TextView passwordView = (TextView) layout.findViewById(R.id.password);
- final ListView listView = (ListView) layout.findViewById(R.id.settings_list);
- listView.setAdapter(new SettingsAdapter(context, user, true));
+ final RecyclerView recyclerView = (RecyclerView) layout.findViewById(R.id.settings_list);
+ LinearLayoutManager layoutManager = new LinearLayoutManager(context);
+ layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
+ recyclerView.setLayoutManager(layoutManager);
+ recyclerView.setAdapter(new SettingsAdapter(context, user, null, true));
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.menu_add_user)
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Util.java b/app/src/main/java/github/daneren2005/dsub/util/Util.java
index 032facd6..f44bc672 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Util.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Util.java
@@ -19,7 +19,7 @@ package github.daneren2005.dsub.util;
import android.annotation.TargetApi;
import android.app.Activity;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
@@ -48,6 +48,8 @@ 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;
import github.daneren2005.dsub.domain.RepeatMode;
@@ -249,6 +251,32 @@ public final class Util {
SharedPreferences prefs = getPreferences(context);
return prefs.getString(Constants.PREFERENCES_KEY_THEME, null);
}
+ public static int getThemeRes(Context context) {
+ return getThemeRes(context, getTheme(context));
+ }
+ public static int getThemeRes(Context context, String theme) {
+ if(context instanceof SubsonicFragmentActivity || context instanceof SettingsActivity) {
+ if ("dark".equals(theme)) {
+ return R.style.Theme_DSub_Dark_No_Actionbar;
+ } else if ("black".equals(theme)) {
+ return R.style.Theme_DSub_Black_No_Actionbar;
+ } else if ("holo".equals(theme)) {
+ return R.style.Theme_DSub_Holo_No_Actionbar;
+ } else {
+ return R.style.Theme_DSub_Light_No_Actionbar;
+ }
+ } else {
+ if ("dark".equals(theme)) {
+ return R.style.Theme_DSub_Dark;
+ } else if ("black".equals(theme)) {
+ return R.style.Theme_DSub_Black;
+ } else if ("holo".equals(theme)) {
+ return R.style.Theme_DSub_Holo;
+ } else {
+ return R.style.Theme_DSub_Light;
+ }
+ }
+ }
public static void setTheme(Context context, String theme) {
SharedPreferences.Editor editor = getPreferences(context).edit();
editor.putString(Constants.PREFERENCES_KEY_THEME, theme);
@@ -256,15 +284,7 @@ public final class Util {
}
public static void applyTheme(Context context, String theme) {
- if ("dark".equals(theme)) {
- context.setTheme(R.style.Theme_DSub_Dark);
- } else if ("black".equals(theme)) {
- context.setTheme(R.style.Theme_DSub_Black);
- } else if ("holo".equals(theme)) {
- context.setTheme(R.style.Theme_DSub_Holo);
- } else {
- context.setTheme(R.style.Theme_DSub_Light);
- }
+ context.setTheme(getThemeRes(context, theme));
SharedPreferences prefs = Util.getPreferences(context);
if(prefs.getBoolean(Constants.PREFERENCES_KEY_OVERRIDE_SYSTEM_LANGUAGE, false)) {
diff --git a/app/src/main/java/github/daneren2005/dsub/view/AlbumCell.java b/app/src/main/java/github/daneren2005/dsub/view/AlbumCell.java
deleted file mode 100644
index 8707ece7..00000000
--- a/app/src/main/java/github/daneren2005/dsub/view/AlbumCell.java
+++ /dev/null
@@ -1,108 +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 2014 (C) Scott Jackson
-*/
-
-package github.daneren2005.dsub.view;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.RatingBar;
-import android.widget.TextView;
-
-import java.io.File;
-
-import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.domain.MusicDirectory;
-import github.daneren2005.dsub.util.FileUtil;
-import github.daneren2005.dsub.util.ImageLoader;
-
-public class AlbumCell extends UpdateView {
- private static final String TAG = AlbumCell.class.getSimpleName();
-
- private Context context;
- private MusicDirectory.Entry album;
- private File file;
-
- private View coverArtView;
- private TextView titleView;
- private TextView artistView;
- private boolean showArtist = true;
-
- public AlbumCell(Context context) {
- super(context);
- this.context = context;
- LayoutInflater.from(context).inflate(R.layout.album_cell_item, this, true);
-
- coverArtView = findViewById(R.id.album_coverart);
- titleView = (TextView) findViewById(R.id.album_title);
- artistView = (TextView) findViewById(R.id.album_artist);
-
- ratingBar = (RatingBar) findViewById(R.id.album_rating);
- ratingBar.setFocusable(false);
- starButton = (ImageButton) findViewById(R.id.album_star);
- starButton.setFocusable(false);
- moreButton = (ImageView) findViewById(R.id.album_more);
- moreButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- v.showContextMenu();
- }
- });
- }
-
- public void setShowArtist(boolean showArtist) {
- this.showArtist = showArtist;
- }
-
- protected void setObjectImpl(Object obj1, Object obj2) {
- this.album = (MusicDirectory.Entry) obj1;
- titleView.setText(album.getAlbumDisplay());
- String artist = "";
- if(showArtist) {
- artist = album.getArtist();
- if (artist == null) {
- artist = "";
- }
- if (album.getYear() != null) {
- artist += " - " + album.getYear();
- }
- } else if(album.getYear() != null) {
- artist += album.getYear();
- }
- artistView.setText(album.getArtist() == null ? "" : artist);
- imageTask = ((ImageLoader)obj2).loadImage(coverArtView, album, false, true);
- file = null;
- }
-
- @Override
- protected void updateBackground() {
- if(file == null) {
- file = FileUtil.getAlbumDirectory(context, album);
- }
-
- exists = file.exists();
- isStarred = album.isStarred();
- isRated = album.getRating();
- }
-
- public MusicDirectory.Entry getEntry() {
- return album;
- }
-
- public File getFile() {
- return file;
- }
-}
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..a1b14f61
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/view/AlbumListCountView.java
@@ -0,0 +1,130 @@
+/*
+ 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 UpdateView2<Integer, Void> {
+ private final String TAG = AlbumListCountView.class.getSimpleName();
+
+ private TextView titleView;
+ private TextView countView;
+ 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(Integer albumListString, Void dummy) {
+ 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/AlbumView.java b/app/src/main/java/github/daneren2005/dsub/view/AlbumView.java
index bd54ea1e..3104864a 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/AlbumView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/AlbumView.java
@@ -16,10 +16,10 @@
Copyright 2009 (C) Sindre Mehus
*/
+
package github.daneren2005.dsub.view;
import android.content.Context;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
@@ -30,75 +30,74 @@ import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.util.FileUtil;
import github.daneren2005.dsub.util.ImageLoader;
-import github.daneren2005.dsub.util.Util;
+
import java.io.File;
-import java.util.List;
-/**
- * Used to display albums in a {@code ListView}.
- *
- * @author Sindre Mehus
- */
-public class AlbumView extends UpdateView {
+public class AlbumView extends UpdateView2<MusicDirectory.Entry, ImageLoader> {
private static final String TAG = AlbumView.class.getSimpleName();
- private Context context;
- private MusicDirectory.Entry album;
private File file;
-
+ private View coverArtView;
private TextView titleView;
private TextView artistView;
- private View coverArtView;
+ private boolean showArtist = true;
- public AlbumView(Context context) {
+ public AlbumView(Context context, boolean cell) {
super(context);
- this.context = context;
- LayoutInflater.from(context).inflate(R.layout.album_list_item, this, true);
+ if(cell) {
+ LayoutInflater.from(context).inflate(R.layout.album_cell_item, this, true);
+ } else {
+ LayoutInflater.from(context).inflate(R.layout.album_list_item, this, true);
+ }
+
+ coverArtView = findViewById(R.id.album_coverart);
titleView = (TextView) findViewById(R.id.album_title);
artistView = (TextView) findViewById(R.id.album_artist);
- coverArtView = findViewById(R.id.album_coverart);
+
ratingBar = (RatingBar) findViewById(R.id.album_rating);
+ ratingBar.setFocusable(false);
starButton = (ImageButton) findViewById(R.id.album_star);
starButton.setFocusable(false);
+ moreButton = (ImageView) findViewById(R.id.more_button);
+ }
- moreButton = (ImageView) findViewById(R.id.album_more);
- moreButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- v.showContextMenu();
- }
- });
+ public void setShowArtist(boolean showArtist) {
+ this.showArtist = showArtist;
}
- protected void setObjectImpl(Object obj1, Object obj2) {
- this.album = (MusicDirectory.Entry) obj1;
+ protected void setObjectImpl(MusicDirectory.Entry album, ImageLoader imageLoader) {
titleView.setText(album.getAlbumDisplay());
- String artist = album.getArtist();
- if(artist == null) {
- artist = "";
- }
- if(album.getYear() != null) {
- artist += " - " + album.getYear();
+ String artist = "";
+ if(showArtist) {
+ artist = album.getArtist();
+ if (artist == null) {
+ artist = "";
+ }
+ if (album.getYear() != null) {
+ artist += " - " + album.getYear();
+ }
+ } else if(album.getYear() != null) {
+ artist += album.getYear();
}
- artistView.setText(artist);
- artistView.setVisibility(album.getArtist() == null ? View.GONE : View.VISIBLE);
- imageTask = ((ImageLoader)obj2).loadImage(coverArtView, album, false, true);
+ artistView.setText(album.getArtist() == null ? "" : artist);
+ imageTask = imageLoader.loadImage(coverArtView, album, false, true);
file = null;
}
@Override
protected void updateBackground() {
if(file == null) {
- file = FileUtil.getAlbumDirectory(context, album);
+ file = FileUtil.getAlbumDirectory(context, item);
}
exists = file.exists();
- isStarred = album.isStarred();
- isRated = album.getRating();
+ isStarred = item.isStarred();
+ isRated = item.getRating();
}
public MusicDirectory.Entry getEntry() {
- return album;
+ return item;
}
public File getFile() {
diff --git a/app/src/main/java/github/daneren2005/dsub/view/ArtistEntryView.java b/app/src/main/java/github/daneren2005/dsub/view/ArtistEntryView.java
index 71bdeb78..f6a6adb3 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/ArtistEntryView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/ArtistEntryView.java
@@ -19,7 +19,6 @@
package github.daneren2005.dsub.view;
import android.content.Context;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
@@ -28,26 +27,21 @@ import android.widget.TextView;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.util.FileUtil;
-import github.daneren2005.dsub.util.ImageLoader;
-import github.daneren2005.dsub.util.Util;
+
import java.io.File;
/**
* Used to display albums in a {@code ListView}.
*
* @author Sindre Mehus
*/
-public class ArtistEntryView extends UpdateView {
+public class ArtistEntryView extends UpdateView<MusicDirectory.Entry> {
private static final String TAG = ArtistEntryView.class.getSimpleName();
- private Context context;
- private MusicDirectory.Entry artist;
private File file;
-
private TextView titleView;
public ArtistEntryView(Context context) {
super(context);
- this.context = context;
LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
titleView = (TextView) findViewById(R.id.item_name);
@@ -61,8 +55,7 @@ public class ArtistEntryView extends UpdateView {
});
}
- protected void setObjectImpl(Object obj) {
- this.artist = (MusicDirectory.Entry) obj;
+ protected void setObjectImpl(MusicDirectory.Entry artist) {
titleView.setText(artist.getTitle());
file = FileUtil.getArtistDirectory(context, artist);
}
@@ -70,7 +63,7 @@ public class ArtistEntryView extends UpdateView {
@Override
protected void updateBackground() {
exists = file.exists();
- isStarred = artist.isStarred();
+ isStarred = item.isStarred();
}
public File getFile() {
diff --git a/app/src/main/java/github/daneren2005/dsub/view/ArtistView.java b/app/src/main/java/github/daneren2005/dsub/view/ArtistView.java
index c255be69..d86c5d26 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/ArtistView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/ArtistView.java
@@ -35,18 +35,14 @@ import java.io.File;
*
* @author Sindre Mehus
*/
-public class ArtistView extends UpdateView {
+public class ArtistView extends UpdateView<Artist> {
private static final String TAG = ArtistView.class.getSimpleName();
-
- private Context context;
- private Artist artist;
- private File file;
+ private File file;
private TextView titleView;
public ArtistView(Context context) {
super(context);
- this.context = context;
LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
titleView = (TextView) findViewById(R.id.item_name);
@@ -60,8 +56,7 @@ public class ArtistView extends UpdateView {
});
}
- protected void setObjectImpl(Object obj) {
- this.artist = (Artist) obj;
+ protected void setObjectImpl(Artist artist) {
titleView.setText(artist.getName());
file = FileUtil.getArtistDirectory(context, artist);
}
@@ -69,7 +64,7 @@ public class ArtistView extends UpdateView {
@Override
protected void updateBackground() {
exists = file.exists();
- isStarred = artist.isStarred();
+ isStarred = item.isStarred();
}
public File getFile() {
diff --git a/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java b/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java
new file mode 100644
index 00000000..01aa42e1
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java
@@ -0,0 +1,40 @@
+/*
+ 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.view.LayoutInflater;
+import android.widget.TextView;
+
+import github.daneren2005.dsub.R;
+
+public class BasicHeaderView extends UpdateView<String> {
+ 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(layout, this, true);
+ nameView = (TextView) findViewById(R.id.item_name);
+ }
+
+ protected void setObjectImpl(String string) {
+ nameView.setText(string);
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/BasicListView.java b/app/src/main/java/github/daneren2005/dsub/view/BasicListView.java
new file mode 100644
index 00000000..ca7e8993
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/view/BasicListView.java
@@ -0,0 +1,44 @@
+/*
+ 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.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import github.daneren2005.dsub.R;
+
+public class BasicListView extends UpdateView<String> {
+ private TextView titleView;
+
+ public BasicListView(Context context) {
+ super(context, false);
+ LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
+
+ titleView = (TextView) findViewById(R.id.item_name);
+ starButton = (ImageButton) findViewById(R.id.item_star);
+ starButton.setFocusable(false);
+ moreButton = (ImageView) findViewById(R.id.item_more);
+ moreButton.setVisibility(View.GONE);
+ }
+
+ protected void setObjectImpl(String string) {
+ titleView.setText(string);
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/ChangeLog.java b/app/src/main/java/github/daneren2005/dsub/view/ChangeLog.java
index 096583c7..e3d24485 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/ChangeLog.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/ChangeLog.java
@@ -42,7 +42,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
diff --git a/app/src/main/java/github/daneren2005/dsub/view/ErrorDialog.java b/app/src/main/java/github/daneren2005/dsub/view/ErrorDialog.java
index 0b9d05a0..3d6eaa52 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/ErrorDialog.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/ErrorDialog.java
@@ -19,7 +19,7 @@
package github.daneren2005.dsub.view;
import android.app.Activity;
-import android.app.AlertDialog;
+import android.support.v7.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
diff --git a/app/src/main/java/github/daneren2005/dsub/view/GenreView.java b/app/src/main/java/github/daneren2005/dsub/view/GenreView.java
index 8dbcf89d..b29aefba 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/GenreView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/GenreView.java
@@ -25,7 +25,7 @@ import android.widget.TextView;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.Genre;
-public class GenreView extends UpdateView {
+public class GenreView extends UpdateView<Genre> {
private static final String TAG = GenreView.class.getSimpleName();
private TextView titleView;
@@ -41,8 +41,7 @@ public class GenreView extends UpdateView {
albumsView = (TextView) findViewById(R.id.genre_albums);
}
- public void setObjectImpl(Object obj) {
- Genre genre = (Genre) obj;
+ public void setObjectImpl(Genre genre) {
titleView.setText(genre.getName());
if(genre.getAlbumCount() != null) {
diff --git a/app/src/main/java/github/daneren2005/dsub/view/GridSpacingDecoration.java b/app/src/main/java/github/daneren2005/dsub/view/GridSpacingDecoration.java
new file mode 100644
index 00000000..3bb3e8a1
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/view/GridSpacingDecoration.java
@@ -0,0 +1,99 @@
+/*
+ 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.graphics.Rect;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+import android.view.View;
+
+public class GridSpacingDecoration extends RecyclerView.ItemDecoration {
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+
+ int spacing = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, view.getResources().getDisplayMetrics());
+ int halfSpacing = spacing / 2;
+
+ int childCount = parent.getChildCount();
+ int childIndex = parent.getChildPosition(view);
+ int spanCount = getTotalSpan(view, parent);
+ int spanIndex = childIndex % spanCount;
+ int spanSize = getSpanSize(parent, childIndex);
+
+ /* INVALID SPAN */
+ if (spanCount < 1 || spanSize > 1) return;
+
+ outRect.top = halfSpacing;
+ outRect.bottom = halfSpacing;
+ outRect.left = halfSpacing;
+ outRect.right = halfSpacing;
+
+ if (isTopEdge(childIndex, spanCount)) {
+ outRect.top = spacing;
+ }
+
+ if (isLeftEdge(spanIndex, spanCount)) {
+ outRect.left = spacing;
+ }
+
+ if (isRightEdge(spanIndex, spanCount)) {
+ outRect.right = spacing;
+ }
+
+ if (isBottomEdge(childIndex, childCount, spanCount)) {
+ outRect.bottom = spacing;
+ }
+ }
+
+ protected int getTotalSpan(View view, RecyclerView parent) {
+ RecyclerView.LayoutManager mgr = parent.getLayoutManager();
+ if (mgr instanceof GridLayoutManager) {
+ return ((GridLayoutManager) mgr).getSpanCount();
+ }
+
+ return -1;
+ }
+ protected int getSpanSize(RecyclerView parent, int childIndex) {
+ RecyclerView.LayoutManager mgr = parent.getLayoutManager();
+ if (mgr instanceof GridLayoutManager) {
+ GridLayoutManager.SpanSizeLookup lookup = ((GridLayoutManager) mgr).getSpanSizeLookup();
+ if(lookup != null) {
+ return lookup.getSpanSize(childIndex);
+ }
+ }
+
+ return 1;
+ }
+
+ protected boolean isLeftEdge(int spanIndex, int spanCount) {
+ return spanIndex == 0;
+ }
+
+ protected boolean isRightEdge(int spanIndex, int spanCount) {
+ return spanIndex == spanCount - 1;
+ }
+
+ protected boolean isTopEdge(int childIndex, int spanCount) {
+ return childIndex < spanCount;
+ }
+
+ protected boolean isBottomEdge(int childIndex, int childCount, int spanCount) {
+ return childIndex >= childCount - spanCount;
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/HeaderGridView.java b/app/src/main/java/github/daneren2005/dsub/view/HeaderGridView.java
deleted file mode 100644
index 8a82f353..00000000
--- a/app/src/main/java/github/daneren2005/dsub/view/HeaderGridView.java
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * 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.view;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.database.DataSetObservable;
-import android.database.DataSetObserver;
-import android.os.Build;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.*;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-
-/**
- * A {@link GridView} that supports adding header rows in a
- * very similar way to {@link android.widget.ListView}.
- * See {@link HeaderGridView#addHeaderView(View, Object, boolean)}
- * See {@link HeaderGridView#addFooterView(View, Object, boolean)}
- */
-public class HeaderGridView extends GridView {
- private static final String TAG = HeaderGridView.class.getSimpleName();
- public static boolean DEBUG = false;
-
- /**
- * A class that represents a fixed view in a list, for example a header at the top
- * or a footer at the bottom.
- */
- private static class FixedViewInfo {
- /**
- * The view to add to the grid
- */
- public View view;
- public ViewGroup viewContainer;
- /**
- * The data backing the view. This is returned from {@link ListAdapter#getItem(int)}.
- */
- public Object data;
- /**
- * <code>true</code> if the fixed view should be selectable in the grid
- */
- public boolean isSelectable;
- }
-
- private int mNumColumns = AUTO_FIT;
- private View mViewForMeasureRowHeight = null;
- private int mRowHeight = -1;
- private static final String LOG_TAG = HeaderGridView.class.getSimpleName();
-
- private ArrayList<FixedViewInfo> mHeaderViewInfos = new ArrayList<FixedViewInfo>();
- private ArrayList<FixedViewInfo> mFooterViewInfos = new ArrayList<FixedViewInfo>();
-
- private void initHeaderGridView() {
- }
-
- public HeaderGridView(Context context) {
- super(context);
- initHeaderGridView();
- }
-
- public HeaderGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initHeaderGridView();
- }
-
- public HeaderGridView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initHeaderGridView();
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- ListAdapter adapter = getAdapter();
- if (adapter != null && adapter instanceof HeaderViewGridAdapter) {
- ((HeaderViewGridAdapter) adapter).setNumColumns(getNumColumnsCompatible());
- ((HeaderViewGridAdapter) adapter).setRowHeight(getRowHeight());
- }
- }
-
- @Override
- public void setClipChildren(boolean clipChildren) {
- // Ignore, since the header rows depend on not being clipped
- }
-
- /**
- * Do not call this method unless you know how it works.
- *
- * @param clipChildren
- */
- public void setClipChildrenSupper(boolean clipChildren) {
- super.setClipChildren(false);
- }
-
- /**
- * Add a fixed view to appear at the top of the grid. If addHeaderView is
- * called more than once, the views will appear in the order they were
- * added. Views added using this call can take focus if they want.
- * <p/>
- * NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap
- * the supplied cursor with one that will also account for header views.
- *
- * @param v The view to add.
- */
- public void addHeaderView(View v) {
- addHeaderView(v, null, true);
- }
-
- /**
- * Add a fixed view to appear at the top of the grid. If addHeaderView is
- * called more than once, the views will appear in the order they were
- * added. Views added using this call can take focus if they want.
- * <p/>
- * NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap
- * the supplied cursor with one that will also account for header views.
- *
- * @param v The view to add.
- * @param data Data to associate with this view
- * @param isSelectable whether the item is selectable
- */
- public void addHeaderView(View v, Object data, boolean isSelectable) {
- ListAdapter adapter = getAdapter();
- if (adapter != null && !(adapter instanceof HeaderViewGridAdapter)) {
- throw new IllegalStateException(
- "Cannot add header view to grid -- setAdapter has already been called.");
- }
-
- ViewGroup.LayoutParams lyp = v.getLayoutParams();
-
- FixedViewInfo info = new FixedViewInfo();
- FrameLayout fl = new FullWidthFixedViewLayout(getContext());
-
- if (lyp != null) {
- v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
- fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
- }
- fl.addView(v);
- info.view = v;
- info.viewContainer = fl;
- info.data = data;
- info.isSelectable = isSelectable;
- mHeaderViewInfos.add(info);
- // in the case of re-adding a header view, or adding one later on,
- // we need to notify the observer
- if (adapter != null) {
- ((HeaderViewGridAdapter) adapter).notifyDataSetChanged();
- }
- }
-
- public void addFooterView(View v) {
- addFooterView(v, null, true);
- }
-
- public void addFooterView(View v, Object data, boolean isSelectable) {
- ListAdapter mAdapter = getAdapter();
- if (mAdapter != null && !(mAdapter instanceof HeaderViewGridAdapter)) {
- throw new IllegalStateException(
- "Cannot add header view to grid -- setAdapter has already been called.");
- }
-
- ViewGroup.LayoutParams lyp = v.getLayoutParams();
-
- FixedViewInfo info = new FixedViewInfo();
- FrameLayout fl = new FullWidthFixedViewLayout(getContext());
-
- if (lyp != null) {
- v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
- fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
- }
- fl.addView(v);
- info.view = v;
- info.viewContainer = fl;
- info.data = data;
- info.isSelectable = isSelectable;
- mFooterViewInfos.add(info);
-
- if (mAdapter != null) {
- ((HeaderViewGridAdapter) mAdapter).notifyDataSetChanged();
- }
- }
-
- public int getHeaderViewCount() {
- return mHeaderViewInfos.size();
- }
-
- public int getFooterViewCount() {
- return mFooterViewInfos.size();
- }
-
- /**
- * Removes a previously-added header view.
- *
- * @param v The view to remove
- * @return true if the view was removed, false if the view was not a header
- * view
- */
- public boolean removeHeaderView(View v) {
- if (mHeaderViewInfos.size() > 0) {
- boolean result = false;
- ListAdapter adapter = getAdapter();
- if (adapter != null && ((HeaderViewGridAdapter) adapter).removeHeader(v)) {
- result = true;
- }
- removeFixedViewInfo(v, mHeaderViewInfos);
- return result;
- }
- return false;
- }
-
- /**
- * Removes a previously-added footer view.
- *
- * @param v The view to remove
- * @return true if the view was removed, false if the view was not a header
- * view
- */
- public boolean removeFooterView(View v) {
- if (mFooterViewInfos.size() > 0) {
- boolean result = false;
- ListAdapter adapter = getAdapter();
- if (adapter != null && ((HeaderViewGridAdapter) adapter).removeFooter(v)) {
- result = true;
- }
- removeFixedViewInfo(v, mFooterViewInfos);
- return result;
- }
- return false;
- }
-
- private void removeFixedViewInfo(View v, ArrayList<FixedViewInfo> where) {
- int len = where.size();
- for (int i = 0; i < len; ++i) {
- FixedViewInfo info = where.get(i);
- if (info.view == v) {
- where.remove(i);
- break;
- }
- }
- }
-
- @TargetApi(11)
- private int getNumColumnsCompatible() {
- if (Build.VERSION.SDK_INT >= 11) {
- return super.getNumColumns();
- } else {
- try {
- Field numColumns = GridView.class.getSuperclass().getDeclaredField("mNumColumns");
- numColumns.setAccessible(true);
- return numColumns.getInt(this);
- } catch (Exception e) {
- if (mNumColumns != -1) {
- return mNumColumns;
- } else {
- return 2;
- }
- }
- }
- }
-
- @TargetApi(16)
- private int getColumnWidthCompatible() {
- if (Build.VERSION.SDK_INT >= 16) {
- return super.getColumnWidth();
- } else {
- try {
- Field numColumns = getClass().getSuperclass().getDeclaredField("mColumnWidth");
- numColumns.setAccessible(true);
- return numColumns.getInt(this);
- } catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mViewForMeasureRowHeight = null;
- }
-
- public void invalidateRowHeight() {
- mRowHeight = -1;
- }
-
- public int getHeaderHeight(int row) {
- if (row >= 0) {
- return mHeaderViewInfos.get(row).view.getMeasuredHeight();
- }
-
- return 0;
- }
-
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- public int getVerticalSpacing(){
- int value = 0;
-
- try {
- int currentapiVersion = android.os.Build.VERSION.SDK_INT;
- if (currentapiVersion < Build.VERSION_CODES.JELLY_BEAN){
- Field field = this.getClass().getSuperclass().getDeclaredField("mVerticalSpacing");
- field.setAccessible(true);
- value = field.getInt(this);
- } else{
- value = super.getVerticalSpacing();
- }
-
- }catch (Exception ex){
-
- }
-
- return value;
- }
-
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- public int getHorizontalSpacing(){
- int value = 0;
-
- try {
- int currentapiVersion = android.os.Build.VERSION.SDK_INT;
- if (currentapiVersion < Build.VERSION_CODES.JELLY_BEAN){
- Field field = this.getClass().getSuperclass().getDeclaredField("mHorizontalSpacing");
- field.setAccessible(true);
- value = field.getInt(this);
- } else{
- value = super.getHorizontalSpacing();
- }
-
- }catch (Exception ex){
-
- }
-
- return value;
- }
-
- public int getRowHeight() {
- if (mRowHeight > 0) {
- // return mRowHeight;
- }
- ListAdapter adapter = getAdapter();
- int numColumns = getNumColumnsCompatible();
-
- // adapter has not been set or has no views in it;
- if (adapter == null || adapter.getCount() <= numColumns * (mHeaderViewInfos.size() + mFooterViewInfos.size()) || numColumns == -1) {
- return -1;
- }
- int mColumnWidth = getColumnWidthCompatible();
- View view = getAdapter().getView(numColumns * mHeaderViewInfos.size(), mViewForMeasureRowHeight, this);
- AbsListView.LayoutParams p = (AbsListView.LayoutParams) view.getLayoutParams();
- if (p == null) {
- p = new AbsListView.LayoutParams(-1, -2, 0);
- view.setLayoutParams(p);
- }
- int childHeightSpec = getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
- int childWidthSpec = getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
- view.measure(childWidthSpec, childHeightSpec);
- mViewForMeasureRowHeight = view;
- mRowHeight = view.getMeasuredHeight();
- return mRowHeight;
- }
-
- @TargetApi(11)
- public void tryToScrollToBottomSmoothly() {
- int lastPos = getAdapter().getCount() - 1;
- if (Build.VERSION.SDK_INT >= 11) {
- smoothScrollToPositionFromTop(lastPos, 0);
- } else {
- setSelection(lastPos);
- }
- }
-
- @TargetApi(11)
- public void tryToScrollToBottomSmoothly(int duration) {
- int lastPos = getAdapter().getCount() - 1;
- if (Build.VERSION.SDK_INT >= 11) {
- smoothScrollToPositionFromTop(lastPos, 0, duration);
- } else {
- setSelection(lastPos);
- }
- }
-
- @Override
- public void setAdapter(ListAdapter adapter) {
- if (mHeaderViewInfos.size() > 0 || mFooterViewInfos.size() > 0) {
- HeaderViewGridAdapter headerViewGridAdapter = new HeaderViewGridAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
- int numColumns = getNumColumnsCompatible();
- if (numColumns > 1) {
- headerViewGridAdapter.setNumColumns(numColumns);
- }
- headerViewGridAdapter.setRowHeight(getRowHeight());
- super.setAdapter(headerViewGridAdapter);
- } else {
- super.setAdapter(adapter);
- }
- }
-
- /**
- * full width
- */
- private class FullWidthFixedViewLayout extends FrameLayout {
-
- public FullWidthFixedViewLayout(Context context) {
- super(context);
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- int realLeft = HeaderGridView.this.getPaddingLeft() + getPaddingLeft();
- // Try to make where it should be, from left, full width
- if (realLeft != left) {
- offsetLeftAndRight(realLeft - left);
- }
- super.onLayout(changed, left, top, right, bottom);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int targetWidth = HeaderGridView.this.getMeasuredWidth()
- - HeaderGridView.this.getPaddingLeft()
- - HeaderGridView.this.getPaddingRight();
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(targetWidth,
- MeasureSpec.getMode(widthMeasureSpec));
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- }
-
- @Override
- public void setNumColumns(int numColumns) {
- super.setNumColumns(numColumns);
- mNumColumns = numColumns;
- ListAdapter adapter = getAdapter();
- if (adapter != null && adapter instanceof HeaderViewGridAdapter) {
- ((HeaderViewGridAdapter) adapter).setNumColumns(numColumns);
- }
- }
-
- /**
- * ListAdapter used when a HeaderGridView has header views. This ListAdapter
- * wraps another one and also keeps track of the header views and their
- * associated data objects.
- * <p>This is intended as a base class; you will probably not need to
- * use this class directly in your own code.
- */
- private static class HeaderViewGridAdapter extends BaseAdapter implements WrapperListAdapter, Filterable {
- // This is used to notify the container of updates relating to number of columns
- // or headers changing, which changes the number of placeholders needed
- private final DataSetObservable mDataSetObservable = new DataSetObservable();
- private final ListAdapter mAdapter;
- static final ArrayList<FixedViewInfo> EMPTY_INFO_LIST =
- new ArrayList<FixedViewInfo>();
-
- // This ArrayList is assumed to NOT be null.
- ArrayList<FixedViewInfo> mHeaderViewInfos;
- ArrayList<FixedViewInfo> mFooterViewInfos;
- private int mNumColumns = 1;
- private int mRowHeight = -1;
- boolean mAreAllFixedViewsSelectable;
- private final boolean mIsFilterable;
- private boolean mCachePlaceHoldView = true;
- // From Recycle Bin or calling getView, this a question...
- private boolean mCacheFirstHeaderView = false;
-
- public HeaderViewGridAdapter(ArrayList<FixedViewInfo> headerViewInfos, ArrayList<FixedViewInfo> footViewInfos, ListAdapter adapter) {
- mAdapter = adapter;
- mIsFilterable = adapter instanceof Filterable;
- if (headerViewInfos == null) {
- mHeaderViewInfos = EMPTY_INFO_LIST;
- } else {
- mHeaderViewInfos = headerViewInfos;
- }
-
- if (footViewInfos == null) {
- mFooterViewInfos = EMPTY_INFO_LIST;
- } else {
- mFooterViewInfos = footViewInfos;
- }
- mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos)
- && areAllListInfosSelectable(mFooterViewInfos);
- }
-
- public void setNumColumns(int numColumns) {
- if (numColumns < 1) {
- return;
- }
- if (mNumColumns != numColumns) {
- mNumColumns = numColumns;
- notifyDataSetChanged();
- }
- }
-
- public void setRowHeight(int height) {
- mRowHeight = height;
- }
-
- public int getHeadersCount() {
- return mHeaderViewInfos.size();
- }
-
- public int getFootersCount() {
- return mFooterViewInfos.size();
- }
-
- @Override
- public boolean isEmpty() {
- return (mAdapter == null || mAdapter.isEmpty()) && getHeadersCount() == 0 && getFootersCount() == 0;
- }
-
- private boolean areAllListInfosSelectable(ArrayList<FixedViewInfo> infos) {
- if (infos != null) {
- for (FixedViewInfo info : infos) {
- if (!info.isSelectable) {
- return false;
- }
- }
- }
- return true;
- }
-
- public boolean removeHeader(View v) {
- for (int i = 0; i < mHeaderViewInfos.size(); i++) {
- FixedViewInfo info = mHeaderViewInfos.get(i);
- if (info.view == v) {
- mHeaderViewInfos.remove(i);
- mAreAllFixedViewsSelectable =
- areAllListInfosSelectable(mHeaderViewInfos) && areAllListInfosSelectable(mFooterViewInfos);
- mDataSetObservable.notifyChanged();
- return true;
- }
- }
- return false;
- }
-
- public boolean removeFooter(View v) {
- for (int i = 0; i < mFooterViewInfos.size(); i++) {
- FixedViewInfo info = mFooterViewInfos.get(i);
- if (info.view == v) {
- mFooterViewInfos.remove(i);
- mAreAllFixedViewsSelectable =
- areAllListInfosSelectable(mHeaderViewInfos) && areAllListInfosSelectable(mFooterViewInfos);
- mDataSetObservable.notifyChanged();
- return true;
- }
- }
- return false;
- }
-
- @Override
- public int getCount() {
- if (mAdapter != null) {
- return (getFootersCount() + getHeadersCount()) * mNumColumns + getAdapterAndPlaceHolderCount();
- } else {
- return (getFootersCount() + getHeadersCount()) * mNumColumns;
- }
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- if (mAdapter != null) {
- return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled();
- } else {
- return true;
- }
- }
-
- private int getAdapterAndPlaceHolderCount() {
- final int adapterCount = (int) (Math.ceil(1f * mAdapter.getCount() / mNumColumns) * mNumColumns);
- return adapterCount;
- }
-
- @Override
- public boolean isEnabled(int position) {
- // Header (negative positions will throw an IndexOutOfBoundsException)
- int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
- if (position < numHeadersAndPlaceholders) {
- return position % mNumColumns == 0
- && mHeaderViewInfos.get(position / mNumColumns).isSelectable;
- }
-
- // Adapter
- final int adjPosition = position - numHeadersAndPlaceholders;
- int adapterCount = 0;
- if (mAdapter != null) {
- adapterCount = getAdapterAndPlaceHolderCount();
- if (adjPosition < adapterCount) {
- return adjPosition < mAdapter.getCount() && mAdapter.isEnabled(adjPosition);
- }
- }
-
- // Footer (off-limits positions will throw an IndexOutOfBoundsException)
- final int footerPosition = adjPosition - adapterCount;
- return footerPosition % mNumColumns == 0
- && mFooterViewInfos.get(footerPosition / mNumColumns).isSelectable;
- }
-
- @Override
- public Object getItem(int position) {
- // Header (negative positions will throw an ArrayIndexOutOfBoundsException)
- int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
- if (position < numHeadersAndPlaceholders) {
- if (position % mNumColumns == 0) {
- return mHeaderViewInfos.get(position / mNumColumns).data;
- }
- return null;
- }
-
- // Adapter
- final int adjPosition = position - numHeadersAndPlaceholders;
- int adapterCount = 0;
- if (mAdapter != null) {
- adapterCount = getAdapterAndPlaceHolderCount();
- if (adjPosition < adapterCount) {
- if (adjPosition < mAdapter.getCount()) {
- return mAdapter.getItem(adjPosition);
- } else {
- return null;
- }
- }
- }
-
- // Footer (off-limits positions will throw an IndexOutOfBoundsException)
- final int footerPosition = adjPosition - adapterCount;
- if (footerPosition % mNumColumns == 0) {
- return mFooterViewInfos.get(footerPosition).data;
- } else {
- return null;
- }
- }
-
- @Override
- public long getItemId(int position) {
- int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
- if (mAdapter != null && position >= numHeadersAndPlaceholders) {
- int adjPosition = position - numHeadersAndPlaceholders;
- int adapterCount = mAdapter.getCount();
- if (adjPosition < adapterCount) {
- return mAdapter.getItemId(adjPosition);
- }
- }
- return -1;
- }
-
- @Override
- public boolean hasStableIds() {
- if (mAdapter != null) {
- return mAdapter.hasStableIds();
- }
- return false;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (DEBUG) {
- Log.d(LOG_TAG, String.format("getView: %s, reused: %s", position, convertView == null));
- }
- // Header (negative positions will throw an ArrayIndexOutOfBoundsException)
- int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
- if (position < numHeadersAndPlaceholders) {
- View headerViewContainer = mHeaderViewInfos
- .get(position / mNumColumns).viewContainer;
- if (position % mNumColumns == 0) {
- return headerViewContainer;
- } else {
- if (convertView == null) {
- convertView = new View(parent.getContext());
- }
- // We need to do this because GridView uses the height of the last item
- // in a row to determine the height for the entire row.
- convertView.setVisibility(View.INVISIBLE);
- convertView.setMinimumHeight(headerViewContainer.getHeight());
- return convertView;
- }
- }
- // Adapter
- final int adjPosition = position - numHeadersAndPlaceholders;
- int adapterCount = 0;
- if (mAdapter != null) {
- adapterCount = getAdapterAndPlaceHolderCount();
- if (adjPosition < adapterCount) {
- if (adjPosition < mAdapter.getCount()) {
- View view = mAdapter.getView(adjPosition, convertView, parent);
- return view;
- } else {
- if (convertView == null) {
- convertView = new View(parent.getContext());
- }
- convertView.setVisibility(View.INVISIBLE);
- convertView.setMinimumHeight(mRowHeight);
- return convertView;
- }
- }
- }
- // Footer
- final int footerPosition = adjPosition - adapterCount;
- if (footerPosition < getCount()) {
- View footViewContainer = mFooterViewInfos
- .get(footerPosition / mNumColumns).viewContainer;
- if (position % mNumColumns == 0) {
- return footViewContainer;
- } else {
- if (convertView == null) {
- convertView = new View(parent.getContext());
- }
- // We need to do this because GridView uses the height of the last item
- // in a row to determine the height for the entire row.
- convertView.setVisibility(View.INVISIBLE);
- convertView.setMinimumHeight(footViewContainer.getHeight());
- return convertView;
- }
- }
- throw new ArrayIndexOutOfBoundsException(position);
- }
-
- @Override
- public int getItemViewType(int position) {
-
- final int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
- final int adapterViewTypeStart = mAdapter == null ? 0 : mAdapter.getViewTypeCount() - 1;
- int type = AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
- if (mCachePlaceHoldView) {
- // Header
- if (position < numHeadersAndPlaceholders) {
- if (position == 0) {
- if (mCacheFirstHeaderView) {
- type = adapterViewTypeStart + mHeaderViewInfos.size() + mFooterViewInfos.size() + 1 + 1;
- }
- }
- if (position % mNumColumns != 0) {
- type = adapterViewTypeStart + (position / mNumColumns + 1);
- }
- }
- }
-
- // Adapter
- final int adjPosition = position - numHeadersAndPlaceholders;
- int adapterCount = 0;
- if (mAdapter != null) {
- adapterCount = getAdapterAndPlaceHolderCount();
- if (adjPosition >= 0 && adjPosition < adapterCount) {
- if (adjPosition < mAdapter.getCount()) {
- type = mAdapter.getItemViewType(adjPosition);
- } else {
- if (mCachePlaceHoldView) {
- type = adapterViewTypeStart + mHeaderViewInfos.size() + 1;
- }
- }
- }
- }
-
- if (mCachePlaceHoldView) {
- // Footer
- final int footerPosition = adjPosition - adapterCount;
- if (footerPosition >= 0 && footerPosition < getCount() && (footerPosition % mNumColumns) != 0) {
- type = adapterViewTypeStart + mHeaderViewInfos.size() + 1 + (footerPosition / mNumColumns + 1);
- }
- }
- if (DEBUG) {
- Log.d(LOG_TAG, String.format("getItemViewType: pos: %s, result: %s", position, type, mCachePlaceHoldView, mCacheFirstHeaderView));
- }
- return type;
- }
-
- /**
- * content view, content view holder, header[0], header and footer placeholder(s)
- *
- * @return
- */
- @Override
- public int getViewTypeCount() {
- int count = mAdapter == null ? 1 : mAdapter.getViewTypeCount();
- if (mCachePlaceHoldView) {
- int offset = mHeaderViewInfos.size() + 1 + mFooterViewInfos.size();
- if (mCacheFirstHeaderView) {
- offset += 1;
- }
- count += offset;
- }
- if (DEBUG) {
- Log.d(LOG_TAG, String.format("getViewTypeCount: %s", count));
- }
- return count;
- }
-
- @Override
- public void registerDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.registerObserver(observer);
- if (mAdapter != null) {
- mAdapter.registerDataSetObserver(observer);
- }
- }
-
- @Override
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.unregisterObserver(observer);
- if (mAdapter != null) {
- mAdapter.unregisterDataSetObserver(observer);
- }
- }
-
- @Override
- public Filter getFilter() {
- if (mIsFilterable) {
- return ((Filterable) mAdapter).getFilter();
- }
- return null;
- }
-
- @Override
- public ListAdapter getWrappedAdapter() {
- return mAdapter;
- }
-
- public void notifyDataSetChanged() {
- mDataSetObservable.notifyChanged();
- }
- }
-}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/PlaylistSongView.java b/app/src/main/java/github/daneren2005/dsub/view/PlaylistSongView.java
index 0264a785..581b92e4 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/PlaylistSongView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/PlaylistSongView.java
@@ -34,16 +34,12 @@ import github.daneren2005.dsub.util.FileUtil;
import github.daneren2005.dsub.util.SyncUtil;
import github.daneren2005.dsub.util.Util;
-public class PlaylistSongView extends UpdateView {
+public class PlaylistSongView extends UpdateView2<Playlist, List<MusicDirectory.Entry>> {
private static final String TAG = PlaylistSongView.class.getSimpleName();
- private Context context;
- private Playlist playlist;
-
private TextView titleView;
private TextView countView;
private int count = 0;
- private List<MusicDirectory.Entry> songs;
public PlaylistSongView(Context context) {
super(context, false);
@@ -54,9 +50,7 @@ public class PlaylistSongView extends UpdateView {
countView = (TextView) findViewById(R.id.basic_count_count);
}
- protected void setObjectImpl(Object obj1, Object obj2) {
- this.playlist = (Playlist) obj1;
- this.songs = (List<MusicDirectory.Entry>) obj2;
+ protected void setObjectImpl(Playlist playlist, List<MusicDirectory.Entry> songs) {
count = 0;
titleView.setText(playlist.getName());
// Make sure to hide initially so it's not present briefly before update
@@ -69,11 +63,11 @@ public class PlaylistSongView extends UpdateView {
count = 0;
// Don't try to lookup playlist for Create New
- if(!"-1".equals(playlist.getId())) {
- MusicDirectory cache = FileUtil.deserialize(context, Util.getCacheName(context, "playlist", playlist.getId()), MusicDirectory.class);
+ if(!"-1".equals(item.getId())) {
+ MusicDirectory cache = FileUtil.deserialize(context, Util.getCacheName(context, "playlist", item.getId()), MusicDirectory.class);
if(cache != null) {
// Try to find song instances in the given playlists
- for(MusicDirectory.Entry song: songs) {
+ for(MusicDirectory.Entry song: item2) {
if(cache.getChildren().contains(song)) {
count++;
}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/PlaylistView.java b/app/src/main/java/github/daneren2005/dsub/view/PlaylistView.java
index 25613984..cb7bd186 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/PlaylistView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/PlaylistView.java
@@ -33,37 +33,27 @@ import github.daneren2005.dsub.util.SyncUtil;
*
* @author Sindre Mehus
*/
-public class PlaylistView extends UpdateView {
+public class PlaylistView extends UpdateView<Playlist> {
private static final String TAG = PlaylistView.class.getSimpleName();
- private Context context;
- private Playlist playlist;
-
private TextView titleView;
public PlaylistView(Context context) {
super(context);
- this.context = context;
LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
titleView = (TextView) findViewById(R.id.item_name);
starButton = (ImageButton) findViewById(R.id.item_star);
starButton.setFocusable(false);
moreButton = (ImageView) findViewById(R.id.item_more);
- moreButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- v.showContextMenu();
- }
- });
}
- protected void setObjectImpl(Object obj) {
- this.playlist = (Playlist) obj;
+ protected void setObjectImpl(Playlist playlist) {
titleView.setText(playlist.getName());
}
@Override
protected void updateBackground() {
- pinned = SyncUtil.isSyncedPlaylist(context, playlist.getId());
+ pinned = SyncUtil.isSyncedPlaylist(context, item.getId());
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/PodcastChannelView.java b/app/src/main/java/github/daneren2005/dsub/view/PodcastChannelView.java
index ada8019e..4878ad67 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/PodcastChannelView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/PodcastChannelView.java
@@ -30,18 +30,14 @@ import github.daneren2005.dsub.util.SyncUtil;
import github.daneren2005.dsub.util.FileUtil;
import java.io.File;
-public class PodcastChannelView extends UpdateView {
+public class PodcastChannelView extends UpdateView<PodcastChannel> {
private static final String TAG = PodcastChannelView.class.getSimpleName();
- private Context context;
- private PodcastChannel channel;
private File file;
-
private TextView titleView;
public PodcastChannelView(Context context) {
super(context);
- this.context = context;
LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
titleView = (TextView) findViewById(R.id.item_name);
@@ -55,8 +51,7 @@ public class PodcastChannelView extends UpdateView {
});
}
- protected void setObjectImpl(Object obj) {
- channel = (PodcastChannel) obj;
+ protected void setObjectImpl(PodcastChannel channel) {
if(channel.getName() != null) {
titleView.setText(channel.getName());
} else {
@@ -67,7 +62,7 @@ public class PodcastChannelView extends UpdateView {
@Override
protected void updateBackground() {
- if(SyncUtil.isSyncedPodcast(context, channel.getId())) {
+ if(SyncUtil.isSyncedPodcast(context, item.getId())) {
if(exists) {
shaded = false;
exists = false;
diff --git a/app/src/main/java/github/daneren2005/dsub/view/SettingView.java b/app/src/main/java/github/daneren2005/dsub/view/SettingView.java
index 1c78706e..d46dc5d2 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/SettingView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/SettingView.java
@@ -17,34 +17,42 @@ package github.daneren2005.dsub.view;
import android.content.Context;
import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.CheckedTextView;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.TextView;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.User;
import static github.daneren2005.dsub.domain.User.Setting;
-public class SettingView extends UpdateView {
- Setting setting;
-
- CheckedTextView view;
+public class SettingView extends UpdateView2<Setting, Boolean> {
+ private final TextView titleView;
+ private final CheckBox checkBox;
public SettingView(Context context) {
super(context, false);
this.context = context;
- LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_multiple_choice, this, true);
+ LayoutInflater.from(context).inflate(R.layout.basic_choice_item, this, true);
- view = (CheckedTextView) findViewById(android.R.id.text1);
+ titleView = (TextView) findViewById(R.id.item_name);
+ checkBox = (CheckBox) findViewById(R.id.item_checkbox);
+ checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if(item != null) {
+ item.setValue(isChecked);
+ }
+ }
+ });
+ checkBox.setClickable(false);
}
- protected void setObjectImpl(Object obj, Object editable) {
- this.setting = (Setting) obj;
-
+ protected void setObjectImpl(Setting setting, Boolean isEditable) {
// Can't edit non-role parts
String name = setting.getName();
if(name.indexOf("Role") == -1) {
- editable = false;
+ item2 = false;
}
int res = -1;
@@ -74,29 +82,28 @@ public class SettingView extends UpdateView {
res = R.string.admin_role_lastfm;
} else {
// Last resort to display the raw value
- view.setText(name);
+ titleView.setText(name);
}
if(res != -1) {
- view.setText(res);
+ titleView.setText(res);
}
if(setting.getValue()) {
- view.setChecked(setting.getValue());
+ checkBox.setChecked(setting.getValue());
} else {
- view.setChecked(false);
+ checkBox.setChecked(false);
}
- if((Boolean) editable) {
- view.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- view.toggle();
- setting.setValue(view.isChecked());
- }
- });
- } else {
- view.setOnClickListener(null);
- }
+ checkBox.setEnabled(item2);
+ }
+
+ @Override
+ public boolean isCheckable() {
+ return item2;
+ }
+
+ public void setChecked(boolean checked) {
+ checkBox.setChecked(checked);
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/ShareView.java b/app/src/main/java/github/daneren2005/dsub/view/ShareView.java
index bfb5b198..12294369 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/ShareView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/ShareView.java
@@ -31,7 +31,7 @@ import java.util.Locale;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.Share;
-public class ShareView extends UpdateView {
+public class ShareView extends UpdateView<Share> {
private static final String TAG = ShareView.class.getSimpleName();
private TextView titleView;
@@ -53,8 +53,7 @@ public class ShareView extends UpdateView {
});
}
- public void setObjectImpl(Object obj) {
- Share share = (Share) obj;
+ public void setObjectImpl(Share share) {
titleView.setText(share.getName());
if(share.getExpires() != null) {
descriptionView.setText(context.getResources().getString(R.string.share_expires, new SimpleDateFormat("E MMM d, yyyy", Locale.ENGLISH).format(share.getExpires())));
diff --git a/app/src/main/java/github/daneren2005/dsub/view/SongView.java b/app/src/main/java/github/daneren2005/dsub/view/SongView.java
index 2fbaedc3..fadf100e 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/SongView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/SongView.java
@@ -38,20 +38,18 @@ import java.io.File;
*
* @author Sindre Mehus
*/
-public class SongView extends UpdateView implements Checkable {
- private static final String TAG = SongView.class.getSimpleName();
-
- private MusicDirectory.Entry song;
-
- private CheckedTextView checkedTextView;
- private TextView titleTextView;
- private TextView artistTextView;
- private TextView durationTextView;
- private TextView statusTextView;
+public class SongView extends UpdateView2<MusicDirectory.Entry, Boolean> implements Checkable {
+ private static final String TAG = SongView.class.getSimpleName();
+
+ private CheckedTextView checkedTextView;
+ private TextView titleTextView;
+ private TextView artistTextView;
+ private TextView durationTextView;
+ private TextView statusTextView;
private ImageView statusImageView;
private ImageView bookmarkButton;
private View bottomRowView;
-
+
private DownloadService downloadService;
private long revision = -1;
private DownloadFile downloadFile;
@@ -68,35 +66,29 @@ public class SongView extends UpdateView implements Checkable {
private boolean isBookmarked = false;
private boolean bookmarked = false;
- public SongView(Context context) {
- super(context);
- LayoutInflater.from(context).inflate(R.layout.song_list_item, this, true);
+ public SongView(Context context) {
+ super(context);
+ LayoutInflater.from(context).inflate(R.layout.song_list_item, this, true);
- checkedTextView = (CheckedTextView) findViewById(R.id.song_check);
- titleTextView = (TextView) findViewById(R.id.song_title);
- artistTextView = (TextView) findViewById(R.id.song_artist);
- durationTextView = (TextView) findViewById(R.id.song_duration);
- statusTextView = (TextView) findViewById(R.id.song_status);
+ checkedTextView = (CheckedTextView) findViewById(R.id.song_check);
+ titleTextView = (TextView) findViewById(R.id.song_title);
+ artistTextView = (TextView) findViewById(R.id.song_artist);
+ durationTextView = (TextView) findViewById(R.id.song_duration);
+ statusTextView = (TextView) findViewById(R.id.song_status);
statusImageView = (ImageView) findViewById(R.id.song_status_icon);
ratingBar = (RatingBar) findViewById(R.id.song_rating);
- starButton = (ImageButton) findViewById(R.id.song_star);
- starButton.setFocusable(false);
+ starButton = (ImageButton) findViewById(R.id.song_star);
+ starButton.setFocusable(false);
bookmarkButton = (ImageButton) findViewById(R.id.song_bookmark);
bookmarkButton.setFocusable(false);
- moreButton = (ImageView) findViewById(R.id.artist_more);
- moreButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- v.showContextMenu();
- }
- });
+ moreButton = (ImageView) findViewById(R.id.more_button);
bottomRowView = findViewById(R.id.song_bottom);
- }
+ }
+
+ public void setObjectImpl(MusicDirectory.Entry song, Boolean checkable) {
+ this.checkable = checkable;
- public void setObjectImpl(Object obj1, Object obj2) {
- this.song = (MusicDirectory.Entry) obj1;
- boolean checkable = (Boolean) obj2;
-
- StringBuilder artist = new StringBuilder(40);
+ StringBuilder artist = new StringBuilder(40);
boolean isPodcast = song instanceof PodcastEpisode;
if(!song.isVideo() || isPodcast) {
@@ -110,11 +102,11 @@ public class SongView extends UpdateView implements Checkable {
else if(song.getArtist() != null) {
artist.append(song.getArtist());
}
-
+
if(isPodcast) {
String status = ((PodcastEpisode) song).getStatus();
int statusRes = -1;
-
+
if("error".equals(status)) {
statusRes = R.string.song_details_error;
} else if("skipped".equals(status)) {
@@ -122,7 +114,7 @@ public class SongView extends UpdateView implements Checkable {
} else if("downloading".equals(status)) {
statusRes = R.string.song_details_downloading;
}
-
+
if(statusRes != -1) {
artist.append(" (");
artist.append(getContext().getString(statusRes));
@@ -136,16 +128,16 @@ public class SongView extends UpdateView implements Checkable {
bottomRowView.setVisibility(View.GONE);
statusTextView.setText(Util.formatDuration(song.getDuration()));
}
-
+
String title = song.getTitle();
Integer track = song.getTrack();
if(track != null && Util.getDisplayTrack(context)) {
title = String.format("%02d", track) + " " + title;
}
- titleTextView.setText(title);
+ titleTextView.setText(title);
artistTextView.setText(artist);
- checkedTextView.setVisibility(checkable && !song.isVideo() ? View.VISIBLE : View.GONE);
+ checkedTextView.setVisibility(checkable ? View.VISIBLE : View.GONE);
this.setBackgroundColor(0x00000000);
ratingBar.setVisibility(View.GONE);
@@ -155,28 +147,28 @@ public class SongView extends UpdateView implements Checkable {
loaded = false;
dontChangeDownloadFile = false;
}
-
+
public void setDownloadFile(DownloadFile downloadFile) {
this.downloadFile = downloadFile;
dontChangeDownloadFile = true;
}
-
+
public DownloadFile getDownloadFile() {
return downloadFile;
}
-
+
@Override
protected void updateBackground() {
- if (downloadService == null) {
+ if (downloadService == null) {
downloadService = DownloadService.getInstance();
if(downloadService == null) {
return;
}
- }
+ }
long newRevision = downloadService.getDownloadListUpdateRevision();
if((revision != newRevision && dontChangeDownloadFile == false) || downloadFile == null) {
- downloadFile = downloadService.forSong(song);
+ downloadFile = downloadService.forSong(item);
revision = newRevision;
}
@@ -184,27 +176,27 @@ public class SongView extends UpdateView implements Checkable {
isSaved = downloadFile.isSaved();
partialFile = downloadFile.getPartialFile();
partialFileExists = partialFile.exists();
- isStarred = song.isStarred();
- isBookmarked = song.getBookmark() != null;
- isRated = song.getRating();
-
+ isStarred = item.isStarred();
+ isBookmarked = item.getBookmark() != null;
+ isRated = item.getRating();
+
// Check if needs to load metadata: check against all fields that we know are null in offline mode
- if(song.getBitRate() == null && song.getDuration() == null && song.getDiscNumber() == null && isWorkDone) {
- song.loadMetadata(downloadFile.getCompleteFile());
+ if(item.getBitRate() == null && item.getDuration() == null && item.getDiscNumber() == null && isWorkDone) {
+ item.loadMetadata(downloadFile.getCompleteFile());
loaded = true;
}
}
@Override
- protected void update() {
+ protected void update() {
if(loaded) {
- setObjectImpl(song, checkedTextView.getVisibility() == View.VISIBLE);
+ setObjectImpl(item, checkedTextView.getVisibility() == View.VISIBLE);
+ }
+ if (downloadService == null || downloadFile == null) {
+ return;
}
- if (downloadService == null || downloadFile == null) {
- return;
- }
- if(song.isStarred()) {
+ if(item.isStarred()) {
if(!starred) {
starButton.setVisibility(View.VISIBLE);
starred = true;
@@ -216,13 +208,13 @@ public class SongView extends UpdateView implements Checkable {
}
}
- if (isWorkDone) {
+ if (isWorkDone) {
int moreImage = isSaved ? R.drawable.download_pinned : R.drawable.download_cached;
if(moreImage != this.moreImage) {
moreButton.setImageResource(moreImage);
this.moreImage = moreImage;
}
- } else if(this.moreImage != R.drawable.download_none_light) {
+ } else if(this.moreImage != R.drawable.download_none_light) {
int[] attrs = new int[] {R.attr.download_none};
TypedArray typedArray = context.obtainStyledAttributes(attrs);
moreButton.setImageResource(typedArray.getResourceId(0, 0));
@@ -230,7 +222,7 @@ public class SongView extends UpdateView implements Checkable {
this.moreImage = R.drawable.download_none_light;
}
- if (downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && partialFileExists) {
+ if (downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && partialFileExists) {
double percentage = (partialFile.length() * 100.0) / downloadFile.getEstimatedSize();
percentage = Math.min(percentage, 100);
statusTextView.setText((int)percentage + " %");
@@ -238,24 +230,24 @@ public class SongView extends UpdateView implements Checkable {
statusImageView.setVisibility(View.VISIBLE);
rightImage = true;
}
- } else if(rightImage) {
- statusTextView.setText(null);
+ } else if(rightImage) {
+ statusTextView.setText(null);
statusImageView.setVisibility(View.GONE);
rightImage = false;
- }
+ }
- boolean playing = downloadService.getCurrentPlaying() == downloadFile;
- if (playing) {
+ boolean playing = downloadService.getCurrentPlaying() == downloadFile;
+ if (playing) {
if(!this.playing) {
this.playing = playing;
int[] attrs = new int[] {R.attr.media_button_start};
TypedArray typedArray = context.obtainStyledAttributes(attrs);
- titleTextView.setCompoundDrawablesWithIntrinsicBounds(typedArray.getResourceId(0, 0), 0, 0, 0);
+ titleTextView.setCompoundDrawablesWithIntrinsicBounds(typedArray.getResourceId(0, 0), 0, 0, 0);
}
- } else {
+ } else {
if(this.playing) {
this.playing = playing;
- titleTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
+ titleTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
}
@@ -295,24 +287,24 @@ public class SongView extends UpdateView implements Checkable {
rating = isRated;
}
- }
+ }
- @Override
- public void setChecked(boolean b) {
- checkedTextView.setChecked(b);
- }
+ @Override
+ public void setChecked(boolean b) {
+ checkedTextView.setChecked(b);
+ }
- @Override
- public boolean isChecked() {
- return checkedTextView.isChecked();
- }
+ @Override
+ public boolean isChecked() {
+ return checkedTextView.isChecked();
+ }
- @Override
- public void toggle() {
- checkedTextView.toggle();
- }
+ @Override
+ public void toggle() {
+ checkedTextView.toggle();
+ }
public MusicDirectory.Entry getEntry() {
- return song;
+ return item;
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/UnscrollableGridView.java b/app/src/main/java/github/daneren2005/dsub/view/UnscrollableGridView.java
deleted file mode 100644
index 3047d5d7..00000000
--- a/app/src/main/java/github/daneren2005/dsub/view/UnscrollableGridView.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package github.daneren2005.dsub.view;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.os.Build;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.AbsListView;
-import android.widget.GridView;
-import android.widget.ListAdapter;
-
-import java.lang.reflect.Field;
-
-/**
- * Created by Scott on 4/26/2014.
- */
-public class UnscrollableGridView extends GridView {
- private static final String TAG = UnscrollableGridView.class.getSimpleName();
-
- public UnscrollableGridView(Context context) {
- super(context);
- }
-
- public UnscrollableGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public UnscrollableGridView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public int getColumnWidth() {
- // This method will be called from onMeasure() too.
- // It's better to use getMeasuredWidth(), as it is safe in this case.
-
- int hSpacing = 20;
- try {
- Field field = GridView.class.getDeclaredField("mHorizontalSpacing");
- field.setAccessible(true);
- hSpacing = field.getInt(this);
- } catch(Exception e) {
-
- }
-
- final int totalHorizontalSpacing = getNumColumnsCompat() > 0 ? (getNumColumnsCompat() - 1) * hSpacing : 0;
- return (getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - totalHorizontalSpacing) / getNumColumnsCompat();
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Sets the padding for this view.
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- final int measuredWidth = getMeasuredWidth();
- final int childWidth = getColumnWidth();
- int childHeight = 0;
-
- // If there's an adapter, use it to calculate the height of this view.
- final ListAdapter adapter = getAdapter();
- final int count;
-
- // There shouldn't be any inherent size (due to padding) if there are no child views.
- if (adapter == null || (count = adapter.getCount()) == 0) {
- setMeasuredDimension(0, 0);
- return;
- }
-
- // Get the first child from the adapter.
- final View child = adapter.getView(0, null, this);
- if (child != null) {
- // Set a default LayoutParams on the child, if it doesn't have one on its own.
- AbsListView.LayoutParams params = (AbsListView.LayoutParams) child.getLayoutParams();
- if (params == null) {
- params = new AbsListView.LayoutParams(AbsListView.LayoutParams.WRAP_CONTENT,
- AbsListView.LayoutParams.WRAP_CONTENT);
- child.setLayoutParams(params);
- }
-
- // Measure the exact width of the child, and the height based on the width.
- // Note: the child takes care of calculating its height.
- int childWidthSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
- int childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- child.measure(childWidthSpec, childHeightSpec);
- childHeight = child.getMeasuredHeight();
- }
-
- int vSpacing = 10;
- try {
- Field field = GridView.class.getDeclaredField("mVerticalSpacing");
- field.setAccessible(true);
- vSpacing = field.getInt(this);
- } catch(Exception e) {
-
- }
-
- // Number of rows required to 'mTotal' items.
- final int rows = (int) Math.ceil((double) getCount() / getNumColumnsCompat());
- final int childrenHeight = childHeight * rows;
- final int totalVerticalSpacing = rows > 0 ? (rows - 1) * vSpacing : 0;
-
- // Total height of this view.
- final int measuredHeight = Math.abs(childrenHeight + getPaddingTop() + getPaddingBottom() + totalVerticalSpacing);
- setMeasuredDimension(measuredWidth, measuredHeight);
- }
-
- private int getNumColumnsCompat() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- return getNumColumnsCompat11();
- } else {
- int columns = 0;
- int children = getChildCount();
- if (children > 0) {
- int width = getChildAt(0).getMeasuredWidth();
- if (width > 0) {
- columns = getWidth() / width;
- }
- }
- return columns > 0 ? columns : AUTO_FIT;
- }
- }
-
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- private int getNumColumnsCompat11() {
- return getNumColumns();
- }
-}
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 f9c62121..8e1029df 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java
@@ -20,9 +20,9 @@ package github.daneren2005.dsub.view;
import android.content.Context;
import android.content.res.TypedArray;
-import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
+import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -37,20 +37,20 @@ import java.util.List;
import java.util.WeakHashMap;
import github.daneren2005.dsub.domain.MusicDirectory;
-import github.daneren2005.dsub.util.ImageLoader;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.util.SilentBackgroundTask;
-public class UpdateView extends LinearLayout {
+public abstract class UpdateView<T> extends LinearLayout {
private static final String TAG = UpdateView.class.getSimpleName();
private static final WeakHashMap<UpdateView, ?> INSTANCES = new WeakHashMap<UpdateView, Object>();
- private static Handler backgroundHandler;
- private static Handler uiHandler;
+ protected static Handler backgroundHandler;
+ protected static Handler uiHandler;
private static Runnable updateRunnable;
private static int activeActivities = 0;
protected Context context;
+ protected T item;
protected RatingBar ratingBar;
protected ImageButton starButton;
protected ImageView moreButton;
@@ -65,6 +65,7 @@ public class UpdateView extends LinearLayout {
protected SilentBackgroundTask<Void> imageTask = null;
protected final boolean autoUpdate;
+ protected boolean checkable;
public UpdateView(Context context) {
this(context, true);
@@ -75,8 +76,8 @@ public class UpdateView extends LinearLayout {
this.autoUpdate = autoUpdate;
setLayoutParams(new AbsListView.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
+ ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
if(autoUpdate) {
INSTANCES.put(this, null);
@@ -89,37 +90,16 @@ public class UpdateView extends LinearLayout {
}
- public void setObject(Object obj) {
+ public void setObject(T obj) {
+ item = obj;
setObjectImpl(obj);
updateBackground();
update();
}
- public void setObject(Object obj1, Object obj2) {
- if(imageTask != null) {
- imageTask.cancel();
- imageTask = null;
- }
-
- setObjectImpl(obj1, obj2);
- backgroundHandler.post(new Runnable() {
- @Override
- public void run() {
- updateBackground();
- uiHandler.post(new Runnable() {
- @Override
- public void run() {
- update();
- }
- });
- }
- });
- }
- protected void setObjectImpl(Object obj) {
-
- }
- protected void setObjectImpl(Object obj1, Object obj2) {
-
+ public void setObject(T obj1, Object obj2) {
+ setObject(obj1, null);
}
+ protected abstract void setObjectImpl(T obj);
private static synchronized void startUpdater() {
if(uiHandler != null) {
@@ -224,8 +204,6 @@ public class UpdateView extends LinearLayout {
MusicDirectory.Entry check = null;
if(view instanceof SongView) {
check = ((SongView) view).getEntry();
- } else if(view instanceof AlbumCell) {
- check = ((AlbumCell) view).getEntry();
} else if(view instanceof AlbumView) {
check = ((AlbumView) view).getEntry();
}
@@ -283,4 +261,45 @@ public class UpdateView extends LinearLayout {
rating = isRated;
}
}
+
+ public boolean isCheckable() {
+ return checkable;
+ }
+
+ public void onClick() {
+
+ }
+
+ public static class UpdateViewHolder<T> extends RecyclerView.ViewHolder {
+ private UpdateView updateView;
+ private View view;
+ private T item;
+
+ public UpdateViewHolder(UpdateView itemView) {
+ super(itemView);
+
+ this.updateView = itemView;
+ this.view = itemView;
+ }
+
+ // Different is so that call is not ambiguous
+ public UpdateViewHolder(View view, boolean different) {
+ super(view);
+ this.view = view;
+ }
+
+ public UpdateView<T> getUpdateView() {
+ return updateView;
+ }
+ public View getView() {
+ return view;
+ }
+ public void setItem(T item) {
+ this.item = item;
+ }
+ public T getItem() {
+ return item;
+ }
+ }
}
+
diff --git a/app/src/main/java/github/daneren2005/dsub/view/UpdateView2.java b/app/src/main/java/github/daneren2005/dsub/view/UpdateView2.java
new file mode 100644
index 00000000..0f0b5455
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/view/UpdateView2.java
@@ -0,0 +1,47 @@
+package github.daneren2005.dsub.view;
+
+import android.content.Context;
+
+public abstract class UpdateView2<T1, T2> extends UpdateView<T1> {
+ protected T2 item2;
+
+ public UpdateView2(Context context) {
+ super(context);
+ }
+
+ public UpdateView2(Context context, boolean autoUpdate) {
+ super(context, autoUpdate);
+ }
+
+ public final void setObject(T1 obj1) {
+ setObject(obj1, null);
+ }
+ @Override
+ public void setObject(T1 obj1, Object obj2) {
+ item = obj1;
+ item2 = (T2) obj2;
+ if(imageTask != null) {
+ imageTask.cancel();
+ imageTask = null;
+ }
+
+ setObjectImpl(item, item2);
+ backgroundHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ updateBackground();
+ uiHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ update();
+ }
+ });
+ }
+ });
+ }
+
+ protected final void setObjectImpl(T1 obj1) {
+ setObjectImpl(obj1, null);
+ }
+ protected abstract void setObjectImpl(T1 obj1, T2 obj2);
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/UserView.java b/app/src/main/java/github/daneren2005/dsub/view/UserView.java
index dec8dbef..a97d755b 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/UserView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/UserView.java
@@ -25,15 +25,12 @@ import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.User;
import github.daneren2005.dsub.util.ImageLoader;
-public class UserView extends UpdateView {
- private User user;
-
+public class UserView extends UpdateView2<User, ImageLoader> {
private TextView usernameView;
private ImageView avatarView;
public UserView(Context context) {
super(context, false);
- this.context = context;
LayoutInflater.from(context).inflate(R.layout.user_list_item, this, true);
usernameView = (TextView) findViewById(R.id.item_name);
@@ -46,9 +43,8 @@ public class UserView extends UpdateView {
});
}
- protected void setObjectImpl(Object obj, Object obj2) {
- this.user = (User) obj;
+ protected void setObjectImpl(User user, ImageLoader imageLoader) {
usernameView.setText(user.getUsername());
- imageTask = ((ImageLoader)obj2).loadAvatar(context, avatarView, user.getUsername());
+ imageTask = imageLoader.loadAvatar(context, avatarView, user.getUsername());
}
}
diff --git a/app/src/main/res/layout-large-land/abstract_fragment_container.xml b/app/src/main/res/layout-large-land/abstract_fragment_container.xml
index 5e3b1561..3901710f 100644
--- a/app/src/main/res/layout-large-land/abstract_fragment_container.xml
+++ b/app/src/main/res/layout-large-land/abstract_fragment_container.xml
@@ -2,8 +2,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
- android:layout_height="0px"
- android:layout_weight="1">
+ android:layout_height="match_parent"
+ android:layout_marginTop="?attr/actionBarSize">
<FrameLayout
android:id="@+id/fragment_container"
diff --git a/app/src/main/res/layout/abstract_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 d9c99f2f..44ac35fd 100644
--- a/app/src/main/res/layout/abstract_fragment_activity.xml
+++ b/app/src/main/res/layout/abstract_fragment_activity.xml
@@ -1,84 +1,137 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.sothree.slidinguppanel.SlidingUpPanelLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sothree="http://schemas.android.com/apk/res-auto"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/slide_up_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:gravity="center_horizontal"
- android:orientation="vertical" >
+ android:gravity="bottom"
+ sothree:umanoPanelHeight="?attr/actionBarSize"
+ sothree:umanoShadowHeight="4dp"
+ sothree:umanoDragView="@+id/slide_up_swipe_target">
- <include layout="@layout/abstract_fragment_container" />
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <View
- android:layout_width="fill_parent"
- android:layout_height="1px"
- android:background="@color/dividerColor"/>
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/main_toolbar"
+ android:layout_height="?attr/actionBarSize"
+ android:layout_width="match_parent"
+ android:background="?attr/colorPrimary"
+ android:elevation="4dp"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ app:popupTheme="?attr/actionbarPopupStyle"/>
+
+ <include layout="@layout/abstract_fragment_container"/>
+ </FrameLayout>
<LinearLayout
- android:id="@+id/bottom_bar"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="@style/BasicButton"
- android:orientation="horizontal">
-
- <github.daneren2005.dsub.view.RecyclingImageView
- android:id="@+id/album_art"
- android:layout_width="50dip"
- android:layout_height="50dip"
- android:layout_gravity="left|center"
- android:scaleType="fitStart"/>
-
- <LinearLayout
- android:layout_width="0dp"
+ android:id="@+id/slide_up_frame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:visibility="gone">
+
+ <FrameLayout
+ android:id="@+id/slide_up_swipe_target"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:orientation="vertical"
- android:paddingLeft="8dip">
+ android:background="?attr/colorPrimary">
- <TextView
- android:id="@+id/track_name"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:textColor="?android:textColorPrimary"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textSize="13sp"
- android:text="@string/search.artists"/>
-
- <TextView
- android:id="@+id/artist_name"
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/now_playing_toolbar"
+ android:layout_height="?attr/actionBarSize"
+ android:layout_width="match_parent"
+ android:elevation="4dp"
+ android:visibility="gone"
+ app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ app:popupTheme="?attr/actionbarPopupStyle"/>
+
+ <LinearLayout
+ android:id="@+id/bottom_bar"
+ android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:textColor="?android:textColorSecondary"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textSize="12sp"
- android:text="@string/search.albums"/>
- </LinearLayout>
-
- <LinearLayout
- android:layout_height="wrap_content"
- android:layout_width="0dp"
- android:layout_weight="1">
-
- <ImageButton
- style="@style/PlaybackControl.Small"
- android:id="@+id/download_previous"
- android:src="?attr/media_button_backward"
- android:layout_width="0dp"
- android:layout_weight="1"/>
-
- <ImageButton
- style="@style/PlaybackControl.Small"
- android:id="@+id/download_start"
- android:src="?attr/media_button_start"
- android:layout_width="0dp"
- android:layout_weight="1"/>
-
- <ImageButton
- style="@style/PlaybackControl.Small"
- android:id="@+id/download_next"
- android:src="?attr/media_button_forward"
- android:layout_width="0dp"
- android:layout_weight="1"/>
- </LinearLayout>
+ style="@style/BasicButton"
+ android:orientation="horizontal"
+ android:elevation="4dp">
+
+ <github.daneren2005.dsub.view.RecyclingImageView
+ android:id="@+id/album_art"
+ android:layout_width="?attr/actionBarSize"
+ android:layout_height="?attr/actionBarSize"
+ android:layout_gravity="left|center"
+ android:scaleType="fitStart"/>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingLeft="8dip">
+
+ <TextView
+ android:id="@+id/track_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:singleLine="true"
+ android:text="@string/main.title"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:scrollHorizontally="true"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ style="?attr/actionbarTitleStyle">
+
+ <requestFocus android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:duplicateParentState="true" />
+ </TextView>
+
+ <TextView
+ android:id="@+id/artist_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:singleLine="true"
+ android:text="@string/main.artist"
+ style="?attr/actionbarSubtitleStyle"/>
+ </LinearLayout>
+
+
+ <LinearLayout
+ android:layout_height="fill_parent"
+ android:layout_width="0dp"
+ android:layout_weight="1">
+
+ <ImageButton
+ style="@style/PlaybackControl.Match"
+ android:id="@+id/download_previous"
+ android:src="?attr/actionbar_backward"
+ android:layout_width="0dp"
+ android:layout_weight="1"/>
+
+ <ImageButton
+ style="@style/PlaybackControl.Match"
+ android:id="@+id/download_start"
+ android:src="?attr/actionbar_start"
+ android:layout_width="0dp"
+ android:layout_weight="1"/>
+
+ <ImageButton
+ style="@style/PlaybackControl.Match"
+ android:id="@+id/download_next"
+ android:src="?attr/actionbar_forward"
+ android:layout_width="0dp"
+ android:layout_weight="1"/>
+ </LinearLayout>
+ </LinearLayout>
+ </FrameLayout>
+
+ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/now_playing_fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
</LinearLayout>
-</LinearLayout> \ No newline at end of file
+</com.sothree.slidinguppanel.SlidingUpPanelLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/abstract_fragment_container.xml b/app/src/main/res/layout/abstract_fragment_container.xml
index 61e17d1d..f13356c4 100644
--- a/app/src/main/res/layout/abstract_fragment_container.xml
+++ b/app/src/main/res/layout/abstract_fragment_container.xml
@@ -2,5 +2,5 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
- android:layout_height="0px"
- android:layout_weight="1"/> \ No newline at end of file
+ android:layout_height="match_parent"
+ android:layout_marginTop="?attr/actionBarSize"/> \ No newline at end of file
diff --git a/app/src/main/res/layout/abstract_list_fragment.xml b/app/src/main/res/layout/abstract_recycler_fragment.xml
index 618a7341..47141450 100644
--- a/app/src/main/res/layout/abstract_list_fragment.xml
+++ b/app/src/main/res/layout/abstract_recycler_fragment.xml
@@ -10,17 +10,12 @@
android:layout_height="fill_parent"
android:orientation="vertical" >
- <View
- android:layout_width="fill_parent"
- android:layout_height="1px"
- android:background="@color/dividerColor"/>
-
- <ListView
- android:id="@+id/fragment_list"
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/fragment_recycler"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0"
- android:fastScrollEnabled="true"/>
+ android:scrollbars="vertical"/>
<include layout="@layout/tab_progress" />
</LinearLayout>
diff --git a/app/src/main/res/layout/actionbar_spinner.xml b/app/src/main/res/layout/actionbar_spinner.xml
index 22055901..4d9f95a4 100644
--- a/app/src/main/res/layout/actionbar_spinner.xml
+++ b/app/src/main/res/layout/actionbar_spinner.xml
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:gravity="fill_horizontal" >
- <Spinner
- android:id="@+id/spinner"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:prompt="@string/common.appname"
- />
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="fill_horizontal" >
+
+ <Spinner
+ android:id="@+id/spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:prompt="@string/common.appname"
+ android:background="@drawable/abc_spinner_mtrl_am_alpha"/>
</RelativeLayout>
diff --git a/app/src/main/res/layout/album_cell_item.xml b/app/src/main/res/layout/album_cell_item.xml
index 3f708e63..fe634c13 100644
--- a/app/src/main/res/layout/album_cell_item.xml
+++ b/app/src/main/res/layout/album_cell_item.xml
@@ -2,7 +2,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:background="?attr/selectableItemBackground">
<RelativeLayout
android:layout_width="match_parent"
@@ -77,7 +78,7 @@
</LinearLayout>
<ImageView
- android:id="@+id/album_more"
+ android:id="@+id/more_button"
android:src="?attr/download_none"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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..e78d0ace
--- /dev/null
+++ b/app/src/main/res/layout/album_list_header.xml
@@ -0,0 +1,29 @@
+<?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="?attr/colorAccent"
+ 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"
+ android:textColor="?android:textColorPrimary"/>
+</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 0ee92edd..150cbd8f 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"
@@ -43,14 +44,16 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:singleLine="true"
android:ellipsize="marquee"
- android:paddingBottom="6dip"/>
+ android:paddingBottom="6dip"
+ android:textColor="?android:textColorPrimary"/>
<TextView
android:id="@+id/album_artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"/>
+ android:singleLine="true"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
@@ -65,7 +68,7 @@
android:visibility="gone"/>
<ImageView
- android:id="@+id/album_more"
+ android:id="@+id/more_button"
android:src="?attr/download_none"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
diff --git a/app/src/main/res/layout/basic_choice_item.xml b/app/src/main/res/layout/basic_choice_item.xml
new file mode 100644
index 00000000..e2dc2204
--- /dev/null
+++ b/app/src/main/res/layout/basic_choice_item.xml
@@ -0,0 +1,27 @@
+<?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:background="?attr/selectableItemBackground">
+
+ <TextView
+ android:id="@+id/item_name"
+ android:layout_width="0dip"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_weight="1"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="left|center_vertical"
+ android:paddingLeft="6dip"
+ android:paddingRight="6dip"
+ android:background="@android:color/transparent"
+ android:textColor="?android:textColorPrimary"/>
+
+ <CheckBox
+ android:id="@+id/item_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_gravity="right|center_vertical"
+ android:checkMark="?android:attr/listChoiceIndicatorMultiple"
+ style="@style/MoreButton"/>
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/basic_count_item.xml b/app/src/main/res/layout/basic_count_item.xml
index 08d276db..ce1aa800 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
@@ -14,7 +14,8 @@
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:background="@android:color/transparent"
- android:text="Text"/>
+ android:text="Text"
+ android:textColor="?android:textColorPrimary"/>
<TextView
android:id="@+id/basic_count_count"
@@ -31,5 +32,6 @@
android:textSize="11sp"
android:gravity="right|center_vertical"
android:layout_gravity="center_vertical"
+ android:textColor="?android:textColorPrimary"
android:visibility="gone"/>
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/basic_header.xml b/app/src/main/res/layout/basic_header.xml
new file mode 100644
index 00000000..b1f94b33
--- /dev/null
+++ b/app/src/main/res/layout/basic_header.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/item_name"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:background="@android:color/transparent"
+ android:textColor="?attr/colorAccent"
+ android:textStyle="bold"
+ android:paddingLeft="6dp"
+ android:paddingRight="6dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"/> \ No newline at end of file
diff --git a/app/src/main/res/layout/basic_list_item.xml b/app/src/main/res/layout/basic_list_item.xml
index 2338f7e0..04fdfe06 100644
--- a/app/src/main/res/layout/basic_list_item.xml
+++ b/app/src/main/res/layout/basic_list_item.xml
@@ -3,7 +3,7 @@
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:background="@android:color/transparent">
+ android:background="?attr/selectableItemBackground">
<TextView
android:id="@+id/item_name"
@@ -15,7 +15,8 @@
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:minHeight="50dip"
- android:background="@android:color/transparent"/>
+ android:background="@android:color/transparent"
+ android:textColor="?android:textColorPrimary"/>
<ImageButton
android:id="@+id/item_star"
diff --git a/app/src/main/res/layout/change_email.xml b/app/src/main/res/layout/change_email.xml
index 18ffc765..87d297be 100644
--- a/app/src/main/res/layout/change_email.xml
+++ b/app/src/main/res/layout/change_email.xml
@@ -15,7 +15,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/admin.change_email_label" />
+ android:text="@string/admin.change_email_label"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/new_email"
android:inputType="textEmailAddress"
diff --git a/app/src/main/res/layout/change_password.xml b/app/src/main/res/layout/change_password.xml
index 1a382a6b..d8043c05 100644
--- a/app/src/main/res/layout/change_password.xml
+++ b/app/src/main/res/layout/change_password.xml
@@ -15,7 +15,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/admin.change_password_label" />
+ android:text="@string/admin.change_password_label"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/new_password"
android:inputType="textPassword"
diff --git a/app/src/main/res/layout/chat_item.xml b/app/src/main/res/layout/chat_item.xml
index f31f7988..bf5d81ca 100644
--- a/app/src/main/res/layout/chat_item.xml
+++ b/app/src/main/res/layout/chat_item.xml
@@ -2,7 +2,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:layout_height="wrap_content"
+ android:background="?attr/selectableItemBackground">
<github.daneren2005.dsub.view.RecyclingImageView
android:id="@+id/chat_avatar"
@@ -34,7 +35,7 @@
android:singleLine="true"
android:text="User"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="?android:textColorSecondary"/>
+ android:textColor="?android:textColorPrimary"/>
<TextView
android:id="@+id/chat_time"
@@ -43,7 +44,8 @@
android:layout_marginLeft="6dip"
android:singleLine="true"
android:text="00:00"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<TextView
@@ -56,6 +58,7 @@
android:linksClickable="true"
android:singleLine="false"
android:text="Message Text Goes Here"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/chat_item_reverse.xml b/app/src/main/res/layout/chat_item_reverse.xml
index b8102193..31875208 100644
--- a/app/src/main/res/layout/chat_item_reverse.xml
+++ b/app/src/main/res/layout/chat_item_reverse.xml
@@ -2,7 +2,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:layout_height="wrap_content"
+ android:background="?attr/selectableItemBackground">
<LinearLayout
android:layout_width="0dip"
@@ -24,7 +25,8 @@
android:layout_marginRight="6dip"
android:singleLine="true"
android:text="00:00"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:textColorSecondary"/>
<TextView
android:id="@+id/chat_username"
@@ -35,7 +37,7 @@
android:singleLine="true"
android:text="User"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="?android:textColorSecondary"/>
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout>
<TextView
@@ -49,7 +51,8 @@
android:singleLine="false"
android:text="Chat message"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_gravity="right"/>
+ android:layout_gravity="right"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<github.daneren2005.dsub.view.RecyclingImageView
diff --git a/app/src/main/res/layout/complex_list_item.xml b/app/src/main/res/layout/complex_list_item.xml
index 67851eca..2aec9451 100644
--- a/app/src/main/res/layout/complex_list_item.xml
+++ b/app/src/main/res/layout/complex_list_item.xml
@@ -1,9 +1,9 @@
<?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="?android:attr/listPreferredItemHeight"
- android:background="@android:color/transparent">
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:background="?attr/selectableItemBackground">
<LinearLayout android:orientation="vertical"
android:layout_width="0dip"
@@ -19,14 +19,16 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:background="@android:color/transparent"/>
+ android:background="@android:color/transparent"
+ android:textColor="?android:textColorPrimary"/>
<TextView
android:id="@+id/item_description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:background="@android:color/transparent"/>
+ android:background="@android:color/transparent"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<ImageButton
diff --git a/app/src/main/res/layout/confirm_password.xml b/app/src/main/res/layout/confirm_password.xml
index 27ee04ea..9ec61c0a 100644
--- a/app/src/main/res/layout/confirm_password.xml
+++ b/app/src/main/res/layout/confirm_password.xml
@@ -15,7 +15,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/admin.add_user_password" />
+ android:text="@string/admin.add_user_password"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/password"
android:inputType="textPassword"
diff --git a/app/src/main/res/layout/create_bookmark.xml b/app/src/main/res/layout/create_bookmark.xml
index f72b39d8..d6f077c3 100644
--- a/app/src/main/res/layout/create_bookmark.xml
+++ b/app/src/main/res/layout/create_bookmark.xml
@@ -14,7 +14,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/common.comment" />
+ android:text="@string/common.comment"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/comment_text"
android:inputType="text"
diff --git a/app/src/main/res/layout/create_podcast.xml b/app/src/main/res/layout/create_podcast.xml
index 5a2ec970..04e74ec3 100644
--- a/app/src/main/res/layout/create_podcast.xml
+++ b/app/src/main/res/layout/create_podcast.xml
@@ -14,7 +14,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/select_podcasts.add_url"/>
+ android:text="@string/select_podcasts.add_url"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/create_podcast_url"
android:inputType="textUri"
diff --git a/app/src/main/res/layout/create_user.xml b/app/src/main/res/layout/create_user.xml
index eac6e5cb..b2d8f6e0 100644
--- a/app/src/main/res/layout/create_user.xml
+++ b/app/src/main/res/layout/create_user.xml
@@ -22,7 +22,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:layout_marginLeft="4dp" />
+ android:layout_marginLeft="4dp"
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -43,7 +44,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:layout_marginLeft="4dp" />
+ android:layout_marginLeft="4dp"
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -64,14 +66,14 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:layout_marginLeft="4dp" />
+ android:layout_marginLeft="4dp"
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout>
- <ListView
+ <android.support.v7.widget.RecyclerView
android:id="@+id/settings_list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0"
- android:fastScrollEnabled="true"/>
-
+ android:scrollbars="vertical"/>
</LinearLayout> \ No newline at end of file
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/download_playlist.xml b/app/src/main/res/layout/download_playlist.xml
index 8a73ef3b..7a83330c 100644
--- a/app/src/main/res/layout/download_playlist.xml
+++ b/app/src/main/res/layout/download_playlist.xml
@@ -1,31 +1,29 @@
<?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="fill_parent"
- android:layout_weight="1">
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1">
<View
- android:layout_width="fill_parent"
- android:layout_height="1px"
- android:background="@color/dividerColor"/>
+ android:layout_width="fill_parent"
+ android:layout_height="1px"
+ android:background="?attr/colorPrimary"/>
<TextView
- android:id="@+id/download_empty"
- android:text="@string/download.empty"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:padding="10dip"/>
+ android:id="@+id/download_empty"
+ android:text="@string/download.empty"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dip"
+ android:textColor="?android:textColorPrimary"/>
- <com.mobeta.android.dslv.DragSortListView
- style="@style/DragDropListView"
+ <android.support.v7.widget.RecyclerView
android:id="@+id/download_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
- android:cacheColorHint="#00000000"
- android:fastScrollEnabled="true"/>
+ android:scrollbars="vertical"/>
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_header.xml b/app/src/main/res/layout/drawer_header.xml
new file mode 100644
index 00000000..fe0a9f2d
--- /dev/null
+++ b/app/src/main/res/layout/drawer_header.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="178dp"
+ android:orientation="vertical"
+ android:weightSum="1"
+ android:background="?attr/selectableItemBackground">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="56dp"
+ android:orientation="horizontal"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ 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"/>
+
+ <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:paddingRight="20dp"/>
+ </LinearLayout>
+
+ <de.hdodenhof.circleimageview.CircleImageView
+ android:id="@+id/header_user_avatar"
+ android:layout_width="70dp"
+ android:layout_height="70dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="38dp"/>
+</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_list_item.xml b/app/src/main/res/layout/drawer_list_item.xml
deleted file mode 100644
index 5f17c9e9..00000000
--- a/app/src/main/res/layout/drawer_list_item.xml
+++ /dev/null
@@ -1,26 +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:textSize="26sp"
- android:singleLine="true"
- android:textColor="?android:textColorPrimary"/>
-</LinearLayout>
diff --git a/app/src/main/res/layout/edit_play_action.xml b/app/src/main/res/layout/edit_play_action.xml
index a1115da6..95a3d7ff 100644
--- a/app/src/main/res/layout/edit_play_action.xml
+++ b/app/src/main/res/layout/edit_play_action.xml
@@ -14,7 +14,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/tasker.edit_shuffle_mode" />
+ android:text="@string/tasker.edit_shuffle_mode"
+ android:textColor="?android:textColorPrimary"/>
<CheckBox
android:id="@+id/edit_shuffle_checkbox"
android:layout_width="wrap_content"
@@ -33,7 +34,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/tasker.edit_shuffle_start_year" />
+ android:text="@string/tasker.edit_shuffle_start_year"
+ android:textColor="?android:textColorPrimary"/>
<CheckBox
android:id="@+id/edit_start_year_checkbox"
@@ -61,7 +63,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/tasker.edit_shuffle_end_year" />
+ android:text="@string/tasker.edit_shuffle_end_year"
+ android:textColor="?android:textColorPrimary"/>
<CheckBox
android:id="@+id/edit_end_year_checkbox"
@@ -89,7 +92,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/tasker.edit_shuffle_genre"/>
+ android:text="@string/tasker.edit_shuffle_genre"
+ android:textColor="?android:textColorPrimary"/>
<Button
android:id="@+id/edit_genre_spinner"
@@ -109,7 +113,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/tasker.edit_server_offline"/>
+ android:text="@string/tasker.edit_server_offline"
+ android:textColor="?android:textColorPrimary"/>
<Spinner
android:id="@+id/edit_offline_spinner"
diff --git a/app/src/main/res/layout/equalizer_bar.xml b/app/src/main/res/layout/equalizer_bar.xml
index 6dc91565..9e3fab5c 100644
--- a/app/src/main/res/layout/equalizer_bar.xml
+++ b/app/src/main/res/layout/equalizer_bar.xml
@@ -1,36 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
- <TextView
- android:id="@+id/equalizer.frequency"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_alignParentLeft="true"
- />
-
- <TextView
- android:id="@+id/equalizer.level"
- android:text="0 dB"
- android:textSize="12sp"
- android:gravity="right"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_alignParentRight="true"
- android:layout_toRightOf="@+id/equalizer.frequency"
- />
-
- <SeekBar
- android:id="@+id/equalizer.bar"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/equalizer.frequency"
- />
+ <TextView
+ android:id="@+id/equalizer.frequency"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_alignParentLeft="true"
+ android:textColor="?android:textColorPrimary"/>
+ <TextView
+ android:id="@+id/equalizer.level"
+ android:text="0 dB"
+ android:textSize="12sp"
+ android:gravity="right"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_alignParentRight="true"
+ android:layout_toRightOf="@+id/equalizer.frequency"
+ android:textColor="?android:textColorSecondary"/>
+ <SeekBar
+ android:id="@+id/equalizer.bar"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/equalizer.frequency"/>
</RelativeLayout>
diff --git a/app/src/main/res/layout/genre_list_item.xml b/app/src/main/res/layout/genre_list_item.xml
index 6affa24c..fb30e167 100644
--- a/app/src/main/res/layout/genre_list_item.xml
+++ b/app/src/main/res/layout/genre_list_item.xml
@@ -3,7 +3,7 @@
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:background="@android:color/transparent">
+ android:background="?attr/selectableItemBackground">
<TextView
android:id="@+id/genre_name"
@@ -17,7 +17,8 @@
android:minHeight="50dip"
android:singleLine="true"
android:ellipsize="marquee"
- android:background="@android:color/transparent"/>
+ android:background="@android:color/transparent"
+ android:textColor="?android:textColorPrimary"/>
<LinearLayout
android:layout_width="wrap_content"
@@ -31,12 +32,14 @@
android:id="@+id/genre_songs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"/>
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:textColorSecondary"/>
<TextView
android:id="@+id/genre_albums"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"/>
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/grid_view.xml b/app/src/main/res/layout/grid_view.xml
deleted file mode 100644
index 599cf92c..00000000
--- a/app/src/main/res/layout/grid_view.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<github.daneren2005.dsub.view.HeaderGridView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/gridview"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1.0"
- android:numColumns="@integer/Grid.Columns"
- android:horizontalSpacing="10dp"
- android:verticalSpacing="10dp"
- android:gravity="center"
- android:stretchMode="columnWidth"
- android:padding="24px"
- android:fastScrollEnabled="true"
- android:scrollbarStyle="outsideOverlay"/> \ No newline at end of file
diff --git a/app/src/main/res/layout/home.xml b/app/src/main/res/layout/home.xml
index e5bf5a70..043886a2 100644
--- a/app/src/main/res/layout/home.xml
+++ b/app/src/main/res/layout/home.xml
@@ -8,7 +8,7 @@
<View
android:layout_width="fill_parent"
android:layout_height="1px"
- android:background="@color/dividerColor"/>
+ android:background="?attr/colorPrimary"/>
<ListView
android:id="@+id/main_list"
diff --git a/app/src/main/res/layout/jukebox_volume.xml b/app/src/main/res/layout/jukebox_volume.xml
deleted file mode 100644
index 0c49f634..00000000
--- a/app/src/main/res/layout/jukebox_volume.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<RelativeLayout
- android:background="@drawable/toast_frame"
- android:padding="20dip"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:orientation="vertical"
- android:id="@+id/toast_layout_root"
- xmlns:android="http://schemas.android.com/apk/res/android">
-
- <TextView
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:id="@+id/jukebox_volume_title"
- android:paddingBottom="12dp"
- android:paddingRight="32dp"
- android:paddingLeft="32dp"
- android:shadowRadius="2.75"
- android:shadowColor="#bb000000"
- android:textColor="#ffffffff"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/download.jukebox_volume"
- android:gravity="center_horizontal"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentLeft="true"/>
-
- <ImageView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:id="@+id/jukebox_volume_image"
- android:paddingRight="12dip"
- android:layout_alignParentLeft="true"
- android:layout_below="@+id/jukebox_volume_title"
- android:src="@drawable/ic_action_volume_dark"/>
-
- <SeekBar
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:id="@+id/jukebox_volume_progress_bar"
- android:paddingBottom="3dp"
- android:layout_alignParentRight="true"
- android:layout_below="@+id/jukebox_volume_title"
- android:layout_toRightOf="@+id/jukebox_volume_image"
- android:indeterminate="false"/>
-</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/lyrics.xml b/app/src/main/res/layout/lyrics.xml
index 747727bd..f2aa7c7f 100644
--- a/app/src/main/res/layout/lyrics.xml
+++ b/app/src/main/res/layout/lyrics.xml
@@ -1,55 +1,54 @@
<?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="fill_parent">
-
- <include layout="@layout/tab_progress"/>
-
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1.0">
-
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <TextView
- android:id="@+id/lyrics_artist"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:gravity="center_horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="10dip"
- android:paddingRight="10dip"
- android:paddingTop="10dip"
- android:paddingBottom="4dip"
- />
-
- <TextView
- android:id="@+id/lyrics_title"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:gravity="center_horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="10dip"
- android:paddingRight="10dip"
- />
-
- <TextView
- android:id="@+id/lyrics_text"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:gravity="center_horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="10dip"
- android:paddingRight="10dip"
- />
-
- </LinearLayout>
-
- </ScrollView>
-
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <include layout="@layout/tab_progress"/>
+
+ <ScrollView
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1.0">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:id="@+id/lyrics_artist"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dip"
+ android:paddingRight="10dip"
+ android:paddingTop="10dip"
+ android:paddingBottom="4dip"
+ android:textColor="?android:textColorPrimary"/>
+
+ <TextView
+ android:id="@+id/lyrics_title"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dip"
+ android:paddingRight="10dip"
+ android:paddingBottom="12dip"
+ android:textColor="?android:textColorPrimary"/>
+
+ <TextView
+ android:id="@+id/lyrics_text"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:gravity="center_horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dip"
+ android:paddingRight="10dip"
+ android:textColor="?android:textColorSecondary"/>
+ </LinearLayout>
+ </ScrollView>
</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/progress.xml b/app/src/main/res/layout/progress.xml
index a1904c11..8a299d63 100644
--- a/app/src/main/res/layout/progress.xml
+++ b/app/src/main/res/layout/progress.xml
@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_weight="1"
- android:layout_width="0dip"
- android:layout_height="fill_parent"
- android:padding="10dp">
+ android:orientation="horizontal"
+ android:layout_weight="1"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:padding="10dp">
- <ProgressBar
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_marginRight="10dp"/>
-
- <TextView
- android:id="@+id/progress_message"
- android:text="@string/progress.wait"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"/>
+ <ProgressBar
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_marginRight="10dp"/>
+ <TextView
+ android:id="@+id/progress_message"
+ android:text="@string/progress.wait"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/save_playlist.xml b/app/src/main/res/layout/save_playlist.xml
index 8bb21748..9a85d24c 100644
--- a/app/src/main/res/layout/save_playlist.xml
+++ b/app/src/main/res/layout/save_playlist.xml
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/save_playlist_root"
- android:padding="10dip"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
+ android:id="@+id/save_playlist_root"
+ android:padding="10dip"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
- <EditText
- android:id="@+id/save_playlist_name"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:inputType="text"
- android:singleLine="true"/>
+ <EditText
+ android:id="@+id/save_playlist_name"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:singleLine="true"/>
<CheckBox
android:id="@+id/save_playlist_overwrite"
@@ -20,7 +20,8 @@
android:text="@string/playlist.overwrite"
android:layout_marginLeft="4dp"
android:checked="false"
- android:visibility="gone"/>
+ android:visibility="gone"
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout>
diff --git a/app/src/main/res/layout/search_buttons.xml b/app/src/main/res/layout/search_buttons.xml
deleted file mode 100644
index 699ad341..00000000
--- a/app/src/main/res/layout/search_buttons.xml
+++ /dev/null
@@ -1,73 +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">
-
- <TextView
- android:id="@+id/search_artists"
- android:text="@string/search.artists"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="#EFEFEF"
- android:textStyle="bold"
- android:background="#A5A5A5"
- android:gravity="center_vertical"
- android:paddingLeft="4dp"/>
-
- <TextView
- android:id="@+id/search_albums"
- android:text="@string/search.albums"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="#EFEFEF"
- android:textStyle="bold"
- android:background="#A5A5A5"
- android:gravity="center_vertical"
- android:paddingLeft="4dp"/>
-
- <TextView
- android:id="@+id/search_songs"
- android:text="@string/search.songs"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="#EFEFEF"
- android:textStyle="bold"
- android:background="#A5A5A5"
- android:gravity="center_vertical"
- android:paddingLeft="4dp"/>
-
- <TextView
- android:id="@+id/search_more_artists"
- android:text="@string/search.more"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:gravity="center"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"/>
-
- <TextView
- android:id="@+id/search_more_albums"
- android:text="@string/search.more"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:gravity="center"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"/>
-
- <TextView
- android:id="@+id/search_more_songs"
- android:text="@string/search.more"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:gravity="center"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"/>
-
-</LinearLayout>
diff --git a/app/src/main/res/layout/seekbar_preference.xml b/app/src/main/res/layout/seekbar_preference.xml
index 030b608b..74dad4cd 100644
--- a/app/src/main/res/layout/seekbar_preference.xml
+++ b/app/src/main/res/layout/seekbar_preference.xml
@@ -9,7 +9,8 @@
android:padding="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:gravity="right" />
+ android:gravity="right"
+ android:textColor="?android:textColorPrimary"/>
<SeekBar
android:id="@+id/seek_bar"
android:padding="15dip"
diff --git a/app/src/main/res/layout/select_album.xml b/app/src/main/res/layout/select_album.xml
index bbdf0e54..e72ccffd 100644
--- a/app/src/main/res/layout/select_album.xml
+++ b/app/src/main/res/layout/select_album.xml
@@ -13,16 +13,15 @@
<View
android:layout_width="fill_parent"
android:layout_height="1px"
- android:background="@color/dividerColor"/>
+ android:background="?attr/colorPrimary"/>
<include layout="@layout/tab_progress"/>
- <ListView
+ <android.support.v7.widget.RecyclerView
android:id="@+id/select_album_entries"
- android:textFilterEnabled="true"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0"
- android:fastScrollEnabled="true"/>
+ android:scrollbars="vertical"/>
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/select_album_header.xml b/app/src/main/res/layout/select_album_header.xml
index d028a476..5b2294f0 100644
--- a/app/src/main/res/layout/select_album_header.xml
+++ b/app/src/main/res/layout/select_album_header.xml
@@ -30,7 +30,8 @@
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:focusable="true"
- android:focusableInTouchMode="true">
+ android:focusableInTouchMode="true"
+ android:textColor="?android:textColorPrimary">
<requestFocus android:focusable="true"
android:focusableInTouchMode="true"
@@ -44,7 +45,8 @@
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:singleLine="true"
- android:ellipsize="end"/>
+ android:ellipsize="end"
+ android:textColor="?android:textColorPrimary"/>
<TextView
android:text="XX SONGS"
@@ -54,7 +56,8 @@
android:paddingTop="14dip"
android:textAppearance="?android:attr/textAppearanceSmall"
android:singleLine="true"
- android:ellipsize="none"/>
+ android:ellipsize="none"
+ android:textColor="?android:textColorSecondary"/>
<TextView
android:text="0:00"
@@ -63,7 +66,8 @@
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:singleLine="true"
- android:ellipsize="none"/>
+ android:ellipsize="none"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
@@ -145,9 +149,16 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout>
</FrameLayout>
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="1px"
+ android:background="?attr/colorPrimary"
+ android:layout_gravity="bottom"/>
</FrameLayout>
diff --git a/app/src/main/res/layout/select_artist_header.xml b/app/src/main/res/layout/select_artist_header.xml
index 2821ce43..9ec94ff1 100644
--- a/app/src/main/res/layout/select_artist_header.xml
+++ b/app/src/main/res/layout/select_artist_header.xml
@@ -2,7 +2,9 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:background="?attr/selectableItemBackground">
+
<LinearLayout
android:id="@+id/select_artist_folder"
android:orientation="horizontal"
@@ -30,14 +32,21 @@
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginTop="6dip"
- android:textAppearance="?android:attr/textAppearanceLarge"/>
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?attr/colorAccent"/>
<TextView android:id="@+id/select_artist_folder_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
- android:textAppearance="?android:attr/textAppearanceSmall"/>
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
</LinearLayout>
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="1px"
+ android:background="?attr/colorPrimary"/>
</LinearLayout> \ No newline at end of file
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..c77528b2
--- /dev/null
+++ b/app/src/main/res/layout/settings_activity.xml
@@ -0,0 +1,21 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <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"
+ app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+ app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
+
+ <FrameLayout
+ android:id="@+id/fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"/>
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/shuffle_dialog.xml b/app/src/main/res/layout/shuffle_dialog.xml
index 295f57cb..63778ed7 100644
--- a/app/src/main/res/layout/shuffle_dialog.xml
+++ b/app/src/main/res/layout/shuffle_dialog.xml
@@ -14,7 +14,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/shuffle.startYear" />
+ android:text="@string/shuffle.startYear"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/start_year"
android:inputType="number"
@@ -36,7 +37,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/shuffle.endYear" />
+ android:text="@string/shuffle.endYear"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/end_year"
android:inputType="number"
@@ -66,7 +68,8 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="4dp"
- android:hint="@string/shuffle.genre"/>
+ android:hint="@string/shuffle.genre"
+ android:textColor="?android:textColorPrimary"/>
<Button
android:id="@+id/genre_combo"
diff --git a/app/src/main/res/layout/song_list_item.xml b/app/src/main/res/layout/song_list_item.xml
index 86f77869..419f9524 100644
--- a/app/src/main/res/layout/song_list_item.xml
+++ b/app/src/main/res/layout/song_list_item.xml
@@ -3,7 +3,8 @@
android:id="@id/drag_handle"
android:orientation="horizontal"
android:layout_width="fill_parent"
- android:layout_height="?android:attr/listPreferredItemHeight">
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:background="?attr/selectableItemBackground">
<CheckedTextView
android:id="@+id/song_check"
@@ -25,17 +26,18 @@
android:layout_gravity="center_vertical">
<TextView
- android:id="@+id/song_title"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_gravity="left|center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:drawablePadding="6dip"
- android:paddingLeft="6dip"
- android:paddingRight="6dip"/>
+ android:id="@+id/song_title"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_gravity="left|center_vertical"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:drawablePadding="6dip"
+ android:paddingLeft="6dip"
+ android:paddingRight="6dip"
+ android:textColor="?android:textColorPrimary"/>
<ImageButton
android:id="@+id/song_bookmark"
@@ -91,7 +93,8 @@
android:textAppearance="?android:attr/textAppearanceSmall"
android:singleLine="true"
android:ellipsize="middle"
- android:paddingLeft="6dip"/>
+ android:paddingLeft="6dip"
+ android:textColor="?android:textColorSecondary"/>
<RatingBar
android:id="@+id/song_rating"
@@ -111,13 +114,14 @@
android:textAppearance="?android:attr/textAppearanceSmall"
android:singleLine="true"
android:paddingLeft="3dip"
- android:paddingRight="4dip"/>
+ android:paddingRight="4dip"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
</LinearLayout>
<ImageView
- android:id="@+id/artist_more"
+ android:id="@+id/more_button"
android:src="?attr/download_none"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
diff --git a/app/src/main/res/layout/start_timer.xml b/app/src/main/res/layout/start_timer.xml
index 9736a31d..59bd60e3 100644
--- a/app/src/main/res/layout/start_timer.xml
+++ b/app/src/main/res/layout/start_timer.xml
@@ -11,7 +11,8 @@
android:layout_marginLeft="8dp"
android:textSize="20dp"
android:paddingRight="10px"
- android:layout_gravity="center"/>
+ android:layout_gravity="center"
+ android:textColor="?android:textColorPrimary"/>
<SeekBar
android:id="@+id/timer_length_bar"
diff --git a/app/src/main/res/layout/sync_dialog.xml b/app/src/main/res/layout/sync_dialog.xml
index 5133b753..fc657186 100644
--- a/app/src/main/res/layout/sync_dialog.xml
+++ b/app/src/main/res/layout/sync_dialog.xml
@@ -8,5 +8,6 @@
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:checked="false"
- android:text="@string/offline.sync_dialog_default"/>
+ android:text="@string/offline.sync_dialog_default"
+ android:textColor="?android:textColorPrimary"/>
</FrameLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/tab_progress.xml b/app/src/main/res/layout/tab_progress.xml
index f6d326ca..7423777f 100644
--- a/app/src/main/res/layout/tab_progress.xml
+++ b/app/src/main/res/layout/tab_progress.xml
@@ -26,6 +26,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout>
</FrameLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/unscrollable_grid_view.xml b/app/src/main/res/layout/unscrollable_grid_view.xml
deleted file mode 100644
index 96bea5ce..00000000
--- a/app/src/main/res/layout/unscrollable_grid_view.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<github.daneren2005.dsub.view.UnscrollableGridView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/gridview"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:numColumns="@integer/Grid.Columns"
- android:horizontalSpacing="10dp"
- android:verticalSpacing="10dp"
- android:gravity="center"
- android:padding="20px"
- android:stretchMode="columnWidth"/> \ No newline at end of file
diff --git a/app/src/main/res/layout/update_playlist.xml b/app/src/main/res/layout/update_playlist.xml
index 7354ef5c..cc7e5ee6 100644
--- a/app/src/main/res/layout/update_playlist.xml
+++ b/app/src/main/res/layout/update_playlist.xml
@@ -22,7 +22,8 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="4dp"
- android:hint="@string/common.name" />
+ android:hint="@string/common.name"
+ android:textColor="?android:textColorPrimary"/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
@@ -36,7 +37,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/common.comment" />
+ android:text="@string/common.comment"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/get_playlist_comment"
android:inputType="text"
@@ -58,7 +60,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/common.public" />
+ android:text="@string/common.public"
+ android:textColor="?android:textColorPrimary"/>
<CheckBox
android:id="@+id/get_playlist_public"
android:layout_width="fill_parent"
diff --git a/app/src/main/res/layout/update_share.xml b/app/src/main/res/layout/update_share.xml
index 92b7137b..ef44e304 100644
--- a/app/src/main/res/layout/update_share.xml
+++ b/app/src/main/res/layout/update_share.xml
@@ -14,7 +14,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/common.name" />
+ android:text="@string/common.name"
+ android:textColor="?android:textColorPrimary"/>
<EditText
android:id="@+id/get_share_name"
android:inputType="text"
@@ -36,7 +37,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/share.expiration" />
+ android:text="@string/share.expiration"
+ android:textColor="?android:textColorPrimary"/>
<DatePicker
android:id="@+id/get_share_expire"
android:layout_width="fill_parent"
@@ -57,7 +59,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:textSize="20dp"
- android:text="@string/share.no_expiration" />
+ android:text="@string/share.no_expiration"
+ android:textColor="?android:textColorPrimary"/>
<CheckBox
android:id="@+id/get_share_no_expire"
android:layout_width="fill_parent"
diff --git a/app/src/main/res/layout/user_header.xml b/app/src/main/res/layout/user_header.xml
index 0b303afe..c8186372 100644
--- a/app/src/main/res/layout/user_header.xml
+++ b/app/src/main/res/layout/user_header.xml
@@ -34,7 +34,8 @@
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:focusable="true"
- android:focusableInTouchMode="true">
+ android:focusableInTouchMode="true"
+ android:textColor="?android:textColorPrimary">
<requestFocus android:focusable="true"
android:focusableInTouchMode="true"
@@ -49,9 +50,16 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:singleLine="true"
android:ellipsize="end"
- android:autoLink="email"/>
+ android:autoLink="email"
+ android:textColor="?android:textColorSecondary"/>
</LinearLayout>
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="1px"
+ android:background="?attr/colorPrimary"
+ android:layout_alignParentBottom="true"/>
</RelativeLayout>
diff --git a/app/src/main/res/layout/user_list_item.xml b/app/src/main/res/layout/user_list_item.xml
index dc2bdab9..aa198578 100644
--- a/app/src/main/res/layout/user_list_item.xml
+++ b/app/src/main/res/layout/user_list_item.xml
@@ -3,7 +3,7 @@
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:background="@android:color/transparent">
+ android:background="?attr/selectableItemBackground">
<github.daneren2005.dsub.view.RecyclingImageView
android:id="@+id/item_avatar"
@@ -22,7 +22,8 @@
android:paddingLeft="12dip"
android:paddingRight="6dip"
android:minHeight="50dip"
- android:background="@android:color/transparent"/>
+ android:background="@android:color/transparent"
+ android:textColor="?android:textColorPrimary"/>
<ImageButton
android:id="@+id/item_star"
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/menu/select_album.xml b/app/src/main/res/menu/select_album.xml
index 3d2228e8..c94a4a3f 100644
--- a/app/src/main/res/menu/select_album.xml
+++ b/app/src/main/res/menu/select_album.xml
@@ -3,7 +3,7 @@
xmlns:compat="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_play_now"
- android:icon="?media_button_start"
+ android:icon="?actionbar_start"
android:title="@string/menu.play"
compat:showAsAction="always|withText"/>
diff --git a/app/src/main/res/menu/select_album_list.xml b/app/src/main/res/menu/select_album_list.xml
index a9196d1c..17148a51 100644
--- a/app/src/main/res/menu/select_album_list.xml
+++ b/app/src/main/res/menu/select_album_list.xml
@@ -3,7 +3,7 @@
xmlns:compat="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_play_now"
- android:icon="?media_button_start"
+ android:icon="?actionbar_start"
android:title="@string/menu.play"
compat:showAsAction="always|withText"/>
diff --git a/app/src/main/res/menu/select_song.xml b/app/src/main/res/menu/select_song.xml
index fc4494cb..d47ad933 100644
--- a/app/src/main/res/menu/select_song.xml
+++ b/app/src/main/res/menu/select_song.xml
@@ -3,7 +3,7 @@
xmlns:compat="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_play_now"
- android:icon="?attr/media_button_start"
+ android:icon="?attr/actionbar_start"
android:title="@string/menu.play"
compat:showAsAction="always|withText"/>
diff --git a/app/src/main/res/menu/select_song_offline.xml b/app/src/main/res/menu/select_song_offline.xml
index c45405fb..7a4a5407 100644
--- a/app/src/main/res/menu/select_song_offline.xml
+++ b/app/src/main/res/menu/select_song_offline.xml
@@ -3,7 +3,7 @@
xmlns:compat="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_play_now"
- android:icon="?attr/media_button_start"
+ android:icon="?attr/actionbar_start"
android:title="@string/menu.play"
compat:showAsAction="always|withText"/>
diff --git a/app/src/main/res/menu/similar_artists.xml b/app/src/main/res/menu/similar_artists.xml
index 771555b6..f6c30fb2 100644
--- a/app/src/main/res/menu/similar_artists.xml
+++ b/app/src/main/res/menu/similar_artists.xml
@@ -4,7 +4,7 @@
<item
android:id="@+id/menu_play_now"
- android:icon="?media_button_start"
+ android:icon="?actionbar_start"
android:title="@string/menu.play"
compat:showAsAction="always|withText"/>
diff --git a/app/src/main/res/values-large/dimens.xml b/app/src/main/res/values-large/dimens.xml
index b08dda86..fe8f1a6c 100644
--- a/app/src/main/res/values-large/dimens.xml
+++ b/app/src/main/res/values-large/dimens.xml
@@ -4,4 +4,6 @@
<dimen name="Button.Small">54dip</dimen>
<dimen name="AlbumArt.Small">96dip</dimen>
<dimen name="AlbumArt.Header">210dip</dimen>
+ <dimen name="BottomBar.Text.Major">18sp</dimen>
+ <dimen name="BottomBar.Text.Minor">16sp</dimen>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values-v16/themes.xml b/app/src/main/res/values-v16/themes.xml
deleted file mode 100644
index 013ac0aa..00000000
--- a/app/src/main/res/values-v16/themes.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="DSub.TextViewStyle" parent="android:Widget.TextView">
- <item name="android:fontFamily">sans-serif-light</item>
- </style>
-
- <style name="DSub.TextViewStyle.Bold" parent="android:Widget.TextView">
- <item name="android:fontFamily">sans-serif</item>
- <item name="android:textStyle">bold</item>
- </style>
-
- <style name="DSub.ButtonStyle" parent="android:Widget.Holo.Button">
- <item name="android:fontFamily">sans-serif-light</item>
- </style>
-</resources> \ 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..2d2ebd7d 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -7,10 +7,16 @@
<attr name="media_button_repeat_off" format="reference"/>
<attr name="media_button_start" format="reference"/>
<attr name="media_button_stop" format="reference"/>
+ <attr name="actionbar_backward" format="reference"/>
+ <attr name="actionbar_forward" format="reference"/>
+ <attr name="actionbar_pause" format="reference"/>
+ <attr name="actionbar_start" format="reference"/>
+ <attr name="actionbar_stop" format="reference"/>
<attr name="chat_send" format="reference"/>
<attr name="add" format="reference"/>
<attr name="download_none" format="reference"/>
<attr name="shuffle" format="reference"/>
+ <attr name="shuffle_button" format="reference"/>
<attr name="refresh" format="reference"/>
<attr name="search" format="reference"/>
<attr name="remove" format="reference"/>
@@ -27,6 +33,19 @@
<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"/>
+ <attr name="actionbarTitleStyle" format="reference"/>
+ <attr name="actionbarSubtitleStyle" format="reference"/>
+ <attr name="actionbarPopupStyle" format="reference"/>
<declare-styleable name="SeekBarPreference">
<attr name="min" format="integer"/>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index b1422ad6..e35d0311 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,17 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <color name="lightBackground">#F1F0E6</color>
- <color name="dividerColor">#FF33B5E5</color>
<color name="appwidget_text">#FFFFFF</color>
<color name="notificationArtist">#434343</color>
<color name="notificationTitle">#000000</color>
- <color name="background_holo_light">#ff33b5e5</color>
<color name="overlayColor">#80000000</color>
- <color name="ics_opaque">#8033b5e5</color>
- <color name="cyan">#ff0099cc</color>
<color name="holo_blue_light">#ff33b5e5</color>
<color name="holo_orange_light">#ffffbb33</color>
<color name="holo_green_light">#ff99cc00</color>
<color name="holo_red_light">#ffff4444</color>
+
+ <color name="lightPrimary">#2196f3</color>
+ <color name="lightPrimaryDark">#1e88e5</color>
+ <color name="lightAccent">#448aff</color>
+
+ <color name="darkPrimary">#f44336</color>
+ <color name="darkPrimaryDark">#e53935</color>
+ <color name="darkAccent">#ff5252</color>
+
+ <color name="holoPrimary">#009688</color>
+ <color name="holoPrimaryDark">#00897b</color>
+ <color name="holoAccent">#64ffda</color>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index be3e843d..9759e1c2 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -4,4 +4,6 @@
<dimen name="Button.Small">46dip</dimen>
<dimen name="AlbumArt.Small">78dip</dimen>
<dimen name="AlbumArt.Header">120dip</dimen>
+ <dimen name="BottomBar.Text.Major">13sp</dimen>
+ <dimen name="BottomBar.Text.Minor">12sp</dimen>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8544c6e3..bb0a997b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -79,6 +79,8 @@
<string name="main.songs_genres">@string/main.albums_genres</string>
<string name="main.back_confirm">Press back again to exit</string>
<string name="main.scan_complete">Completed scan of Server</string>
+ <string name="main.artist">Artist</string>
+ <string name="main.title">Title</string>
<string name="menu.search">Search</string>
<string name="menu.shuffle">Shuffle</string>
@@ -234,7 +236,9 @@
<string name="starring_content_starred">Starred \"%s\"</string>
<string name="starring_content_unstarred">Unstarred \"%s\"</string>
<string name="starring_content_error">Failed to update \"%s\", please try later.</string>
-
+
+ <string name="playlist.mine">My Playlists</string>
+ <string name="playlist.shared">Shared Playlists</string>
<string name="playlist_error">Failed to grab list of playlists</string>
<string name="updated_playlist">Added %1$s songs to \"%2$s\"</string>
<string name="updated_playlist_error">Failed to update \"%s\", please try later.</string>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 43271afd..83fa4a42 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="BasicButton">
- <item name="android:background">@drawable/abc_item_background_holo_light</item>
+ <item name="android:background">?attr/selectableItemBackground</item>
</style>
<style name="MoreButton" parent="BasicButton">
@@ -23,15 +23,12 @@
<item name="android:layout_width">@dimen/Button.Small</item>
<item name="android:layout_height">@dimen/Button.Small</item>
</style>
-
- <style name="MenuBarButton" parent="@style/BasicButton">
- <item name="android:layout_width">0dip</item>
- <item name="android:layout_height">45dip</item>
- <item name="android:layout_weight">1</item>
- <item name="android:textSize">14sp</item>
- <item name="android:textStyle">bold</item>
- <item name="android:textColor">?android:textColorPrimary</item>
- </style>
+
+ <style name="PlaybackControl.Match" parent="@style/PlaybackControl">
+ <item name="android:padding">4dip</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_width">wrap_content</item>
+ </style>
<style name="DownloadActionButton" parent="@style/BasicButton">
<item name="android:layout_width">wrap_content</item>
@@ -52,44 +49,4 @@
<item name="android:paddingRight">16dip</item>
<item name="android:paddingLeft">16dip</item>
</style>
-
- <style name="DragDropListView">
- <item name="drag_enabled">true</item>
- <item name="collapsed_height">1dp</item>
- <item name="drag_scroll_start">1.0</item>
- <item name="max_drag_scroll_speed">2.0</item>
- <item name="float_alpha">0.6</item>
- <item name="slide_shuffle_speed">0.3</item>
- <item name="track_drag_sort">false</item>
- <item name="use_default_controller">true</item>
- <item name="drag_handle_id">@id/drag_handle</item>
- <item name="sort_enabled">true</item>
- <item name="remove_enabled">false</item>
- <item name="remove_mode">flingRemove</item>
- <item name="drag_start_mode">onLongPress</item>
- <item name="float_background_color">@android:color/transparent</item>
- </style>
-
- <style name="MainAlbumButton">
- <item name="android:drawablePadding">6dip</item>
- <item name="android:layout_width">fill_parent</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
- <item name="android:gravity">center_vertical</item>
- <item name="android:paddingLeft">6dip</item>
- <item name="android:paddingRight">6dip</item>
- <item name="android:minHeight">46dip</item>
- </style>
-
- <style name="MainAlbumButtonLabel">
- <item name="android:layout_width">fill_parent</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
- <item name="android:textColor">@color/cyan</item>
- <item name="android:gravity">center_vertical</item>
- <item name="android:paddingLeft">6dp</item>
- <item name="android:textAllCaps">true</item>
- <item name="android:textStyle">bold</item>
- <item name="android:textSize">16sp</item>
- </style>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 78a2c34d..fb47af81 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.DarkActionBar">
<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>
@@ -10,34 +8,51 @@
<item name="media_button_repeat_off">@drawable/media_repeat_off_light</item>
<item name="media_button_start">@drawable/media_start_light</item>
<item name="media_button_stop">@drawable/media_stop_light</item>
+ <item name="actionbar_backward">@drawable/media_backward_dark</item>
+ <item name="actionbar_forward">@drawable/media_forward_dark</item>
+ <item name="actionbar_pause">@drawable/media_pause_dark</item>
+ <item name="actionbar_start">@drawable/media_start_dark</item>
+ <item name="actionbar_stop">@drawable/media_stop_dark</item>
<item name="chat_send">@drawable/ic_menu_chat_send_light</item>
- <item name="add">@drawable/ic_action_add_light</item>
+ <item name="add">@drawable/ic_action_add_dark</item>
<item name="download_none">@drawable/download_none_light</item>
- <item name="shuffle">@drawable/ic_menu_shuffle_light</item>
- <item name="refresh">@drawable/ic_menu_refresh_light</item>
- <item name="search">@drawable/ic_menu_search_light</item>
- <item name="remove">@drawable/ic_menu_remove_light</item>
- <item name="save">@drawable/ic_menu_save_light</item>
+ <item name="shuffle">@drawable/ic_menu_shuffle_dark</item>
+ <item name="shuffle_button">@drawable/ic_menu_shuffle_light</item>
+ <item name="refresh">@drawable/ic_menu_refresh_dark</item>
+ <item name="search">@drawable/ic_menu_search_dark</item>
+ <item name="remove">@drawable/ic_menu_remove_dark</item>
+ <item name="save">@drawable/ic_menu_save_dark</item>
<item name="volume">@drawable/ic_action_volume_light</item>
<item name="toggle_list">@drawable/action_toggle_list_light</item>
<item name="select_server">@drawable/main_select_server_light</item>
<item name="downloading">@drawable/downloading_light</item>
<item name="bookmark">@drawable/ic_menu_bookmark_light</item>
<item name="share">@drawable/ic_menu_share_light</item>
- <item name="add_person">@drawable/ic_menu_add_person_light</item>
- <item name="password">@drawable/ic_menu_password_light</item>
+ <item name="add_person">@drawable/ic_menu_add_person_dark</item>
+ <item name="password">@drawable/ic_menu_password_dark</item>
<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="android:textViewStyle">@style/DSub.TextViewStyle</item>
- <item name="android:buttonStyle">@style/DSub.ButtonStyle.Light</item>
+ <item name="radio">@drawable/ic_menu_radio_dark</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="drawerArrowStyle">@style/DSub.DrawerArrow</item>
- <item name="colorAccent">@color/cyan</item>
+ <item name="colorPrimary">@color/lightPrimary</item>
+ <item name="colorPrimaryDark">@color/lightPrimaryDark</item>
+ <item name="colorAccent">@color/lightAccent</item>
+ <item name="actionbarTitleStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse</item>
+ <item name="actionbarSubtitleStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse</item>
+ <item name="actionbarPopupStyle">@style/ThemeOverlay.AppCompat.Light</item>
+ <item name="android:spinnerItemStyle">@style/DarkSpinnerItem</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>
@@ -45,10 +60,16 @@
<item name="media_button_repeat_off">@drawable/media_repeat_off</item>
<item name="media_button_start">@drawable/media_start_dark</item>
<item name="media_button_stop">@drawable/media_stop_dark</item>
+ <item name="actionbar_backward">@drawable/media_backward_dark</item>
+ <item name="actionbar_forward">@drawable/media_forward_dark</item>
+ <item name="actionbar_pause">@drawable/media_pause_dark</item>
+ <item name="actionbar_start">@drawable/media_start_dark</item>
+ <item name="actionbar_stop">@drawable/media_stop_dark</item>
<item name="chat_send">@drawable/ic_menu_chat_send_dark</item>
<item name="add">@drawable/ic_action_add_dark</item>
<item name="download_none">@drawable/download_none_dark</item>
<item name="shuffle">@drawable/ic_menu_shuffle_dark</item>
+ <item name="shuffle_button">@drawable/ic_menu_shuffle_dark</item>
<item name="refresh">@drawable/ic_menu_refresh_dark</item>
<item name="search">@drawable/ic_menu_search_dark</item>
<item name="remove">@drawable/ic_menu_remove_dark</item>
@@ -64,46 +85,60 @@
<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="android:textViewStyle">@style/DSub.TextViewStyle</item>
- <item name="android:buttonStyle">@style/DSub.ButtonStyle.Dark</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="drawerArrowStyle">@style/DSub.DrawerArrow</item>
- <item name="colorAccent">@color/cyan</item>
+ <item name="colorPrimary">@color/darkPrimary</item>
+ <item name="colorPrimaryDark">@color/darkPrimaryDark</item>
+ <item name="colorAccent">@color/darkAccent</item>
+ <item name="actionbarTitleStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Title</item>
+ <item name="actionbarSubtitleStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle</item>
+ <item name="actionbarPopupStyle">@style/ThemeOverlay.AppCompat.Dark</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>
<style name="Theme.DSub.Holo" parent="Theme.DSub.Dark">
<item name="android:windowBackground">@drawable/background</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>
+ <item name="colorPrimary">@color/holoPrimary</item>
+ <item name="colorPrimaryDark">@color/holoPrimaryDark</item>
+ <item name="colorAccent">@color/holoAccent</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 name="Theme.DSub.Light.No_Actionbar" parent="Theme.DSub.Light">
+ <item name="windowActionBar">false</item>
+ <item name="windowNoTitle">true</item>
</style>
-
- <style name="DSub.TextViewStyle" parent="android:Widget.TextView">
+ <style name="Theme.DSub.Black.No_Actionbar" parent="Theme.DSub.Black">
+ <item name="windowActionBar">false</item>
+ <item name="windowNoTitle">true</item>
</style>
-
- <style name="DSub.TextViewStyle.Bold" parent="android:Widget.TextView">
- <item name="android:textStyle">bold</item>
+ <style name="Theme.DSub.Dark.No_Actionbar" parent="Theme.DSub.Dark">
+ <item name="windowActionBar">false</item>
+ <item name="windowNoTitle">true</item>
</style>
-
- <style name="DSub.ButtonStyle.Dark" parent="android:Widget.Holo.Button">
- </style>
- <style name="DSub.ButtonStyle.Light" parent="android:Widget.Holo.Light.Button">
+ <style name="Theme.DSub.Holo.No_Actionbar" parent="Theme.DSub.Holo">
+ <item name="windowActionBar">false</item>
+ <item name="windowNoTitle">true</item>
</style>
<style name="DSub.DrawerArrow" parent="Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
</style>
+
+ <style name="DarkSpinnerItem" parent="Widget.AppCompat.TextView.SpinnerItem">
+ <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+ </style>
</resources>