From c90da12d795ad13d538a85a3c7fa11f5d5bc1e1b Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Thu, 25 Jun 2015 17:46:37 -0700 Subject: #517 Replace ContextMenu with PopupMenu --- app/src/main/res/values-es/strings.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app/src/main/res/values-es') diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index cd255e13..b91bc929 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -176,8 +176,7 @@ Reproduciendo en aleatorio Mostrar disco Letras - Eliminar de la cola - Borrar todo + Borrar todo Pantalla encendida Aleatorio Cambiar -- cgit v1.2.3 From a78354743c4862c8faac3e925176f86a78df9d63 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Thu, 2 Jul 2015 18:02:38 -0700 Subject: #332 Start of long multi select --- .../dsub/activity/SubsonicFragmentActivity.java | 4 + .../daneren2005/dsub/adapter/EntryGridAdapter.java | 13 +--- .../daneren2005/dsub/adapter/SectionAdapter.java | 86 +++++++++++++++++++--- .../dsub/fragments/SelectDirectoryFragment.java | 13 ++++ .../github/daneren2005/dsub/view/SongView.java | 16 +--- .../github/daneren2005/dsub/view/UpdateView.java | 4 + app/src/main/res/menu/select_song_context.xml | 31 -------- .../main/res/menu/select_song_context_offline.xml | 21 ------ app/src/main/res/values-de/strings.xml | 3 +- app/src/main/res/values-es/strings.xml | 3 +- app/src/main/res/values-fr/strings.xml | 3 +- app/src/main/res/values-hu/strings.xml | 3 +- app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values/strings.xml | 5 +- app/src/main/res/values/themes.xml | 3 + 15 files changed, 108 insertions(+), 101 deletions(-) (limited to 'app/src/main/res/values-es') diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java index 43bd15c7..0e9101f8 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java @@ -838,4 +838,8 @@ public class SubsonicFragmentActivity extends SubsonicActivity { } } } + + public Toolbar getActiveToolbar() { + return slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED ? nowPlayingToolbar : mainToolbar; + } } diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java index 48b278ec..0c699b89 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java @@ -41,7 +41,6 @@ public class EntryGridAdapter extends SectionAdapter { private ImageLoader imageLoader; private boolean largeAlbums; private boolean showArtist = false; - private boolean checkable = true; private View header; public EntryGridAdapter(Context context, List entries, ImageLoader imageLoader, boolean largeCell) { @@ -83,14 +82,7 @@ public class EntryGridAdapter extends SectionAdapter { albumView.setObject(entry, imageLoader); } else if(viewType == VIEW_TYPE_SONG) { SongView songView = (SongView) view; - songView.setObject(entry, checkable && !entry.isVideo()); - } - } - - @Override - public void setChecked(UpdateView updateView, boolean checked) { - if(updateView instanceof SongView) { - ((SongView) updateView).setChecked(checked); + songView.setObject(entry, checkable && !entry.isVideo() && currentActionMode != null); } } @@ -122,9 +114,6 @@ public class EntryGridAdapter extends SectionAdapter { public void setShowArtist(boolean showArtist) { this.showArtist = showArtist; } - public void setCheckable(boolean checkable) { - this.checkable = checkable; - } public void removeAt(int index) { sections.get(0).remove(index); diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java index 6f5def3e..b5592520 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java @@ -18,7 +18,9 @@ package github.daneren2005.dsub.adapter; import android.content.Context; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; import android.util.Log; +import android.view.ActionMode; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -30,6 +32,7 @@ import java.util.Arrays; import java.util.List; import github.daneren2005.dsub.R; +import github.daneren2005.dsub.activity.SubsonicFragmentActivity; import github.daneren2005.dsub.view.BasicHeaderView; import github.daneren2005.dsub.view.UpdateView; import github.daneren2005.dsub.view.UpdateView.UpdateViewHolder; @@ -43,7 +46,9 @@ public abstract class SectionAdapter extends RecyclerView.Adapter> sections; protected boolean singleSectionHeader; protected OnItemClickedListener onItemClickedListener; - private List selected = new ArrayList<>(); + protected List selected = new ArrayList<>(); + protected ActionMode currentActionMode; + protected boolean checkable = true; protected SectionAdapter() {} public SectionAdapter(Context context, List section) { @@ -80,7 +85,7 @@ public abstract class SectionAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter extends RecyclerView.Adapter extends RecyclerView.Adapter holder) { + final UpdateView updateView = holder.getUpdateView(); + if (context instanceof SubsonicFragmentActivity && currentActionMode == null) { + final SubsonicFragmentActivity fragmentActivity = (SubsonicFragmentActivity) context; + Toolbar toolbar = fragmentActivity.getActiveToolbar(); + + toolbar.startActionMode(new ActionMode.Callback() { + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + currentActionMode = mode; + fragmentActivity.onCreateOptionsMenu(menu); + + T item = holder.getItem(); + selected.add(item); + setChecked(updateView, true); + + notifyDataSetChanged(); + mode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size())); + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + if (fragmentActivity.onOptionsItemSelected(item)) { + currentActionMode.finish(); + return true; + } else { + return false; + } + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + currentActionMode = null; + selected.clear(); + notifyDataSetChanged(); + } + }); + } + } public interface OnItemClickedListener { void onItemClicked(T item); diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 9f66a27e..ed6afd46 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -420,6 +420,19 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } playNow(Arrays.asList(entry)); + } else { + List songs = new ArrayList(); + + if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PLAY_NOW_AFTER, false)) { + Iterator it = entries.listIterator(entries.indexOf(entry)); + while(it.hasNext()) { + songs.add((Entry) it.next()); + } + } else { + songs.add(entry); + } + + playNow(songs); } } diff --git a/app/src/main/java/github/daneren2005/dsub/view/SongView.java b/app/src/main/java/github/daneren2005/dsub/view/SongView.java index fadf100e..e789c5de 100644 --- a/app/src/main/java/github/daneren2005/dsub/view/SongView.java +++ b/app/src/main/java/github/daneren2005/dsub/view/SongView.java @@ -38,7 +38,7 @@ import java.io.File; * * @author Sindre Mehus */ -public class SongView extends UpdateView2 implements Checkable { +public class SongView extends UpdateView2 { private static final String TAG = SongView.class.getSimpleName(); private CheckedTextView checkedTextView; @@ -290,18 +290,8 @@ public class SongView extends UpdateView2 impleme } @Override - public void setChecked(boolean b) { - checkedTextView.setChecked(b); - } - - @Override - public boolean isChecked() { - return checkedTextView.isChecked(); - } - - @Override - public void toggle() { - checkedTextView.toggle(); + public void setChecked(boolean checked) { + checkedTextView.setChecked(checked); } public MusicDirectory.Entry getEntry() { diff --git a/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java b/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java index 8e1029df..5043e7bc 100644 --- a/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java +++ b/app/src/main/java/github/daneren2005/dsub/view/UpdateView.java @@ -27,6 +27,7 @@ import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; +import android.widget.Checkable; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; @@ -265,6 +266,9 @@ public abstract class UpdateView extends LinearLayout { public boolean isCheckable() { return checkable; } + public void setChecked(boolean checked) { + + } public void onClick() { diff --git a/app/src/main/res/menu/select_song_context.xml b/app/src/main/res/menu/select_song_context.xml index d8fc211c..eae8a8bc 100644 --- a/app/src/main/res/menu/select_song_context.xml +++ b/app/src/main/res/menu/select_song_context.xml @@ -6,37 +6,6 @@ android:id="@+id/song_menu_info" android:title="@string/common.info" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - Alle auswählen %d Lieder ausgewählt. - %d Lieder deselektiert. - Mehr + Mehr Offline Suche... Fehler: Keine SD-Karte verfügbar. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index b91bc929..3c2593e2 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -130,8 +130,7 @@ Seleccionar todo Seleccionadas %d canciones - %d canciones deseleccionadas - Más + Más Offline Buscando... Error: No hay tarjeta SD disponible diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index d547a261..cea3c77d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -129,8 +129,7 @@ Tout sélectionner %d pistes sélectionnées. - %d pistes désélectionnées. - Plus + Plus Déconnecté Recherche en cours... Erreur : Aucune carte SD card disponible. diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 6a28c051..816e605a 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -139,8 +139,7 @@ Összes jelölése be/ki %d dal kijelölve. - %d dal visszavonva. - Továbbiak + Továbbiak Offline Keresés... Hiba: SD kártya nem áll rendelkezésre! diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a3bb71be..0f904d95 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -89,7 +89,6 @@ Выбрать все %d композиций выбрано. - Выбор снят с %d композиций. Еще Оффлайн Выполняется поиск... diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 877b510f..f7c91da3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -141,9 +141,8 @@ Offline media Select all - %d tracks selected. - %d tracks unselected. - More + %d selected. + More Offline Searching... Error: No SD card available. diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index fb47af81..76f0250c 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -51,6 +51,7 @@ @style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse @style/ThemeOverlay.AppCompat.Light @style/DarkSpinnerItem + true -- cgit v1.2.3 From fbd1a68042dfc3601eaa0a9e37b3957bbdd51420 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 22 Jul 2015 20:03:30 -0700 Subject: Update details dialogs, remove play/cache/delete from more menus to keep context menus smaller --- .../daneren2005/dsub/adapter/DetailsAdapter.java | 62 +++++++ .../daneren2005/dsub/adapter/SectionAdapter.java | 29 +++- .../daneren2005/dsub/fragments/MainFragment.java | 57 +++++-- .../dsub/fragments/SelectDirectoryFragment.java | 12 -- .../dsub/fragments/SelectPlaylistFragment.java | 60 ++++--- .../dsub/fragments/SelectPodcastsFragment.java | 30 +++- .../dsub/fragments/SubsonicFragment.java | 178 ++++++--------------- .../dsub/service/OfflineMusicService.java | 46 +++++- .../daneren2005/dsub/service/RESTMusicService.java | 2 +- .../github/daneren2005/dsub/util/FileUtil.java | 19 ++- .../java/github/daneren2005/dsub/util/Util.java | 32 ++++ app/src/main/res/layout/details_item.xml | 28 ++++ app/src/main/res/menu/select_album_context.xml | 40 +---- .../main/res/menu/select_album_context_offline.xml | 30 +--- app/src/main/res/menu/select_artist_context.xml | 40 +---- .../res/menu/select_artist_context_offline.xml | 30 ---- app/src/main/res/menu/select_bookmark_context.xml | 12 -- app/src/main/res/menu/select_playlist_context.xml | 15 -- .../res/menu/select_playlist_context_offline.xml | 14 +- .../res/menu/select_podcast_episode_context.xml | 12 +- .../select_podcast_episode_context_offline.xml | 8 +- app/src/main/res/values-de/strings.xml | 8 +- app/src/main/res/values-es/strings.xml | 8 +- app/src/main/res/values-fr/strings.xml | 6 - app/src/main/res/values-hu/strings.xml | 6 - app/src/main/res/values-ru/strings.xml | 6 - app/src/main/res/values/strings.xml | 44 ++++- 27 files changed, 399 insertions(+), 435 deletions(-) create mode 100644 app/src/main/java/github/daneren2005/dsub/adapter/DetailsAdapter.java create mode 100644 app/src/main/res/layout/details_item.xml delete mode 100644 app/src/main/res/menu/select_artist_context_offline.xml (limited to 'app/src/main/res/values-es') diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/DetailsAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/DetailsAdapter.java new file mode 100644 index 00000000..efafe27a --- /dev/null +++ b/app/src/main/java/github/daneren2005/dsub/adapter/DetailsAdapter.java @@ -0,0 +1,62 @@ +/* + This file is part of Subsonic. + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see . + Copyright 2015 (C) Scott Jackson +*/ + +package github.daneren2005.dsub.adapter; + +import android.content.Context; +import android.text.SpannableString; +import android.text.method.LinkMovementMethod; +import android.text.util.Linkify; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import java.util.List; + +import github.daneren2005.dsub.R; + +public class DetailsAdapter extends ArrayAdapter { + private List headers; + private List details; + + public DetailsAdapter(Context context, int layout, List headers, List details) { + super(context, layout, headers); + + this.headers = headers; + this.details = details; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent){ + View view; + if(convertView == null) { + view = LayoutInflater.from(getContext()).inflate(R.layout.details_item, null); + } else { + view = convertView; + } + + TextView nameView = (TextView) view.findViewById(R.id.detail_name); + TextView detailsView = (TextView) view.findViewById(R.id.detail_value); + + nameView.setText(headers.get(position)); + + detailsView.setText(details.get(position)); + Linkify.addLinks(detailsView, Linkify.ALL); + + return view; + } +} diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java index 9d577409..3f6086d5 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java @@ -178,9 +178,7 @@ public abstract class SectionAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter extends RecyclerView.Adapter { } private void showAboutDialog() { - new LoadingTask(context) { + new LoadingTask(context) { + Long[] used; + long bytesTotalFs; + long bytesAvailableFs; + @Override - protected String doInBackground() throws Throwable { + protected Void doInBackground() throws Throwable { File rootFolder = FileUtil.getMusicDirectory(context); StatFs stat = new StatFs(rootFolder.getPath()); - long bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize(); - long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize(); - - Pair used = FileUtil.getUsedSize(context, rootFolder); - - return getResources().getString(R.string.main_about_text, - context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName, - used.getFirst(), - Util.formatLocalizedBytes(used.getSecond(), context), - Util.formatLocalizedBytes(Util.getCacheSizeMB(context) * 1024L * 1024L, context), - Util.formatLocalizedBytes(bytesAvailableFs, context), - Util.formatLocalizedBytes(bytesTotalFs, context)); + bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize(); + bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize(); + + used = FileUtil.getUsedSize(context, rootFolder); + return null; } @Override - protected void done(String msg) { + protected void done(Void result) { + List headers = new ArrayList<>(); + List details = new ArrayList<>(); + + headers.add(R.string.details_author); + details.add("Scott Jackson"); + + headers.add(R.string.details_email); + details.add("dsub.android@gmail.com"); + try { - Util.info(context, R.string.main_about_title, msg); + headers.add(R.string.details_version); + details.add(context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName); } catch(Exception e) { - Util.toast(context, "Failed to open dialog"); + details.add(""); } + + Resources res = context.getResources(); + headers.add(R.string.details_files_cached); + details.add(Long.toString(used[0])); + + headers.add(R.string.details_files_permanent); + details.add(Long.toString(used[1])); + + headers.add(R.string.details_used_space); + details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(used[2], context), Util.formatLocalizedBytes(Util.getCacheSizeMB(context) * 1024L * 1024L, context))); + + headers.add(R.string.details_available_space); + details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(bytesAvailableFs, context), Util.formatLocalizedBytes(bytesTotalFs, context))); + + Util.showDetailsDialog(context, R.string.main_about_title, headers, details); } }.execute(); } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 2ab8316c..555e308e 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -360,18 +360,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } @Override public boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, Entry entry) { - if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PLAY_NOW_AFTER, false) && menuItem.getItemId() == R.id.song_menu_play_now) { - List songs = new ArrayList(); - songs.add(entry); - Iterator it = entries.listIterator(entries.indexOf(entry)); - while(it.hasNext()) { - songs.add((Entry) it.next()); - } - - playNow(songs); - return true; - } - if(onContextItemSelected(menuItem, entry)) { return true; } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java index 5b7e68a6..b1587e24 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java @@ -68,40 +68,13 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { @Override public boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, Playlist playlist) { - SubsonicFragment fragment; - Bundle args; - FragmentTransaction trans; switch (menuItem.getItemId()) { - case R.id.playlist_menu_download: - downloadPlaylist(playlist.getId(), playlist.getName(), false, true, false, false, true); - break; case R.id.playlist_menu_sync: syncPlaylist(playlist); break; case R.id.playlist_menu_stop_sync: stopSyncPlaylist(playlist); break; - case R.id.playlist_menu_play_now: - fragment = new SelectDirectoryFragment(); - args = new Bundle(); - args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId()); - args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName()); - args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true); - fragment.setArguments(args); - - replaceFragment(fragment); - break; - case R.id.playlist_menu_play_shuffled: - fragment = new SelectDirectoryFragment(); - args = new Bundle(); - args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId()); - args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName()); - args.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, true); - args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true); - fragment.setArguments(args); - - replaceFragment(fragment); - break; case R.id.playlist_menu_delete: deletePlaylist(playlist); break; @@ -213,12 +186,33 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { } private void displayPlaylistInfo(final Playlist playlist) { - String message = "Owner: " + playlist.getOwner() + "\nComments: " + - ((playlist.getComment() == null) ? "" : playlist.getComment()) + - "\nSong Count: " + playlist.getSongCount() + - ((playlist.getPublic() == null) ? "" : ("\nPublic: " + playlist.getPublic())) + - "\nCreated: " + Util.formatDate(context, playlist.getCreated()); - Util.info(context, playlist.getName(), message); + List headers = new ArrayList<>(); + List details = new ArrayList<>(); + + if(playlist.getOwner() != null) { + headers.add(R.string.details_owner); + details.add(playlist.getOwner()); + } + + if(playlist.getComment() != null) { + headers.add(R.string.details_comments); + details.add(playlist.getComment()); + } + + headers.add(R.string.details_song_count); + details.add(playlist.getSongCount()); + + if(playlist.getPublic() != null) { + headers.add(R.string.details_public); + details.add(Boolean.toString(playlist.getPublic())); + } + + if(playlist.getCreated() != null) { + headers.add(R.string.details_created); + details.add(Util.formatDate(context, playlist.getCreated())); + } + + Util.showDetailsDialog(context, R.string.details_title_playlist, headers, details); } private void updatePlaylistInfo(final Playlist playlist) { diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java index f8afce6e..381453c0 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java @@ -214,13 +214,29 @@ public class SelectPodcastsFragment extends SelectRecyclerFragment headers = new ArrayList<>(); + List details = new ArrayList<>(); + + if(channel.getName() != null) { + headers.add(R.string.details_title); + details.add(channel.getName()); + } + + headers.add(R.string.details_url); + details.add(channel.getUrl()); + headers.add(R.string.details_status); + details.add(channel.getStatus()); + + if(channel.getErrorMessage() != null) { + headers.add(R.string.details_error); + details.add(channel.getErrorMessage()); + } + if(channel.getDescription() != null) { + headers.add(R.string.details_description); + details.add(channel.getDescription()); + } + + Util.showDetailsDialog(context, R.string.details_title_podcast, headers, details); } private void deletePodcast(final PodcastChannel channel) { diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java index 438649c3..6925b2da 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java @@ -241,9 +241,8 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } else if(selected instanceof Artist) { Artist artist = (Artist) selected; if(Util.isOffline(context)) { - menuInflater.inflate(R.menu.select_artist_context_offline, menu); - } - else { + // menuInflater.inflate(R.menu.select_artist_context_offline, menu); + } else { menuInflater.inflate(R.menu.select_artist_context, menu); menu.findItem(R.id.artist_menu_star).setTitle(artist.isStarred() ? R.string.common_unstar : R.string.common_star); @@ -281,56 +280,6 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if(!prefs.getBoolean(Constants.PREFERENCES_KEY_MENU_RATING, true)) { menu.setGroupVisible(R.id.hide_rating, false); } - - if(!Util.isOffline(context)) { - // If we are looking at a standard song view, get downloadFile to cache what options to show - if(updateView instanceof SongView) { - SongView songView = (SongView) updateView; - DownloadFile downloadFile = songView.getDownloadFile(); - - try { - if(downloadFile != null) { - if(downloadFile.isWorkDone()) { - // Remove permanent cache menu if already perma cached - if(downloadFile.isSaved()) { - menu.removeItem(R.id.song_menu_pin); - } - - // Remove cache option no matter what if already downloaded - menu.removeItem(R.id.song_menu_download); - } else { - // Remove delete option if nothing to delete - menu.removeItem(R.id.song_menu_delete); - } - } - } catch(Exception e) { - Log.w(TAG, "Failed to lookup downloadFile info", e); - } - } - // Apply similar logic to album views - else if(updateView instanceof AlbumView || updateView instanceof ArtistView || updateView instanceof ArtistEntryView) { - File folder = null; - int id = 0; - if(updateView instanceof AlbumView) { - folder = ((AlbumView) updateView).getFile(); - id = R.id.album_menu_delete; - } else if(updateView instanceof ArtistView) { - folder = ((ArtistView) updateView).getFile(); - id = R.id.artist_menu_delete; - } else if(updateView instanceof ArtistEntryView) { - folder = ((ArtistEntryView) updateView).getFile(); - id = R.id.artist_menu_delete; - } - - try { - if(folder != null && !folder.exists()) { - menu.removeItem(id); - } - } catch(Exception e) { - Log.w(TAG, "Failed to lookup album directory info", e); - } - } - } } protected void recreateContextMenu(Menu menu) { @@ -355,60 +304,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR songs.add(entry); switch (menuItem.getItemId()) { - case R.id.artist_menu_play_now: - downloadRecursively(artist.getId(), false, false, true, false, false); - break; - case R.id.artist_menu_play_shuffled: - downloadRecursively(artist.getId(), false, false, true, true, false); - break; - case R.id.artist_menu_play_next: - downloadRecursively(artist.getId(), false, true, false, false, false, true); - break; - case R.id.artist_menu_play_last: - downloadRecursively(artist.getId(), false, true, false, false, false); - break; - case R.id.artist_menu_download: - downloadRecursively(artist.getId(), false, true, false, false, true); - break; - case R.id.artist_menu_pin: - downloadRecursively(artist.getId(), true, true, false, false, true); - break; - case R.id.artist_menu_delete: - deleteRecursively(artist); - break; case R.id.artist_menu_star: toggleStarred(artist); break; - case R.id.album_menu_play_now: - artistOverride = true; - downloadRecursively(entry.getId(), false, false, true, false, false); - break; - case R.id.album_menu_play_shuffled: - artistOverride = true; - downloadRecursively(entry.getId(), false, false, true, true, false); - break; - case R.id.album_menu_play_next: - artistOverride = true; - downloadRecursively(entry.getId(), false, true, false, false, false, true); - break; - case R.id.album_menu_play_last: - artistOverride = true; - downloadRecursively(entry.getId(), false, true, false, false, false); - break; - case R.id.album_menu_download: - artistOverride = true; - downloadRecursively(entry.getId(), false, true, false, false, true); - break; - case R.id.album_menu_pin: - artistOverride = true; - downloadRecursively(entry.getId(), true, true, false, false, true); - break; case R.id.album_menu_star: toggleStarred(entry); break; - case R.id.album_menu_delete: - deleteRecursively(entry); - break; case R.id.album_menu_info: displaySongInfo(entry); break; @@ -418,21 +319,9 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR case R.id.album_menu_share: createShare(songs); break; - case R.id.song_menu_play_now: - playNow(songs); - break; - case R.id.song_menu_play_next: - getDownloadService().download(songs, false, false, true, false); - break; - case R.id.song_menu_play_last: - getDownloadService().download(songs, false, false, false, false); - break; case R.id.song_menu_download: getDownloadService().downloadBackground(songs, false); break; - case R.id.song_menu_pin: - getDownloadService().downloadBackground(songs, true); - break; case R.id.song_menu_delete: getDownloadService().delete(songs); break; @@ -1262,7 +1151,6 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } - @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) public void displaySongInfo(final Entry song) { Integer duration = null; Integer bitrate = null; @@ -1302,55 +1190,83 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } } - String msg = ""; + List headers = new ArrayList<>(); + List details = new ArrayList<>(); if(song instanceof PodcastEpisode) { - msg += "Podcast: " + song.getArtist() + "\nStatus: " + ((PodcastEpisode)song).getStatus(); + headers.add(R.string.details_podcast); + details.add(song.getArtist()); + + headers.add(R.string.details_status); + details.add(((PodcastEpisode)song).getStatus()); } else if(!song.isVideo()) { if(song.getArtist() != null && !"".equals(song.getArtist())) { - msg += "Artist: " + song.getArtist(); + headers.add(R.string.details_artist); + details.add(song.getArtist()); } if(song.getAlbum() != null && !"".equals(song.getAlbum())) { - msg += "\nAlbum: " + song.getAlbum(); + headers.add(R.string.details_album); + details.add(song.getAlbum()); } } if(song.getTrack() != null && song.getTrack() != 0) { - msg += "\nTrack: " + song.getTrack(); + headers.add(R.string.details_track); + details.add(Integer.toString(song.getTrack())); } if(song.getGenre() != null && !"".equals(song.getGenre())) { - msg += "\nGenre: " + song.getGenre(); + headers.add(R.string.details_genre); + details.add(song.getGenre()); } if(song.getYear() != null && song.getYear() != 0) { - msg += "\nYear: " + song.getYear(); + headers.add(R.string.details_year); + details.add(Integer.toString(song.getYear())); } if(!Util.isOffline(context) && song.getSuffix() != null) { - msg += "\nServer Format: " + song.getSuffix(); + headers.add(R.string.details_server_format); + details.add(song.getSuffix()); + if(song.getBitRate() != null && song.getBitRate() != 0) { - msg += "\nServer Bitrate: " + song.getBitRate() + " kbps"; + headers.add(R.string.details_server_bitrate); + details.add(song.getBitRate() + " kbps"); } } if(format != null && !"".equals(format)) { - msg += "\nCached Format: " + format; + headers.add(R.string.details_cached_format); + details.add(format); } if(bitrate != null && bitrate != 0) { - msg += "\nCached Bitrate: " + bitrate + " kbps"; + headers.add(R.string.details_cached_bitrate); + details.add(bitrate + " kbps"); } if(size != 0) { - msg += "\nSize: " + Util.formatLocalizedBytes(size, context); + headers.add(R.string.details_size); + details.add(Util.formatLocalizedBytes(size, context)); } if(song.getDuration() != null && song.getDuration() != 0) { - msg += "\nLength: " + Util.formatDuration(song.getDuration()); + headers.add(R.string.details_length); + details.add(Util.formatDuration(song.getDuration())); } if(song.getBookmark() != null) { - msg += "\nBookmark Position: " + Util.formatDuration(song.getBookmark().getPosition() / 1000); + headers.add(R.string.details_bookmark_position); + details.add(Util.formatDuration(song.getBookmark().getPosition() / 1000)); } if(song.getRating() != 0) { - msg += "\nRating: " + song.getRating() + " stars"; + headers.add(R.string.details_rating); + details.add(song.getRating() + " stars"); } if(song instanceof PodcastEpisode) { - msg += "\n\nDescription: " + song.getAlbum(); + headers.add(R.string.details_description); + details.add(song.getAlbum()); } - Util.info(context, song.getTitle(), msg); + int title; + if(song.isDirectory()) { + title = R.string.details_title_album; + } else if(song instanceof PodcastEpisode) { + title = R.string.details_title_podcast; + } else { + title = R.string.details_title_song; + } + Util.showDetailsDialog(context, title, headers, details); } protected void playVideo(Entry entry) { diff --git a/app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java b/app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java index b4105d07..8ebf4c13 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java @@ -382,6 +382,42 @@ public class OfflineMusicService implements MusicService { String id = file.getName(); String filename = server + ": " + FileUtil.getBaseName(id); Playlist playlist = new Playlist(server, filename); + + Reader reader = null; + BufferedReader buffer = null; + try { + int songCount = 0; + reader = new FileReader(file); + buffer = new BufferedReader(reader); + + String line = buffer.readLine(); + while( (line = buffer.readLine()) != null ){ + // No matter what, end file can't have .complete in it + line = line.replace(".complete", ""); + File entryFile = new File(line); + + // Don't add file to playlist if it doesn't exist as cached or pinned! + File checkFile = entryFile; + if(!checkFile.exists()) { + // If normal file doens't exist, check if .complete version does + checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName()) + + ".complete." + FileUtil.getExtension(entryFile.getName())); + } + + String entryName = getName(entryFile); + if(checkFile.exists() && entryName != null){ + songCount++; + } + } + + playlist.setSongCount(Integer.toString(songCount)); + } catch(Exception e) { + Log.w(TAG, "Failed to count songs in playlist", e); + } finally { + Util.close(buffer); + Util.close(reader); + } + playlists.add(playlist); } } @@ -684,10 +720,16 @@ public class OfflineMusicService implements MusicService { for(File file: dir.listFiles()) { BufferedReader br = new BufferedReader(new FileReader(file)); while ((line = br.readLine()) != null && !"".equals(line)) { + String[] parts = line.split("\t"); + PodcastChannel channel = new PodcastChannel(); - channel.setId(line); - channel.setName(line); + channel.setId(parts[0]); + channel.setName(parts[0]); channel.setStatus("completed"); + + if(parts.length > 1) { + channel.setUrl(parts[1]); + } if(FileUtil.getPodcastDirectory(context, channel).exists() && !channels.contains(channel)) { channels.add(channel); diff --git a/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java b/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java index 459c8c9e..ed34e1cb 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java @@ -1204,7 +1204,7 @@ public class RESTMusicService implements MusicService { String content = ""; for(PodcastChannel channel: channels) { - content += channel.getName() + "\n"; + content += channel.getName() + "\t" + channel.getUrl() + "\n"; } File file = FileUtil.getPodcastFile(context, Util.getServerName(context, getInstance(context))); diff --git a/app/src/main/java/github/daneren2005/dsub/util/FileUtil.java b/app/src/main/java/github/daneren2005/dsub/util/FileUtil.java index 990eae06..185a6b29 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/FileUtil.java +++ b/app/src/main/java/github/daneren2005/dsub/util/FileUtil.java @@ -741,23 +741,28 @@ public class FileUtil { return index == -1 ? name : name.substring(0, index); } - public static Pair getUsedSize(Context context, File file) { + public static Long[] getUsedSize(Context context, File file) { long number = 0L; + long permanent = 0L; long size = 0L; if(file.isFile()) { if(isMediaFile(file)) { - return new Pair(1L, file.length()); + if(file.getAbsolutePath().indexOf(".complete") == -1) { + permanent++; + } + return new Long[] {1L, permanent, file.length()}; } else { - return new Pair(0L, 0L); + return new Long[] {0L, 0L, 0L}; } } else { for (File child : FileUtil.listFiles(file)) { - Pair pair = getUsedSize(context, child); - number += pair.getFirst(); - size += pair.getSecond(); + Long[] pair = getUsedSize(context, child); + number += pair[0]; + permanent += pair[1]; + size += pair[2]; } - return new Pair(number, size); + return new Long[] {number, permanent, size}; } } diff --git a/app/src/main/java/github/daneren2005/dsub/util/Util.java b/app/src/main/java/github/daneren2005/dsub/util/Util.java index ce26bf1e..db0cb7c1 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/Util.java +++ b/app/src/main/java/github/daneren2005/dsub/util/Util.java @@ -19,6 +19,7 @@ package github.daneren2005.dsub.util; import android.annotation.TargetApi; import android.app.Activity; +import android.support.annotation.StringRes; import android.support.v7.app.AlertDialog; import android.content.ComponentName; import android.content.Context; @@ -45,11 +46,14 @@ import android.text.method.LinkMovementMethod; import android.text.util.Linkify; import android.util.Log; import android.view.Gravity; +import android.widget.ArrayAdapter; +import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import github.daneren2005.dsub.R; import github.daneren2005.dsub.activity.SettingsActivity; import github.daneren2005.dsub.activity.SubsonicFragmentActivity; +import github.daneren2005.dsub.adapter.DetailsAdapter; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState; import github.daneren2005.dsub.domain.RepeatMode; @@ -73,8 +77,10 @@ import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.List; import java.util.Locale; import java.util.TimeZone; @@ -1137,6 +1143,32 @@ public final class Util { ((TextView)dialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); } + public static void showDetailsDialog(Context context, @StringRes int title, List headers, List details) { + List headerStrings = new ArrayList<>(); + for(@StringRes Integer res: headers) { + headerStrings.add(context.getResources().getString(res)); + } + showDetailsDialog(context, context.getResources().getString(title), headerStrings, details); + } + public static void showDetailsDialog(Context context, String title, List headers, List details) { + ListView listView = new ListView(context); + listView.setAdapter(new DetailsAdapter(context, R.layout.details_item, headers, details)); + listView.setDivider(null); + listView.setScrollbarFadingEnabled(false); + + new AlertDialog.Builder(context) + // .setIcon(android.R.drawable.ic_dialog_info) + .setTitle(title) + .setView(listView) + .setPositiveButton(R.string.common_close, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int i) { + dialog.dismiss(); + } + }) + .show(); + } + public static void sleepQuietly(long millis) { try { Thread.sleep(millis); diff --git a/app/src/main/res/layout/details_item.xml b/app/src/main/res/layout/details_item.xml new file mode 100644 index 00000000..4ef5fef0 --- /dev/null +++ b/app/src/main/res/layout/details_item.xml @@ -0,0 +1,28 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/select_album_context.xml b/app/src/main/res/menu/select_album_context.xml index 5b2529e7..388fd1f5 100644 --- a/app/src/main/res/menu/select_album_context.xml +++ b/app/src/main/res/menu/select_album_context.xml @@ -1,48 +1,10 @@ - - + - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/menu/select_album_context_offline.xml b/app/src/main/res/menu/select_album_context_offline.xml index a1805f5b..60858d91 100644 --- a/app/src/main/res/menu/select_album_context_offline.xml +++ b/app/src/main/res/menu/select_album_context_offline.xml @@ -1,31 +1,9 @@ - - - - - - - - + - - - - - + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/menu/select_bookmark_context.xml b/app/src/main/res/menu/select_bookmark_context.xml index 2b1b83fd..d52db105 100644 --- a/app/src/main/res/menu/select_bookmark_context.xml +++ b/app/src/main/res/menu/select_bookmark_context.xml @@ -14,18 +14,6 @@ android:id="@+id/song_menu_show_artist" android:title="@string/menu.show_artist"/> - - - - - - diff --git a/app/src/main/res/menu/select_playlist_context.xml b/app/src/main/res/menu/select_playlist_context.xml index 47033d9c..4941e94b 100644 --- a/app/src/main/res/menu/select_playlist_context.xml +++ b/app/src/main/res/menu/select_playlist_context.xml @@ -7,21 +7,6 @@ android:title="@string/common.info" /> - - - - - - diff --git a/app/src/main/res/menu/select_playlist_context_offline.xml b/app/src/main/res/menu/select_playlist_context_offline.xml index d63aec17..6745d850 100644 --- a/app/src/main/res/menu/select_playlist_context_offline.xml +++ b/app/src/main/res/menu/select_playlist_context_offline.xml @@ -1,13 +1,7 @@ - - + - - \ No newline at end of file diff --git a/app/src/main/res/menu/select_podcast_episode_context.xml b/app/src/main/res/menu/select_podcast_episode_context.xml index bacccda3..31f2a051 100644 --- a/app/src/main/res/menu/select_podcast_episode_context.xml +++ b/app/src/main/res/menu/select_podcast_episode_context.xml @@ -7,7 +7,7 @@ android:title="@string/common.info" /> - @@ -23,16 +23,16 @@ android:id="@+id/song_menu_play_last" android:title="@string/common.play_last"/> - - - - - + - - @@ -23,8 +23,8 @@ android:id="@+id/song_menu_play_last" android:title="@string/common.play_last"/> - - diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index cd387b65..d4a239a6 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -42,13 +42,7 @@ Willkommen zu DSub! Die App ist aktuell für den Subsonic-Demo-Server konfiguriert. Nachdem Sie Ihren eigenen Server aufgesetzt haben (verfügbar unter subsonic.org) könne Sie diesen unter Einstellungen konfigurieren. Über DSub - Autor: Scott Jackson - \nEmail: dsub.android@gmail.com - \nVersion: %1$s - \nLokal gespeicherte Titel: %2$s - \nGenutzter Speicher: %3$s von %4$s - \nVerfügbarer Speicher: %5$s von %6$s - FAQ + FAQ Cache vs Permanenter Cache: diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3c2593e2..e4d80211 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -41,13 +41,7 @@ Bienvenido! Bienvenido a DSub! Ahora la aplicación está configurada para usar el servidor de demostración de Subsonic. Cuando configures tu servidor personal (disponible en subsonic.org), accede a Preferencias y cambia la configuración para conectarte. Acerca de DSub - Autor: Scott Jackson - \nEmail: dsub.android@gmail.com - \nVersión: %1$s - \nArchivos en caché: %2$s - \nEspacio usado: %3$s of %4$s - \nEspacio disponible: %5$s of %6$s - Seleccionar servidor + Seleccionar servidor Reproducción aleatoria Modo Offline Modo Online diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index cea3c77d..84e3dd75 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -41,12 +41,6 @@ Bienvenue ! Bienvenue dans DSub ! L\'application est actuellement configurée pour se connecter au serveur de démo Subsonic (demo.subsonic.org). Vous pouvez configurer votre propre serveur dans les paramètres. Choisir Paramètres et mettre à jour la configuration pour vous y connecter. A propos de DSub - Auteur : Scott Jackson - \nEmail : dsub.android@gmail.com - \nVersion : %1$s - \nFichiers en cache : %2$s - \nEspace utilisé : %3$s de %4$s - \nEspace dispo. : %5$s de %6$s FAQ Üdvözli a DSub! Az alkalmazás még nincs beállítva. Miután konfigurálta saját kiszolgálóját (elérhető: subsonic.org), húzza balról jobbra az oldalsávot, lépjen be a Beállítások menüpontba és adja meg a kapcsolódási adatokat! DSub információk - Fejlesztő: Scott Jackson - \nEmail: dsub.android@gmail.com - \nVerzió: %1$s - \nGyorsítótárazott fájlok: %2$s - \nFelhasznált tároló: %3$s/%4$s - \nFelhasználható tároló: %5$s/%6$s GYIK Добро пожаловать в DSub! Это приложение настроено на работу с демо сервером Subsonic. После настройки Вашего персонального сервера (доступен на subsonic.org), пожалуйста, перейдите в Настройки и измените параметры для подключения. О программе DSub - Автор: Scott Jackson - \nEmail: dsub.android@gmail.com - \nВерсия: %1$s - \nFiles Cached: %2$s - \nИспользовано места: %3$s из %4$s - \nДоступно места: %5$s из %6$s Выбрать сервер Случайное воспроизведение Отключиться diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f7c91da3..74d69e5e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,6 +25,7 @@ cache No data Warning + Close Home Library @@ -42,12 +43,6 @@ Welcome to DSub! The app is currently configured to use the Subsonic demo server. After you\'ve set up your personal server (available from subsonic.org), please go to Settings and change the configuration to connect to it. About DSub - Author: Scott Jackson - \nEmail: dsub.android@gmail.com - \nVersion: %1$s - \nFiles Cached: %2$s - \nUsed Space: %3$s of %4$s - \nAvailable Space: %5$s of %6$s FAQ Toggle offline: Do Nothing + Song Details + Album Details + Podcast Details + Playlist Details + Podcast + Status + Artist + Album + Track + Genre + Year + Server Format + Server Bitrate + Cached Format + Cached Bitrate + Size + Length + Bookmark Position + Rating + Description + Owner + Comments + Song Count + Public + Created + Title + URL + Error Message + Author + Email + Version + Files Cached + Permanent Cached + Used Space + Available Space + %1$s of %2$s + No songs One song -- cgit v1.2.3 From c04ae69ec580c7d86eed872626cc98bdd2769c81 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 22 Jul 2015 20:26:21 -0700 Subject: #506 Show sleep time remaining --- .../daneren2005/dsub/fragments/NowPlayingFragment.java | 16 ++++++++++++---- .../github/daneren2005/dsub/service/DownloadService.java | 6 ++++++ app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-hu/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 3 +-- app/src/main/res/values/strings.xml | 2 +- 8 files changed, 20 insertions(+), 11 deletions(-) (limited to 'app/src/main/res/values-es') diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java index bec43a22..c754f370 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java @@ -131,6 +131,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis private boolean scrollWhenLoaded = false; private int lastY = 0; private int currentPlayingSize = 0; + private MenuItem timerMenu; /** * Called when the activity is first created. @@ -525,10 +526,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis menuInflater.inflate(R.menu.nowplaying_offline, menu); } else { menuInflater.inflate(R.menu.nowplaying, menu); - - if(downloadService != null && downloadService.getSleepTimer()) { - menu.findItem(R.id.menu_toggle_timer).setTitle(R.string.download_stop_timer); - } + } + if(downloadService != null && downloadService.getSleepTimer()) { + int timeRemaining = downloadService.getSleepTimeRemaining(); + timerMenu = menu.findItem(R.id.menu_toggle_timer); + timerMenu.setTitle(context.getResources().getString(R.string.download_stop_time_remaining, Util.formatDuration(timeRemaining))); } if(downloadService != null && downloadService.getKeepScreenOn()) { menu.findItem(R.id.menu_screen_on_off).setChecked(true); @@ -1380,6 +1382,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis progressBar.setProgress(0); progressBar.setEnabled(false); } + + DownloadService downloadService = getDownloadService(); + if(downloadService.getSleepTimer() && timerMenu != null) { + int timeRemaining = downloadService.getSleepTimeRemaining(); + timerMenu.setTitle(context.getResources().getString(R.string.download_stop_time_remaining, Util.formatDuration(timeRemaining))); + } } @Override diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java index ab757c59..a9f82919 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java @@ -157,6 +157,7 @@ public class DownloadService extends Service { private Timer sleepTimer; private int timerDuration; + private long timerStart; private boolean autoPlayStart = false; private MediaRouteManager mediaRouter; @@ -1808,6 +1809,11 @@ public class DownloadService extends Service { } }, timerDuration * 60 * 1000); + timerStart = System.currentTimeMillis(); + } + + public int getSleepTimeRemaining() { + return (int) (timerStart + (timerDuration * 60 * 1000) - System.currentTimeMillis()) / 1000; } public void stopSleepTimer() { diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index d4a239a6..c370c77c 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -206,7 +206,6 @@ Fernbedienung ist nicht erlaubt. Bitte aktivieren Sie den Jukebox-Modus unter Nutzer > Einstellungen auf Ihrem Subsonic-Server. Timer: Starte Timer - Stoppe Timer Video muss zuerst heruntergeladen werden Stream kann nicht wiedergegeben werden. Wiedergabe: %1$d/%2$d diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index e4d80211..f56e939e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -191,7 +191,6 @@ Control remoto no permitido. Por favor, active el modo jukebox en Users > Settings en su servidor Subsonic. Temporizador Iniciar temporizador - Detener temporizador El vídeo ha de ser descargado antes Ningún reproductor puede reproducir este stream %1$d/%2$d diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 84e3dd75..4674ca32 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -191,7 +191,6 @@ Mode télécommande non autorisée. Activer le mode jukebox.Users > Settings on your Subsonic server. Minuteur : Démarrer le minuteur - Arrêter le minuteur La vidéo doit d\'abord être téléchargée Aucun lecteur ne peut afficher ce flux Lecture : %1$d/%2$d diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 481a4c99..91cdf202 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -202,7 +202,6 @@ A távvezérlés nem lehetséges! Engedélyezze a Jukebox módot a Users > Settings menüben a Subsonic kiszolgálón! Időhossz: Időzítő indítása - Időzítő megállítása A videót először le kell tölteni! Nincs megfelelő lejátszó a stream megjelenítéséhez! Lejátszás: %1$d/%2$d diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 15c79a69..ffbb0485 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -123,8 +123,7 @@ Удаленное управление запрещено. Пожалуйста, активируйте режим jukebox в разделе Настройки > Проигрыватели на вашем сервере Subsonic. Длительность Запустить таймер - Остановить таймер - Необходимо сначала скачать видео + Необходимо сначала скачать видео Нет плеера для воспроизведения потока \"%s\" добавлено в закладки diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 74d69e5e..b783f0b9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -207,7 +207,7 @@ Remote control is not allowed. Please enable jukebox mode in Users > Settings on your Subsonic server. Timer: Start Timer - Stop Timer + Stop in %1$s Video needs to be downloaded first No player can play this stream Playing: %1$d/%2$d -- cgit v1.2.3