Compare commits
45 Commits
Author | SHA1 | Date |
---|---|---|
Andrew Rabert | 4c1bb5375d | |
Andrew Rabert | f1a9686eb4 | |
Andrew Rabert | 279adc166b | |
Andrew Rabert | c20a64ab15 | |
Andrew Rabert | aa4c877046 | |
Jordi Masip | 09c5d7ee51 | |
Andrew Rabert | 27b0dc742c | |
Andrew Rabert | 63df26cdfd | |
Andrew Rabert | 49f15f2a0d | |
Andrew Rabert | 2c3c9ede14 | |
Andrew Rabert | ef2e19ebf2 | |
Andrew Rabert | 4c5406c916 | |
Andrew Rabert | 072a6d7870 | |
Andrew Rabert | 5ae04b3643 | |
Andrew Rabert | 79ea6cb082 | |
Robert Robinson | 8cfae03550 | |
Andrew Rabert | 298a06ab5b | |
anasofiagribeiro | 41d17f960e | |
Andrew Rabert | a861e035ab | |
Morgan Lim | 4598f849ff | |
Morgan Lim | d37a72b2a0 | |
Andrew Rabert | e102dea3d3 | |
Andrew Rabert | a69b1385c0 | |
Morgan Lim | f506bfb14a | |
Morgan Lim | 0f525befca | |
Morgan Lim | d3d6186fb7 | |
Andrew Rabert | d10ea92edd | |
Andrew Rabert | d1f1331f35 | |
Andrew Rabert | 4fd53e74c5 | |
Andrew Rabert | 6704e05da2 | |
Andrew Rabert | e79aff9e98 | |
Andrew Rabert | ffa048177e | |
Andrew Rabert | f6d308c37c | |
Simão Mata | 3c17e91ca8 | |
Andrew Rabert | ec083cd79d | |
Simão Mata | cfae0d30b5 | |
Andrew Rabert | ecdae8c6e3 | |
Andrew Rabert | 76efc2c62c | |
Andrew Rabert | 26848852ac | |
Simão Mata | 377f21d732 | |
Simão Mata | 8af307da28 | |
Andrew Rabert | 3d7b173cb1 | |
Andrew Rabert | e7ea8d4dfc | |
dddddd-mmmmmm | e2280304e4 | |
emaiannone | 061c318e05 |
|
@ -1,6 +1,14 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
## Version 0.5.1
|
||||
_2020-04-30_
|
||||
* Add option to force server-side media scan
|
||||
* Change to local artist sorting (case-insensitive)
|
||||
* Fix crash while offline (#25)
|
||||
* Fix read timeout not being respected
|
||||
* Fix switching to playlist on app resume
|
||||
|
||||
## Version 0.5.0
|
||||
_2020-01-15_
|
||||
* Add 24kbps and 48kbps options
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
# Audinaut
|
||||
⚠ No longer maintained.
|
||||
|
||||
Although not a direct replacement, I've since moved onto syncing an Opus version
|
||||
of my entire library to my phone using [harmonize](https://github.com/nvllsvm/harmonize)
|
||||
and [Syncthing](https://syncthing.net/).
|
||||
|
||||
---
|
||||
<img src="audinaut.png" align="left" width="200" hspace="10" vspace="10">
|
||||
|
||||
A Subsonic client for Android.
|
||||
|
|
|
@ -2,23 +2,18 @@ apply plugin: 'com.android.application'
|
|||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.2"
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion "31.0.0"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "net.nullsum.audinaut"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 201
|
||||
versionName '0.5.0'
|
||||
targetSdkVersion 30
|
||||
versionCode 202
|
||||
versionName '0.5.1'
|
||||
setProperty("archivesBaseName", "Audinaut $versionName")
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
checkReleaseBuilds false
|
||||
warning 'InvalidPackage'
|
||||
|
@ -31,16 +26,16 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation 'com.esotericsoftware:kryo:4.0.2'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation 'com.github.hannesa2:AndroidSlidingUpPanel:4.1.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.3.1'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
implementation 'com.github.hannesa2:AndroidSlidingUpPanel:4.4.1'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation "androidx.media:media:1.1.0"
|
||||
implementation "androidx.media:media:1.5.0"
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
}
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.61'
|
||||
ext.kotlin_version = '1.6.0'
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
android:icon="@drawable/launch"
|
||||
android:label="@string/common.appname"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:theme="@style/LaunchScreen">
|
||||
|
||||
<uses-library android:name="android.test.runner" />
|
||||
|
|
|
@ -65,10 +65,10 @@ public class QueryReceiverActivity extends AppCompatActivity {
|
|||
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
|
||||
if (albumId.indexOf("ar-") == 0) {
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||
albumId = albumId.replace("ar-", "");
|
||||
albumId = albumId.replaceFirst("ar-", "");
|
||||
} else if (albumId.indexOf("so-") == 0) {
|
||||
intent.putExtra(Constants.INTENT_EXTRA_SEARCH_SONG, name);
|
||||
albumId = albumId.replace("so-", "");
|
||||
albumId = albumId.replaceFirst("so-", "");
|
||||
}
|
||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, albumId);
|
||||
if (name != null) {
|
||||
|
|
|
@ -21,11 +21,10 @@ package net.nullsum.audinaut.activity;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -68,8 +67,6 @@ import net.nullsum.audinaut.util.UserUtil;
|
|||
import net.nullsum.audinaut.util.Util;
|
||||
import net.nullsum.audinaut.view.UpdateView;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -85,7 +82,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||
private static ImageLoader IMAGE_LOADER;
|
||||
|
||||
static {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
|
||||
// If Android Pie or older, set night mode by system clock
|
||||
if (Build.VERSION.SDK_INT<29) {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
|
||||
} else {
|
||||
// Else, for Android 10+, follow system dark mode setting
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
final List<SubsonicFragment> backStack = new ArrayList<>();
|
||||
|
@ -835,7 +838,6 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||
}
|
||||
Util.setActiveServer(this, instance);
|
||||
invalidate();
|
||||
UserUtil.refreshCurrentUser(this);
|
||||
updateDrawerHeader();
|
||||
}
|
||||
}
|
||||
|
@ -863,7 +865,6 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
|
|||
service.setOnline(isOffline);
|
||||
}
|
||||
|
||||
UserUtil.seedCurrentUser(this);
|
||||
this.updateDrawerHeader();
|
||||
drawer.closeDrawers();
|
||||
}
|
||||
|
|
|
@ -37,8 +37,9 @@ import androidx.appcompat.widget.Toolbar;
|
|||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.sothree.slidinguppanel.PanelSlideListener;
|
||||
import com.sothree.slidinguppanel.PanelState;
|
||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
|
||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState;
|
||||
|
||||
import net.nullsum.audinaut.R;
|
||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||
|
@ -56,7 +57,6 @@ import net.nullsum.audinaut.updates.Updater;
|
|||
import net.nullsum.audinaut.util.Constants;
|
||||
import net.nullsum.audinaut.util.FileUtil;
|
||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||
import net.nullsum.audinaut.util.UserUtil;
|
||||
import net.nullsum.audinaut.util.Util;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -69,7 +69,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||
private static boolean infoDialogDisplayed;
|
||||
private static boolean sessionInitialized = false;
|
||||
private SlidingUpPanelLayout slideUpPanel;
|
||||
private SlidingUpPanelLayout.PanelSlideListener panelSlideListener;
|
||||
private PanelSlideListener panelSlideListener;
|
||||
private boolean isPanelClosing = false;
|
||||
private boolean resuming = false;
|
||||
private NowPlayingFragment nowPlayingFragment;
|
||||
|
@ -168,7 +168,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||
}
|
||||
|
||||
slideUpPanel = findViewById(R.id.slide_up_panel);
|
||||
panelSlideListener = new SlidingUpPanelLayout.PanelSlideListener() {
|
||||
panelSlideListener = new PanelSlideListener() {
|
||||
@Override
|
||||
public void onPanelSlide(View panel, float slideOffset) {
|
||||
Util.hideKeyboard(panel);
|
||||
|
@ -367,7 +367,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||
getIntent().removeExtra(Constants.INTENT_EXTRA_VIEW_ALBUM);
|
||||
}
|
||||
|
||||
UserUtil.seedCurrentUser(this);
|
||||
createAccount();
|
||||
runWhenServiceAvailable(() -> getDownloadService().addOnSongChangedListener(SubsonicFragmentActivity.this));
|
||||
resuming = false;
|
||||
|
@ -416,7 +415,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||
drawerToggle.setDrawerIndicatorEnabled(false);
|
||||
}
|
||||
|
||||
if (savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == SlidingUpPanelLayout.PanelState.EXPANDED.hashCode()) {
|
||||
if (savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == PanelState.EXPANDED.hashCode()) {
|
||||
panelSlideListener.onPanelStateChanged(null, null, PanelState.EXPANDED);
|
||||
}
|
||||
}
|
||||
|
@ -535,12 +534,12 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||
|
||||
@Override
|
||||
public void openNowPlaying() {
|
||||
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
|
||||
slideUpPanel.setPanelState(PanelState.EXPANDED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeNowPlaying() {
|
||||
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
||||
slideUpPanel.setPanelState(PanelState.COLLAPSED);
|
||||
isPanelClosing = true;
|
||||
}
|
||||
|
||||
|
@ -705,7 +704,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
|
|||
getImageLoader().loadImage(coverArtView, song, false, height, false);
|
||||
|
||||
// We need to update it immediately since it won't update if updater is not running for it
|
||||
if (nowPlayingFragment != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
|
||||
if (nowPlayingFragment != null && slideUpPanel.getPanelState() == PanelState.COLLAPSED) {
|
||||
nowPlayingFragment.onMetadataUpdate(song, fieldChange);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,17 +17,12 @@ package net.nullsum.audinaut.adapter;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
import androidx.appcompat.view.ActionMode;
|
||||
|
|
|
@ -17,7 +17,6 @@ package net.nullsum.audinaut.fragments;
|
|||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.OnGestureListener;
|
||||
|
@ -57,17 +56,12 @@ import net.nullsum.audinaut.util.MenuUtil;
|
|||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||
import net.nullsum.audinaut.util.Util;
|
||||
import net.nullsum.audinaut.view.AutoRepeatButton;
|
||||
import net.nullsum.audinaut.view.FadeOutAnimation;
|
||||
import net.nullsum.audinaut.view.FastScroller;
|
||||
import net.nullsum.audinaut.view.UpdateView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
|
||||
import static net.nullsum.audinaut.domain.PlayerState.COMPLETED;
|
||||
|
@ -105,11 +99,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
private ImageButton repeatButton;
|
||||
private View toggleListButton;
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
private DownloadFile currentPlaying;
|
||||
private int swipeDistance;
|
||||
private int swipeVelocity;
|
||||
private ScheduledFuture<?> hideControlsFuture;
|
||||
private List<DownloadFile> songList;
|
||||
private DownloadFileAdapter songListAdapter;
|
||||
private boolean seekInProgress = false;
|
||||
|
@ -201,7 +193,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
return null;
|
||||
}
|
||||
}.execute();
|
||||
setControlsVisible(true);
|
||||
});
|
||||
previousButton.setOnRepeatListener(() -> changeProgress(true));
|
||||
|
||||
|
@ -214,7 +205,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
return true;
|
||||
}
|
||||
}.execute();
|
||||
setControlsVisible(true);
|
||||
});
|
||||
nextButton.setOnRepeatListener(() -> changeProgress(false));
|
||||
|
||||
|
@ -269,12 +259,10 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
break;
|
||||
}
|
||||
updateRepeatButton();
|
||||
setControlsVisible(true);
|
||||
});
|
||||
|
||||
toggleListButton.setOnClickListener(view -> {
|
||||
toggleFullscreenAlbumArt();
|
||||
setControlsVisible(true);
|
||||
});
|
||||
|
||||
View overlay = rootView.findViewById(R.id.download_overlay_buttons);
|
||||
|
@ -308,7 +296,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
public void onProgressChanged(final SeekBar seekBar, final int position, final boolean fromUser) {
|
||||
if (fromUser) {
|
||||
positionTextView.setText(Util.formatDuration(position / 1000));
|
||||
setControlsVisible(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -473,7 +460,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
if (controller != null) {
|
||||
SubsonicFragment fragment = new EqualizerFragment();
|
||||
replaceFragment(fragment);
|
||||
setControlsVisible(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -510,19 +496,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
}
|
||||
|
||||
private void onResumeHandlers() {
|
||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
setControlsVisible(true);
|
||||
|
||||
final DownloadService downloadService = getDownloadService();
|
||||
if (downloadService == null || downloadService.getCurrentPlaying() == null || startFlipped) {
|
||||
playlistFlipper.setDisplayedChild(1);
|
||||
startFlipped = false;
|
||||
}
|
||||
|
||||
if (currentPlaying == null && downloadService != null && null == downloadService.getCurrentPlaying()) {
|
||||
setAlbumArt(null, false);
|
||||
}
|
||||
|
||||
context.runWhenServiceAvailable(() -> {
|
||||
if (primaryFragment) {
|
||||
DownloadService downloadService1 = getDownloadService();
|
||||
|
@ -540,11 +513,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
}
|
||||
|
||||
private void onPauseHandlers() {
|
||||
if (executorService != null) {
|
||||
DownloadService downloadService = getDownloadService();
|
||||
if (downloadService != null) {
|
||||
downloadService.removeOnSongChangeListener(this);
|
||||
}
|
||||
DownloadService downloadService = getDownloadService();
|
||||
if (downloadService != null) {
|
||||
downloadService.removeOnSongChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -581,29 +552,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
return songListAdapter;
|
||||
}
|
||||
|
||||
private void scheduleHideControls() {
|
||||
if (hideControlsFuture != null) {
|
||||
hideControlsFuture.cancel(false);
|
||||
}
|
||||
|
||||
final Handler handler = new Handler();
|
||||
Runnable runnable = () -> handler.post(() -> setControlsVisible(false));
|
||||
hideControlsFuture = executorService.schedule(runnable, 3000L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void setControlsVisible(boolean visible) {
|
||||
try {
|
||||
long duration = 1700L;
|
||||
FadeOutAnimation.createAndStart(rootView.findViewById(R.id.download_overlay_buttons), !visible, duration);
|
||||
|
||||
if (visible) {
|
||||
scheduleHideControls();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Scroll to current playing/downloading.
|
||||
private void scrollToCurrent() {
|
||||
if (getDownloadService() == null || songListAdapter == null) {
|
||||
|
@ -693,7 +641,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
|
|||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent me) {
|
||||
setControlsVisible(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
||||
|
||||
Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener);
|
||||
indexes.sortChildren(context);
|
||||
indexes.sortChildren();
|
||||
items = new ArrayList<>(indexes.getShortcuts().size() + indexes.getArtists().size());
|
||||
items.addAll(indexes.getShortcuts());
|
||||
items.addAll(indexes.getArtists());
|
||||
|
@ -184,8 +184,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
|
|||
}
|
||||
|
||||
Indexes indexes = new Indexes();
|
||||
//indexes.setArtists = artists;
|
||||
indexes.sortChildren(context);
|
||||
indexes.sortChildren();
|
||||
items = new ArrayList<>(indexes.getArtists());
|
||||
|
||||
entries = dir.getChildren(false, true);
|
||||
|
|
|
@ -530,6 +530,15 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||
return false;
|
||||
});
|
||||
|
||||
Preference serverStartScanPreference = new Preference(context);
|
||||
serverStartScanPreference.setKey(Constants.PREFERENCES_KEY_START_SCAN + instance);
|
||||
serverStartScanPreference.setPersistent(false);
|
||||
serverStartScanPreference.setTitle(R.string.settings_start_scan_title);
|
||||
serverStartScanPreference.setOnPreferenceClickListener(preference -> {
|
||||
startScan(instance);
|
||||
return false;
|
||||
});
|
||||
|
||||
screen.addPreference(serverNamePreference);
|
||||
screen.addPreference(serverUrlPreference);
|
||||
screen.addPreference(serverInternalUrlPreference);
|
||||
|
@ -538,6 +547,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||
screen.addPreference(serverPasswordPreference);
|
||||
screen.addPreference(authMethodPreference);
|
||||
screen.addPreference(serverTestConnectionPreference);
|
||||
screen.addPreference(serverStartScanPreference);
|
||||
screen.addPreference(serverOpenBrowser);
|
||||
screen.addPreference(serverRemoveServerPreference);
|
||||
|
||||
|
@ -607,6 +617,42 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||
}
|
||||
}
|
||||
|
||||
private void startScan(final int instance) {
|
||||
LoadingTask<Boolean> task = new LoadingTask<Boolean>(context) {
|
||||
@Override
|
||||
protected Boolean doInBackground() throws Throwable {
|
||||
MusicService musicService = MusicServiceFactory.getOnlineService();
|
||||
|
||||
try {
|
||||
musicService.setInstance(instance);
|
||||
musicService.startScan(context);
|
||||
return true;
|
||||
} finally {
|
||||
musicService.setInstance(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Boolean licenseValid) {
|
||||
Log.d(TAG, "Finished media scan start");
|
||||
Util.toast(context, R.string.settings_media_scan_started);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
super.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(Throwable error) {
|
||||
Log.w(TAG, error.toString(), error);
|
||||
new ErrorDialog(context, getResources().getString(R.string.settings_media_scan_start_failed) +
|
||||
" " + getErrorMessage(error), false);
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
|
||||
private void testConnection(final int instance) {
|
||||
LoadingTask<Boolean> task = new LoadingTask<Boolean>(context) {
|
||||
private int previousInstance;
|
||||
|
|
|
@ -245,6 +245,10 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||
views.setImageViewResource(R.id.control_play, R.drawable.widget_media_start);
|
||||
}
|
||||
|
||||
// Set next/back button images
|
||||
views.setImageViewResource(R.id.control_next, R.drawable.widget_media_forward);
|
||||
views.setImageViewResource(R.id.control_previous, R.drawable.widget_media_backward);
|
||||
|
||||
// Set the cover art
|
||||
try {
|
||||
boolean large = false;
|
||||
|
|
|
@ -24,21 +24,30 @@ import net.nullsum.audinaut.service.DownloadService;
|
|||
import net.nullsum.audinaut.util.Constants;
|
||||
|
||||
public class PlayActionReceiver extends BroadcastReceiver {
|
||||
private Bundle lastdata = null;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (lastdata.equals(intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE))) {
|
||||
// nothing has changed; we can safely return
|
||||
return;
|
||||
}
|
||||
updateValues(intent);
|
||||
if (intent.hasExtra(Constants.TASKER_EXTRA_BUNDLE)) {
|
||||
Bundle data = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
||||
Boolean startShuffled = data.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE);
|
||||
Boolean startShuffled = lastdata.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE);
|
||||
|
||||
Intent start = new Intent(context, DownloadService.class);
|
||||
start.setAction(DownloadService.START_PLAY);
|
||||
start.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, startShuffled);
|
||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR));
|
||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR));
|
||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE));
|
||||
start.putExtra(Constants.PREFERENCES_KEY_OFFLINE, data.getInt(Constants.PREFERENCES_KEY_OFFLINE));
|
||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, lastdata.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR));
|
||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, lastdata.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR));
|
||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, lastdata.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE));
|
||||
start.putExtra(Constants.PREFERENCES_KEY_OFFLINE, lastdata.getInt(Constants.PREFERENCES_KEY_OFFLINE));
|
||||
context.startService(start);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateValues(Intent intent) {
|
||||
lastdata = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import net.nullsum.audinaut.domain.MusicFolder;
|
|||
import net.nullsum.audinaut.domain.Playlist;
|
||||
import net.nullsum.audinaut.domain.SearchCritera;
|
||||
import net.nullsum.audinaut.domain.SearchResult;
|
||||
import net.nullsum.audinaut.domain.User;
|
||||
import net.nullsum.audinaut.util.FileUtil;
|
||||
import net.nullsum.audinaut.util.ProgressListener;
|
||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||
|
@ -617,21 +616,8 @@ public class CachedMusicService implements MusicService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) {
|
||||
User result = null;
|
||||
|
||||
try {
|
||||
result = musicService.getUser(refresh, username, context, progressListener);
|
||||
FileUtil.serialize(context, result, getCacheName(context, "user-" + username));
|
||||
} catch (Exception e) {
|
||||
// Don't care
|
||||
}
|
||||
|
||||
if (result == null && !refresh) {
|
||||
result = FileUtil.deserialize(context, getCacheName(context, "user-" + username), User.class);
|
||||
}
|
||||
|
||||
return result;
|
||||
public void startScan(Context c) throws Exception {
|
||||
musicService.startScan(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,7 +28,6 @@ import net.nullsum.audinaut.domain.MusicFolder;
|
|||
import net.nullsum.audinaut.domain.Playlist;
|
||||
import net.nullsum.audinaut.domain.SearchCritera;
|
||||
import net.nullsum.audinaut.domain.SearchResult;
|
||||
import net.nullsum.audinaut.domain.User;
|
||||
import net.nullsum.audinaut.util.ProgressListener;
|
||||
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
||||
|
||||
|
@ -87,7 +86,7 @@ public interface MusicService {
|
|||
|
||||
MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||
|
||||
User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception;
|
||||
void startScan(Context c) throws Exception;
|
||||
|
||||
void setInstance(Integer instance) throws Exception;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import net.nullsum.audinaut.domain.MusicFolder;
|
|||
import net.nullsum.audinaut.domain.Playlist;
|
||||
import net.nullsum.audinaut.domain.SearchCritera;
|
||||
import net.nullsum.audinaut.domain.SearchResult;
|
||||
import net.nullsum.audinaut.domain.User;
|
||||
import net.nullsum.audinaut.util.Constants;
|
||||
import net.nullsum.audinaut.util.FileUtil;
|
||||
import net.nullsum.audinaut.util.ProgressListener;
|
||||
|
@ -70,6 +69,7 @@ public class OfflineMusicService implements MusicService {
|
|||
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) {
|
||||
List<Artist> artists = new ArrayList<>();
|
||||
List<Entry> entries = new ArrayList<>();
|
||||
|
||||
File root = FileUtil.getMusicDirectory(context);
|
||||
for (File file : FileUtil.listFiles(root)) {
|
||||
if (file.isDirectory()) {
|
||||
|
@ -499,7 +499,7 @@ public class OfflineMusicService implements MusicService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception {
|
||||
public void startScan(Context c) throws Exception {
|
||||
throw new OfflineException();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import android.util.Log;
|
|||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.nullsum.audinaut.R;
|
||||
import net.nullsum.audinaut.domain.Genre;
|
||||
import net.nullsum.audinaut.domain.Indexes;
|
||||
import net.nullsum.audinaut.domain.MusicDirectory;
|
||||
|
@ -32,7 +33,6 @@ import net.nullsum.audinaut.domain.MusicFolder;
|
|||
import net.nullsum.audinaut.domain.Playlist;
|
||||
import net.nullsum.audinaut.domain.SearchCritera;
|
||||
import net.nullsum.audinaut.domain.SearchResult;
|
||||
import net.nullsum.audinaut.domain.User;
|
||||
import net.nullsum.audinaut.fragments.MainFragment;
|
||||
import net.nullsum.audinaut.service.parser.EntryListParser;
|
||||
import net.nullsum.audinaut.service.parser.ErrorParser;
|
||||
|
@ -44,7 +44,6 @@ import net.nullsum.audinaut.service.parser.PlaylistParser;
|
|||
import net.nullsum.audinaut.service.parser.PlaylistsParser;
|
||||
import net.nullsum.audinaut.service.parser.RandomSongsParser;
|
||||
import net.nullsum.audinaut.service.parser.SearchResult2Parser;
|
||||
import net.nullsum.audinaut.service.parser.UserParser;
|
||||
import net.nullsum.audinaut.util.Constants;
|
||||
import net.nullsum.audinaut.util.FileUtil;
|
||||
import net.nullsum.audinaut.util.Pair;
|
||||
|
@ -591,7 +590,7 @@ public class RESTMusicService implements MusicService {
|
|||
public Response getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception {
|
||||
|
||||
OkHttpClient eagerClient = client.newBuilder()
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(Util.getNetworkTimeoutMs(context), TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
|
@ -656,24 +655,17 @@ public class RESTMusicService implements MusicService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception {
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
public void startScan(Context context) throws Exception {
|
||||
String url = getRestUrl(context, "startScan", null);
|
||||
|
||||
parameters.put("username", username);
|
||||
|
||||
String url = getRestUrl(context, "getUser", parameters);
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
List<User> users = new UserParser(context, getInstance(context)).parse(response.body().byteStream());
|
||||
if (users.size() > 0) {
|
||||
// Should only have returned one anyways
|
||||
return users.get(0);
|
||||
if (response.isSuccessful()) {
|
||||
Log.d(TAG, "Media scan started" + response.toString());
|
||||
} else {
|
||||
return null;
|
||||
Log.w(TAG, "media scan start failed" + response.toString());
|
||||
Util.toast(context, R.string.settings_media_scan_start_failed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package net.nullsum.audinaut.util;
|
|||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Paint;
|
||||
|
|
|
@ -67,6 +67,7 @@ public final class Constants {
|
|||
public static final String PREFERENCES_KEY_SERVER_INTERNAL_URL = "serverInternalUrl";
|
||||
public static final String PREFERENCES_KEY_SERVER_LOCAL_NETWORK_SSID = "serverLocalNetworkSSID";
|
||||
public static final String PREFERENCES_KEY_TEST_CONNECTION = "serverTestConnection";
|
||||
public static final String PREFERENCES_KEY_START_SCAN = "serverStartScan";
|
||||
public static final String PREFERENCES_KEY_OPEN_BROWSER = "openBrowser";
|
||||
public static final String PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId";
|
||||
public static final String PREFERENCES_KEY_USERNAME = "username";
|
||||
|
|
|
@ -26,13 +26,13 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.BitmapFactory;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.media.MediaMetadataCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.media.app.NotificationCompat.MediaStyle;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.MediaMetadataCompat;
|
||||
|
||||
import net.nullsum.audinaut.R;
|
||||
import net.nullsum.audinaut.activity.SubsonicActivity;
|
||||
|
@ -77,18 +77,27 @@ public final class Notifications {
|
|||
.setComponent(new ComponentName(context, DownloadService.class))
|
||||
.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
|
||||
int[] compactActions = new int[]{0, 1, 2};
|
||||
|
||||
MediaSessionCompat mediaSession = new MediaSessionCompat(context, "Audinaut");
|
||||
MediaSessionCompat.Token mediaToken = mediaSession.getSessionToken();
|
||||
MediaMetadataCompat.Builder metadataBuilder = new MediaMetadataCompat.Builder();
|
||||
mediaSession.setMetadata(metadataBuilder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, -1).build());
|
||||
|
||||
mediaSession.setMetadata(metadataBuilder
|
||||
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, -1)
|
||||
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, getAlbumArt(context, song))
|
||||
//.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, R.drawable.notification_logo)
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, song.getTitle())
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, song.getArtist())
|
||||
.build() );
|
||||
|
||||
MediaStyle mediaStyle = new MediaStyle()
|
||||
.setShowActionsInCompactView(compactActions)
|
||||
.setShowCancelButton(true)
|
||||
.setCancelButtonIntent(PendingIntent.getService(context, 0, cancelIntent, 0))
|
||||
.setMediaSession(mediaSession.getSessionToken());
|
||||
.setMediaSession(mediaToken);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_PLAYING_ID)
|
||||
.setChannelId(CHANNEL_PLAYING_ID)
|
||||
.setSmallIcon(R.drawable.stat_notify_playing)
|
||||
.setContentTitle(song.getTitle())
|
||||
.setContentText(song.getArtist())
|
||||
.setSubText(song.getAlbum())
|
||||
|
@ -97,6 +106,7 @@ public final class Notifications {
|
|||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setShowWhen(false)
|
||||
.setLargeIcon(getAlbumArt(context, song))
|
||||
.setSmallIcon(R.drawable.notification_logo)
|
||||
.setStyle(mediaStyle)
|
||||
.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, 0));
|
||||
addActions(context, builder, playing);
|
||||
|
|
|
@ -18,10 +18,9 @@ package net.nullsum.audinaut.util;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
|
||||
import net.nullsum.audinaut.R;
|
||||
import net.nullsum.audinaut.activity.SettingsActivity;
|
||||
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
||||
|
||||
public final class ThemeUtil {
|
||||
private static final String THEME_DARK = "dark";
|
||||
|
@ -32,7 +31,15 @@ public final class ThemeUtil {
|
|||
|
||||
public static String getTheme(Context context) {
|
||||
SharedPreferences prefs = Util.getPreferences(context);
|
||||
String theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, null);
|
||||
String theme;
|
||||
|
||||
if (Build.VERSION.SDK_INT<29) {
|
||||
// If Android Pie or older, default to null (handled below as light)
|
||||
theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, null);
|
||||
} else {
|
||||
// Else, for Android 10+, default to follow system dark mode setting
|
||||
theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, THEME_DAY_NIGHT);
|
||||
}
|
||||
|
||||
if (THEME_DAY_NIGHT.equals(theme)) {
|
||||
int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
|
@ -58,6 +65,9 @@ public final class ThemeUtil {
|
|||
}
|
||||
|
||||
private static int getThemeRes(Context context, String theme) {
|
||||
if(theme == null)
|
||||
return R.style.Theme_Audinaut_Light;
|
||||
|
||||
switch (theme) {
|
||||
case THEME_DARK:
|
||||
return R.style.Theme_Audinaut_Dark;
|
||||
|
|
|
@ -17,63 +17,8 @@ package net.nullsum.audinaut.util;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import net.nullsum.audinaut.domain.User;
|
||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
||||
|
||||
public final class UserUtil {
|
||||
private static final String TAG = UserUtil.class.getSimpleName();
|
||||
|
||||
private static int instance = -1;
|
||||
private static int instanceHash = -1;
|
||||
private static User currentUser;
|
||||
|
||||
public static void refreshCurrentUser(Context context) {
|
||||
currentUser = null;
|
||||
seedCurrentUser(context);
|
||||
}
|
||||
|
||||
public static void seedCurrentUser(Context context) {
|
||||
// Only try to seed if online
|
||||
if (Util.isOffline(context)) {
|
||||
currentUser = null;
|
||||
return;
|
||||
}
|
||||
|
||||
final int instance = Util.getActiveServer(context);
|
||||
final int instanceHash = (instance == 0) ? 0 : Util.getRestUrl(context).hashCode();
|
||||
if (UserUtil.instance == instance && UserUtil.instanceHash == instanceHash && currentUser != null) {
|
||||
return;
|
||||
} else {
|
||||
UserUtil.instance = instance;
|
||||
UserUtil.instanceHash = instanceHash;
|
||||
}
|
||||
|
||||
new SilentBackgroundTask<Void>(context) {
|
||||
@Override
|
||||
protected Void doInBackground() throws Throwable {
|
||||
currentUser = MusicServiceFactory.getMusicService(context).getUser(false, getCurrentUsername(context, instance), context, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done(Void result) {
|
||||
if (context instanceof AppCompatActivity) {
|
||||
((AppCompatActivity) context).supportInvalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(Throwable error) {
|
||||
// Don't do anything, supposed to be background pull
|
||||
Log.e(TAG, "Failed to seed user information");
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private static String getCurrentUsername(Context context, int instance) {
|
||||
SharedPreferences prefs = Util.getPreferences(context);
|
||||
return prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
|
||||
|
|
|
@ -41,12 +41,11 @@ import android.text.util.Linkify;
|
|||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
|
@ -122,6 +121,11 @@ public final class Util {
|
|||
editor.apply();
|
||||
}
|
||||
|
||||
public static int getNetworkTimeoutMs(Context context) {
|
||||
SharedPreferences prefs = getPreferences(context);
|
||||
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_NETWORK_TIMEOUT, "30000"));
|
||||
}
|
||||
|
||||
public static boolean isScreenLitOnDownload(Context context) {
|
||||
SharedPreferences prefs = getPreferences(context);
|
||||
return prefs.getBoolean(Constants.PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD, false);
|
||||
|
@ -301,6 +305,8 @@ public final class Util {
|
|||
private static String getRestUrl(Context context, String method, SharedPreferences prefs, int instance, boolean allowAltAddress, @Nullable Map<String, String> parameters) {
|
||||
String serverUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
|
||||
|
||||
if (serverUrl == null) return "OFFLINE";
|
||||
|
||||
HttpUrl.Builder builder;
|
||||
builder = HttpUrl.parse(serverUrl).newBuilder();
|
||||
|
||||
|
@ -1146,7 +1152,7 @@ public final class Util {
|
|||
}
|
||||
|
||||
public static void hideKeyboard(View view) {
|
||||
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
|
||||
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE);
|
||||
|
||||
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class RecyclingImageView extends AppCompatImageView {
|
|||
if (drawable instanceof BitmapDrawable) {
|
||||
if (isBitmapRecycled(drawable)) {
|
||||
this.setImageDrawable(null);
|
||||
setInvalidated(true);
|
||||
this.invalidated = true;
|
||||
}
|
||||
} else if (drawable instanceof TransitionDrawable) {
|
||||
TransitionDrawable transitionDrawable = (TransitionDrawable) drawable;
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package net.nullsum.audinaut.domain
|
||||
|
||||
import android.content.Context
|
||||
import java.io.Serializable
|
||||
import java.util.*
|
||||
|
||||
class Indexes(var shortcuts: MutableList<Artist> = mutableListOf(),
|
||||
var artists: MutableList<Artist> = mutableListOf(),
|
||||
var entries: MutableList<MusicDirectory.Entry> = mutableListOf()) : Serializable {
|
||||
fun sortChildren(context: Context) {
|
||||
|
||||
fun sortChildren() {
|
||||
shortcuts.sortBy { s -> s.id.toLowerCase(Locale.ROOT) }
|
||||
artists.sortBy { a -> a.name.toLowerCase(Locale.ROOT) }
|
||||
entries.sortBy { e -> e.artist.toLowerCase(Locale.ROOT) }
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 343 B |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.0 KiB |
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<size android:width="1dip" />
|
||||
<solid android:color="@android:color/darker_gray" />
|
||||
</shape>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@color/lightElement" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@color/lightElement" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
|
||||
</vector>
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M8,5v14l11,-7z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M6,6h12v12H6z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M3.24,6.15C2.51,6.43 2,7.17 2,8v12c0,1.1 0.89,2 2,2h16c1.11,0 2,-0.9 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2L8.3,6l8.26,-3.34L15.88,1 3.24,6.15zM7,20c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM20,12h-2v-2h-2v2L4,12L4,8h16v4z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M10.59,9.17L5.41,4 4,5.41l5.17,5.17 1.42,-1.41zM14.5,4l2.04,2.04L4,18.59 5.41,20 17.96,7.46 20,9.5L20,4h-5.5zM14.83,13.41l-1.41,1.41 3.13,3.13L14.5,20L20,20v-5.5l-2.04,2.04 -3.13,-3.13z"/>
|
||||
</vector>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/background_material_dark" />
|
||||
<corners android:radius="@dimen/Card.Radius" />
|
||||
<padding
|
||||
android:bottom="0dip"
|
||||
android:left="0dip"
|
||||
android:right="0dip"
|
||||
android:top="0dip" />
|
||||
</shape>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/black" />
|
||||
<corners android:radius="@dimen/Card.Radius" />
|
||||
<padding
|
||||
android:bottom="0dip"
|
||||
android:left="0dip"
|
||||
android:right="0dip"
|
||||
android:top="0dip" />
|
||||
</shape>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="@dimen/Card.Radius" />
|
||||
<padding
|
||||
android:bottom="0dip"
|
||||
android:left="0dip"
|
||||
android:right="0dip"
|
||||
android:top="0dip" />
|
||||
</shape>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@color/darkElement" android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@color/darkElement" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M15,3L6,3c-0.83,0 -1.54,0.5 -1.84,1.22l-3.02,7.05c-0.09,0.23 -0.14,0.47 -0.14,0.73v1.91l0.01,0.01L1,14c0,1.1 0.9,2 2,2h6.31l-0.95,4.57 -0.03,0.32c0,0.41 0.17,0.79 0.44,1.06L9.83,23l6.59,-6.59c0.36,-0.36 0.58,-0.86 0.58,-1.41L17,5c0,-1.1 -0.9,-2 -2,-2zM19,3v12h4L23,3h-4z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M15,3L6,3c-0.83,0 -1.54,0.5 -1.84,1.22l-3.02,7.05c-0.09,0.23 -0.14,0.47 -0.14,0.73v1.91l0.01,0.01L1,14c0,1.1 0.9,2 2,2h6.31l-0.95,4.57 -0.03,0.32c0,0.41 0.17,0.79 0.44,1.06L9.83,23l6.59,-6.59c0.36,-0.36 0.58,-0.86 0.58,-1.41L17,5c0,-1.1 -0.9,-2 -2,-2zM19,3v12h4L23,3h-4z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-1.91l-0.01,-0.01L23,10z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-1.91l-0.01,-0.01L23,10z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M16.5,12c1.38,0 2.49,-1.12 2.49,-2.5S17.88,7 16.5,7C15.12,7 14,8.12 14,9.5s1.12,2.5 2.5,2.5zM9,11c1.66,0 2.99,-1.34 2.99,-3S10.66,5 9,5C7.34,5 6,6.34 6,8s1.34,3 3,3zM16.5,14c-1.83,0 -5.5,0.92 -5.5,2.75L11,19h11v-2.25c0,-1.83 -3.67,-2.75 -5.5,-2.75zM9,13c-2.33,0 -7,1.17 -7,3.5L2,19h7v-2.25c0,-0.85 0.33,-2.34 2.37,-3.47C10.5,13.1 9.66,13 9,13z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM6,9h12v2L6,11L6,9zM14,14L6,14v-2h8v2zM18,8L6,8L6,6h12v2z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M12,1c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7c0,-4.97 -4.03,-9 -9,-9z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M3.24,6.15C2.51,6.43 2,7.17 2,8v12c0,1.1 0.89,2 2,2h16c1.11,0 2,-0.9 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2L8.3,6l8.26,-3.34L15.88,1 3.24,6.15zM7,20c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM20,12h-2v-2h-2v2L4,12L4,8h16v4z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?attr/element_color" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="126dp" android:tint="@color/lightPrimary"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="126dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:alpha="0.5" android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:alpha="0.8" android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:alpha="0.5" android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
|
||||
</vector>
|
|
@ -0,0 +1,22 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="166.67238dp"
|
||||
android:height="166.67238dp"
|
||||
android:viewportWidth="590.5714"
|
||||
android:viewportHeight="590.5714">
|
||||
<path
|
||||
android:pathData="M206.005,279.058L168.45,348.748C184.87,406.824 193.208,407.309 212.776,486.676C214.12,458.428 238.971,423.03 261.053,402.367C267.354,435.872 255.68,377.04 293.141,513.627C332.1,391.999 316.533,500.618 337.637,405.064C348.539,371.558 363.777,427.159 376.932,476.217C452.166,375.314 412.799,348.86 433.271,294.932L371.724,290.632C392.73,306.667 408.833,320.407 409.993,322.306C377.679,324.685 415.733,456.748 356.878,338.121C335.655,295.343 295.371,348.196 299.665,415.388C297.95,376.901 250.874,314.022 240.121,357.059C228.277,404.462 217.057,313.826 200.801,314.747C200.801,314.747 210.188,298.25 223.167,280.258L206.005,279.058z"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="1.06667"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M299.698,57.766C203.66,58.469 106.33,194.128 115.327,470.79C173.525,604.547 148.628,384.605 194.797,317.036C217.046,284.475 360.513,287.543 378.398,310.373C453.87,406.714 408.23,613.071 475.558,467.012C493.324,197.684 398.733,59.207 301.967,57.773C301.211,57.762 300.454,57.761 299.698,57.766zM300.304,107.547C338.677,107.626 377.044,151.72 392.763,245.132C283.141,223.071 277.21,231.481 206.389,242.036C221.118,154.237 260.713,107.465 300.304,107.547z"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="4.26667"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeLineCap="butt"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M8,5v14l11,-7z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@color/darkElement" android:pathData="M12,4L12,1L8,5l4,4L12,6c3.31,0 6,2.69 6,6 0,1.01 -0.25,1.97 -0.7,2.8l1.46,1.46C19.54,15.03 20,13.57 20,12c0,-4.42 -3.58,-8 -8,-8zM12,18c-3.31,0 -6,-2.69 -6,-6 0,-1.01 0.25,-1.97 0.7,-2.8L5.24,7.74C4.46,8.97 4,10.43 4,12c0,4.42 3.58,8 8,8v3l4,-4 -4,-4v3z"/>
|
||||
</vector>
|
|
@ -1,5 +0,0 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@color/darkElement" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
|
||||
</vector>
|
|
@ -1,66 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/notification_image"
|
||||
android:layout_width="64.0dip"
|
||||
android:layout_height="64.0dip"
|
||||
android:layout_weight="0.0"
|
||||
android:gravity="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="11.0dip">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_title"
|
||||
style="@style/NotificationText.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:ellipsize="marquee"
|
||||
android:focusable="true"
|
||||
android:singleLine="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_artist"
|
||||
style="@style/NotificationText.Content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:scrollHorizontally="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_album"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_previous"
|
||||
style="@style/NotificationButton"
|
||||
app:srcCompat="@drawable/notification_media_backward" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_pause"
|
||||
style="@style/NotificationButton"
|
||||
android:layout_width="54dip"
|
||||
android:padding="0dip"
|
||||
app:srcCompat="@drawable/notification_media_pause" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_next"
|
||||
style="@style/NotificationButton"
|
||||
app:srcCompat="@drawable/notification_media_forward" />
|
||||
</LinearLayout>
|
|
@ -1,97 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="128dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/notification_image"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="128dp"
|
||||
android:gravity="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="11.0dip">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_title"
|
||||
style="@style/NotificationText.Title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left|center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="marquee"
|
||||
android:focusable="true"
|
||||
android:singleLine="true" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/notification_close"
|
||||
style="@style/NotificationButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right"
|
||||
app:srcCompat="@drawable/notification_close"
|
||||
android:visibility="invisible" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_artist"
|
||||
style="@style/NotificationText.Content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:scrollHorizontally="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notification_album"
|
||||
style="@style/NotificationText.Content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingBottom="10dp"
|
||||
android:scrollHorizontally="true" />
|
||||
|
||||
<ImageView
|
||||
style="@style/NotificationDivider"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="1dp" />
|
||||
|
||||
<LinearLayout
|
||||
style="@style/NotificationLayoutDivider"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:showDividers="middle">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_previous"
|
||||
style="@style/NotificationButton.Expanded"
|
||||
app:srcCompat="@drawable/notification_media_backward" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_pause"
|
||||
style="@style/NotificationButton.Expanded"
|
||||
app:srcCompat="@drawable/notification_media_pause" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_next"
|
||||
style="@style/NotificationButton.Expanded"
|
||||
app:srcCompat="@drawable/notification_media_forward" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -11,5 +11,4 @@
|
|||
<color name="black">#000000</color>
|
||||
<color name="darkElement">#CCFFFFFF</color>
|
||||
|
||||
<color name="nowPlayingShadow">#44000000</color>
|
||||
</resources>
|
||||
|
|
|
@ -95,7 +95,6 @@
|
|||
<string name="download.playerstate_downloading">Downloading - %s</string>
|
||||
<string name="download.playerstate_mobile_disabled">Waiting for WiFi network to download</string>
|
||||
<string name="download.playerstate_buffering">Buffering</string>
|
||||
<string name="download.playerstate_playing_shuffle">Shuffle mode</string>
|
||||
<string name="download.menu_show_album">Show Album</string>
|
||||
<string name="download.menu_remove_all">Remove all</string>
|
||||
<string name="download.menu_shuffle">Shuffle</string>
|
||||
|
@ -124,6 +123,7 @@
|
|||
|
||||
<string name="settings.title">Settings</string>
|
||||
<string name="settings.test_connection_title">Test connection</string>
|
||||
<string name="settings.start_scan_title">Start Media Scan Now</string>
|
||||
<string name="settings.servers_add">Add Server</string>
|
||||
<string name="settings.servers_remove">Remove Server</string>
|
||||
<string name="settings.servers_title">Servers</string>
|
||||
|
@ -152,6 +152,8 @@
|
|||
<string name="settings.testing_connection">Testing connection…</string>
|
||||
<string name="settings.testing_ok">Connection is OK</string>
|
||||
<string name="settings.connection_failure">Connection failure.</string>
|
||||
<string name="settings.media_scan_started">Media scan started</string>
|
||||
<string name="settings.media_scan_start_failed">Could not start media scan</string>
|
||||
<string name="settings.invalid_url">Please specify a valid URL.</string>
|
||||
<string name="settings.invalid_username">Please specify a valid username (no trailing spaces).</string>
|
||||
<string name="settings.appearance_title">Appearance</string>
|
||||
|
@ -159,8 +161,8 @@
|
|||
<string name="settings.theme_light">Light</string>
|
||||
<string name="settings.theme_dark">Dark</string>
|
||||
<string name="settings.theme_black">Black</string>
|
||||
<string name="settings.theme_day_night">Day/Night</string>
|
||||
<string name="settings.theme_day_black_night">Day/Black Night</string>
|
||||
<string name="settings.theme_day_night">Dynamic (Light/Dark)</string>
|
||||
<string name="settings.theme_day_black_night">Dynamic (Light/Black)</string>
|
||||
<string name="settings.theme_fullscreen">Fullscreen</string>
|
||||
<string name="settings.theme_fullscreen_summary">Hide as many UI elements as Android will allow</string>
|
||||
<string name="settings.track_title">Display Track #</string>
|
||||
|
|
|
@ -19,32 +19,6 @@
|
|||
<item name="background">?attr/selectableItemBackgroundBorderless</item>
|
||||
</style>
|
||||
|
||||
<style name="NotificationButton.ExpandedBase">
|
||||
<item name="android:padding">2dip</item>
|
||||
<item name="background">?attr/selectableItemBackgroundBorderless</item>
|
||||
<item name="android:layout_width">0dp</item>
|
||||
<item name="android:layout_height">fill_parent</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:layout_gravity">center</item>
|
||||
<item name="android:scaleType">fitCenter</item>
|
||||
</style>
|
||||
|
||||
<style name="NotificationButton.Expanded" parent="@style/NotificationButton.ExpandedBase">
|
||||
<item name="android:padding">10dip</item>
|
||||
</style>
|
||||
|
||||
<style name="NotificationText.Title" parent="@android:style/TextAppearance.Material.Notification.Title" />
|
||||
|
||||
<style name="NotificationText.Content" parent="@android:style/TextAppearance.Material.Notification" />
|
||||
|
||||
<style name="NotificationLayoutDivider">
|
||||
<item name="divider">@drawable/notification_divider</item>
|
||||
</style>
|
||||
|
||||
<style name="NotificationDivider">
|
||||
<item name="background">@drawable/notification_divider</item>
|
||||
</style>
|
||||
|
||||
<style name="MoreButton" parent="@style/BasicButton">
|
||||
<item name="android:paddingRight">2dp</item>
|
||||
</style>
|
||||
|
|
|
@ -147,10 +147,6 @@
|
|||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="DarkSpinnerItem" parent="Widget.AppCompat.TextView.SpinnerItem">
|
||||
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
|
||||
</style>
|
||||
|
||||
<style name="LightActionMode" parent="@style/Widget.AppCompat.ActionMode">
|
||||
<item name="titleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse</item>
|
||||
<item name="subtitleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse</item>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<!-- Trust preinstalled CAs -->
|
||||
<certificates src="system"/>
|
||||
|
||||
<!-- Additionally trust user added CAs -->
|
||||
<certificates src="user"/>
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
|
@ -3,7 +3,6 @@
|
|||
android:title="@string/settings.appearance_title">
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="light"
|
||||
android:entries="@array/themeNames"
|
||||
android:entryValues="@array/themeValues"
|
||||
android:key="theme"
|
||||
|
|
BIN
audinaut.png
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
@ -4,7 +4,7 @@ buildscript {
|
|||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Sat Aug 24 13:47:57 EDT 2019
|
||||
#Sun Nov 01 18:55:24 EST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
|
||||
|
|