Compare commits
73 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 | |
Andrew Rabert | 8fc54ac68c | |
Andrew Rabert | 8f4d3be90b | |
Andrew Rabert | a6a784037e | |
dddddd-mmmmmm | 2ed89ab72f | |
Andrew Rabert | d5b56eecdd | |
dddddd-mmmmmm | 81086c4a3a | |
dddddd-mmmmmm | 02d94e1a6c | |
dddddd-mmmmmm | 5141eb6e81 | |
dddddd-mmmmmm | 4254c8ad9f | |
Andrew Rabert | bf9e9ad1e6 | |
Andrew Rabert | 02a8b1909a | |
Morgan Lim | ff4a1f3b13 | |
Morgan Lim | 153ccdd46a | |
Morgan Lim | 507c9008aa | |
Morgan Lim | 35a112509e | |
Andrew Rabert | af89b8ea76 | |
Morgan Lim | 0a84e9376a | |
Morgan Lim | 717cab5dd5 | |
Andrew Rabert | 13810a07a5 | |
Andrew Rabert | b147cc10dc | |
mlim15 | 357cbd2ba1 | |
Andrew Rabert | 435d770716 | |
Andrew Rabert | 4503ae4133 | |
Andrew Rabert | d43cfb1ce3 | |
mlim15 | cc0faa19ce | |
mlim15 | 8078eeff74 | |
mlim15 | d176ed4036 | |
mlim15 | cf4ab6bf05 |
18
CHANGELOG.md
|
@ -1,6 +1,24 @@
|
|||
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
|
||||
* Add adaptive icon
|
||||
* Add support for p= authentication
|
||||
* Change to MediaStyle playback notification
|
||||
* Fix SSID selection
|
||||
* Fix keyboard being visible when switching to now playing
|
||||
* Fix now playing icon when using light theme
|
||||
|
||||
## Version 0.4.1
|
||||
_2019-12-28_
|
||||
* Revert attempt to fix infinite loop as it sometimes deleted valid files.
|
||||
|
|
|
@ -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 200
|
||||
versionName '0.4.1'
|
||||
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,14 +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.2.2'
|
||||
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.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()
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
@ -46,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,9 +168,10 @@ 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -366,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;
|
||||
|
@ -415,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);
|
||||
}
|
||||
}
|
||||
|
@ -534,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;
|
||||
}
|
||||
|
||||
|
@ -704,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);
|
||||
|
|
|
@ -28,6 +28,7 @@ import android.preference.ListPreference;
|
|||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.SwitchPreference;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
@ -469,6 +470,12 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
|
|||
serverPasswordPreference.setSummary("***");
|
||||
serverPasswordPreference.setTitle(R.string.settings_server_password);
|
||||
|
||||
final SwitchPreference authMethodPreference = new SwitchPreference(context);
|
||||
authMethodPreference.setKey(Constants.PREFERENCES_KEY_AUTH_METHOD + instance);
|
||||
authMethodPreference.setSummary(R.string.settings_auth_summary);
|
||||
authMethodPreference.setDefaultValue(true); // use Token/Salt by default
|
||||
authMethodPreference.setTitle(R.string.settings_auth_method);
|
||||
|
||||
final Preference serverOpenBrowser = new Preference(context);
|
||||
serverOpenBrowser.setKey(Constants.PREFERENCES_KEY_OPEN_BROWSER);
|
||||
serverOpenBrowser.setPersistent(false);
|
||||
|
@ -523,13 +530,24 @@ 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);
|
||||
screen.addPreference(serverLocalNetworkSSIDPreference);
|
||||
screen.addPreference(serverUsernamePreference);
|
||||
screen.addPreference(serverPasswordPreference);
|
||||
screen.addPreference(authMethodPreference);
|
||||
screen.addPreference(serverTestConnectionPreference);
|
||||
screen.addPreference(serverStartScanPreference);
|
||||
screen.addPreference(serverOpenBrowser);
|
||||
screen.addPreference(serverRemoveServerPreference);
|
||||
|
||||
|
@ -599,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,10 +67,12 @@ 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";
|
||||
public static final String PREFERENCES_KEY_PASSWORD = "password";
|
||||
public static final String PREFERENCES_KEY_AUTH_METHOD = "authMethod";
|
||||
public static final String PREFERENCES_KEY_THEME = "theme";
|
||||
public static final String PREFERENCES_KEY_FULL_SCREEN = "fullScreen";
|
||||
public static final String PREFERENCES_KEY_DISPLAY_TRACK = "displayTrack";
|
||||
|
|
|
@ -23,14 +23,16 @@ import android.content.ComponentName;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
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 android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.media.app.NotificationCompat.MediaStyle;
|
||||
|
||||
import net.nullsum.audinaut.R;
|
||||
import net.nullsum.audinaut.activity.SubsonicActivity;
|
||||
|
@ -67,28 +69,52 @@ public final class Notifications {
|
|||
}
|
||||
|
||||
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
|
||||
|
||||
RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
|
||||
setupViews(expandedContentView, context, song, true, playing);
|
||||
|
||||
RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
|
||||
setupViews(smallContentView, context, song, false, playing);
|
||||
|
||||
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
|
||||
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
|
||||
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
|
||||
final Notification notification = new NotificationCompat.Builder(context, CHANNEL_PLAYING_ID)
|
||||
Intent cancelIntent = new Intent("KEYCODE_MEDIA_STOP")
|
||||
.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)
|
||||
.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(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.getTitle())
|
||||
.setContentText(song.getArtist())
|
||||
.setSubText(song.getAlbum())
|
||||
.setTicker(song.getTitle())
|
||||
.setOngoing(playing)
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setCustomContentView(smallContentView)
|
||||
.setCustomBigContentView(expandedContentView)
|
||||
.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, 0))
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW).build();
|
||||
.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);
|
||||
final Notification notification = builder.build();
|
||||
|
||||
if(playing) {
|
||||
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
|
||||
}
|
||||
|
||||
playShowing = true;
|
||||
if (downloadForeground && downloadShowing) {
|
||||
|
@ -116,13 +142,7 @@ public final class Notifications {
|
|||
AudinautWidgetProvider.notifyInstances(context, downloadService, playing);
|
||||
}
|
||||
|
||||
private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean expanded, boolean playing) {
|
||||
// Use the same text for the ticker and the expanded notification
|
||||
String title = song.getTitle();
|
||||
String arist = song.getArtist();
|
||||
String album = song.getAlbum();
|
||||
|
||||
// Set the album art.
|
||||
private static Bitmap getAlbumArt(Context context, MusicDirectory.Entry song) {
|
||||
try {
|
||||
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
|
||||
Bitmap bitmap = null;
|
||||
|
@ -131,90 +151,42 @@ public final class Notifications {
|
|||
}
|
||||
if (bitmap == null) {
|
||||
// set default album art
|
||||
rv.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
|
||||
return BitmapFactory.decodeResource(context.getResources(), R.drawable.unknown_album);
|
||||
} else {
|
||||
imageLoader.setNowPlayingSmall(bitmap);
|
||||
rv.setImageViewBitmap(R.id.notification_image, bitmap);
|
||||
return bitmap;
|
||||
}
|
||||
} catch (Exception x) {
|
||||
Log.w(TAG, "Failed to get notification cover art", x);
|
||||
rv.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
|
||||
return BitmapFactory.decodeResource(context.getResources(), R.drawable.unknown_album);
|
||||
}
|
||||
}
|
||||
|
||||
// set the text for the notifications
|
||||
rv.setTextViewText(R.id.notification_title, title);
|
||||
rv.setTextViewText(R.id.notification_artist, arist);
|
||||
rv.setTextViewText(R.id.notification_album, album);
|
||||
|
||||
boolean persistent = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false);
|
||||
if (persistent) {
|
||||
if (expanded) {
|
||||
rv.setImageViewResource(R.id.control_pause, playing ? R.drawable.notification_media_pause : R.drawable.notification_media_start);
|
||||
|
||||
rv.setImageViewResource(R.id.control_previous, R.drawable.notification_media_backward);
|
||||
rv.setImageViewResource(R.id.control_next, R.drawable.notification_media_forward);
|
||||
} else {
|
||||
rv.setImageViewResource(R.id.control_previous, playing ? R.drawable.notification_media_pause : R.drawable.notification_media_start);
|
||||
rv.setImageViewResource(R.id.control_pause, R.drawable.notification_media_forward);
|
||||
rv.setImageViewResource(R.id.control_next, R.drawable.notification_close);
|
||||
}
|
||||
} else {
|
||||
// Necessary for switching back since it appears to re-use the same layout
|
||||
rv.setImageViewResource(R.id.control_previous, R.drawable.notification_media_backward);
|
||||
rv.setImageViewResource(R.id.control_pause, R.drawable.notification_media_pause);
|
||||
rv.setImageViewResource(R.id.control_next, R.drawable.notification_media_forward);
|
||||
}
|
||||
|
||||
// Create actions for media buttons
|
||||
private static void addActions(final Context context, final NotificationCompat.Builder builder, final boolean playing) {
|
||||
PendingIntent pendingIntent;
|
||||
int previous = 0, pause, next, close = 0;
|
||||
if (persistent && !expanded) {
|
||||
pause = R.id.control_previous;
|
||||
next = R.id.control_pause;
|
||||
close = R.id.control_next;
|
||||
} else {
|
||||
previous = R.id.control_previous;
|
||||
pause = R.id.control_pause;
|
||||
next = R.id.control_next;
|
||||
}
|
||||
|
||||
if (persistent && close == 0 && expanded) {
|
||||
close = R.id.notification_close;
|
||||
rv.setViewVisibility(close, View.VISIBLE);
|
||||
}
|
||||
|
||||
if (previous > 0) {
|
||||
Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
|
||||
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
|
||||
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
|
||||
rv.setOnClickPendingIntent(previous, pendingIntent);
|
||||
}
|
||||
Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
|
||||
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
|
||||
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
|
||||
builder.addAction(R.drawable.notification_media_backward, "Previous", pendingIntent);
|
||||
if (playing) {
|
||||
Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE");
|
||||
pauseIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||
pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
|
||||
pendingIntent = PendingIntent.getService(context, 0, pauseIntent, 0);
|
||||
rv.setOnClickPendingIntent(pause, pendingIntent);
|
||||
builder.addAction(R.drawable.notification_media_pause, "Pause", pendingIntent);
|
||||
} else {
|
||||
Intent prevIntent = new Intent("KEYCODE_MEDIA_START");
|
||||
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));
|
||||
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
|
||||
rv.setOnClickPendingIntent(pause, pendingIntent);
|
||||
Intent playIntent = new Intent("KEYCODE_MEDIA_PLAY");
|
||||
playIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||
playIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));
|
||||
pendingIntent = PendingIntent.getService(context, 0, playIntent, 0);
|
||||
builder.addAction(R.drawable.notification_media_start, "Play", pendingIntent);
|
||||
}
|
||||
Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT");
|
||||
nextIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||
nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT));
|
||||
pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0);
|
||||
rv.setOnClickPendingIntent(next, pendingIntent);
|
||||
if (close > 0) {
|
||||
Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP");
|
||||
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
|
||||
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
|
||||
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
|
||||
rv.setOnClickPendingIntent(close, pendingIntent);
|
||||
}
|
||||
builder.addAction(R.drawable.notification_media_forward, "Next", pendingIntent);
|
||||
}
|
||||
|
||||
public static void hidePlayingNotification(final Context context, final DownloadService downloadService, Handler handler) {
|
||||
|
|
|
@ -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,6 +41,8 @@ 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;
|
||||
|
@ -119,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);
|
||||
|
@ -298,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();
|
||||
|
||||
|
@ -323,18 +332,24 @@ public final class Util {
|
|||
builder.addPathSegment("rest");
|
||||
builder.addPathSegment(method + ".view");
|
||||
|
||||
int hash = (username + password).hashCode();
|
||||
Pair<String, String> values = tokens.get(hash);
|
||||
if (values == null) {
|
||||
String salt = new BigInteger(130, getRandom()).toString(32);
|
||||
String token = md5Hex(password + salt);
|
||||
values = new Pair<>(salt, token);
|
||||
tokens.put(hash, values);
|
||||
builder.addQueryParameter("u", username);
|
||||
|
||||
if (prefs.getBoolean(Constants.PREFERENCES_KEY_AUTH_METHOD + instance, true)) {
|
||||
int hash = (username + password).hashCode();
|
||||
Pair<String, String> values = tokens.get(hash);
|
||||
if (values == null) {
|
||||
String salt = new BigInteger(130, getRandom()).toString(32);
|
||||
String token = md5Hex(password + salt);
|
||||
values = new Pair<>(salt, token);
|
||||
tokens.put(hash, values);
|
||||
}
|
||||
|
||||
builder.addQueryParameter("s", values.getFirst());
|
||||
builder.addQueryParameter("t", values.getSecond());
|
||||
} else {
|
||||
builder.addQueryParameter("p", password);
|
||||
}
|
||||
|
||||
builder.addQueryParameter("u", username);
|
||||
builder.addQueryParameter("s", values.getFirst());
|
||||
builder.addQueryParameter("t", values.getSecond());
|
||||
builder.addQueryParameter("v", Constants.REST_PROTOCOL_VERSION_SUBSONIC);
|
||||
builder.addQueryParameter("c", Constants.REST_CLIENT_ID);
|
||||
|
||||
|
@ -1135,4 +1150,10 @@ public final class Util {
|
|||
|
||||
return random;
|
||||
}
|
||||
|
||||
public static void hideKeyboard(View view) {
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<adaptive-icon
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
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>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="48.0"
|
||||
android:viewportHeight="48.0">
|
||||
<path
|
||||
android:fillColor="#3F3F3F"
|
||||
android:pathData="M0,0 l 0,-100 100,100 0,0 -100,100z" />
|
||||
</vector>
|
|
@ -0,0 +1,184 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:viewportWidth="590.5714"
|
||||
android:viewportHeight="590.5714"
|
||||
android:width="590.5714dp"
|
||||
android:height="590.5714dp">
|
||||
<group
|
||||
android:translateX="-82.92544"
|
||||
android:translateY="-164.7266">
|
||||
<group
|
||||
android:scaleX="0.6475929"
|
||||
android:scaleY="0.6468909"
|
||||
android:translateX="148.4574"
|
||||
android:translateY="176.1372">
|
||||
<clip-path
|
||||
android:pathData="M226.37425 605.31463L578.5552 898.41451 815.86565 898.59552 814.7542 566.66728 403.02131 236.4829C258.46412 375.28405 223.29168 363.17172 252.15774 479.26269Z" />
|
||||
<path
|
||||
android:pathData="M249.6397 165.7266H697.3483A165.7143 165.7143 0 0 1 863.0626 331.4409V777.1119A165.7143 165.7143 0 0 1 697.3483 942.8262H249.6397A165.7143 165.7143 0 0 1 83.92544 777.1119V331.4409A165.7143 165.7143 0 0 1 249.6397 165.7266Z">
|
||||
<aapt:attr
|
||||
name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="116.0774"
|
||||
android:startY="243.6558"
|
||||
android:endX="601.3173"
|
||||
android:endY="689.3493"
|
||||
android:tileMode="clamp">
|
||||
<item
|
||||
android:color="#77000000"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M331.62492 552.7354c0.72527 -15.24559 14.13826 -34.3497 26.05629 -45.50156 3.40059 18.08281 -2.90069 -13.669 17.31711 60.04752 21.02632 -65.64317 12.62531 -7.02152 24.01543 -58.59228 5.88355 -18.08321 14.10692 11.92488 21.20653 38.40148 40.60438 -54.45752 19.35837 -68.73406 30.4072 -97.83931l-122.65619 -8.56713 -20.26856 37.61178c8.86185 31.34374 13.36152 31.6047 23.92219 74.4395z"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#D0B0B0"
|
||||
android:strokeWidth="0.5397026">
|
||||
<aapt:attr
|
||||
name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="372.3981"
|
||||
android:startY="459.9542"
|
||||
android:endX="374.6396"
|
||||
android:endY="647.8042"
|
||||
android:tileMode="clamp">
|
||||
<item
|
||||
android:color="#C83D00"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FFFFFF"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M327.02744 492.83652l11.39671 27.80674c6.79448 -10.33546 8.27016 -36.53845 18.79995 -42.39154 4.75016 22.51793 16.67487 45.33845 20.77813 63.04779 8.76249 -23.32953 14.06952 -67.27625 24.62406 -60.07173 12.47 5.64487 22.66228 33.95061 17.85786 43.41171 -0.36026 0.70945 35.97493 -32.83724 35.67943 -34.61028 -0.29551 -1.77303 -54.66862 -56.88491 -57.47592 -58.21469 -2.80731 -1.32977 -72.39899 1.77304 -72.39899 1.77304l-22.16295 39.0068z"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#DEA369"
|
||||
android:strokeWidth="0.5397026">
|
||||
<aapt:attr
|
||||
name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="373.7826"
|
||||
android:startY="457.2065"
|
||||
android:endX="376.2011"
|
||||
android:endY="575.4747"
|
||||
android:tileMode="clamp">
|
||||
<item
|
||||
android:color="#D0BF40"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FE4732"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M326.27022 455.5126c8.77351 -0.49739 14.82934 48.41956 21.22148 22.83644 5.80358 -23.22752 31.21007 10.70757 32.13581 31.47907 -2.31737 -36.26359 19.4236 -64.78742 30.87794 -41.70038 31.76438 64.02339 11.22662 -7.2515 28.66653 -8.53564 -1.62528 -2.65955 -57.47593 -48.31523 -73.2855 -47.13321 -15.80957 1.18202 -39.61626 43.05372 -39.61626 43.05372z"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#C1AB34"
|
||||
android:strokeWidth="0.5397026">
|
||||
<aapt:attr
|
||||
name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="374.4492"
|
||||
android:startY="448.3223"
|
||||
android:endX="380.7424"
|
||||
android:endY="541.3069"
|
||||
android:tileMode="clamp">
|
||||
<item
|
||||
android:color="#FFFD93"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FF7D13"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<group
|
||||
android:scaleX="0.5397026"
|
||||
android:scaleY="0.5397026"
|
||||
android:translateX="167.3064"
|
||||
android:translateY="192.7248">
|
||||
<path
|
||||
android:pathData="M393.65234 238.15234c-96.76642 -1.43358 -195.7063 134.17501 -186.63867 413.01563 58.19797 133.75726 33.29955 -86.18552 79.46875 -153.75391 22.24905 -32.56135 165.71666 -29.49247 183.60156 -6.66211 75.47168 96.3408 29.83239 302.6978 97.16016 156.63867 17.76663 -269.32857 -76.82538 -407.8047 -173.5918 -409.23828z"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#F5F5F5"
|
||||
android:strokeWidth="4">
|
||||
<aapt:attr
|
||||
name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="387.6964"
|
||||
android:startY="771.4392"
|
||||
android:endX="389.097"
|
||||
android:endY="147.1536"
|
||||
android:tileMode="clamp">
|
||||
<item
|
||||
android:color="#267797"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#A77797"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</group>
|
||||
<group
|
||||
android:scaleX="0.5397026"
|
||||
android:scaleY="0.5397026"
|
||||
android:translateX="167.2811"
|
||||
android:translateY="192.7248">
|
||||
<clip-path
|
||||
android:pathData="M295.66887 424.96942l62.04175 53.59779 191.5675 31.59449 1.08845 -85.47437L431.99745 300.28404 313.90043 407.19752Z" />
|
||||
<path
|
||||
android:pathData="M393.65234 238.15234c-96.76642 -1.43358 -195.7063 134.17501 -186.63867 413.01563 58.19797 133.75726 33.29955 -86.18552 79.46875 -153.75391 22.24905 -32.56135 165.71666 -29.49247 183.60156 -6.66211 75.47168 96.3408 29.83239 302.6978 97.16016 156.63867 17.76663 -269.32857 -76.82538 -407.8047 -173.5918 -409.23828z"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#F5F5F5"
|
||||
android:strokeAlpha="0.232"
|
||||
android:strokeWidth="4">
|
||||
<aapt:attr
|
||||
name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="294.0023"
|
||||
android:startY="324.6501"
|
||||
android:endX="517.636"
|
||||
android:endY="480.116"
|
||||
android:tileMode="clamp">
|
||||
<item
|
||||
android:color="#3B000000"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M328.178 420.70284c38.22209 -5.6969 41.4239 -10.23485 100.5871 1.67162 -17.23601 -102.43063 -84.93377 -94.98395 -100.5871 -1.67162z"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#F1F1F1"
|
||||
android:strokeWidth="2.15881">
|
||||
<aapt:attr
|
||||
name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="351.1998"
|
||||
android:startY="341.9985"
|
||||
android:endX="415.4821"
|
||||
android:endY="379.1636"
|
||||
android:tileMode="clamp">
|
||||
<item
|
||||
android:color="#9FA5D4"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#A2C6DB"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</group>
|
||||
</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,4 +1,4 @@
|
|||
<vector android:alpha="0.8" android:height="24dp" android:tint="#FFFFFF"
|
||||
<vector android:alpha="0.8" 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="M8,5v14l11,-7z"/>
|
||||
|
|
|
@ -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>
|
|
@ -37,7 +37,9 @@
|
|||
</string-array>
|
||||
|
||||
<string-array name="maxBitrateValues">
|
||||
<item>24</item>
|
||||
<item>32</item>
|
||||
<item>48</item>
|
||||
<item>64</item>
|
||||
<item>80</item>
|
||||
<item>96</item>
|
||||
|
@ -51,7 +53,9 @@
|
|||
</string-array>
|
||||
|
||||
<string-array name="maxBitrateNames">
|
||||
<item>@string/settings.max_bitrate_24</item>
|
||||
<item>@string/settings.max_bitrate_32</item>
|
||||
<item>@string/settings.max_bitrate_48</item>
|
||||
<item>@string/settings.max_bitrate_64</item>
|
||||
<item>@string/settings.max_bitrate_80</item>
|
||||
<item>@string/settings.max_bitrate_96</item>
|
||||
|
|
|
@ -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>
|
||||
|
@ -135,6 +135,8 @@
|
|||
<string name="settings.server_internal_address">Local network address</string>
|
||||
<string name="settings.server_username">Username</string>
|
||||
<string name="settings.server_password">Password</string>
|
||||
<string name="settings.auth_method">Authentication Method</string>
|
||||
<string name="settings.auth_summary">Use token/salt authentication?</string>
|
||||
<string name="settings.server_open_browser">Open in browser</string>
|
||||
<string name="settings.cache_title">Music cache</string>
|
||||
<string name="settings.preload_wifi">Songs to preload (Wifi)</string>
|
||||
|
@ -150,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>
|
||||
|
@ -157,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>
|
||||
|
@ -168,7 +172,9 @@
|
|||
<string name="settings.network_title">Network</string>
|
||||
<string name="settings.max_bitrate_wifi">Max Audio bitrate - Wi-Fi</string>
|
||||
<string name="settings.max_bitrate_mobile">Max Audio bitrate - Mobile</string>
|
||||
<string name="settings.max_bitrate_24">24 Kbps</string>
|
||||
<string name="settings.max_bitrate_32">32 Kbps</string>
|
||||
<string name="settings.max_bitrate_48">48 Kbps</string>
|
||||
<string name="settings.max_bitrate_64">64 Kbps</string>
|
||||
<string name="settings.max_bitrate_80">80 Kbps</string>
|
||||
<string name="settings.max_bitrate_96">96 Kbps</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
|
||||
|
|