aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java113
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/MergeAdapter.java290
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/SackOfViewsAdapter.java181
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java41
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java267
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/AlbumListCountView.java132
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java5
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/UpdateView.java4
-rw-r--r--app/src/main/res/layout/album_list_header.xml28
-rw-r--r--app/src/main/res/layout/album_list_item.xml3
-rw-r--r--app/src/main/res/layout/basic_count_item.xml2
-rw-r--r--app/src/main/res/layout/main_buttons.xml157
12 files changed, 386 insertions, 837 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java
new file mode 100644
index 00000000..e451bc19
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java
@@ -0,0 +1,113 @@
+/*
+ This file is part of Subsonic.
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+ Copyright 2015 (C) Scott Jackson
+*/
+
+package github.daneren2005.dsub.adapter;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+
+import java.util.List;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.ServerInfo;
+import github.daneren2005.dsub.util.Util;
+import github.daneren2005.dsub.view.AlbumListCountView;
+import github.daneren2005.dsub.view.BasicHeaderView;
+import github.daneren2005.dsub.view.BasicListView;
+import github.daneren2005.dsub.view.UpdateView;
+
+public class MainAdapter extends SectionAdapter<Integer> {
+ public static final int VIEW_TYPE_ALBUM_LIST = 1;
+ public static final int VIEW_TYPE_ALBUM_COUNT_LIST = 2;
+
+ public MainAdapter(Context context, List<String> headers, List<List<Integer>> sections, OnItemClickedListener onItemClickedListener) {
+ super(context, headers, sections);
+ this.onItemClickedListener = onItemClickedListener;
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ UpdateView updateView;
+ if(viewType == VIEW_TYPE_ALBUM_LIST) {
+ updateView = new BasicListView(context);
+ } else {
+ updateView = new AlbumListCountView(context);
+ }
+
+ return new UpdateView.UpdateViewHolder(updateView);
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Integer item, int viewType) {
+ UpdateView updateView = holder.getUpdateView();
+
+ if(viewType == VIEW_TYPE_ALBUM_LIST) {
+ updateView.setObject(context.getResources().getString(item));
+ } else {
+ // Hacky method to make sure updateBackground is called in background thread
+ updateView.setObject(item, null);
+ }
+ }
+
+ @Override
+ public int getItemViewType(Integer item) {
+ if(item == R.string.main_albums_newest) {
+ return VIEW_TYPE_ALBUM_COUNT_LIST;
+ } else {
+ return VIEW_TYPE_ALBUM_LIST;
+ }
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
+ return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.album_list_header));
+ }
+ @Override
+ public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header) {
+ UpdateView view = holder.getUpdateView();
+ CheckBox checkBox = (CheckBox) view.findViewById(R.id.item_checkbox);
+
+ String display;
+ if ("albums".equals(header)) {
+ display = context.getResources().getString(R.string.main_albums_title);
+
+ if(!Util.isOffline(context) && ServerInfo.canAlbumListPerFolder(context)) {
+ checkBox.setVisibility(View.VISIBLE);
+ checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ Util.setAlbumListsPerFolder(context, isChecked);
+ }
+ });
+ checkBox.setChecked(Util.getAlbumListsPerFolder(context));
+ } else {
+ checkBox.setVisibility(View.GONE);
+ }
+ } else if("videos".equals(header)) {
+ display = context.getResources().getString(R.string.main_videos);
+ checkBox.setVisibility(View.GONE);
+ } else {
+ display = header;
+ checkBox.setVisibility(View.GONE);
+ }
+
+ if(view != null) {
+ view.setObject(display);
+ }
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/MergeAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/MergeAdapter.java
deleted file mode 100644
index a2db4cf0..00000000
--- a/app/src/main/java/github/daneren2005/dsub/adapter/MergeAdapter.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/***
- Copyright (c) 2008-2009 CommonsWare, LLC
- Portions (c) 2009 Google, Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License"); you may
- not use this file except in compliance with the License. You may obtain
- a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-package github.daneren2005.dsub.adapter;
-
-import android.database.DataSetObserver;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ListAdapter;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Arrays;
-
-/**
- * Adapter that merges multiple child adapters and views
- * into a single contiguous whole.
- * <p/>
- * Adapters used as pieces within MergeAdapter must
- * have view type IDs monotonically increasing from 0. Ideally,
- * adapters also have distinct ranges for their row ids, as
- * returned by getItemId().
- */
-public class MergeAdapter extends BaseAdapter {
-
- private final CascadeDataSetObserver observer = new CascadeDataSetObserver();
- private final ArrayList<ListAdapter> pieces = new ArrayList<ListAdapter>();
-
- /**
- * Stock constructor, simply chaining to the superclass.
- */
- public MergeAdapter() {
- super();
- }
-
- /**
- * Adds a new adapter to the roster of things to appear
- * in the aggregate list.
- *
- * @param adapter Source for row views for this section
- */
- public void addAdapter(ListAdapter adapter) {
- pieces.add(adapter);
- adapter.registerDataSetObserver(observer);
- }
-
- public void removeAdapter(ListAdapter adapter) {
- adapter.unregisterDataSetObserver(observer);
- pieces.remove(adapter);
- }
-
- /**
- * Adds a new View to the roster of things to appear
- * in the aggregate list.
- *
- * @param view Single view to add
- */
- public ListAdapter addView(View view) {
- return addView(view, false);
- }
-
- /**
- * Adds a new View to the roster of things to appear
- * in the aggregate list.
- *
- * @param view Single view to add
- * @param enabled false if views are disabled, true if enabled
- */
- public ListAdapter addView(View view, boolean enabled) {
- return addViews(Arrays.asList(view), enabled);
- }
-
- /**
- * Adds a list of views to the roster of things to appear
- * in the aggregate list.
- *
- * @param views List of views to add
- */
- public ListAdapter addViews(List<View> views) {
- return addViews(views, false);
- }
-
- /**
- * Adds a list of views to the roster of things to appear
- * in the aggregate list.
- *
- * @param views List of views to add
- * @param enabled false if views are disabled, true if enabled
- */
- public ListAdapter addViews(List<View> views, boolean enabled) {
- ListAdapter adapter = enabled ? new EnabledSackAdapter(views) : new SackOfViewsAdapter(views);
- addAdapter(adapter);
- return adapter;
- }
-
- /**
- * Get the data item associated with the specified
- * position in the data set.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public Object getItem(int position) {
- for (ListAdapter piece : pieces) {
- int size = piece.getCount();
-
- if (position < size) {
- return (piece.getItem(position));
- }
-
- position -= size;
- }
-
- return (null);
- }
-
- /**
- * How many items are in the data set represented by this
- * Adapter.
- */
- @Override
- public int getCount() {
- int total = 0;
-
- for (ListAdapter piece : pieces) {
- total += piece.getCount();
- }
-
- return (total);
- }
-
- /**
- * Returns the number of types of Views that will be
- * created by getView().
- */
- @Override
- public int getViewTypeCount() {
- int total = 0;
-
- for (ListAdapter piece : pieces) {
- total += piece.getViewTypeCount();
- }
-
- return (Math.max(total, 1)); // needed for setListAdapter() before content add'
- }
-
- /**
- * Get the type of View that will be created by getView()
- * for the specified item.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public int getItemViewType(int position) {
- int typeOffset = 0;
- int result = -1;
-
- for (ListAdapter piece : pieces) {
- int size = piece.getCount();
-
- if (position < size) {
- result = typeOffset + piece.getItemViewType(position);
- break;
- }
-
- position -= size;
- typeOffset += piece.getViewTypeCount();
- }
-
- return (result);
- }
-
- /**
- * Are all items in this ListAdapter enabled? If yes it
- * means all items are selectable and clickable.
- */
- @Override
- public boolean areAllItemsEnabled() {
- return (false);
- }
-
- /**
- * Returns true if the item at the specified position is
- * not a separator.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public boolean isEnabled(int position) {
- for (ListAdapter piece : pieces) {
- int size = piece.getCount();
-
- if (position < size) {
- return (piece.isEnabled(position));
- }
-
- position -= size;
- }
-
- return (false);
- }
-
- /**
- * Get a View that displays the data at the specified
- * position in the data set.
- *
- * @param position Position of the item whose data we want
- * @param convertView View to recycle, if not null
- * @param parent ViewGroup containing the returned View
- */
- @Override
- public View getView(int position, View convertView,
- ViewGroup parent) {
- for (ListAdapter piece : pieces) {
- int size = piece.getCount();
-
- if (position < size) {
-
- return (piece.getView(position, convertView, parent));
- }
-
- position -= size;
- }
-
- return (null);
- }
-
- /**
- * Get the row id associated with the specified position
- * in the list.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public long getItemId(int position) {
- for (ListAdapter piece : pieces) {
- int size = piece.getCount();
-
- if (position < size) {
- return (piece.getItemId(position));
- }
-
- position -= size;
- }
-
- return (-1);
- }
-
- private static class EnabledSackAdapter extends SackOfViewsAdapter {
- public EnabledSackAdapter(List<View> views) {
- super(views);
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return (true);
- }
-
- @Override
- public boolean isEnabled(int position) {
- return (true);
- }
- }
-
- private class CascadeDataSetObserver extends DataSetObserver {
- @Override
- public void onChanged() {
- notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated() {
- notifyDataSetInvalidated();
- }
- }
-}
-
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SackOfViewsAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SackOfViewsAdapter.java
deleted file mode 100644
index e4744cc5..00000000
--- a/app/src/main/java/github/daneren2005/dsub/adapter/SackOfViewsAdapter.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/***
- Copyright (c) 2008-2009 CommonsWare, LLC
- Portions (c) 2009 Google, Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License"); you may
- not use this file except in compliance with the License. You may obtain
- a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-package github.daneren2005.dsub.adapter;
-
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ListView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Adapter that simply returns row views from a list.
- * <p/>
- * If you supply a size, you must implement newView(), to
- * create a required view. The adapter will then cache these
- * views.
- * <p/>
- * If you supply a list of views in the constructor, that
- * list will be used directly. If any elements in the list
- * are null, then newView() will be called just for those
- * slots.
- * <p/>
- * Subclasses may also wish to override areAllItemsEnabled()
- * (default: false) and isEnabled() (default: false), if some
- * of their rows should be selectable.
- * <p/>
- * It is assumed each view is unique, and therefore will not
- * get recycled.
- * <p/>
- * Note that this adapter is not designed for long lists. It
- * is more for screens that should behave like a list. This
- * is particularly useful if you combine this with other
- * adapters (e.g., SectionedAdapter) that might have an
- * arbitrary number of rows, so it all appears seamless.
- */
-public class SackOfViewsAdapter extends BaseAdapter {
- private List<View> views = null;
-
- /**
- * Constructor creating an empty list of views, but with
- * a specified count. Subclasses must override newView().
- */
- public SackOfViewsAdapter(int count) {
- super();
-
- views = new ArrayList<View>(count);
-
- for (int i = 0; i < count; i++) {
- views.add(null);
- }
- }
-
- /**
- * Constructor wrapping a supplied list of views.
- * Subclasses must override newView() if any of the elements
- * in the list are null.
- */
- public SackOfViewsAdapter(List<View> views) {
- for (View view : views) {
- view.setLayoutParams(new ListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
- }
- this.views = views;
- }
-
- /**
- * Get the data item associated with the specified
- * position in the data set.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public Object getItem(int position) {
- return (views.get(position));
- }
-
- /**
- * How many items are in the data set represented by this
- * Adapter.
- */
- @Override
- public int getCount() {
- return (views.size());
- }
-
- /**
- * Returns the number of types of Views that will be
- * created by getView().
- */
- @Override
- public int getViewTypeCount() {
- return (getCount());
- }
-
- /**
- * Get the type of View that will be created by getView()
- * for the specified item.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public int getItemViewType(int position) {
- return (position);
- }
-
- /**
- * Are all items in this ListAdapter enabled? If yes it
- * means all items are selectable and clickable.
- */
- @Override
- public boolean areAllItemsEnabled() {
- return (false);
- }
-
- /**
- * Returns true if the item at the specified position is
- * not a separator.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public boolean isEnabled(int position) {
- return (false);
- }
-
- /**
- * Get a View that displays the data at the specified
- * position in the data set.
- *
- * @param position Position of the item whose data we want
- * @param convertView View to recycle, if not null
- * @param parent ViewGroup containing the returned View
- */
- @Override
- public View getView(int position, View convertView,
- ViewGroup parent) {
- View result = views.get(position);
-
- if (result == null) {
- result = newView(position, parent);
- views.set(position, result);
- }
-
- return (result);
- }
-
- /**
- * Get the row id associated with the specified position
- * in the list.
- *
- * @param position Position of the item whose data we want
- */
- @Override
- public long getItemId(int position) {
- return (position);
- }
-
- /**
- * Create a new View to go into the list at the specified
- * position.
- *
- * @param position Position of the item whose data we want
- * @param parent ViewGroup containing the returned View
- */
- protected View newView(int position, ViewGroup parent) {
- throw new RuntimeException("You must override newView()!");
- }
-}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java
index 599870d7..f57012b5 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java
@@ -77,6 +77,7 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
@Override
public void onClick(View v) {
T item = holder.getItem();
+ updateView.onClick();
if (updateView.isCheckable()) {
if (selected.contains(item)) {
selected.remove(item);
@@ -136,15 +137,17 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
}
int subPosition = 0;
+ int subHeader = 0;
for(List<T> section: sections) {
- if(position == subPosition) {
- int index = sections.indexOf(section);
- onBindHeaderHolder(holder, headers.get(index));
+ boolean validHeader = headers.get(subHeader) != null;
+ if(position == subPosition && validHeader) {
+ onBindHeaderHolder(holder, headers.get(subHeader));
return;
}
- if(position <= (subPosition + section.size())) {
- T item = section.get(position - subPosition - 1);
+ int headerOffset = validHeader ? 1 : 0;
+ if(position < (subPosition + section.size() + headerOffset)) {
+ T item = section.get(position - subPosition - headerOffset);
onBindViewHolder(holder, item, getItemViewType(item));
if(updateView.isCheckable()) {
@@ -154,7 +157,11 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
return;
}
- subPosition += section.size() + 1;
+ subPosition += section.size();
+ if(validHeader) {
+ subPosition += 1;
+ }
+ subHeader++;
}
}
@@ -164,7 +171,12 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
return sections.get(0).size();
}
- int count = headers.size();
+ int count = 0;
+ for(String header: headers) {
+ if(header != null) {
+ count++;
+ }
+ }
for(List<T> section: sections) {
count += section.size();
}
@@ -179,16 +191,23 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH
}
int subPosition = 0;
+ int subHeader = 0;
for(List<T> section: sections) {
- if(position == subPosition) {
+ boolean validHeader = headers.get(subHeader) != null;
+ if(position == subPosition && validHeader) {
return VIEW_TYPE_HEADER;
}
- if(position <= (subPosition + section.size())) {
- return getItemViewType(section.get(position - subPosition - 1));
+ int headerOffset = validHeader ? 1 : 0;
+ if(position < (subPosition + section.size() + headerOffset)) {
+ return getItemViewType(section.get(position - subPosition - headerOffset));
}
- subPosition += section.size() + 1;
+ subPosition += section.size();
+ if(validHeader) {
+ subPosition += 1;
+ }
+ subHeader++;
}
return -1;
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
index 0c33ef8c..90a91383 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
@@ -9,28 +9,23 @@ import android.os.Build;
import android.os.Bundle;
import android.os.StatFs;
import android.util.Log;
-import android.view.ContextMenu;
-import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.ListView;
-import android.widget.TextView;
+
import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.adapter.MainAdapter;
+import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.ServerInfo;
import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.FileUtil;
import github.daneren2005.dsub.util.LoadingTask;
import github.daneren2005.dsub.util.Pair;
+import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.UserUtil;
-import github.daneren2005.dsub.adapter.MergeAdapter;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
@@ -41,37 +36,13 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-public class MainFragment extends SubsonicFragment {
+public class MainFragment extends SelectRecyclerFragment<Integer> {
private static final String TAG = MainFragment.class.getSimpleName();
- private LayoutInflater inflater;
- private TextView countView;
-
- private static final int MENU_GROUP_SERVER = 10;
- private static final int MENU_ITEM_SERVER_BASE = 100;
-
- @Override
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- this.inflater = inflater;
- rootView = inflater.inflate(R.layout.home, container, false);
-
- createLayout();
- return rootView;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
+ public MainFragment() {
+ super();
+ pullToRefresh = false;
+ serialize = false;
}
@Override
@@ -116,100 +87,56 @@ public class MainFragment extends SubsonicFragment {
}
@Override
- protected void refresh(boolean refresh) {
- createLayout();
+ public int getOptionsMenu() {
+ return 0;
}
- private void createLayout() {
- View buttons = inflater.inflate(R.layout.main_buttons, null);
-
- 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 CheckBox albumsPerFolderCheckbox = (CheckBox) buttons.findViewById(R.id.main_albums_per_folder);
- if(!Util.isOffline(context) && ServerInfo.canAlbumListPerFolder(context)) {
- albumsPerFolderCheckbox.setChecked(Util.getAlbumListsPerFolder(context));
- albumsPerFolderCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- Util.setAlbumListsPerFolder(context, isChecked);
- }
- });
- } else {
- albumsPerFolderCheckbox.setVisibility(View.GONE);
- }
-
- int instance = Util.getActiveServer(context);
- String name = Util.getServerName(context, instance);
+ @Override
+ public SectionAdapter getAdapter(List objs) {
+ List<List<Integer>> sections = new ArrayList<>();
+ List<String> headers = new ArrayList<>();
- ListView list = (ListView) rootView.findViewById(R.id.main_list);
+ List<Integer> offline = Arrays.asList(R.string.main_offline);
+ sections.add(offline);
+ headers.add(null);
- MergeAdapter adapter = new MergeAdapter();
- 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);
- list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (view == offlineButton) {
- toggleOffline();
- } else if (view == albumsNewestButton) {
- showAlbumList("newest");
- } else if (view == albumsRandomButton) {
- showAlbumList("random");
- } else if (view == albumsHighestButton) {
- showAlbumList("highest");
- } else if (view == albumsRecentButton) {
- showAlbumList("recent");
- } else if (view == albumsFrequentButton) {
- showAlbumList("frequent");
- } else if (view == albumsStarredButton) {
- showAlbumList("starred");
- } else if(view == albumsGenresButton) {
- showAlbumList("genres");
- } else if(view == albumsYearButton) {
- showAlbumList("years");
- } else if(view == albumsAlphabeticalButton) {
- showAlbumList("alphabeticalByName");
- } else if(view == videosButton) {
- showVideos();
- }
- }
- });
- setTitle(R.string.common_appname);
+ return new MainAdapter(context, headers, sections, this);
+ }
- if(!Util.isOffline(context)) {
- getMostRecentCount();
- }
+ @Override
+ public List<Integer> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
+ return Arrays.asList(0);
+ }
+
+ @Override
+ public int getTitleResource() {
+ return R.string.common_appname;
}
private void toggleOffline() {
@@ -247,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();
@@ -447,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/view/AlbumListCountView.java b/app/src/main/java/github/daneren2005/dsub/view/AlbumListCountView.java
new file mode 100644
index 00000000..81695f53
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/view/AlbumListCountView.java
@@ -0,0 +1,132 @@
+/*
+ This file is part of Subsonic.
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+ Copyright 2015 (C) Scott Jackson
+*/
+
+package github.daneren2005.dsub.view;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.service.MusicService;
+import github.daneren2005.dsub.service.MusicServiceFactory;
+import github.daneren2005.dsub.util.Constants;
+import github.daneren2005.dsub.util.FileUtil;
+import github.daneren2005.dsub.util.Util;
+
+public class AlbumListCountView extends UpdateView {
+ private final String TAG = AlbumListCountView.class.getSimpleName();
+
+ private TextView titleView;
+ private TextView countView;
+ private int albumListString;
+ private int startCount;
+ private int count = 0;
+
+ public AlbumListCountView(Context context) {
+ super(context, false);
+ this.context = context;
+ LayoutInflater.from(context).inflate(R.layout.basic_count_item, this, true);
+
+ titleView = (TextView) findViewById(R.id.basic_count_name);
+ countView = (TextView) findViewById(R.id.basic_count_count);
+ }
+
+ protected void setObjectImpl(Object obj1, Object obj2) {
+ this.albumListString = (Integer) obj1;
+ titleView.setText(albumListString);
+
+ SharedPreferences prefs = Util.getPreferences(context);
+ startCount = prefs.getInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0);
+ count = startCount;
+ update();
+ }
+
+ @Override
+ protected void updateBackground() {
+ try {
+ String recentAddedFile = Util.getCacheName(context, "recent_count");
+ ArrayList<String> recents = FileUtil.deserialize(context, recentAddedFile, ArrayList.class);
+ if (recents == null) {
+ recents = new ArrayList<String>();
+ }
+
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ MusicDirectory recentlyAdded = musicService.getAlbumList("newest", 20, 0, context, null);
+
+ // If first run, just put everything in it and return 0
+ boolean firstRun = recents.isEmpty();
+
+ // Count how many new albums are in the list
+ count = 0;
+ for (MusicDirectory.Entry album : recentlyAdded.getChildren()) {
+ if (!recents.contains(album.getId())) {
+ recents.add(album.getId());
+ count++;
+ }
+ }
+
+ // Keep recents list from growing infinitely
+ while (recents.size() > 40) {
+ recents.remove(0);
+ }
+ FileUtil.serialize(context, recents, recentAddedFile);
+
+ if (!firstRun) {
+ // Add the old count which will get cleared out after viewing recents
+ count += startCount;
+ SharedPreferences.Editor editor = Util.getPreferences(context).edit();
+ editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), count);
+ editor.commit();
+ }
+ } catch(Exception e) {
+ Log.w(TAG, "Failed to refresh most recent count", e);
+ }
+ }
+
+ @Override
+ protected void update() {
+ // Update count display with appropriate information
+ if(count <= 0) {
+ countView.setVisibility(View.GONE);
+ } else {
+ String displayName;
+ if(count < 10) {
+ displayName = "0" + count;
+ } else {
+ displayName = "" + count;
+ }
+
+ countView.setText(displayName);
+ countView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void onClick() {
+ SharedPreferences.Editor editor = Util.getPreferences(context).edit();
+ editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0);
+ editor.commit();
+
+ count = 0;
+ update();
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java b/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java
index d8111692..b5dad2d1 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/BasicHeaderView.java
@@ -25,9 +25,12 @@ public class BasicHeaderView extends UpdateView {
TextView nameView;
public BasicHeaderView(Context context) {
+ this(context, R.layout.basic_header);
+ }
+ public BasicHeaderView(Context context, int layout) {
super(context, false);
- LayoutInflater.from(context).inflate(R.layout.basic_header, this, true);
+ LayoutInflater.from(context).inflate(layout, this, true);
nameView = (TextView) findViewById(R.id.item_name);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java b/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java
index 62d1672d..44831c60 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java
@@ -288,6 +288,10 @@ public class UpdateView extends LinearLayout {
return checkable;
}
+ public void onClick() {
+
+ }
+
public static class UpdateViewHolder<T> extends RecyclerView.ViewHolder {
private UpdateView updateView;
private View view;
diff --git a/app/src/main/res/layout/album_list_header.xml b/app/src/main/res/layout/album_list_header.xml
new file mode 100644
index 00000000..58af3353
--- /dev/null
+++ b/app/src/main/res/layout/album_list_header.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/item_name"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:background="@android:color/transparent"
+ android:textColor="@color/cyan"
+ android:textStyle="bold"
+ android:paddingLeft="6dp"
+ android:paddingRight="6dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"/>
+
+ <CheckBox
+ android:id="@+id/item_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/main.albums_per_folder"
+ android:layout_marginRight="6dp"
+ android:layout_gravity="right"/>
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/album_list_item.xml b/app/src/main/res/layout/album_list_item.xml
index 67c052eb..c43e52a8 100644
--- a/app/src/main/res/layout/album_list_item.xml
+++ b/app/src/main/res/layout/album_list_item.xml
@@ -3,7 +3,8 @@
android:id="@id/drag_handle"
android:orientation="horizontal"
android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:background="?attr/selectableItemBackground">
<RelativeLayout
android:layout_width="@dimen/AlbumArt.Small"
diff --git a/app/src/main/res/layout/basic_count_item.xml b/app/src/main/res/layout/basic_count_item.xml
index 08d276db..7f71c5a6 100644
--- a/app/src/main/res/layout/basic_count_item.xml
+++ b/app/src/main/res/layout/basic_count_item.xml
@@ -2,7 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:background="@android:color/transparent"
+ android:background="?attr/selectableItemBackground"
android:minHeight="50dip">
<TextView
diff --git a/app/src/main/res/layout/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>
-