First snapshot (beta 0.9)
- playlists working (not all features added yet) - minor fixes and improvements
This commit is contained in:
parent
de15a34365
commit
11ee05ce64
30 changed files with 1055 additions and 126 deletions
|
|
@ -17,14 +17,14 @@ repositories {
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 22
|
compileSdkVersion 22
|
||||||
buildToolsVersion "21.1.2"
|
buildToolsVersion "22"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.kabouzeid.gramophone"
|
applicationId "com.kabouzeid.gramophone"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 22
|
targetSdkVersion 22
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "0.9b"
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|
|
||||||
|
|
@ -36,34 +36,37 @@ MERGED from com.crashlytics.sdk.android:crashlytics:2.2.1:9:5
|
||||||
ADDED from AndroidManifest.xml:9:22
|
ADDED from AndroidManifest.xml:9:22
|
||||||
application
|
application
|
||||||
ADDED from AndroidManifest.xml:11:5
|
ADDED from AndroidManifest.xml:11:5
|
||||||
MERGED from com.android.support:appcompat-v7:21.0.3:16:5
|
MERGED from com.afollestad:material-dialogs:0.6.4.1:12:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
MERGED from com.android.support:appcompat-v7:22.0.0:22:5
|
||||||
MERGED from com.android.support:gridlayout-v7:21.0.3:16:5
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
MERGED from com.android.support:recyclerview-v7:22.0.0:22:5
|
||||||
MERGED from com.android.support:recyclerview-v7:21.0.3:17:5
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
MERGED from com.android.support:appcompat-v7:22.0.0:22:5
|
||||||
MERGED from com.android.support:palette-v7:21.0.3:16:5
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
MERGED from com.android.support:recyclerview-v7:22.0.0:22:5
|
||||||
MERGED from com.android.support:support-v13:21.0.3:16:5
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
MERGED from com.android.support:gridlayout-v7:22.0.0:22:5
|
||||||
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
|
MERGED from com.android.support:palette-v7:22.0.0:22:5
|
||||||
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
|
MERGED from com.android.support:support-v13:22.0.0:22:5
|
||||||
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
|
MERGED from com.android.support:cardview-v7:22.0.0:22:5
|
||||||
MERGED from com.nhaarman.listviewanimations:lib-core:3.1.0:26:5
|
MERGED from com.nhaarman.listviewanimations:lib-core:3.1.0:26:5
|
||||||
MERGED from com.nhaarman.listviewanimations:lib-manipulation:3.1.0:26:5
|
MERGED from com.nhaarman.listviewanimations:lib-manipulation:3.1.0:26:5
|
||||||
MERGED from com.nhaarman.listviewanimations:lib-core-slh:3.1.0:26:5
|
MERGED from com.nhaarman.listviewanimations:lib-core-slh:3.1.0:26:5
|
||||||
MERGED from com.melnykov:floatingactionbutton:1.2.0:12:5
|
MERGED from com.melnykov:floatingactionbutton:1.2.0:12:5
|
||||||
MERGED from com.android.support:recyclerview-v7:21.0.3:17:5
|
MERGED from com.android.support:recyclerview-v7:22.0.0:22:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
MERGED from com.android.support:recyclerview-v7:21.0.3:17:5
|
MERGED from com.android.support:recyclerview-v7:22.0.0:22:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
MERGED from com.afollestad:material-dialogs:0.6.3.0:12:5
|
|
||||||
MERGED from com.android.support:appcompat-v7:21.0.3:16:5
|
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
|
||||||
MERGED from com.crashlytics.sdk.android:crashlytics:2.2.1:11:5
|
MERGED from com.crashlytics.sdk.android:crashlytics:2.2.1:11:5
|
||||||
MERGED from com.crashlytics.sdk.android:answers:1.1.1:9:5
|
MERGED from com.crashlytics.sdk.android:answers:1.1.1:9:5
|
||||||
MERGED from io.fabric.sdk.android:fabric:1.1.1:9:5
|
MERGED from io.fabric.sdk.android:fabric:1.1.1:9:5
|
||||||
MERGED from io.fabric.sdk.android:fabric:1.1.1:9:5
|
MERGED from io.fabric.sdk.android:fabric:1.1.1:9:5
|
||||||
MERGED from com.crashlytics.sdk.android:beta:1.1.1:9:5
|
MERGED from com.crashlytics.sdk.android:beta:1.1.1:9:5
|
||||||
MERGED from io.fabric.sdk.android:fabric:1.1.1:9:5
|
MERGED from io.fabric.sdk.android:fabric:1.1.1:9:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:16:5
|
MERGED from com.android.support:support-v4:22.0.0:22:5
|
||||||
android:label
|
android:label
|
||||||
ADDED from AndroidManifest.xml:15:9
|
ADDED from AndroidManifest.xml:15:9
|
||||||
android:allowBackup
|
android:allowBackup
|
||||||
|
|
@ -74,7 +77,7 @@ MERGED from com.android.support:support-v4:21.0.3:16:5
|
||||||
ADDED from AndroidManifest.xml:16:9
|
ADDED from AndroidManifest.xml:16:9
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:12:9
|
ADDED from AndroidManifest.xml:12:9
|
||||||
activity#gramophone.ui.activities.MainActivity
|
activity#com.kabouzeid.gramophone.ui.activities.MainActivity
|
||||||
ADDED from AndroidManifest.xml:17:9
|
ADDED from AndroidManifest.xml:17:9
|
||||||
android:label
|
android:label
|
||||||
ADDED from AndroidManifest.xml:19:13
|
ADDED from AndroidManifest.xml:19:13
|
||||||
|
|
@ -90,27 +93,27 @@ category#android.intent.category.LAUNCHER
|
||||||
ADDED from AndroidManifest.xml:23:17
|
ADDED from AndroidManifest.xml:23:17
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:23:27
|
ADDED from AndroidManifest.xml:23:27
|
||||||
activity#gramophone.ui.activities.AlbumDetailActivity
|
activity#com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity
|
||||||
ADDED from AndroidManifest.xml:26:9
|
ADDED from AndroidManifest.xml:26:9
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:26:19
|
ADDED from AndroidManifest.xml:26:19
|
||||||
activity#gramophone.ui.activities.ArtistDetailActivity
|
activity#com.kabouzeid.gramophone.ui.activities.ArtistDetailActivity
|
||||||
ADDED from AndroidManifest.xml:28:9
|
ADDED from AndroidManifest.xml:28:9
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:28:19
|
ADDED from AndroidManifest.xml:28:19
|
||||||
activity#gramophone.ui.activities.MusicControllerActivity
|
activity#com.kabouzeid.gramophone.ui.activities.MusicControllerActivity
|
||||||
ADDED from AndroidManifest.xml:30:9
|
ADDED from AndroidManifest.xml:30:9
|
||||||
android:parentActivityName
|
android:parentActivityName
|
||||||
ADDED from AndroidManifest.xml:32:13
|
ADDED from AndroidManifest.xml:32:13
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:31:13
|
ADDED from AndroidManifest.xml:31:13
|
||||||
service#gramophone.service.MusicService
|
service#com.kabouzeid.gramophone.service.MusicService
|
||||||
ADDED from AndroidManifest.xml:35:9
|
ADDED from AndroidManifest.xml:35:9
|
||||||
android:enabled
|
android:enabled
|
||||||
ADDED from AndroidManifest.xml:37:13
|
ADDED from AndroidManifest.xml:37:13
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:36:13
|
ADDED from AndroidManifest.xml:36:13
|
||||||
receiver#gramophone.service.MediaButtonIntentReceiver
|
receiver#com.kabouzeid.gramophone.service.MediaButtonIntentReceiver
|
||||||
ADDED from AndroidManifest.xml:40:9
|
ADDED from AndroidManifest.xml:40:9
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:40:19
|
ADDED from AndroidManifest.xml:40:19
|
||||||
|
|
@ -126,7 +129,7 @@ ADDED from AndroidManifest.xml:46:9
|
||||||
ADDED from AndroidManifest.xml:48:13
|
ADDED from AndroidManifest.xml:48:13
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:47:13
|
ADDED from AndroidManifest.xml:47:13
|
||||||
activity#gramophone.ui.activities.tageditor.SongTagEditorActivity
|
activity#com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity
|
||||||
ADDED from AndroidManifest.xml:50:9
|
ADDED from AndroidManifest.xml:50:9
|
||||||
android:label
|
android:label
|
||||||
ADDED from AndroidManifest.xml:52:13
|
ADDED from AndroidManifest.xml:52:13
|
||||||
|
|
@ -134,42 +137,67 @@ ADDED from AndroidManifest.xml:50:9
|
||||||
ADDED from AndroidManifest.xml:53:13
|
ADDED from AndroidManifest.xml:53:13
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:51:13
|
ADDED from AndroidManifest.xml:51:13
|
||||||
activity#gramophone.ui.activities.tageditor.AlbumTagEditorActivity
|
activity#com.kabouzeid.gramophone.ui.activities.tageditor.AlbumTagEditorActivity
|
||||||
ADDED from AndroidManifest.xml:55:9
|
ADDED from AndroidManifest.xml:55:9
|
||||||
android:label
|
android:label
|
||||||
ADDED from AndroidManifest.xml:57:13
|
ADDED from AndroidManifest.xml:57:13
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:56:13
|
ADDED from AndroidManifest.xml:56:13
|
||||||
activity#gramophone.ui.activities.SearchActivity
|
activity#com.kabouzeid.gramophone.ui.activities.SearchActivity
|
||||||
ADDED from AndroidManifest.xml:59:9
|
ADDED from AndroidManifest.xml:59:9
|
||||||
android:label
|
android:label
|
||||||
ADDED from AndroidManifest.xml:61:13
|
ADDED from AndroidManifest.xml:61:13
|
||||||
android:name
|
android:name
|
||||||
ADDED from AndroidManifest.xml:60:13
|
ADDED from AndroidManifest.xml:60:13
|
||||||
|
receiver#com.kabouzeid.gramophone.widget.MusicPlayerWidget
|
||||||
|
ADDED from AndroidManifest.xml:64:9
|
||||||
|
android:name
|
||||||
|
ADDED from AndroidManifest.xml:64:19
|
||||||
|
intent-filter#android.appwidget.action.APPWIDGET_UPDATE
|
||||||
|
ADDED from AndroidManifest.xml:65:13
|
||||||
|
action#android.appwidget.action.APPWIDGET_UPDATE
|
||||||
|
ADDED from AndroidManifest.xml:66:17
|
||||||
|
android:name
|
||||||
|
ADDED from AndroidManifest.xml:66:25
|
||||||
|
meta-data#android.appwidget.provider
|
||||||
|
ADDED from AndroidManifest.xml:69:13
|
||||||
|
android:resource
|
||||||
|
ADDED from AndroidManifest.xml:71:17
|
||||||
|
android:name
|
||||||
|
ADDED from AndroidManifest.xml:70:17
|
||||||
|
activity#com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity
|
||||||
|
ADDED from AndroidManifest.xml:74:9
|
||||||
|
android:label
|
||||||
|
ADDED from AndroidManifest.xml:76:13
|
||||||
|
android:name
|
||||||
|
ADDED from AndroidManifest.xml:75:13
|
||||||
uses-sdk
|
uses-sdk
|
||||||
INJECTED from AndroidManifest.xml:0:0 reason: use-sdk injection requested
|
INJECTED from AndroidManifest.xml:0:0 reason: use-sdk injection requested
|
||||||
MERGED from com.android.support:appcompat-v7:21.0.3:15:5
|
MERGED from com.afollestad:material-dialogs:0.6.4.1:8:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
MERGED from com.android.support:appcompat-v7:22.0.0:20:5
|
||||||
MERGED from com.android.support:gridlayout-v7:21.0.3:15:5
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
MERGED from com.android.support:recyclerview-v7:22.0.0:20:5
|
||||||
MERGED from com.android.support:recyclerview-v7:21.0.3:15:5
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
MERGED from com.android.support:appcompat-v7:22.0.0:20:5
|
||||||
MERGED from com.android.support:palette-v7:21.0.3:15:5
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
MERGED from com.android.support:recyclerview-v7:22.0.0:20:5
|
||||||
MERGED from com.android.support:support-v13:21.0.3:15:5
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
MERGED from com.android.support:gridlayout-v7:22.0.0:20:5
|
||||||
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
|
MERGED from com.android.support:palette-v7:22.0.0:20:5
|
||||||
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
|
MERGED from com.android.support:support-v13:22.0.0:20:5
|
||||||
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
|
MERGED from com.android.support:cardview-v7:22.0.0:20:5
|
||||||
MERGED from com.nhaarman.listviewanimations:lib-core:3.1.0:22:5
|
MERGED from com.nhaarman.listviewanimations:lib-core:3.1.0:22:5
|
||||||
MERGED from com.nhaarman.listviewanimations:lib-manipulation:3.1.0:22:5
|
MERGED from com.nhaarman.listviewanimations:lib-manipulation:3.1.0:22:5
|
||||||
MERGED from com.nhaarman.listviewanimations:lib-core-slh:3.1.0:22:5
|
MERGED from com.nhaarman.listviewanimations:lib-core-slh:3.1.0:22:5
|
||||||
MERGED from com.melnykov:floatingactionbutton:1.2.0:8:5
|
MERGED from com.melnykov:floatingactionbutton:1.2.0:8:5
|
||||||
MERGED from com.android.support:recyclerview-v7:21.0.3:15:5
|
MERGED from com.android.support:recyclerview-v7:22.0.0:20:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
MERGED from com.github.ksoichiro:android-observablescrollview:1.3.0:21:5
|
MERGED from com.github.ksoichiro:android-observablescrollview:1.5.0:21:5
|
||||||
MERGED from com.android.support:recyclerview-v7:21.0.3:15:5
|
MERGED from com.android.support:recyclerview-v7:22.0.0:20:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
MERGED from com.afollestad:material-dialogs:0.6.3.0:8:5
|
|
||||||
MERGED from com.android.support:appcompat-v7:21.0.3:15:5
|
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
|
||||||
MERGED from com.crashlytics.sdk.android:crashlytics:2.2.1:7:5
|
MERGED from com.crashlytics.sdk.android:crashlytics:2.2.1:7:5
|
||||||
MERGED from com.crashlytics.sdk.android:answers:1.1.1:7:5
|
MERGED from com.crashlytics.sdk.android:answers:1.1.1:7:5
|
||||||
MERGED from io.fabric.sdk.android:fabric:1.1.1:7:5
|
MERGED from io.fabric.sdk.android:fabric:1.1.1:7:5
|
||||||
|
|
@ -177,7 +205,7 @@ MERGED from io.fabric.sdk.android:fabric:1.1.1:7:5
|
||||||
MERGED from com.crashlytics.sdk.android:beta:1.1.1:7:5
|
MERGED from com.crashlytics.sdk.android:beta:1.1.1:7:5
|
||||||
MERGED from io.fabric.sdk.android:fabric:1.1.1:7:5
|
MERGED from io.fabric.sdk.android:fabric:1.1.1:7:5
|
||||||
MERGED from asia.ivity.android:drag-sort-listview:1.0:6:5
|
MERGED from asia.ivity.android:drag-sort-listview:1.0:6:5
|
||||||
MERGED from com.android.support:support-v4:21.0.3:15:5
|
MERGED from com.android.support:support-v4:22.0.0:20:5
|
||||||
android:targetSdkVersion
|
android:targetSdkVersion
|
||||||
INJECTED from AndroidManifest.xml:0:0
|
INJECTED from AndroidManifest.xml:0:0
|
||||||
INJECTED from AndroidManifest.xml:0:0
|
INJECTED from AndroidManifest.xml:0:0
|
||||||
|
|
@ -185,13 +213,14 @@ MERGED from com.android.support:support-v4:21.0.3:15:5
|
||||||
INJECTED from AndroidManifest.xml:0:0
|
INJECTED from AndroidManifest.xml:0:0
|
||||||
INJECTED from AndroidManifest.xml:0:0
|
INJECTED from AndroidManifest.xml:0:0
|
||||||
activity#android.support.v7.widget.TestActivity
|
activity#android.support.v7.widget.TestActivity
|
||||||
ADDED from com.android.support:recyclerview-v7:21.0.3:18:9
|
ADDED from com.android.support:recyclerview-v7:22.0.0:23:9
|
||||||
MERGED from com.android.support:recyclerview-v7:21.0.3:18:9
|
MERGED from com.android.support:recyclerview-v7:22.0.0:23:9
|
||||||
MERGED from com.android.support:recyclerview-v7:21.0.3:18:9
|
MERGED from com.android.support:recyclerview-v7:22.0.0:23:9
|
||||||
|
MERGED from com.android.support:recyclerview-v7:22.0.0:23:9
|
||||||
android:label
|
android:label
|
||||||
ADDED from com.android.support:recyclerview-v7:21.0.3:18:19
|
ADDED from com.android.support:recyclerview-v7:22.0.0:25:13
|
||||||
android:name
|
android:name
|
||||||
ADDED from com.android.support:recyclerview-v7:21.0.3:18:60
|
ADDED from com.android.support:recyclerview-v7:22.0.0:24:13
|
||||||
activity#com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeTouchListenerTestActivity
|
activity#com.nhaarman.listviewanimations.itemmanipulation.swipedismiss.SwipeTouchListenerTestActivity
|
||||||
ADDED from com.nhaarman.listviewanimations:lib-manipulation:3.1.0:27:9
|
ADDED from com.nhaarman.listviewanimations:lib-manipulation:3.1.0:27:9
|
||||||
android:name
|
android:name
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@ import android.widget.ArrayAdapter;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.helper.AddToPlaylistDialogHelper;
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
||||||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||||
|
|
@ -62,6 +64,12 @@ public class PlayingQueueAdapter extends ArrayAdapter<Song> {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_delete_from_disk:
|
||||||
|
Toast.makeText(activity, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
case R.id.action_add_to_playlist:
|
||||||
|
AddToPlaylistDialogHelper.getDialog(activity, song).show();
|
||||||
|
return true;
|
||||||
case R.id.action_remove_from_playing_queue:
|
case R.id.action_remove_from_playing_queue:
|
||||||
MusicPlayerRemote.removeFromQueue(position);
|
MusicPlayerRemote.removeFromQueue(position);
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,14 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.kabouzeid.gramophone.App;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||||
|
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -36,7 +40,7 @@ public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
holder.playlistName.setText(dataSet.get(position).playlistName);
|
holder.playlistName.setText(dataSet.get(position).name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -44,20 +48,46 @@ public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHo
|
||||||
return dataSet.size();
|
return dataSet.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
|
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||||
public TextView playlistName;
|
public TextView playlistName;
|
||||||
|
|
||||||
public ViewHolder(View itemView) {
|
public ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
playlistName = (TextView) itemView.findViewById(R.id.playlist_name);
|
playlistName = (TextView) itemView.findViewById(R.id.playlist_name);
|
||||||
itemView.setOnClickListener(this);
|
itemView.setOnClickListener(this);
|
||||||
|
itemView.setOnLongClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
Pair[] sharedViews = null;
|
Pair[] sharedViews = null;
|
||||||
if (activity instanceof AbsFabActivity) sharedViews = ((AbsFabActivity)activity).getSharedViewsWithFab(sharedViews);
|
if (activity instanceof AbsFabActivity)
|
||||||
NavigationUtil.goToPlaylist(activity, dataSet.get(getPosition()).id, sharedViews);
|
sharedViews = ((AbsFabActivity) activity).getSharedViewsWithFab(sharedViews);
|
||||||
|
NavigationUtil.goToPlaylist(activity, dataSet.get(getAdapterPosition()).id, sharedViews);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View view) {
|
||||||
|
final Playlist playlist = dataSet.get(getAdapterPosition());
|
||||||
|
new MaterialDialog.Builder(activity)
|
||||||
|
.title(activity.getResources().getString(R.string.delete_playlist) + playlist.name)
|
||||||
|
.positiveText(activity.getResources().getString(R.string.ok))
|
||||||
|
.negativeText(activity.getResources().getString(R.string.cancel))
|
||||||
|
.callback(new MaterialDialog.ButtonCallback() {
|
||||||
|
@Override
|
||||||
|
public void onPositive(MaterialDialog dialog) {
|
||||||
|
super.onPositive(dialog);
|
||||||
|
dialog.dismiss();
|
||||||
|
PlaylistsUtil.deletePlaylist(activity, playlist.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNegative(MaterialDialog dialog) {
|
||||||
|
super.onNegative(dialog);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.helper.AddToPlaylistDialogHelper;
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
||||||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||||
|
|
@ -22,6 +24,7 @@ import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||||
import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
|
import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
|
||||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||||
|
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -75,7 +78,7 @@ public class AlbumSongAdapter extends RecyclerView.Adapter<AlbumSongAdapter.View
|
||||||
itemView.setOnClickListener(new View.OnClickListener() {
|
itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
MusicPlayerRemote.openQueue(dataSet, getPosition(), true);
|
MusicPlayerRemote.openQueue(dataSet, getAdapterPosition(), true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -88,18 +91,24 @@ public class AlbumSongAdapter extends RecyclerView.Adapter<AlbumSongAdapter.View
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_delete_from_disk:
|
||||||
|
Toast.makeText(activity, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
case R.id.action_add_to_playlist:
|
||||||
|
AddToPlaylistDialogHelper.getDialog(activity, dataSet.get(getAdapterPosition())).show();
|
||||||
|
return true;
|
||||||
case R.id.action_play_next:
|
case R.id.action_play_next:
|
||||||
MusicPlayerRemote.playNext(dataSet.get(getPosition()));
|
MusicPlayerRemote.playNext(dataSet.get(getAdapterPosition()));
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_add_to_current_playing:
|
case R.id.action_add_to_current_playing:
|
||||||
MusicPlayerRemote.enqueue(dataSet.get(getPosition()));
|
MusicPlayerRemote.enqueue(dataSet.get(getAdapterPosition()));
|
||||||
case R.id.action_tag_editor:
|
case R.id.action_tag_editor:
|
||||||
Intent intent = new Intent(activity, SongTagEditorActivity.class);
|
Intent intent = new Intent(activity, SongTagEditorActivity.class);
|
||||||
intent.putExtra(AppKeys.E_ID, dataSet.get(getPosition()).id);
|
intent.putExtra(AppKeys.E_ID, dataSet.get(getAdapterPosition()).id);
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_details:
|
case R.id.action_details:
|
||||||
String songFilePath = SongFilePathLoader.getSongFilePath(activity, dataSet.get(getPosition()).id);
|
String songFilePath = SongFilePathLoader.getSongFilePath(activity, dataSet.get(getAdapterPosition()).id);
|
||||||
File songFile = new File(songFilePath);
|
File songFile = new File(songFilePath);
|
||||||
SongDetailDialogHelper.getDialog(activity, songFile).show();
|
SongDetailDialogHelper.getDialog(activity, songFile).show();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -107,13 +116,13 @@ public class AlbumSongAdapter extends RecyclerView.Adapter<AlbumSongAdapter.View
|
||||||
Pair[] albumPairs = null;
|
Pair[] albumPairs = null;
|
||||||
if (activity instanceof AbsFabActivity)
|
if (activity instanceof AbsFabActivity)
|
||||||
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs);
|
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs);
|
||||||
NavigationUtil.goToAlbum(activity, dataSet.get(getPosition()).albumId, albumPairs);
|
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).albumId, albumPairs);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_go_to_artist:
|
case R.id.action_go_to_artist:
|
||||||
Pair[] artistPairs = null;
|
Pair[] artistPairs = null;
|
||||||
if (activity instanceof AbsFabActivity)
|
if (activity instanceof AbsFabActivity)
|
||||||
artistPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(artistPairs);
|
artistPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(artistPairs);
|
||||||
NavigationUtil.goToArtist(activity, dataSet.get(getPosition()).artistId, artistPairs);
|
NavigationUtil.goToArtist(activity, dataSet.get(getAdapterPosition()).artistId, artistPairs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ import android.widget.ArrayAdapter;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.helper.AddToPlaylistDialogHelper;
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
||||||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||||
|
|
@ -67,6 +69,12 @@ public class ArtistSongAdapter extends ArrayAdapter<Song> {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_delete_from_disk:
|
||||||
|
Toast.makeText(activity, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
case R.id.action_add_to_playlist:
|
||||||
|
AddToPlaylistDialogHelper.getDialog(activity, song).show();
|
||||||
|
return true;
|
||||||
case R.id.action_play_next:
|
case R.id.action_play_next:
|
||||||
MusicPlayerRemote.playNext(song);
|
MusicPlayerRemote.playNext(song);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,15 @@ import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.helper.AddToPlaylistDialogHelper;
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
||||||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||||
|
import com.kabouzeid.gramophone.misc.DragSortRecycler;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
|
@ -97,6 +100,12 @@ public class PlaylistSongAdapter extends RecyclerView.Adapter<PlaylistSongAdapte
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_delete_from_disk:
|
||||||
|
Toast.makeText(activity, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
case R.id.action_add_to_playlist:
|
||||||
|
AddToPlaylistDialogHelper.getDialog(activity, dataSet.get(getAdapterPosition())).show();
|
||||||
|
return true;
|
||||||
case R.id.action_delete_from_playlist:
|
case R.id.action_delete_from_playlist:
|
||||||
int position = getAdapterPosition();
|
int position = getAdapterPosition();
|
||||||
PlaylistsUtil.removeFromPlaylist(activity, dataSet.remove(position));
|
PlaylistsUtil.removeFromPlaylist(activity, dataSet.remove(position));
|
||||||
|
|
@ -114,7 +123,7 @@ public class PlaylistSongAdapter extends RecyclerView.Adapter<PlaylistSongAdapte
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_details:
|
case R.id.action_details:
|
||||||
String songFilePath = SongFilePathLoader.getSongFilePath(activity, dataSet.get(getPosition()).id);
|
String songFilePath = SongFilePathLoader.getSongFilePath(activity, dataSet.get(getAdapterPosition()).id);
|
||||||
File songFile = new File(songFilePath);
|
File songFile = new File(songFilePath);
|
||||||
SongDetailDialogHelper.getDialog(activity, songFile).show();
|
SongDetailDialogHelper.getDialog(activity, songFile).show();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.helper.AddToPlaylistDialogHelper;
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
||||||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||||
|
|
@ -93,6 +95,12 @@ public class SongAdapter extends RecyclerView.Adapter<SongAdapter.ViewHolder> {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_delete_from_disk:
|
||||||
|
Toast.makeText(activity, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
case R.id.action_add_to_playlist:
|
||||||
|
AddToPlaylistDialogHelper.getDialog(activity, dataSet.get(getAdapterPosition())).show();
|
||||||
|
return true;
|
||||||
case R.id.action_play_next:
|
case R.id.action_play_next:
|
||||||
MusicPlayerRemote.playNext(dataSet.get(getPosition()));
|
MusicPlayerRemote.playNext(dataSet.get(getPosition()));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.kabouzeid.gramophone.helper;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
||||||
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by karim on 17.03.15.
|
||||||
|
*/
|
||||||
|
public class AddToPlaylistDialogHelper {
|
||||||
|
public static MaterialDialog getDialog(final Context context, final Song song) {
|
||||||
|
List<Song> tmpSong = new ArrayList<>();
|
||||||
|
tmpSong.add(song);
|
||||||
|
return getDialog(context, tmpSong);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MaterialDialog getDialog(final Context context, final List<Song> songs) {
|
||||||
|
final List<Playlist> playlists = PlaylistLoader.getAllPlaylists(context);
|
||||||
|
CharSequence[] playlistNames = new CharSequence[playlists.size() + 1];
|
||||||
|
playlistNames[0] = context.getResources().getString(R.string.action_new_playlist);
|
||||||
|
for (int i = 1; i < playlistNames.length; i++) {
|
||||||
|
playlistNames[i] = playlists.get(i-1).name;
|
||||||
|
}
|
||||||
|
return new MaterialDialog.Builder(context)
|
||||||
|
.items(playlistNames)
|
||||||
|
.itemsCallback(new MaterialDialog.ListCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSelection(MaterialDialog materialDialog, View view, int i, CharSequence charSequence) {
|
||||||
|
if (i == 0) {
|
||||||
|
materialDialog.dismiss();
|
||||||
|
CreatePlaylistDialogHelper.getDialog(context, songs).show();
|
||||||
|
} else {
|
||||||
|
materialDialog.dismiss();
|
||||||
|
PlaylistsUtil.addToPlaylist(context, songs, playlists.get(i - 1).id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.kabouzeid.gramophone.helper;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by karim on 17.03.15.
|
||||||
|
*/
|
||||||
|
public class CreatePlaylistDialogHelper {
|
||||||
|
public static MaterialDialog getDialog(final Context context, final Song song) {
|
||||||
|
List<Song> tmpSong = new ArrayList<>();
|
||||||
|
tmpSong.add(song);
|
||||||
|
return getDialog(context, tmpSong);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MaterialDialog getDialog(final Context context, final List<Song> songs) {
|
||||||
|
final EditText editText = new EditText(context);
|
||||||
|
ViewGroup layout = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.dialog_create_playlist, null);
|
||||||
|
if (editText.getParent() != null) {((ViewGroup) editText.getParent()).removeView(editText);}
|
||||||
|
layout.addView(editText, new LinearLayout.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
return new MaterialDialog.Builder(context)
|
||||||
|
.title(context.getResources().getString(R.string.action_new_playlist))
|
||||||
|
.customView(layout, false)
|
||||||
|
.positiveText(context.getResources().getString(R.string.ok))
|
||||||
|
.negativeText(context.getResources().getString(R.string.cancel))
|
||||||
|
.callback(new MaterialDialog.ButtonCallback() {
|
||||||
|
@Override
|
||||||
|
public void onPositive(MaterialDialog dialog) {
|
||||||
|
super.onPositive(dialog);
|
||||||
|
final String playlistName = editText.getText().toString();
|
||||||
|
if (!playlistName.trim().equals("")) {
|
||||||
|
dialog.dismiss();
|
||||||
|
final int playlistId = PlaylistsUtil.createPlaylist(context, playlistName);
|
||||||
|
if (playlistId != -1) {
|
||||||
|
if (songs != null) {
|
||||||
|
PlaylistsUtil.addToPlaylist(context, songs, playlistId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNegative(MaterialDialog dialog) {
|
||||||
|
super.onNegative(dialog);
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MaterialDialog getDialog(final Context context) {
|
||||||
|
return getDialog(context, (List<Song>) null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.adapter.PlayingQueueAdapter;
|
import com.kabouzeid.gramophone.adapter.PlayingQueueAdapter;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
||||||
import com.mobeta.android.dslv.DragSortListView;
|
import com.mobeta.android.dslv.DragSortListView;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -16,8 +17,8 @@ import java.util.List;
|
||||||
* Created by karim on 24.01.15.
|
* Created by karim on 24.01.15.
|
||||||
*/
|
*/
|
||||||
public class PlayingQueueDialogHelper {
|
public class PlayingQueueDialogHelper {
|
||||||
public static MaterialDialog getDialog(Activity activity) {
|
public static MaterialDialog getDialog(final Activity activity) {
|
||||||
List<Song> playingQueue = MusicPlayerRemote.getPlayingQueue();
|
final List<Song> playingQueue = MusicPlayerRemote.getPlayingQueue();
|
||||||
if (playingQueue.isEmpty()) {
|
if (playingQueue.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +27,7 @@ public class PlayingQueueDialogHelper {
|
||||||
.title(activity.getResources().getString(R.string.label_current_playing_queue))
|
.title(activity.getResources().getString(R.string.label_current_playing_queue))
|
||||||
.customView(R.layout.dialog_playlist, false)
|
.customView(R.layout.dialog_playlist, false)
|
||||||
.positiveText(activity.getResources().getString(R.string.close))
|
.positiveText(activity.getResources().getString(R.string.close))
|
||||||
.negativeText(activity.getResources().getString(R.string.save_as_playlist))
|
.neutralText(activity.getResources().getString(R.string.save_as_playlist))
|
||||||
.callback(new MaterialDialog.ButtonCallback() {
|
.callback(new MaterialDialog.ButtonCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onPositive(MaterialDialog dialog) {
|
public void onPositive(MaterialDialog dialog) {
|
||||||
|
|
@ -35,8 +36,10 @@ public class PlayingQueueDialogHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNegative(MaterialDialog dialog) {
|
public void onNeutral(MaterialDialog dialog) {
|
||||||
super.onNegative(dialog);
|
super.onNegative(dialog);
|
||||||
|
dialog.dismiss();
|
||||||
|
AddToPlaylistDialogHelper.getDialog(activity, playingQueue).show();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ public class LastFMAlbumInfoUtil {
|
||||||
public static void downloadAlbumInfoJSON(final Context context, final String album, final String artist, final Response.Listener<JSONObject> callbackSuccess, final Response.ErrorListener callbackError) {
|
public static void downloadAlbumInfoJSON(final Context context, final String album, final String artist, final Response.Listener<JSONObject> callbackSuccess, final Response.ErrorListener callbackError) {
|
||||||
App app = (App) context.getApplicationContext();
|
App app = (App) context.getApplicationContext();
|
||||||
String albumUrl = LastFMAlbumInfoUtil.getAlbumUrl(album, artist);
|
String albumUrl = LastFMAlbumInfoUtil.getAlbumUrl(album, artist);
|
||||||
JsonObjectRequest albumInfoJSONRequest = new JsonObjectRequest(0, albumUrl, null, new Response.Listener<JSONObject>() {
|
JsonObjectRequest albumInfoJSONRequest = new JsonObjectRequest(0, albumUrl, (JSONObject)null, new Response.Listener<JSONObject>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(JSONObject response) {
|
public void onResponse(JSONObject response) {
|
||||||
LastFMAlbumInfoUtil.saveAlbumJSONDataToCacheAndDisk(context, album, artist, response);
|
LastFMAlbumInfoUtil.saveAlbumJSONDataToCacheAndDisk(context, album, artist, response);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ public class LastFMArtistBiographyLoader {
|
||||||
private static void downloadArtistBio(final Context context, final String artist, final ArtistBioLoaderCallback callback) {
|
private static void downloadArtistBio(final Context context, final String artist, final ArtistBioLoaderCallback callback) {
|
||||||
App app = (App) context.getApplicationContext();
|
App app = (App) context.getApplicationContext();
|
||||||
String artistUrl = LastFMArtistInfoUtil.getArtistUrl(artist);
|
String artistUrl = LastFMArtistInfoUtil.getArtistUrl(artist);
|
||||||
JsonObjectRequest artistInfoJSONRequest = new JsonObjectRequest(0, artistUrl, null, new Response.Listener<JSONObject>() {
|
JsonObjectRequest artistInfoJSONRequest = new JsonObjectRequest(0, artistUrl, (JSONObject)null, new Response.Listener<JSONObject>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(JSONObject response) {
|
public void onResponse(JSONObject response) {
|
||||||
LastFMArtistInfoUtil.saveArtistJSONDataToCacheAndDisk(context, artist, response);
|
LastFMArtistInfoUtil.saveArtistJSONDataToCacheAndDisk(context, artist, response);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package com.kabouzeid.gramophone.lastfm.artist;
|
package com.kabouzeid.gramophone.lastfm.artist;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
|
@ -101,7 +100,7 @@ public class LastFMArtistInfoUtil {
|
||||||
public static void downloadArtistJSON(final Context context, final String artist, final Response.Listener<JSONObject> callback) {
|
public static void downloadArtistJSON(final Context context, final String artist, final Response.Listener<JSONObject> callback) {
|
||||||
App app = (App) context.getApplicationContext();
|
App app = (App) context.getApplicationContext();
|
||||||
String artistUrl = LastFMArtistInfoUtil.getArtistUrl(artist);
|
String artistUrl = LastFMArtistInfoUtil.getArtistUrl(artist);
|
||||||
JsonObjectRequest artistInfoJSONRequest = new JsonObjectRequest(0, artistUrl, null, new Response.Listener<JSONObject>() {
|
JsonObjectRequest artistInfoJSONRequest = new JsonObjectRequest(0, artistUrl, (JSONObject)null, new Response.Listener<JSONObject>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(JSONObject response) {
|
public void onResponse(JSONObject response) {
|
||||||
LastFMArtistInfoUtil.saveArtistJSONDataToCacheAndDisk(context, artist, response);
|
LastFMArtistInfoUtil.saveArtistJSONDataToCacheAndDisk(context, artist, response);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,469 @@
|
||||||
|
/*
|
||||||
|
* DragSortRecycler
|
||||||
|
*
|
||||||
|
* Added drag and drop functionality to your RecyclerView
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright 2014 Emile Belanger.
|
||||||
|
*
|
||||||
|
* 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 com.kabouzeid.gramophone.misc;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
|
||||||
|
public class DragSortRecycler extends RecyclerView.ItemDecoration implements RecyclerView.OnItemTouchListener {
|
||||||
|
|
||||||
|
final String TAG = "DragSortRecycler";
|
||||||
|
|
||||||
|
final boolean DEBUG = false;
|
||||||
|
|
||||||
|
private int dragHandleWidth = 0;
|
||||||
|
|
||||||
|
private int selectedDragItemPos = -1;
|
||||||
|
|
||||||
|
private int fingerAnchorY;
|
||||||
|
|
||||||
|
private int fingerY;
|
||||||
|
|
||||||
|
private int fingerOffsetInViewY;
|
||||||
|
|
||||||
|
private float autoScrollWindow = 0.1f;
|
||||||
|
private float autoScrollSpeed = 0.5f;
|
||||||
|
|
||||||
|
private BitmapDrawable floatingItem;
|
||||||
|
private Rect floatingItemStatingBounds;
|
||||||
|
private Rect floatingItemBounds;
|
||||||
|
|
||||||
|
|
||||||
|
private float floatingItemAlpha = 0.5f;
|
||||||
|
private int floatingItemBgColor = 0;
|
||||||
|
|
||||||
|
private int viewHandleId = -1;
|
||||||
|
|
||||||
|
|
||||||
|
OnItemMovedListener moveInterface;
|
||||||
|
|
||||||
|
private boolean isDragging;
|
||||||
|
@Nullable
|
||||||
|
OnDragStateChangedListener dragStateChangedListener;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public interface OnItemMovedListener
|
||||||
|
{
|
||||||
|
public void onItemMoved(int from, int to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnDragStateChangedListener {
|
||||||
|
public void onDragStart();
|
||||||
|
public void onDragStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void debugLog(String log)
|
||||||
|
{
|
||||||
|
if (DEBUG)
|
||||||
|
Log.d(TAG, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecyclerView.OnScrollListener getScrollListener()
|
||||||
|
{
|
||||||
|
return scrollListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the item move interface
|
||||||
|
*/
|
||||||
|
public void setOnItemMovedListener(OnItemMovedListener swif)
|
||||||
|
{
|
||||||
|
moveInterface = swif;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewHandleId(int id)
|
||||||
|
{
|
||||||
|
viewHandleId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLeftDragArea(int w)
|
||||||
|
{
|
||||||
|
dragHandleWidth = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFloatingAlpha(float a)
|
||||||
|
{
|
||||||
|
floatingItemAlpha = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFloatingBgColor(int c)
|
||||||
|
{
|
||||||
|
floatingItemBgColor = c;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Set the window at top and bottom of list, must be between 0 and 0.5
|
||||||
|
For example 0.1 uses the top and bottom 10% of the lists for scrolling
|
||||||
|
*/
|
||||||
|
public void setAutoScrollWindow(float w)
|
||||||
|
{
|
||||||
|
autoScrollWindow = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set the autoscroll speed, default is 0.5
|
||||||
|
*/
|
||||||
|
public void setAutoScrollSpeed(float speed)
|
||||||
|
{
|
||||||
|
autoScrollSpeed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(Rect outRect, View view, RecyclerView rv, RecyclerView.State state) {
|
||||||
|
super.getItemOffsets(outRect, view, rv, state);
|
||||||
|
|
||||||
|
debugLog("getItemOffsets");
|
||||||
|
|
||||||
|
debugLog("View top = " + view.getTop());
|
||||||
|
if (selectedDragItemPos != -1)
|
||||||
|
{
|
||||||
|
int itemPos = rv.getChildPosition(view);
|
||||||
|
debugLog("itemPos =" + itemPos);
|
||||||
|
|
||||||
|
if(!canDragOver(itemPos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Movement of finger
|
||||||
|
float totalMovement = fingerY-fingerAnchorY;
|
||||||
|
|
||||||
|
if (itemPos == selectedDragItemPos)
|
||||||
|
{
|
||||||
|
view.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Make view visible incase invisible
|
||||||
|
view.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
//Find middle of the floatingItem
|
||||||
|
float floatMiddleY = floatingItemBounds.top + floatingItemBounds.height()/2;
|
||||||
|
|
||||||
|
//Moving down the list
|
||||||
|
//These will auto-animate if the device continually sends touch motion events
|
||||||
|
// if (totalMovment>0)
|
||||||
|
{
|
||||||
|
if ((itemPos > selectedDragItemPos) && (view.getTop() < floatMiddleY))
|
||||||
|
{
|
||||||
|
float amountUp = (floatMiddleY - view.getTop()) / (float)view.getHeight();
|
||||||
|
// amountUp *= 0.5f;
|
||||||
|
if (amountUp > 1)
|
||||||
|
amountUp = 1;
|
||||||
|
|
||||||
|
outRect.top = -(int)(floatingItemBounds.height()*amountUp);
|
||||||
|
outRect.bottom = (int)(floatingItemBounds.height()*amountUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}//Moving up the list
|
||||||
|
// else if (totalMovment < 0)
|
||||||
|
{
|
||||||
|
if((itemPos < selectedDragItemPos) && (view.getBottom() > floatMiddleY))
|
||||||
|
{
|
||||||
|
float amountDown = ((float)view.getBottom() - floatMiddleY) / (float)view.getHeight();
|
||||||
|
// amountDown *= 0.5f;
|
||||||
|
if (amountDown > 1)
|
||||||
|
amountDown = 1;
|
||||||
|
|
||||||
|
outRect.top = (int)(floatingItemBounds.height()*amountDown);
|
||||||
|
outRect.bottom = -(int)(floatingItemBounds.height()*amountDown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outRect.top = 0;
|
||||||
|
outRect.bottom = 0;
|
||||||
|
//Make view visible incase invisible
|
||||||
|
view.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the new position by scanning through the items on
|
||||||
|
* screen and finding the positional relationship.
|
||||||
|
* This *seems* to work, another method would be to use
|
||||||
|
* getItemOffsets, but I think that could miss items?..
|
||||||
|
*/
|
||||||
|
private int getNewPostion(RecyclerView rv)
|
||||||
|
{
|
||||||
|
int itemsOnScreen = rv.getLayoutManager().getChildCount();
|
||||||
|
|
||||||
|
float floatMiddleY = floatingItemBounds.top + floatingItemBounds.height()/2;
|
||||||
|
|
||||||
|
int above=0;
|
||||||
|
int below = Integer.MAX_VALUE;
|
||||||
|
for (int n=0;n < itemsOnScreen;n++) //Scan though items on screen, however they may not
|
||||||
|
{ // be in order!
|
||||||
|
|
||||||
|
View view = rv.getLayoutManager().getChildAt(n);
|
||||||
|
|
||||||
|
if (view.getVisibility() != View.VISIBLE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int itemPos = rv.getChildPosition(view);
|
||||||
|
|
||||||
|
if (itemPos == selectedDragItemPos) //Don't check against itself!
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float viewMiddleY = view.getTop() + view.getHeight()/2;
|
||||||
|
if (floatMiddleY > viewMiddleY) //Is above this item
|
||||||
|
{
|
||||||
|
if (itemPos > above)
|
||||||
|
above = itemPos;
|
||||||
|
}
|
||||||
|
else if (floatMiddleY <= viewMiddleY) //Is below this item
|
||||||
|
{
|
||||||
|
if (itemPos < below)
|
||||||
|
below = itemPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debugLog("above = " + above + " below = " + below);
|
||||||
|
|
||||||
|
if (below != Integer.MAX_VALUE) {
|
||||||
|
if (below < selectedDragItemPos) //Need to count itself
|
||||||
|
below++;
|
||||||
|
return below - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (above < selectedDragItemPos)
|
||||||
|
above++;
|
||||||
|
|
||||||
|
return above;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||||
|
debugLog("onInterceptTouchEvent");
|
||||||
|
|
||||||
|
//if (e.getAction() == MotionEvent.ACTION_DOWN)
|
||||||
|
{
|
||||||
|
View itemView = rv.findChildViewUnder(e.getX(), e.getY());
|
||||||
|
|
||||||
|
if (itemView==null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean dragging = false;
|
||||||
|
|
||||||
|
if ((dragHandleWidth > 0 ) && (e.getX() < dragHandleWidth))
|
||||||
|
{
|
||||||
|
dragging = true;
|
||||||
|
}
|
||||||
|
else if (viewHandleId != -1)
|
||||||
|
{
|
||||||
|
//Find the handle in the list item
|
||||||
|
View handleView = itemView.findViewById(viewHandleId);
|
||||||
|
|
||||||
|
if (handleView == null)
|
||||||
|
{
|
||||||
|
Log.e(TAG, "The view ID " + viewHandleId + " was not found in the RecycleView item");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//View should be visible to drag
|
||||||
|
if(handleView.getVisibility()!=View.VISIBLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//We need to find the relative position of the handle to the parent view
|
||||||
|
//Then we can work out if the touch is within the handle
|
||||||
|
int[] parentItemPos = new int[2];
|
||||||
|
itemView.getLocationInWindow(parentItemPos);
|
||||||
|
|
||||||
|
int[] handlePos = new int[2];
|
||||||
|
handleView.getLocationInWindow(handlePos);
|
||||||
|
|
||||||
|
int xRel = handlePos[0] - parentItemPos[0];
|
||||||
|
int yRel = handlePos[1] - parentItemPos[1];
|
||||||
|
|
||||||
|
Rect touchBounds = new Rect(itemView.getLeft() + xRel, itemView.getTop() + yRel,
|
||||||
|
itemView.getLeft() + xRel + handleView.getWidth(),
|
||||||
|
itemView.getTop() + yRel + handleView.getHeight()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (touchBounds.contains((int)e.getX(), (int)e.getY()))
|
||||||
|
dragging = true;
|
||||||
|
|
||||||
|
debugLog("parentItemPos = " + parentItemPos[0] + " " + parentItemPos[1]);
|
||||||
|
debugLog("handlePos = " + handlePos[0] + " " + handlePos[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (dragging)
|
||||||
|
{
|
||||||
|
debugLog("Started Drag");
|
||||||
|
|
||||||
|
setIsDragging(true);
|
||||||
|
|
||||||
|
floatingItem = createFloatingBitmap(itemView);
|
||||||
|
|
||||||
|
fingerAnchorY = (int)e.getY();
|
||||||
|
fingerOffsetInViewY = fingerAnchorY - itemView.getTop();
|
||||||
|
fingerY = fingerAnchorY;
|
||||||
|
|
||||||
|
selectedDragItemPos = rv.getChildPosition(itemView);
|
||||||
|
debugLog("selectedDragItemPos = " + selectedDragItemPos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||||
|
debugLog("onTouchEvent");
|
||||||
|
|
||||||
|
if ((e.getAction() == MotionEvent.ACTION_UP) ||
|
||||||
|
(e.getAction() == MotionEvent.ACTION_CANCEL))
|
||||||
|
{
|
||||||
|
if ((e.getAction() == MotionEvent.ACTION_UP) && selectedDragItemPos != -1)
|
||||||
|
{
|
||||||
|
int newPos = getNewPostion(rv);
|
||||||
|
if (moveInterface != null)
|
||||||
|
moveInterface.onItemMoved(selectedDragItemPos, newPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsDragging(false);
|
||||||
|
selectedDragItemPos = -1;
|
||||||
|
floatingItem = null;
|
||||||
|
rv.invalidateItemDecorations();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fingerY = (int)e.getY();
|
||||||
|
|
||||||
|
if (floatingItem!=null)
|
||||||
|
{
|
||||||
|
floatingItemBounds.top = fingerY - fingerOffsetInViewY;
|
||||||
|
|
||||||
|
if (floatingItemBounds.top < -floatingItemStatingBounds.height()/2) //Allow half the view out the top
|
||||||
|
floatingItemBounds.top = -floatingItemStatingBounds.height()/2;
|
||||||
|
|
||||||
|
floatingItemBounds.bottom = floatingItemBounds.top + floatingItemStatingBounds.height();
|
||||||
|
|
||||||
|
floatingItem.setBounds(floatingItemBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Do auto scrolling at end of list
|
||||||
|
float scrollAmount=0;
|
||||||
|
if (fingerY > (rv.getHeight() * (1-autoScrollWindow)))
|
||||||
|
{
|
||||||
|
scrollAmount = (fingerY - (rv.getHeight() * (1-autoScrollWindow)));
|
||||||
|
}
|
||||||
|
else if (fingerY < (rv.getHeight() * autoScrollWindow))
|
||||||
|
{
|
||||||
|
scrollAmount = (fingerY - (rv.getHeight() * autoScrollWindow));
|
||||||
|
}
|
||||||
|
debugLog("Scroll: " + scrollAmount);
|
||||||
|
|
||||||
|
scrollAmount *= autoScrollSpeed;
|
||||||
|
rv.scrollBy(0, (int)scrollAmount);
|
||||||
|
|
||||||
|
rv.invalidateItemDecorations();// Redraw
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setIsDragging(final boolean dragging) {
|
||||||
|
if(dragging != isDragging) {
|
||||||
|
isDragging = dragging;
|
||||||
|
if(dragStateChangedListener != null) {
|
||||||
|
if (isDragging) {
|
||||||
|
dragStateChangedListener.onDragStart();
|
||||||
|
} else {
|
||||||
|
dragStateChangedListener.onDragStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnDragStateChangedListener(final OnDragStateChangedListener dragStateChangedListener) {
|
||||||
|
this.dragStateChangedListener = dragStateChangedListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Paint bgColor = new Paint();
|
||||||
|
@Override
|
||||||
|
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||||
|
if (floatingItem != null) {
|
||||||
|
floatingItem.setAlpha((int)(255 * floatingItemAlpha));
|
||||||
|
bgColor.setColor(floatingItemBgColor);
|
||||||
|
c.drawRect(floatingItemBounds,bgColor);
|
||||||
|
floatingItem.draw(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RecyclerView.OnScrollListener scrollListener = 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) {
|
||||||
|
super.onScrolled(recyclerView, dx, dy);
|
||||||
|
debugLog("Scrolled: " + dx + " " + dy);
|
||||||
|
fingerAnchorY -= dy;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param position
|
||||||
|
* @return True if we can drag the item over this position, False if not.
|
||||||
|
*/
|
||||||
|
protected boolean canDragOver(int position) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private BitmapDrawable createFloatingBitmap(View v)
|
||||||
|
{
|
||||||
|
floatingItemStatingBounds = new Rect(v.getLeft(), v.getTop(),v.getRight(), v.getBottom());
|
||||||
|
floatingItemBounds = new Rect(floatingItemStatingBounds);
|
||||||
|
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(floatingItemStatingBounds.width(),
|
||||||
|
floatingItemStatingBounds.height(), Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
v.draw(canvas);
|
||||||
|
|
||||||
|
BitmapDrawable retDrawable = new BitmapDrawable(v.getResources(), bitmap);
|
||||||
|
retDrawable.setBounds(floatingItemBounds);
|
||||||
|
|
||||||
|
return retDrawable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.kabouzeid.gramophone.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by karim on 17.03.15.
|
||||||
|
*/
|
||||||
|
public class DataBaseChangedEvent {
|
||||||
|
public static final int PLAYLISTS_CHANGED = 0;
|
||||||
|
public static final int ALBUMS_CHANGED = 1;
|
||||||
|
public static final int ARTISTS_CHANGED = 2;
|
||||||
|
public static final int SONGS_CHANGED = 3;
|
||||||
|
public static final int DATABASE_CHANGED = 4;
|
||||||
|
|
||||||
|
private int action;
|
||||||
|
|
||||||
|
public DataBaseChangedEvent(int action) {
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,15 +2,15 @@ package com.kabouzeid.gramophone.model;
|
||||||
|
|
||||||
public class Playlist {
|
public class Playlist {
|
||||||
public int id;
|
public int id;
|
||||||
public String playlistName;
|
public String name;
|
||||||
|
|
||||||
public Playlist(final int id, final String playlistName) {
|
public Playlist(final int id, final String name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.playlistName = playlistName;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Playlist() {
|
public Playlist() {
|
||||||
this.id = -1;
|
this.id = -1;
|
||||||
this.playlistName = "";
|
this.name = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.github.ksoichiro.android.observablescrollview.ObservableRecyclerView;
|
import com.github.ksoichiro.android.observablescrollview.ObservableRecyclerView;
|
||||||
import com.kabouzeid.gramophone.App;
|
import com.kabouzeid.gramophone.App;
|
||||||
|
|
@ -264,6 +265,7 @@ public class AlbumDetailActivity extends AbsFabActivity {
|
||||||
NavigationUtil.openPlayingQueueDialog(this);
|
NavigationUtil.openPlayingQueueDialog(this);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_settings:
|
case R.id.action_settings:
|
||||||
|
Toast.makeText(this, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_current_playing:
|
case R.id.action_current_playing:
|
||||||
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithFab(null));
|
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithFab(null));
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,7 @@ public class ArtistDetailActivity extends AbsFabActivity {
|
||||||
Toast.makeText(ArtistDetailActivity.this, getResources().getString(R.string.updating), Toast.LENGTH_SHORT).show();
|
Toast.makeText(ArtistDetailActivity.this, getResources().getString(R.string.updating), Toast.LENGTH_SHORT).show();
|
||||||
setUpArtistImageAndApplyPalette(true);
|
setUpArtistImageAndApplyPalette(true);
|
||||||
case R.id.action_settings:
|
case R.id.action_settings:
|
||||||
|
Toast.makeText(this, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_current_playing:
|
case R.id.action_current_playing:
|
||||||
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithFab(null));
|
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithFab(null));
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.google.samples.apps.iosched.ui.widget.SlidingTabLayout;
|
import com.google.samples.apps.iosched.ui.widget.SlidingTabLayout;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.helper.AboutDeveloperDialogHelper;
|
import com.kabouzeid.gramophone.helper.AboutDeveloperDialogHelper;
|
||||||
|
import com.kabouzeid.gramophone.helper.CreatePlaylistDialogHelper;
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.helper.PlayingQueueDialogHelper;
|
import com.kabouzeid.gramophone.helper.PlayingQueueDialogHelper;
|
||||||
import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
|
import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
|
||||||
|
|
@ -58,6 +59,7 @@ public class MainActivity extends AbsFabActivity
|
||||||
private MainActivityViewPagerAdapter viewPagerAdapter;
|
private MainActivityViewPagerAdapter viewPagerAdapter;
|
||||||
private ViewPager viewPager;
|
private ViewPager viewPager;
|
||||||
private SlidingTabLayout slidingTabLayout;
|
private SlidingTabLayout slidingTabLayout;
|
||||||
|
private int currentPage = -1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
@ -78,6 +80,7 @@ public class MainActivity extends AbsFabActivity
|
||||||
viewPagerAdapter = new MainActivityViewPagerAdapter(this);
|
viewPagerAdapter = new MainActivityViewPagerAdapter(this);
|
||||||
viewPager.setAdapter(viewPagerAdapter);
|
viewPager.setAdapter(viewPagerAdapter);
|
||||||
int startPosition = PreferenceUtils.getInstace(this).getStartPage();
|
int startPosition = PreferenceUtils.getInstace(this).getStartPage();
|
||||||
|
currentPage = startPosition;
|
||||||
viewPager.setCurrentItem(startPosition);
|
viewPager.setCurrentItem(startPosition);
|
||||||
navigationDrawerFragment.setItemChecked(startPosition);
|
navigationDrawerFragment.setItemChecked(startPosition);
|
||||||
|
|
||||||
|
|
@ -93,6 +96,8 @@ public class MainActivity extends AbsFabActivity
|
||||||
public void onPageSelected(final int position) {
|
public void onPageSelected(final int position) {
|
||||||
PreferenceUtils.getInstace(MainActivity.this).setStartPage(position);
|
PreferenceUtils.getInstace(MainActivity.this).setStartPage(position);
|
||||||
navigationDrawerFragment.setItemChecked(position);
|
navigationDrawerFragment.setItemChecked(position);
|
||||||
|
currentPage = position;
|
||||||
|
invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -210,7 +215,14 @@ public class MainActivity extends AbsFabActivity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.drawer, menu);
|
switch (currentPage){
|
||||||
|
case 3:
|
||||||
|
getMenuInflater().inflate(R.menu.menu_playlists, menu);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
getMenuInflater().inflate(R.menu.drawer, menu);
|
||||||
|
break;
|
||||||
|
}
|
||||||
restoreActionBar();
|
restoreActionBar();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -229,10 +241,17 @@ public class MainActivity extends AbsFabActivity
|
||||||
}
|
}
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
case R.id.action_licenses:
|
||||||
|
Toast.makeText(this, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
case R.id.action_new_playlist:
|
||||||
|
CreatePlaylistDialogHelper.getDialog(this).show();
|
||||||
|
return true;
|
||||||
case R.id.action_search:
|
case R.id.action_search:
|
||||||
startActivity(new Intent(MainActivity.this, SearchActivity.class));
|
startActivity(new Intent(MainActivity.this, SearchActivity.class));
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_settings:
|
case R.id.action_settings:
|
||||||
|
Toast.makeText(this, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_about:
|
case R.id.action_about:
|
||||||
AboutDeveloperDialogHelper.getDialog(this).show();
|
AboutDeveloperDialogHelper.getDialog(this).show();
|
||||||
|
|
@ -277,7 +296,7 @@ public class MainActivity extends AbsFabActivity
|
||||||
context.getResources().getString(R.string.songs),
|
context.getResources().getString(R.string.songs),
|
||||||
context.getResources().getString(R.string.albums),
|
context.getResources().getString(R.string.albums),
|
||||||
context.getResources().getString(R.string.artists),
|
context.getResources().getString(R.string.artists),
|
||||||
context.getResources().getString(R.string.playlists)
|
context.getResources().getString(R.string.playlists) + " BETA"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,9 @@ import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.helper.AddToPlaylistDialogHelper;
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.helper.PlayingQueueDialogHelper;
|
|
||||||
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
||||||
import com.kabouzeid.gramophone.lastfm.artist.LastFMArtistImageUrlLoader;
|
import com.kabouzeid.gramophone.lastfm.artist.LastFMArtistImageUrlLoader;
|
||||||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||||
|
|
@ -388,6 +387,12 @@ public class MusicControllerActivity extends AbsFabActivity {
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
case R.id.action_settings:
|
||||||
|
Toast.makeText(this, "This feature is not available yet", Toast.LENGTH_SHORT).show();
|
||||||
|
return true;
|
||||||
|
case R.id.action_add_to_playlist:
|
||||||
|
AddToPlaylistDialogHelper.getDialog(this, song).show();
|
||||||
|
return true;
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ import com.kabouzeid.gramophone.adapter.songadapter.PlaylistSongAdapter;
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
||||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||||
|
import com.kabouzeid.gramophone.misc.DragSortRecycler;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||||
|
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -34,10 +36,27 @@ public class PlaylistDetailActivity extends AbsFabActivity {
|
||||||
setUpToolBar();
|
setUpToolBar();
|
||||||
|
|
||||||
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
|
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
|
||||||
List<PlaylistSong> songs = PlaylistSongLoader.getPlaylistSongList(this, playlist.id);
|
final List<PlaylistSong> songs = PlaylistSongLoader.getPlaylistSongList(this, playlist.id);
|
||||||
PlaylistSongAdapter adapter = new PlaylistSongAdapter(this, songs);
|
final PlaylistSongAdapter adapter = new PlaylistSongAdapter(this, songs);
|
||||||
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
|
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
DragSortRecycler dragSortRecycler = new DragSortRecycler();
|
||||||
|
dragSortRecycler.setViewHandleId(R.id.album_art);
|
||||||
|
|
||||||
|
dragSortRecycler.setOnItemMovedListener(new DragSortRecycler.OnItemMovedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemMoved(int from, int to) {
|
||||||
|
PlaylistSong song = songs.remove(from);
|
||||||
|
songs.add(to, song);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
PlaylistsUtil.moveItem(PlaylistDetailActivity.this, playlist.id, from, to);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
recyclerView.addItemDecoration(dragSortRecycler);
|
||||||
|
recyclerView.addOnItemTouchListener(dragSortRecycler);
|
||||||
|
recyclerView.setOnScrollListener(dragSortRecycler.getScrollListener());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getIntentExtras() {
|
private void getIntentExtras() {
|
||||||
|
|
@ -51,7 +70,7 @@ public class PlaylistDetailActivity extends AbsFabActivity {
|
||||||
|
|
||||||
private void setUpToolBar() {
|
private void setUpToolBar() {
|
||||||
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
|
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
|
||||||
getSupportActionBar().setTitle(playlist.playlistName);
|
getSupportActionBar().setTitle(playlist.name);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,19 @@ package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments;
|
||||||
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.app.Fragment;
|
|
||||||
import android.support.v7.widget.GridLayoutManager;
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.App;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.adapter.PlaylistAdapter;
|
import com.kabouzeid.gramophone.adapter.PlaylistAdapter;
|
||||||
import com.kabouzeid.gramophone.adapter.songadapter.SongAdapter;
|
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
||||||
import com.kabouzeid.gramophone.loader.SongLoader;
|
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -37,12 +36,27 @@ public class PlaylistViewFragment extends AbsMainActivityFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpRecyclerView() {
|
private void setUpRecyclerView() {
|
||||||
List<Playlist> playlists = PlaylistLoader.getAllPlaylists(getActivity());
|
|
||||||
PlaylistAdapter adapter = new PlaylistAdapter(getActivity(), playlists);
|
|
||||||
|
|
||||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 1));
|
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 1));
|
||||||
recyclerView.setAdapter(adapter);
|
|
||||||
recyclerView.setPadding(0, getTopPadding(), 0, getBottomPadding());
|
recyclerView.setPadding(0, getTopPadding(), 0, getBottomPadding());
|
||||||
|
setUpAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpAdapter(){
|
||||||
|
if(recyclerView != null) {
|
||||||
|
List<Playlist> playlists = PlaylistLoader.getAllPlaylists(getActivity());
|
||||||
|
PlaylistAdapter adapter = new PlaylistAdapter(getActivity(), playlists);
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onDataBaseEvent(DataBaseChangedEvent event) {
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case DataBaseChangedEvent.PLAYLISTS_CHANGED:
|
||||||
|
case DataBaseChangedEvent.DATABASE_CHANGED:
|
||||||
|
setUpAdapter();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -56,4 +70,16 @@ public class PlaylistViewFragment extends AbsMainActivityFragment {
|
||||||
super.disableViews();
|
super.disableViews();
|
||||||
recyclerView.setEnabled(false);
|
recyclerView.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
App.bus.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
App.bus.unregister(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,13 @@ import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.App;
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
|
||||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
|
||||||
|
|
@ -18,6 +22,9 @@ import java.util.List;
|
||||||
* Created by karim on 16.03.15.
|
* Created by karim on 16.03.15.
|
||||||
*/
|
*/
|
||||||
public class PlaylistsUtil {
|
public class PlaylistsUtil {
|
||||||
|
public static final String MUSIC_ONLY_SELECTION = MediaStore.Audio.AudioColumns.IS_MUSIC + "=1"
|
||||||
|
+ " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''"; //$NON-NLS-2$
|
||||||
|
|
||||||
public static int createPlaylist(final Context context, final String name) {
|
public static int createPlaylist(final Context context, final String name) {
|
||||||
if (name != null && name.length() > 0) {
|
if (name != null && name.length() > 0) {
|
||||||
final ContentResolver resolver = context.getContentResolver();
|
final ContentResolver resolver = context.getContentResolver();
|
||||||
|
|
@ -32,55 +39,93 @@ public class PlaylistsUtil {
|
||||||
values.put(MediaStore.Audio.PlaylistsColumns.NAME, name);
|
values.put(MediaStore.Audio.PlaylistsColumns.NAME, name);
|
||||||
final Uri uri = resolver.insert(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
final Uri uri = resolver.insert(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||||
values);
|
values);
|
||||||
return Integer.parseInt(uri.getLastPathSegment());
|
cursor.close();
|
||||||
|
if (uri != null) {
|
||||||
|
Toast.makeText(context, context.getResources().getString(R.string.created_playlist) + name, Toast.LENGTH_SHORT).show();
|
||||||
|
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
||||||
|
return Integer.parseInt(uri.getLastPathSegment());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
Toast.makeText(context, context.getResources().getString(R.string.create_playlist_failed) + name, Toast.LENGTH_SHORT).show();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deletePlaylist(final Context context, final int playlistId) {
|
public static void clearPlaylist(final Context context, final int playlistId) {
|
||||||
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
||||||
context.getContentResolver().delete(uri, null, null);
|
context.getContentResolver().delete(uri, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addToPlaylist(final Context context, final Song song, final long playlistId) {
|
public static void deletePlaylist(final Context context, final int playlistId) {
|
||||||
|
final Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
||||||
|
String where = MediaStore.Audio.Playlists._ID + "=?";
|
||||||
|
String[] whereVal = {String.valueOf(playlistId)};
|
||||||
|
context.getContentResolver().delete(uri, where, whereVal);
|
||||||
|
Toast.makeText(context, context.getResources().getString(R.string.deleted_playlist) + getNameForPlaylist(context, playlistId), Toast.LENGTH_SHORT).show();
|
||||||
|
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addToPlaylist(final Context context, final Song song, final int playlistId) {
|
||||||
List<Song> helperList = new ArrayList<>();
|
List<Song> helperList = new ArrayList<>();
|
||||||
helperList.add(song);
|
helperList.add(song);
|
||||||
addToPlaylist(context, helperList, playlistId);
|
addToPlaylist(context, helperList, playlistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addToPlaylist(final Context context, final List<Song> songs, final long playlistId) {
|
public static void addToPlaylist(final Context context, final List<Song> songs, final int playlistId) {
|
||||||
|
final int size = songs.size();
|
||||||
final ContentResolver resolver = context.getContentResolver();
|
final ContentResolver resolver = context.getContentResolver();
|
||||||
|
|
||||||
final String[] projection = new String[]{
|
final String[] projection = new String[]{
|
||||||
MediaStore.Audio.PlaylistsColumns.NAME
|
"max(" + MediaStore.Audio.Playlists.Members.PLAY_ORDER + ")",
|
||||||
};
|
};
|
||||||
|
|
||||||
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
||||||
Cursor cursor = resolver.query(uri, projection, null, null, null);
|
Cursor cursor = null;
|
||||||
cursor.moveToFirst();
|
int base = 0;
|
||||||
final String playlistName = cursor.getString(0);
|
|
||||||
cursor.close();
|
|
||||||
|
|
||||||
ContentValues[] contentValues = new ContentValues[songs.size()];
|
try {
|
||||||
for (int i = 0; i < songs.size(); i++) {
|
cursor = resolver.query(uri, projection, null, null, null);
|
||||||
contentValues[i] = new ContentValues();
|
|
||||||
contentValues[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, songs.get(i).id);
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
base = cursor.getInt(0) + 1;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolver.bulkInsert(uri, contentValues);
|
int numinserted = 0;
|
||||||
Toast.makeText(context, "Added " + contentValues.length + " songs to playlist " + playlistName, Toast.LENGTH_SHORT).show();
|
for (int offSet = 0; offSet < size; offSet += 1000) {
|
||||||
//TODO add string resource
|
numinserted += resolver.bulkInsert(uri, makeInsertItems(songs, offSet, 1000, base));
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.makeText(context, context.getResources().getString(R.string.inserted_titles_to_playlist_1) + numinserted + context.getResources().getString(R.string.inserted_titles_to_playlist_2) + getNameForPlaylist(context, playlistId) + ".", Toast.LENGTH_SHORT).show();
|
||||||
|
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ContentValues[] makeInsertItems(final List<Song> songs, final int offset, int len, final int base) {
|
||||||
|
if (offset + len > songs.size()) {
|
||||||
|
len = songs.size() - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentValues[] contentValues = new ContentValues[len];
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
contentValues[i] = new ContentValues();
|
||||||
|
contentValues[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, base + offset + i);
|
||||||
|
contentValues[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, songs.get(offset + i).id);
|
||||||
|
}
|
||||||
|
return contentValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeFromPlaylist(final Context context, final PlaylistSong song) {
|
public static void removeFromPlaylist(final Context context, final PlaylistSong song) {
|
||||||
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
|
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
|
||||||
"external", song.playlistId);
|
"external", song.playlistId);
|
||||||
String selection = MediaStore.Audio.Playlists.Members._ID+ " =?";
|
String selection = MediaStore.Audio.Playlists.Members._ID + " =?";
|
||||||
String[] selectionArgs = new String[]{String.valueOf(song.idInPlayList)};
|
String[] selectionArgs = new String[]{String.valueOf(song.idInPlayList)};
|
||||||
|
|
||||||
context.getContentResolver().delete(uri, selection, selectionArgs);
|
context.getContentResolver().delete(uri, selection, selectionArgs);
|
||||||
|
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeFromPlaylist(final Context context, final List<PlaylistSong> songs) {
|
public static void removeFromPlaylist(final Context context, final List<PlaylistSong> songs) {
|
||||||
|
|
@ -95,5 +140,47 @@ public class PlaylistsUtil {
|
||||||
selection = selection.substring(0, selection.length() - 2) + ")";
|
selection = selection.substring(0, selection.length() - 2) + ")";
|
||||||
|
|
||||||
context.getContentResolver().delete(uri, selection, selectionArgs);
|
context.getContentResolver().delete(uri, selection, selectionArgs);
|
||||||
|
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getSongCountForPlaylist(final Context context, final long playlistId) {
|
||||||
|
Cursor c = context.getContentResolver().query(
|
||||||
|
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId),
|
||||||
|
new String[]{BaseColumns._ID}, MUSIC_ONLY_SELECTION, null, null);
|
||||||
|
|
||||||
|
if (c != null) {
|
||||||
|
int count = 0;
|
||||||
|
if (c.moveToFirst()) {
|
||||||
|
count = c.getCount();
|
||||||
|
}
|
||||||
|
c.close();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void moveItem(final Context context, int playlistId, int from, int to) {
|
||||||
|
MediaStore.Audio.Playlists.Members.moveItem(context.getContentResolver(),
|
||||||
|
playlistId, from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getNameForPlaylist(final Context context, final int id) {
|
||||||
|
Cursor cursor = context.getContentResolver().query(
|
||||||
|
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||||
|
new String[]{MediaStore.Audio.PlaylistsColumns.NAME},
|
||||||
|
BaseColumns._ID + "=?",
|
||||||
|
new String[]{String.valueOf(id)},
|
||||||
|
null);
|
||||||
|
if (cursor != null) {
|
||||||
|
try {
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
return cursor.getString(0);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
app/src/main/res/layout/dialog_create_playlist.xml
Normal file
9
app/src/main/res/layout/dialog_create_playlist.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-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:gravity="start"
|
||||||
|
android:paddingLeft="@dimen/md_dialog_frame_margin"
|
||||||
|
android:paddingRight="@dimen/md_dialog_frame_margin">
|
||||||
|
</LinearLayout>
|
||||||
|
|
@ -4,13 +4,13 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="4dp"
|
||||||
android:elevation="3dp"
|
android:elevation="3dp"
|
||||||
android:foreground="?rect_selector">
|
android:foreground="?rect_selector">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_margin="4dp"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@
|
||||||
app:showAsAction="always"/>
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_search"
|
android:id="@+id/action_search"
|
||||||
android:icon="@drawable/abc_ic_search_api_mtrl_alpha"
|
android:icon="@drawable/abc_ic_search_api_mtrl_alpha"
|
||||||
android:title="@string/action_search"
|
android:title="@string/action_search"
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_playing_queue"
|
android:id="@+id/action_playing_queue"
|
||||||
|
|
@ -29,8 +29,14 @@
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_about"
|
|
||||||
android:orderInCategory="101"
|
android:orderInCategory="101"
|
||||||
|
android:id="@+id/action_licenses"
|
||||||
|
android:title="Open Source Licenses"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_about"
|
||||||
|
android:orderInCategory="102"
|
||||||
android:title="@string/action_about"
|
android:title="@string/action_about"
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_settings"
|
|
||||||
android:orderInCategory="100"
|
|
||||||
android:title="@string/action_settings"
|
|
||||||
app:showAsAction="never"/>
|
|
||||||
</menu>
|
|
||||||
45
app/src/main/res/menu/menu_playlists.xml
Normal file
45
app/src/main/res/menu/menu_playlists.xml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_current_playing"
|
||||||
|
android:icon="@drawable/music_box"
|
||||||
|
android:title="@string/action_current_playing"
|
||||||
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_search"
|
||||||
|
android:icon="@drawable/abc_ic_search_api_mtrl_alpha"
|
||||||
|
android:title="@string/action_search"
|
||||||
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_new_playlist"
|
||||||
|
android:title="@string/action_new_playlist"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_playing_queue"
|
||||||
|
android:icon="@drawable/ic_queue_music_white_24dp"
|
||||||
|
android:title="@string/action_playing_queue"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_settings"
|
||||||
|
android:icon="@drawable/settings"
|
||||||
|
android:orderInCategory="100"
|
||||||
|
android:title="@string/action_settings"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_licenses"
|
||||||
|
android:orderInCategory="101"
|
||||||
|
android:title="Open Source Licenses"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_about"
|
||||||
|
android:orderInCategory="102"
|
||||||
|
android:title="@string/action_about"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
</menu>
|
||||||
|
|
@ -73,8 +73,16 @@
|
||||||
<string name="loading">Loading…</string>
|
<string name="loading">Loading…</string>
|
||||||
<string name="added_title_to_playing_queue">Added 1 title to the playing queue.</string>
|
<string name="added_title_to_playing_queue">Added 1 title to the playing queue.</string>
|
||||||
<string name="added_titles_to_playing_queue_1">Added </string>
|
<string name="added_titles_to_playing_queue_1">Added </string>
|
||||||
<string name="added_titles_to_playing_queue_2"> titles to the playing queue.</string>
|
<string name="added_titles_to_playing_queue_2">\u0020titles to the playing queue.</string>
|
||||||
<string name="title_activity_playlist_detail">PlaylistDetailActivity</string>
|
<string name="title_activity_playlist_detail">PlaylistDetailActivity</string>
|
||||||
<string name="action_delete_from_playlist">Delete from playlist</string>
|
<string name="action_delete_from_playlist">Delete from playlist</string>
|
||||||
|
<string name="inserted_titles_to_playlist_1">Inserted\u0020</string>
|
||||||
|
<string name="inserted_titles_to_playlist_2">\u0020titles to playlist\u0020</string>
|
||||||
|
<string name="action_new_playlist">New playlist</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
<string name="created_playlist">Created playlist\u0020</string>
|
||||||
|
<string name="deleted_playlist">Deleted playlist\u0020</string>
|
||||||
|
<string name="create_playlist_failed">Could not create playlist\u0020</string>
|
||||||
|
<string name="delete_playlist">Delete playlist\u0020</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue