aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/drawable-hdpi/ic_menu_share_dark.pngbin0 -> 737 bytes
-rw-r--r--res/drawable-hdpi/ic_menu_share_light.pngbin0 -> 825 bytes
-rw-r--r--res/drawable-mdpi/ic_menu_share_dark.pngbin0 -> 455 bytes
-rw-r--r--res/drawable-mdpi/ic_menu_share_light.pngbin0 -> 534 bytes
-rw-r--r--res/drawable-xhdpi/ic_menu_share_dark.pngbin0 -> 947 bytes
-rw-r--r--res/drawable-xhdpi/ic_menu_share_light.pngbin0 -> 1101 bytes
-rw-r--r--res/drawable-xxhdpi/ic_menu_share_dark.pngbin0 -> 1592 bytes
-rw-r--r--res/drawable-xxhdpi/ic_menu_share_light.pngbin0 -> 1790 bytes
-rw-r--r--res/layout/complex_list_item.xml50
-rw-r--r--res/layout/update_share.xml69
-rw-r--r--res/menu/select_share_context.xml17
-rw-r--r--res/values/arrays.xml4
-rw-r--r--res/values/strings.xml19
-rw-r--r--src/github/daneren2005/dsub/activity/SubsonicActivity.java15
-rw-r--r--src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java3
-rw-r--r--src/github/daneren2005/dsub/domain/MusicDirectory.java3
-rw-r--r--src/github/daneren2005/dsub/domain/Share.java22
-rw-r--r--src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java29
-rw-r--r--src/github/daneren2005/dsub/fragments/SelectShareFragment.java216
-rw-r--r--src/github/daneren2005/dsub/fragments/SubsonicFragment.java11
-rw-r--r--src/github/daneren2005/dsub/service/CachedMusicService.java15
-rw-r--r--src/github/daneren2005/dsub/service/MusicService.java6
-rw-r--r--src/github/daneren2005/dsub/service/RESTMusicService.java82
-rw-r--r--src/github/daneren2005/dsub/service/parser/ShareParser.java12
-rw-r--r--src/github/daneren2005/dsub/util/Constants.java2
-rw-r--r--src/github/daneren2005/dsub/view/ShareAdapter.java55
-rw-r--r--src/github/daneren2005/dsub/view/ShareView.java65
27 files changed, 682 insertions, 13 deletions
diff --git a/res/drawable-hdpi/ic_menu_share_dark.png b/res/drawable-hdpi/ic_menu_share_dark.png
new file mode 100644
index 00000000..218aa864
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_share_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_share_light.png b/res/drawable-hdpi/ic_menu_share_light.png
new file mode 100644
index 00000000..cfd19d43
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_share_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_share_dark.png b/res/drawable-mdpi/ic_menu_share_dark.png
new file mode 100644
index 00000000..c37aadba
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_share_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_share_light.png b/res/drawable-mdpi/ic_menu_share_light.png
new file mode 100644
index 00000000..72eeb598
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_share_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_share_dark.png b/res/drawable-xhdpi/ic_menu_share_dark.png
new file mode 100644
index 00000000..41073d1f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_menu_share_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_share_light.png b/res/drawable-xhdpi/ic_menu_share_light.png
new file mode 100644
index 00000000..36f9f55f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_menu_share_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_menu_share_dark.png b/res/drawable-xxhdpi/ic_menu_share_dark.png
new file mode 100644
index 00000000..1fa12609
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_menu_share_dark.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_menu_share_light.png b/res/drawable-xxhdpi/ic_menu_share_light.png
new file mode 100644
index 00000000..7511340b
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_menu_share_light.png
Binary files differ
diff --git a/res/layout/complex_list_item.xml b/res/layout/complex_list_item.xml
new file mode 100644
index 00000000..87fa7b2f
--- /dev/null
+++ b/res/layout/complex_list_item.xml
@@ -0,0 +1,50 @@
+<?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">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_gravity="center_vertical"
+ android:paddingLeft="6dip"
+ android:paddingRight="6dip"
+ android:gravity="left|center_vertical">
+
+ <TextView
+ 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"/>
+
+ <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"/>
+ </LinearLayout>
+
+ <ImageButton
+ android:id="@+id/item_star"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right|center_vertical"
+ android:src="@drawable/ic_stat_star"
+ android:background="@android:color/transparent"
+ android:focusable="false"
+ android:visibility="gone"/>
+
+ <ImageView
+ android:id="@+id/item_more"
+ android:src="?attr/download_none"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_gravity="right|center_vertical"
+ android:paddingRight="10dip"
+ android:background="@drawable/menubar_button"/>
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/update_share.xml b/res/layout/update_share.xml
new file mode 100644
index 00000000..92b7137b
--- /dev/null
+++ b/res/layout/update_share.xml
@@ -0,0 +1,69 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/get_share_name_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:textSize="20dp"
+ android:text="@string/common.name" />
+ <EditText
+ android:id="@+id/get_share_name"
+ android:inputType="text"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="4dp"
+ android:hint="@string/common.name" />
+ </LinearLayout>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/get_share_expire_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:textSize="20dp"
+ android:text="@string/share.expiration" />
+ <DatePicker
+ android:id="@+id/get_share_expire"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="4dp"
+ android:calendarViewShown="false"/>
+ </LinearLayout>
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/get_share_no_expire_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:textSize="20dp"
+ android:text="@string/share.no_expiration" />
+ <CheckBox
+ android:id="@+id/get_share_no_expire"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="4dp"
+ android:checked="false"/>
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/res/menu/select_share_context.xml b/res/menu/select_share_context.xml
new file mode 100644
index 00000000..3ef2826f
--- /dev/null
+++ b/res/menu/select_share_context.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:compat="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@+id/share_menu_info"
+ android:title="@string/common.info"/>
+
+ <item
+ android:id="@+id/share_update_info"
+ android:title="@string/playlist.update_info"
+ />
+
+ <item
+ android:id="@+id/share_menu_delete"
+ android:title="@string/common.delete"/>
+</menu>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 4b8caa96..a9702496 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -6,6 +6,7 @@
<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/menu.settings</item>
</string-array>
@@ -16,6 +17,7 @@
<item>Playlist</item>
<item>Podcast</item>
<item>Bookmark</item>
+ <item>Share</item>
<item>Chat</item>
<item>Settings</item>
</string-array>
@@ -26,6 +28,7 @@
<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_settings_light</item>
</array>
@@ -36,6 +39,7 @@
<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_settings_dark</item>
</array>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 744b6dcd..2c0d2ff3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -31,6 +31,7 @@
<string name="button_bar.now_playing">Now Playing</string>
<string name="button_bar.podcasts">Podcasts</string>
<string name="button_bar.bookmarks">Bookmarks</string>
+ <string name="button_bar.shares">Shares</string>
<string name="button_bar.chat">Chat</string>
<string name="main.welcome_title">Welcome!</string>
@@ -389,6 +390,24 @@
<string name="shuffle.genre">Genre:</string>
<string name="shuffle.pick_genre">Pick a genre</string>
+ <string name="share.info">Owner: %1$s
+ \nDescription: %2$s
+ \nURL: %3$s
+ \nCreation: %4$s
+ \nLast Visited: %5$s
+ \nExpiration: %6$s
+ \nVisit Count: %7$s
+
+ </string>
+ <string name="share.expires">Expires: %s</string>
+ <string name="share.expires_never">Never Expires</string>
+ <string name="share.deleted">Deleted share %s</string>
+ <string name="share.deleted_error">Failed to delete share %s</string>
+ <string name="share.no_expiration">No expiration</string>
+ <string name="share.expiration">Expires:</string>
+ <string name="share.updated_info">Updated share information for %s</string>
+ <string name="share.updated_info_error">Failed to update share information for %s</string>
+
<string name="music_service.retry">A network error occurred. Retrying %1$d of %2$d.</string>
<string name="background_task.wait">Please wait...</string>
diff --git a/src/github/daneren2005/dsub/activity/SubsonicActivity.java b/src/github/daneren2005/dsub/activity/SubsonicActivity.java
index bc239b4b..77a592bb 100644
--- a/src/github/daneren2005/dsub/activity/SubsonicActivity.java
+++ b/src/github/daneren2005/dsub/activity/SubsonicActivity.java
@@ -375,6 +375,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
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);
+ 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);
if(drawerItems == null || !enabledItems[0] == podcastsEnabled || !enabledItems[1] == bookmarksEnabled || !enabledItems[2] == chatEnabled) {
@@ -412,15 +413,23 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
drawerItemsIconsList.remove(4 - alreadyRemoved);
alreadyRemoved++;
}
-
- // Selectively remove chat listing: [5]
- if(!chatEnabled) {
+
+ // Selectively remove shared listing [5]
+ if(!bookmarksEnabled) {
drawerItemsList.remove(5 - alreadyRemoved);
drawerItemsDescriptionsList.remove(5 - alreadyRemoved);
drawerItemsIconsList.remove(5 - alreadyRemoved);
alreadyRemoved++;
}
+ // Selectively remove chat listing: [6]
+ if(!chatEnabled) {
+ drawerItemsList.remove(6 - alreadyRemoved);
+ drawerItemsDescriptionsList.remove(6 - alreadyRemoved);
+ drawerItemsIconsList.remove(6 - alreadyRemoved);
+ alreadyRemoved++;
+ }
+
// Put list back together
if(alreadyRemoved > 0) {
drawerItems = drawerItemsList.toArray(new String[0]);
diff --git a/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
index b51eb29b..423e1c23 100644
--- a/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
+++ b/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
@@ -53,6 +53,7 @@ import github.daneren2005.dsub.fragments.SelectBookmarkFragment;
import github.daneren2005.dsub.fragments.SelectDirectoryFragment;
import github.daneren2005.dsub.fragments.SelectPlaylistFragment;
import github.daneren2005.dsub.fragments.SelectPodcastsFragment;
+import github.daneren2005.dsub.fragments.SelectShareFragment;
import github.daneren2005.dsub.fragments.SubsonicFragment;
import github.daneren2005.dsub.service.DownloadFile;
import github.daneren2005.dsub.service.DownloadService;
@@ -381,6 +382,8 @@ public class SubsonicFragmentActivity extends SubsonicActivity {
return new SelectPodcastsFragment();
} else if("Bookmark".equals(fragmentType)) {
return new SelectBookmarkFragment();
+ } else if("Share".equals(fragmentType)) {
+ return new SelectShareFragment();
} else {
return new MainFragment();
}
diff --git a/src/github/daneren2005/dsub/domain/MusicDirectory.java b/src/github/daneren2005/dsub/domain/MusicDirectory.java
index b5707daf..8233ee48 100644
--- a/src/github/daneren2005/dsub/domain/MusicDirectory.java
+++ b/src/github/daneren2005/dsub/domain/MusicDirectory.java
@@ -72,6 +72,9 @@ public class MusicDirectory implements Serializable {
public void addChild(Entry child) {
children.add(child);
}
+ public void addChildren(List<Entry> children) {
+ this.children.addAll(children);
+ }
public void replaceChildren(List<Entry> children) {
this.children = children;
diff --git a/src/github/daneren2005/dsub/domain/Share.java b/src/github/daneren2005/dsub/domain/Share.java
index d19496f9..31ab7b8d 100644
--- a/src/github/daneren2005/dsub/domain/Share.java
+++ b/src/github/daneren2005/dsub/domain/Share.java
@@ -41,6 +41,14 @@ public class Share implements Serializable {
public Share() {
entries = new ArrayList<Entry>();
}
+
+ public String getName() {
+ if(description != null && !"".equals(description)) {
+ return description;
+ } else {
+ return url.replaceFirst(".*/([^/?]+).*", "$1");
+ }
+ }
public String getId() {
return id;
@@ -55,7 +63,7 @@ public class Share implements Serializable {
}
public void setUrl(String url) {
- this.url = url;
+ this.url = url;
}
public String getDescription() {
@@ -129,12 +137,20 @@ public class Share implements Serializable {
public void setVisitCount(Long visitCount) {
this.visitCount = visitCount;
}
-
+
+ public MusicDirectory getMusicDirectory() {
+ MusicDirectory dir = new MusicDirectory();
+ dir.addChildren(entries);
+ dir.setId(getId());
+ dir.setName(getName());
+ return dir;
+ }
+
public List<Entry> getEntries() {
return this.entries;
}
public void addEntry(Entry entry) {
- entries.add(entry);
+ entries.add(entry);
}
}
diff --git a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
index acc659b2..f16c197d 100644
--- a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
+++ b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
@@ -21,6 +21,7 @@ import android.widget.ListView;
import android.widget.TextView;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.domain.Share;
import github.daneren2005.dsub.util.ImageLoader;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.view.EntryAdapter;
@@ -131,6 +132,8 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
podcastId = args.getString(Constants.INTENT_EXTRA_NAME_PODCAST_ID);
podcastName = args.getString(Constants.INTENT_EXTRA_NAME_PODCAST_NAME);
podcastDescription = args.getString(Constants.INTENT_EXTRA_NAME_PODCAST_DESCRIPTION);
+ Object shareObj = args.getSerializable(Constants.INTENT_EXTRA_NAME_SHARE);
+ share = (shareObj != null) ? (Share) shareObj : null;
albumListType = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
albumListExtra = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA);
albumListSize = args.getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0);
@@ -363,6 +366,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
getPlaylist(playlistId, playlistName, refresh);
} else if(podcastId != null) {
getPodcast(podcastId, podcastName, refresh);
+ } else if (share != null) {
+ if(showAll) {
+ getRecursiveMusicDirectory(share.getId(), share.getName(), refresh);
+ } else {
+ getShare(share, refresh);
+ }
} else if (albumListType != null) {
getAlbumList(albumListType, albumListSize);
} else {
@@ -397,7 +406,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
new LoadTask() {
@Override
protected MusicDirectory load(MusicService service) throws Exception {
- MusicDirectory root = service.getMusicDirectory(id, name, refresh, context, this);
+ MusicDirectory root;
+ if(share == null) {
+ root = service.getMusicDirectory(id, name, refresh, context, this);
+ } else {
+ root = share.getMusicDirectory();
+ }
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
getSongsRecursively(root, songs);
root.replaceChildren(songs);
@@ -442,6 +456,17 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
}.execute();
}
+ private void getShare(final Share share, final boolean refresh) {
+ setTitle(share.getName());
+
+ new LoadTask() {
+ @Override
+ protected MusicDirectory load(MusicService service) throws Exception {
+ return share.getMusicDirectory();
+ }
+ }.execute();
+ }
+
private void getAlbumList(final String albumListType, final int size) {
showHeader = false;
@@ -564,7 +589,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
}
}
- if (hasSubFolders && id != null) {
+ if (hasSubFolders && (id != null || share != null)) {
downloadRecursively(id, false, append, !append, shuffle, false);
} else {
selectAll(true, false);
diff --git a/src/github/daneren2005/dsub/fragments/SelectShareFragment.java b/src/github/daneren2005/dsub/fragments/SelectShareFragment.java
new file mode 100644
index 00000000..556fc8da
--- /dev/null
+++ b/src/github/daneren2005/dsub/fragments/SelectShareFragment.java
@@ -0,0 +1,216 @@
+package github.daneren2005.dsub.fragments;
+
+import android.app.AlertDialog;
+import android.app.DatePickerDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.Log;
+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;
+import android.widget.EditText;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.Share;
+import github.daneren2005.dsub.service.MusicService;
+import github.daneren2005.dsub.service.MusicServiceFactory;
+import github.daneren2005.dsub.service.OfflineException;
+import github.daneren2005.dsub.service.ServerTooOldException;
+import github.daneren2005.dsub.util.Constants;
+import github.daneren2005.dsub.util.LoadingTask;
+import github.daneren2005.dsub.util.ProgressListener;
+import github.daneren2005.dsub.util.Util;
+import github.daneren2005.dsub.view.ShareAdapter;
+
+/**
+ * Created by Scott on 12/28/13.
+ */
+public class SelectShareFragment extends SelectListFragment<Share> {
+ private static final String TAG = SelectShareFragment.class.getSimpleName();
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, view, menuInfo);
+ android.view.MenuInflater inflater = context.getMenuInflater();
+ inflater.inflate(R.menu.select_share_context, menu);
+ recreateContextMenu(menu);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem menuItem) {
+ if(menuItem.getGroupId() != getSupportTag()) {
+ return false;
+ }
+
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
+ Share share = (Share) listView.getItemAtPosition(info.position);
+
+ switch (menuItem.getItemId()) {
+ case R.id.share_menu_info:
+ displayShareInfo(share);
+ break;
+ case R.id.share_menu_delete:
+ deleteShare(share);
+ break;
+ case R.id.share_update_info:
+ updateShareInfo(share);
+ break;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int getOptionsMenu() {
+ return R.menu.abstract_top_menu;
+ }
+
+ @Override
+ public ArrayAdapter getAdapter(List<Share> objs) {
+ return new ShareAdapter(context, objs);
+ }
+
+ @Override
+ public List<Share> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
+ return musicService.getShares(context, listener);
+ }
+
+ @Override
+ public int getTitleResource() {
+ return R.string.button_bar_shares;
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Share share = (Share) parent.getItemAtPosition(position);
+
+ SubsonicFragment fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putSerializable(Constants.INTENT_EXTRA_NAME_SHARE, share);
+ fragment.setArguments(args);
+
+ replaceFragment(fragment, R.id.fragment_list_layout);
+ }
+
+ private void displayShareInfo(final Share share) {
+ String message = context.getResources().getString(R.string.share_info,
+ share.getUsername(), (share.getDescription() != null) ? share.getDescription() : "", share.getUrl(),
+ share.getCreated(), share.getLastVisited(), share.getExpires(), share.getVisitCount());
+ Util.info(context, share.getName(), message);
+ }
+
+ private void updateShareInfo(final Share share) {
+ View dialogView = context.getLayoutInflater().inflate(R.layout.update_share, null);
+ final EditText nameBox = (EditText)dialogView.findViewById(R.id.get_share_name);
+ final DatePicker expireBox = (DatePicker)dialogView.findViewById(R.id.get_share_expire);
+ final CheckBox noExpiresBox = (CheckBox)dialogView.findViewById(R.id.get_share_no_expire);
+
+ nameBox.setText(share.getDescription());
+ Date expires = share.getExpires();
+ if(expires != null) {
+ expireBox.updateDate(expires.getYear() + 1900, expires.getMonth(), expires.getDate());
+ }
+
+ boolean noExpires = share.getExpires() == null;
+ if(noExpires) {
+ expireBox.setEnabled(false);
+ noExpiresBox.setChecked(true);
+ }
+
+ noExpiresBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ expireBox.setEnabled(!isChecked);
+ }
+ });
+
+ new AlertDialog.Builder(context)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle(R.string.playlist_update_info)
+ .setView(dialogView)
+ .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ new LoadingTask<Void>(context, false) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ Long expiresIn = 0L;
+ if (!noExpiresBox.isChecked()) {
+ Date expires = new Date(expireBox.getYear() - 1900, expireBox.getMonth(), expireBox.getDayOfMonth());
+ expiresIn = expires.getTime();
+ }
+
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ musicService.updateShare(share.getId(), nameBox.getText().toString(), expiresIn, context, null);
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ refresh();
+ Util.toast(context, context.getResources().getString(R.string.share_updated_info, share.getName()));
+ }
+
+ @Override
+ protected void error(Throwable error) {
+ String msg;
+ if (error instanceof OfflineException || error instanceof ServerTooOldException) {
+ msg = getErrorMessage(error);
+ } else {
+ msg = context.getResources().getString(R.string.share_updated_info_error, share.getName()) + " " + getErrorMessage(error);
+ }
+
+ Util.toast(context, msg, false);
+ }
+ }.execute();
+ }
+
+ })
+ .setNegativeButton(R.string.common_cancel, null)
+ .show();
+ }
+
+ private void deleteShare(final Share share) {
+ Util.confirmDialog(context, R.string.common_delete, share.getName(), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ new LoadingTask<Void>(context, false) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ musicService.deleteShare(share.getId(), context, null);
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ adapter.remove(share);
+ adapter.notifyDataSetChanged();
+ Util.toast(context, context.getResources().getString(R.string.share_deleted, share.getName()));
+ }
+
+ @Override
+ protected void error(Throwable error) {
+ String msg;
+ if (error instanceof OfflineException || error instanceof ServerTooOldException) {
+ msg = getErrorMessage(error);
+ } else {
+ msg = context.getResources().getString(R.string.share_deleted_error, share.getName()) + " " + getErrorMessage(error);
+ }
+
+ Util.toast(context, msg, false);
+ }
+ }.execute();
+ }
+ });
+ }
+}
diff --git a/src/github/daneren2005/dsub/fragments/SubsonicFragment.java b/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
index c9040048..626d4259 100644
--- a/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
+++ b/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
@@ -51,6 +51,7 @@ import github.daneren2005.dsub.domain.Genre;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.Playlist;
import github.daneren2005.dsub.domain.PodcastEpisode;
+import github.daneren2005.dsub.domain.Share;
import github.daneren2005.dsub.service.DownloadFile;
import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.service.DownloadServiceImpl;
@@ -90,6 +91,7 @@ public class SubsonicFragment extends Fragment {
protected boolean invalidated = false;
protected static Random random = new Random();
protected GestureDetector gestureScanner;
+ protected Share share;
public SubsonicFragment() {
super();
@@ -662,10 +664,15 @@ public class SubsonicFragment extends Fragment {
protected List<MusicDirectory.Entry> doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(context);
MusicDirectory root;
- if(isDirectory)
+ if(share != null) {
+ root = share.getMusicDirectory();
+ }
+ else if(isDirectory) {
root = musicService.getMusicDirectory(id, name, false, context, this);
- else
+ }
+ else {
root = musicService.getPlaylist(true, id, name, context, this);
+ }
List<MusicDirectory.Entry> songs = new LinkedList<MusicDirectory.Entry>();
getSongsRecursively(root, songs);
return songs;
diff --git a/src/github/daneren2005/dsub/service/CachedMusicService.java b/src/github/daneren2005/dsub/service/CachedMusicService.java
index 221ea03c..21c2ae68 100644
--- a/src/github/daneren2005/dsub/service/CachedMusicService.java
+++ b/src/github/daneren2005/dsub/service/CachedMusicService.java
@@ -328,6 +328,21 @@ public class CachedMusicService implements MusicService {
}
@Override
+ public List<Share> createShare(List<String> ids, String description, Long expires, Context context, ProgressListener progressListener) throws Exception {
+ return musicService.createShare(ids, description, expires, context, progressListener);
+ }
+
+ @Override
+ public void deleteShare(String id, Context context, ProgressListener progressListener) throws Exception {
+ musicService.deleteShare(id, context, progressListener);
+ }
+
+ @Override
+ public void updateShare(String id, String description, Long expires, Context context, ProgressListener progressListener) throws Exception {
+ musicService.updateShare(id, description, expires, context, progressListener);
+ }
+
+ @Override
public List<ChatMessage> getChatMessages(Long since, Context context, ProgressListener progressListener) throws Exception {
return musicService.getChatMessages(since, context, progressListener);
}
diff --git a/src/github/daneren2005/dsub/service/MusicService.java b/src/github/daneren2005/dsub/service/MusicService.java
index 1fb317ce..7e19e49e 100644
--- a/src/github/daneren2005/dsub/service/MusicService.java
+++ b/src/github/daneren2005/dsub/service/MusicService.java
@@ -116,6 +116,12 @@ public interface MusicService {
void setStarred(String id, boolean starred, Context context, ProgressListener progressListener) throws Exception;
List<Share> getShares(Context context, ProgressListener progressListener) throws Exception;
+
+ List<Share> createShare(List<String> ids, String description, Long expires, Context context, ProgressListener progressListener) throws Exception;
+
+ void deleteShare(String id, Context context, ProgressListener progressListener) throws Exception;
+
+ void updateShare(String id, String description, Long expires, Context context, ProgressListener progressListener) throws Exception;
List<ChatMessage> getChatMessages(Long since, Context context, ProgressListener progressListener) throws Exception;
diff --git a/src/github/daneren2005/dsub/service/RESTMusicService.java b/src/github/daneren2005/dsub/service/RESTMusicService.java
index febabc69..6d55cbd3 100644
--- a/src/github/daneren2005/dsub/service/RESTMusicService.java
+++ b/src/github/daneren2005/dsub/service/RESTMusicService.java
@@ -835,6 +835,88 @@ public class RESTMusicService implements MusicService {
}
@Override
+ public List<Share> createShare(List<String> ids, String description, Long expires, Context context, ProgressListener progressListener) throws Exception {
+ List<String> parameterNames = new LinkedList<String>();
+ List<Object> parameterValues = new LinkedList<Object>();
+
+ for (String id : ids) {
+ parameterNames.add("id");
+ parameterValues.add(id);
+ }
+
+ if (description != null) {
+ parameterNames.add("description");
+ parameterValues.add(description);
+ }
+
+ if (expires > 0) {
+ parameterNames.add("expires");
+ parameterValues.add(expires);
+ }
+
+ Reader reader = getReader(context, progressListener, "createShare", null, parameterNames, parameterValues);
+ try {
+ return new ShareParser(context).parse(reader, progressListener);
+ }
+ finally {
+ Util.close(reader);
+ }
+ }
+
+ @Override
+ public void deleteShare(String id, Context context, ProgressListener progressListener) throws Exception {
+ checkServerVersion(context, "1.6", "Shares not supported.");
+
+ HttpParams params = new BasicHttpParams();
+ HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS);
+
+ List<String> parameterNames = new ArrayList<String>();
+ List<Object> parameterValues = new ArrayList<Object>();
+
+ parameterNames.add("id");
+ parameterValues.add(id);
+
+ Reader reader = getReader(context, progressListener, "deleteShare", params, parameterNames, parameterValues);
+
+ try {
+ new ErrorParser(context).parse(reader);
+ }
+ finally {
+ Util.close(reader);
+ }
+ }
+
+ @Override
+ public void updateShare(String id, String description, Long expires, Context context, ProgressListener progressListener) throws Exception {
+ checkServerVersion(context, "1.6", "Updating share not supported.");
+
+ HttpParams params = new BasicHttpParams();
+ HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS);
+
+ List<String> parameterNames = new ArrayList<String>();
+ List<Object> parameterValues = new ArrayList<Object>();
+
+ parameterNames.add("id");
+ parameterValues.add(id);
+
+ if (description != null) {
+ parameterNames.add("description");
+ parameterValues.add(description);
+ }
+
+ parameterNames.add("expires");
+ parameterValues.add(expires);
+
+ Reader reader = getReader(context, progressListener, "updateShare", params, parameterNames, parameterValues);
+ try {
+ new ErrorParser(context).parse(reader);
+ }
+ finally {
+ Util.close(reader);
+ }
+ }
+
+ @Override
public List<ChatMessage> getChatMessages(Long since, Context context, ProgressListener progressListener) throws Exception {
checkServerVersion(context, "1.2", "Chat not supported.");
diff --git a/src/github/daneren2005/dsub/service/parser/ShareParser.java b/src/github/daneren2005/dsub/service/parser/ShareParser.java
index c317e799..4688faf8 100644
--- a/src/github/daneren2005/dsub/service/parser/ShareParser.java
+++ b/src/github/daneren2005/dsub/service/parser/ShareParser.java
@@ -19,6 +19,8 @@
package github.daneren2005.dsub.service.parser;
import android.content.Context;
+import android.util.Log;
+
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.Share;
import github.daneren2005.dsub.util.ProgressListener;
@@ -31,8 +33,9 @@ import java.util.List;
* @author Joshua Bahnsen
*/
public class ShareParser extends MusicDirectoryEntryParser {
+ private static final String TAG = ShareParser.class.getSimpleName();
- public ShareParser(Context context) {
+ public ShareParser(Context context) {
super(context);
}
@@ -54,15 +57,18 @@ public class ShareParser extends MusicDirectoryEntryParser {
if ("share".equals(name)) {
share = new Share();
share.setCreated(get("created"));
+ share.setUrl(get("url"));
share.setDescription(get("description"));
share.setExpires(get("expires"));
share.setId(get("id"));
share.setLastVisited(get("lastVisited"));
- share.setUrl(get("url"));
share.setUsername(get("username"));
share.setVisitCount(getLong("visitCount"));
+ dir.add(share);
} else if ("entry".equals(name)) {
- share.addEntry(parseEntry(null));
+ if(share != null) {
+ share.addEntry(parseEntry(null));
+ }
} else if ("error".equals(name)) {
handleError();
}
diff --git a/src/github/daneren2005/dsub/util/Constants.java b/src/github/daneren2005/dsub/util/Constants.java
index 4383a964..c51e1ee1 100644
--- a/src/github/daneren2005/dsub/util/Constants.java
+++ b/src/github/daneren2005/dsub/util/Constants.java
@@ -59,6 +59,7 @@ public final class Constants {
public static final String INTENT_EXTRA_NAME_PODCAST_ID = "subsonic.podcast.id";
public static final String INTENT_EXTRA_NAME_PODCAST_NAME = "subsonic.podcast.name";
public static final String INTENT_EXTRA_NAME_PODCAST_DESCRIPTION = "subsonic.podcast.description";
+ public static final String INTENT_EXTRA_NAME_SHARE = "subsonic.share";
public static final String INTENT_EXTRA_FRAGMENT_TYPE = "fragmentType";
public static final String INTENT_EXTRA_REFRESH_LISTINGS = "refreshListings";
@@ -134,6 +135,7 @@ public final class Constants {
public static final String PREFERENCES_KEY_MENU_PLAY_NEXT = "showPlayNext";
public static final String PREFERENCES_KEY_MENU_PLAY_LAST = "showPlayLast";
public static final String PREFERENCES_KEY_MENU_STAR = "showStar";
+ public static final String PREFERENCES_KEY_SHARED_ENABLED = "sharedEnabled";
public static final String OFFLINE_SCROBBLE_COUNT = "scrobbleCount";
public static final String OFFLINE_SCROBBLE_ID = "scrobbleID";
diff --git a/src/github/daneren2005/dsub/view/ShareAdapter.java b/src/github/daneren2005/dsub/view/ShareAdapter.java
new file mode 100644
index 00000000..362e1c83
--- /dev/null
+++ b/src/github/daneren2005/dsub/view/ShareAdapter.java
@@ -0,0 +1,55 @@
+/*
+ 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.view;
+
+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;
+
+/**
+ * @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;
+ }
+
+ @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;
+ }
+}
diff --git a/src/github/daneren2005/dsub/view/ShareView.java b/src/github/daneren2005/dsub/view/ShareView.java
new file mode 100644
index 00000000..d00e9d7c
--- /dev/null
+++ b/src/github/daneren2005/dsub/view/ShareView.java
@@ -0,0 +1,65 @@
+/*
+ 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.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 java.text.SimpleDateFormat;
+import java.util.Locale;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.Share;
+
+public class ShareView extends UpdateView {
+ private static final String TAG = ShareView.class.getSimpleName();
+
+ private TextView titleView;
+ private TextView descriptionView;
+
+ public ShareView(Context context) {
+ super(context);
+ LayoutInflater.from(context).inflate(R.layout.complex_list_item, this, true);
+
+ titleView = (TextView) findViewById(R.id.item_name);
+ descriptionView = (TextView) findViewById(R.id.item_description);
+ 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();
+ }
+ });
+ }
+
+ public void setObjectImpl(Object obj) {
+ Share share = (Share) obj;
+ 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())));
+ } else {
+ descriptionView.setText(context.getResources().getString(R.string.share_expires_never));
+ }
+ }
+}