mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-03-03 10:57:40 +01:00
Refactored remaining Activities
This commit is contained in:
parent
cf90abb77e
commit
1b9b127424
@ -44,17 +44,6 @@
|
||||
android:name="android.app.searchable"
|
||||
android:resource="@xml/searchable"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.EqualizerActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/equalizer.label"
|
||||
android:launchMode="singleTask"/>
|
||||
<activity
|
||||
android:name=".activity.ServerSelectorActivity"
|
||||
android:label="@string/server_selector.label" />
|
||||
<activity
|
||||
android:name=".activity.EditServerActivity"
|
||||
android:label="@string/server_editor.label" />
|
||||
|
||||
<service
|
||||
android:name=".service.MediaPlayerService"
|
||||
|
@ -1,280 +0,0 @@
|
||||
/*
|
||||
This file is part of Subsonic.
|
||||
|
||||
Subsonic is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Subsonic is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2011 (C) Sindre Mehus
|
||||
*/
|
||||
package org.moire.ultrasonic.activity;
|
||||
|
||||
import android.media.audiofx.Equalizer;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
import org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.audiofx.EqualizerController;
|
||||
import org.moire.ultrasonic.service.MediaPlayerController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import kotlin.Lazy;
|
||||
import timber.log.Timber;
|
||||
|
||||
import static org.koin.java.KoinJavaComponent.inject;
|
||||
|
||||
/**
|
||||
* Equalizer controls.
|
||||
*
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EqualizerActivity extends ResultActivity
|
||||
{
|
||||
private static final int MENU_GROUP_PRESET = 100;
|
||||
|
||||
private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>();
|
||||
private EqualizerController equalizerController;
|
||||
private Equalizer equalizer;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle)
|
||||
{
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.equalizer);
|
||||
|
||||
EqualizerController.get().observe(this, new Observer<EqualizerController>() {
|
||||
@Override
|
||||
public void onChanged(EqualizerController controller) {
|
||||
if (controller != null) {
|
||||
Timber.d("EqualizerController Observer.onChanged received controller");
|
||||
equalizerController = controller;
|
||||
equalizer = controller.equalizer;
|
||||
setup();
|
||||
} else {
|
||||
Timber.d("EqualizerController Observer.onChanged has no controller");
|
||||
equalizerController = null;
|
||||
equalizer = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (equalizerController == null) return;
|
||||
equalizerController.saveSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
if (equalizer == null) return;
|
||||
|
||||
short currentPreset;
|
||||
try
|
||||
{
|
||||
currentPreset = equalizer.getCurrentPreset();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
currentPreset = -1;
|
||||
}
|
||||
|
||||
for (short preset = 0; preset < equalizer.getNumberOfPresets(); preset++)
|
||||
{
|
||||
MenuItem menuItem = menu.add(MENU_GROUP_PRESET, preset, preset, equalizer.getPresetName(preset));
|
||||
if (preset == currentPreset)
|
||||
{
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
menu.setGroupCheckable(MENU_GROUP_PRESET, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem menuItem)
|
||||
{
|
||||
if (equalizer == null) return true;
|
||||
try
|
||||
{
|
||||
short preset = (short) menuItem.getItemId();
|
||||
equalizer.usePreset(preset);
|
||||
updateBars();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Show a dialog
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setup()
|
||||
{
|
||||
initEqualizer();
|
||||
|
||||
final View presetButton = findViewById(R.id.equalizer_preset);
|
||||
registerForContextMenu(presetButton);
|
||||
presetButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
presetButton.showContextMenu();
|
||||
}
|
||||
});
|
||||
|
||||
CheckBox enabledCheckBox = (CheckBox) findViewById(R.id.equalizer_enabled);
|
||||
enabledCheckBox.setChecked(equalizer.getEnabled());
|
||||
enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
|
||||
{
|
||||
setEqualizerEnabled(b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setEqualizerEnabled(boolean enabled)
|
||||
{
|
||||
if (equalizer == null) return;
|
||||
equalizer.setEnabled(enabled);
|
||||
updateBars();
|
||||
}
|
||||
|
||||
private void updateBars()
|
||||
{
|
||||
if (equalizer == null) return;
|
||||
try
|
||||
{
|
||||
for (Map.Entry<Short, SeekBar> entry : bars.entrySet())
|
||||
{
|
||||
short band = entry.getKey();
|
||||
SeekBar bar = entry.getValue();
|
||||
bar.setEnabled(equalizer.getEnabled());
|
||||
short minEQLevel = equalizer.getBandLevelRange()[0];
|
||||
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Show a dialog
|
||||
}
|
||||
}
|
||||
|
||||
private void initEqualizer()
|
||||
{
|
||||
if (equalizer == null) return;
|
||||
LinearLayout layout = (LinearLayout) findViewById(R.id.equalizer_layout);
|
||||
|
||||
try
|
||||
{
|
||||
short[] bandLevelRange = equalizer.getBandLevelRange();
|
||||
short numberOfBands = equalizer.getNumberOfBands();
|
||||
|
||||
final short minEQLevel = bandLevelRange[0];
|
||||
final short maxEQLevel = bandLevelRange[1];
|
||||
|
||||
for (short i = 0; i < numberOfBands; i++)
|
||||
{
|
||||
final short band = i;
|
||||
|
||||
View bandBar = LayoutInflater.from(this).inflate(R.layout.equalizer_bar, null);
|
||||
TextView freqTextView;
|
||||
|
||||
if (bandBar != null)
|
||||
{
|
||||
freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
||||
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
||||
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
||||
|
||||
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
|
||||
|
||||
bars.put(band, bar);
|
||||
bar.setMax(maxEQLevel - minEQLevel);
|
||||
short level = equalizer.getBandLevel(band);
|
||||
bar.setProgress(level - minEQLevel);
|
||||
bar.setEnabled(equalizer.getEnabled());
|
||||
updateLevelText(levelTextView, level);
|
||||
|
||||
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
short level = (short) (progress + minEQLevel);
|
||||
if (fromUser)
|
||||
{
|
||||
try
|
||||
{
|
||||
equalizer.setBandLevel(band, level);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Show a dialog
|
||||
}
|
||||
}
|
||||
updateLevelText(levelTextView, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
layout.addView(bandBar);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Show a dialog
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateLevelText(TextView levelTextView, short level)
|
||||
{
|
||||
if (levelTextView != null)
|
||||
{
|
||||
levelTextView.setText(String.format("%s%d dB", level > 0 ? "+" : "", level / 100));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package org.moire.ultrasonic.activity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import org.moire.ultrasonic.util.Constants;
|
||||
import org.moire.ultrasonic.util.Util;
|
||||
|
||||
/**
|
||||
* Created by Joshua Bahnsen on 12/30/13.
|
||||
*/
|
||||
public class ResultActivity extends AppCompatActivity
|
||||
{
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
switch (resultCode)
|
||||
{
|
||||
case Constants.RESULT_CLOSE_ALL:
|
||||
setResult(Constants.RESULT_CLOSE_ALL);
|
||||
finish();
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
public void startActivityForResultWithoutTransition(Activity currentActivity, Class<? extends Activity> newActivity)
|
||||
{
|
||||
startActivityForResultWithoutTransition(currentActivity, new Intent(currentActivity, newActivity));
|
||||
}
|
||||
|
||||
public void startActivityForResultWithoutTransition(Activity currentActivity, Intent intent)
|
||||
{
|
||||
startActivityForResult(intent, 0);
|
||||
Util.disablePendingTransition(currentActivity);
|
||||
}
|
||||
}
|
@ -1,255 +0,0 @@
|
||||
/*
|
||||
This file is part of Ultrasonic.
|
||||
|
||||
Subsonic is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Subsonic is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2009 (C) Sindre Mehus
|
||||
*/
|
||||
package org.moire.ultrasonic.activity;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import timber.log.Timber;
|
||||
import android.view.*;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.widget.*;
|
||||
import net.simonvt.menudrawer.MenuDrawer;
|
||||
import net.simonvt.menudrawer.Position;
|
||||
import static org.koin.java.KoinJavaComponent.inject;
|
||||
|
||||
import org.koin.java.KoinJavaComponent;
|
||||
import org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider;
|
||||
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||
import org.moire.ultrasonic.domain.MusicDirectory.Entry;
|
||||
import org.moire.ultrasonic.domain.PlayerState;
|
||||
import org.moire.ultrasonic.domain.Share;
|
||||
import org.moire.ultrasonic.featureflags.Feature;
|
||||
import org.moire.ultrasonic.featureflags.FeatureStorage;
|
||||
import org.moire.ultrasonic.fragment.SelectAlbumFragment;
|
||||
import org.moire.ultrasonic.service.*;
|
||||
import org.moire.ultrasonic.subsonic.ImageLoaderProvider;
|
||||
import org.moire.ultrasonic.subsonic.SubsonicImageLoaderProxy;
|
||||
import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader;
|
||||
import org.moire.ultrasonic.util.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import kotlin.Lazy;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SubsonicTabActivity extends ResultActivity
|
||||
{
|
||||
private static final Pattern COMPILE = Pattern.compile(":");
|
||||
protected static String theme;
|
||||
private static SubsonicTabActivity instance;
|
||||
|
||||
private boolean destroyed;
|
||||
|
||||
private static final String STATE_MENUDRAWER = "org.moire.ultrasonic.menuDrawer";
|
||||
private static final String STATE_ACTIVE_VIEW_ID = "org.moire.ultrasonic.activeViewId";
|
||||
private static final String STATE_ACTIVE_POSITION = "org.moire.ultrasonic.activePosition";
|
||||
private static final int DIALOG_ASK_FOR_SHARE_DETAILS = 102;
|
||||
|
||||
private final Lazy<MediaPlayerController> mediaPlayerControllerLazy = inject(MediaPlayerController.class);
|
||||
private final Lazy<MediaPlayerLifecycleSupport> lifecycleSupport = inject(MediaPlayerLifecycleSupport.class);
|
||||
protected Lazy<ImageLoaderProvider> imageLoader = inject(ImageLoaderProvider.class);
|
||||
|
||||
public MenuDrawer menuDrawer;
|
||||
private int activePosition = 1;
|
||||
private int menuActiveViewId;
|
||||
private View nowPlayingView;
|
||||
View chatMenuItem;
|
||||
View bookmarksMenuItem;
|
||||
View sharesMenuItem;
|
||||
public static boolean nowPlayingHidden;
|
||||
boolean licenseValid;
|
||||
private EditText shareDescription;
|
||||
TimeSpanPicker timeSpanPicker;
|
||||
CheckBox hideDialogCheckBox;
|
||||
CheckBox noExpirationCheckBox;
|
||||
CheckBox saveAsDefaultsCheckBox;
|
||||
ShareDetails shareDetails;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle)
|
||||
{
|
||||
super.onCreate(bundle);
|
||||
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
|
||||
if (bundle != null)
|
||||
{
|
||||
activePosition = bundle.getInt(STATE_ACTIVE_POSITION);
|
||||
menuActiveViewId = bundle.getInt(STATE_ACTIVE_VIEW_ID);
|
||||
}
|
||||
|
||||
menuDrawer = MenuDrawer.attach(this, MenuDrawer.Type.BEHIND, Position.LEFT, MenuDrawer.MENU_DRAG_WINDOW);
|
||||
menuDrawer.setMenuView(R.layout.menu_main);
|
||||
|
||||
chatMenuItem = findViewById(R.id.menu_chat);
|
||||
bookmarksMenuItem = findViewById(R.id.menu_bookmarks);
|
||||
sharesMenuItem = findViewById(R.id.menu_shares);
|
||||
|
||||
//setActionBarDisplayHomeAsUp(true);
|
||||
|
||||
TextView activeView = (TextView) findViewById(menuActiveViewId);
|
||||
|
||||
if (activeView != null)
|
||||
{
|
||||
menuDrawer.setActiveView(activeView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle bundle)
|
||||
{
|
||||
super.onPostCreate(bundle);
|
||||
instance = this;
|
||||
|
||||
int visibility = ActiveServerProvider.Companion.isOffline(this) ? View.GONE : View.VISIBLE;
|
||||
chatMenuItem.setVisibility(visibility);
|
||||
bookmarksMenuItem.setVisibility(visibility);
|
||||
sharesMenuItem.setVisibility(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
Util.applyTheme(this);
|
||||
instance = this;
|
||||
|
||||
Util.registerMediaButtonEventReceiver(this, false);
|
||||
// Lifecycle support's constructor registers some event receivers so it should be created early
|
||||
lifecycleSupport.getValue().onCreate();
|
||||
|
||||
// Make sure to update theme
|
||||
if (theme != null && !theme.equals(Util.getTheme(this)))
|
||||
{
|
||||
theme = Util.getTheme(this);
|
||||
restart();
|
||||
}
|
||||
|
||||
// This must be filled here because onCreate is called before the derived objects would call setContentView
|
||||
getNowPlayingView();
|
||||
|
||||
if (!nowPlayingHidden)
|
||||
{
|
||||
//showNowPlaying();
|
||||
}
|
||||
else
|
||||
{
|
||||
//hideNowPlaying();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case android.R.id.home:
|
||||
menuDrawer.toggleMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy()
|
||||
{
|
||||
Util.unregisterMediaButtonEventReceiver(this, false);
|
||||
super.onDestroy();
|
||||
destroyed = true;
|
||||
nowPlayingView = null;
|
||||
imageLoader.getValue().clearImageLoader();
|
||||
}
|
||||
|
||||
protected void restart()
|
||||
{
|
||||
Intent intent = new Intent(this, this.getClass());
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
intent.putExtras(getIntent());
|
||||
startActivityForResultWithoutTransition(this, intent);
|
||||
Timber.d("Restarting activity...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish()
|
||||
{
|
||||
super.finish();
|
||||
Util.disablePendingTransition(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDestroyed()
|
||||
{
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
private void getNowPlayingView()
|
||||
{
|
||||
if (nowPlayingView == null)
|
||||
{
|
||||
try {
|
||||
nowPlayingView = findViewById(R.id.now_playing);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
Timber.w(exception, "An exception has occurred while trying to get the nowPlayingView by findViewById");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SubsonicTabActivity getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle inState)
|
||||
{
|
||||
super.onRestoreInstanceState(inState);
|
||||
menuDrawer.restoreState(inState.getParcelable(STATE_MENUDRAWER));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putParcelable(STATE_MENUDRAWER, menuDrawer.saveState());
|
||||
outState.putInt(STATE_ACTIVE_VIEW_ID, menuActiveViewId);
|
||||
outState.putInt(STATE_ACTIVE_POSITION, activePosition);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,271 @@
|
||||
package org.moire.ultrasonic.fragment;
|
||||
|
||||
import android.media.audiofx.Equalizer;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.audiofx.EqualizerController;
|
||||
import org.moire.ultrasonic.util.Util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public class EqualizerFragment extends Fragment {
|
||||
|
||||
private static final int MENU_GROUP_PRESET = 100;
|
||||
|
||||
private final Map<Short, SeekBar> bars = new HashMap<>();
|
||||
private EqualizerController equalizerController;
|
||||
private Equalizer equalizer;
|
||||
private LinearLayout equalizerLayout;
|
||||
private View presetButton;
|
||||
private CheckBox enabledCheckBox;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
Util.applyTheme(this.getContext());
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.equalizer, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
FragmentTitle.Companion.setTitle(this, R.string.equalizer_label);
|
||||
equalizerLayout = view.findViewById(R.id.equalizer_layout);
|
||||
presetButton = view.findViewById(R.id.equalizer_preset);
|
||||
enabledCheckBox = view.findViewById(R.id.equalizer_enabled);
|
||||
|
||||
EqualizerController.get().observe(getViewLifecycleOwner(), new Observer<EqualizerController>() {
|
||||
@Override
|
||||
public void onChanged(EqualizerController controller) {
|
||||
if (controller != null) {
|
||||
Timber.d("EqualizerController Observer.onChanged received controller");
|
||||
equalizerController = controller;
|
||||
equalizer = controller.equalizer;
|
||||
setup();
|
||||
} else {
|
||||
Timber.d("EqualizerController Observer.onChanged has no controller");
|
||||
equalizerController = null;
|
||||
equalizer = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
if (equalizerController == null) return;
|
||||
equalizerController.saveSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(@NotNull ContextMenu menu, @NotNull View view, ContextMenu.ContextMenuInfo menuInfo)
|
||||
{
|
||||
super.onCreateContextMenu(menu, view, menuInfo);
|
||||
if (equalizer == null) return;
|
||||
|
||||
short currentPreset;
|
||||
try
|
||||
{
|
||||
currentPreset = equalizer.getCurrentPreset();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
currentPreset = -1;
|
||||
}
|
||||
|
||||
for (short preset = 0; preset < equalizer.getNumberOfPresets(); preset++)
|
||||
{
|
||||
MenuItem menuItem = menu.add(MENU_GROUP_PRESET, preset, preset, equalizer.getPresetName(preset));
|
||||
if (preset == currentPreset)
|
||||
{
|
||||
menuItem.setChecked(true);
|
||||
}
|
||||
}
|
||||
menu.setGroupCheckable(MENU_GROUP_PRESET, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(@NotNull MenuItem menuItem)
|
||||
{
|
||||
if (equalizer == null) return true;
|
||||
try
|
||||
{
|
||||
short preset = (short) menuItem.getItemId();
|
||||
equalizer.usePreset(preset);
|
||||
updateBars();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Show a dialog
|
||||
Timber.i(ex, "An exception has occurred in EqualizerFragment onContextItemSelected");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setup()
|
||||
{
|
||||
initEqualizer();
|
||||
|
||||
registerForContextMenu(presetButton);
|
||||
presetButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
presetButton.showContextMenu();
|
||||
}
|
||||
});
|
||||
|
||||
enabledCheckBox.setChecked(equalizer.getEnabled());
|
||||
enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b)
|
||||
{
|
||||
setEqualizerEnabled(b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setEqualizerEnabled(boolean enabled)
|
||||
{
|
||||
if (equalizer == null) return;
|
||||
equalizer.setEnabled(enabled);
|
||||
updateBars();
|
||||
}
|
||||
|
||||
private void updateBars()
|
||||
{
|
||||
if (equalizer == null) return;
|
||||
try
|
||||
{
|
||||
for (Map.Entry<Short, SeekBar> entry : bars.entrySet())
|
||||
{
|
||||
short band = entry.getKey();
|
||||
SeekBar bar = entry.getValue();
|
||||
bar.setEnabled(equalizer.getEnabled());
|
||||
short minEQLevel = equalizer.getBandLevelRange()[0];
|
||||
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Show a dialog
|
||||
Timber.i(ex, "An exception has occurred in EqualizerFragment updateBars");
|
||||
}
|
||||
}
|
||||
|
||||
private void initEqualizer()
|
||||
{
|
||||
if (equalizer == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
short[] bandLevelRange = equalizer.getBandLevelRange();
|
||||
short numberOfBands = equalizer.getNumberOfBands();
|
||||
|
||||
final short minEQLevel = bandLevelRange[0];
|
||||
final short maxEQLevel = bandLevelRange[1];
|
||||
|
||||
for (short i = 0; i < numberOfBands; i++)
|
||||
{
|
||||
final short band = i;
|
||||
|
||||
View bandBar = LayoutInflater.from(getContext()).inflate(R.layout.equalizer_bar, null);
|
||||
TextView freqTextView;
|
||||
|
||||
if (bandBar != null)
|
||||
{
|
||||
freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
||||
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
||||
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
||||
|
||||
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
|
||||
|
||||
bars.put(band, bar);
|
||||
bar.setMax(maxEQLevel - minEQLevel);
|
||||
short level = equalizer.getBandLevel(band);
|
||||
bar.setProgress(level - minEQLevel);
|
||||
bar.setEnabled(equalizer.getEnabled());
|
||||
updateLevelText(levelTextView, level);
|
||||
|
||||
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
short level = (short) (progress + minEQLevel);
|
||||
if (fromUser)
|
||||
{
|
||||
try
|
||||
{
|
||||
equalizer.setBandLevel(band, level);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Show a dialog?
|
||||
Timber.i(ex, "An exception has occurred in Equalizer onProgressChanged");
|
||||
}
|
||||
}
|
||||
updateLevelText(levelTextView, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
equalizerLayout.addView(bandBar);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Show a dialog?
|
||||
Timber.i(ex, "An exception has occurred while initializing Equalizer");
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateLevelText(TextView levelTextView, short level)
|
||||
{
|
||||
if (levelTextView != null)
|
||||
{
|
||||
levelTextView.setText(String.format("%s%d dB", level > 0 ? "+" : "", level / 100));
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,6 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.activity.ServerSelectorActivity;
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider;
|
||||
import org.moire.ultrasonic.data.ServerSetting;
|
||||
import org.moire.ultrasonic.util.Constants;
|
||||
@ -265,14 +264,7 @@ public class MainFragment extends Fragment {
|
||||
|
||||
private void showServers()
|
||||
{
|
||||
final Intent intent = new Intent(getContext(), ServerSelectorActivity.class);
|
||||
startActivityForResult(intent, 0);
|
||||
}
|
||||
|
||||
public void startActivityForResultWithoutTransition(Activity currentActivity, Intent intent)
|
||||
{
|
||||
startActivityForResult(intent, 0);
|
||||
Util.disablePendingTransition(currentActivity);
|
||||
Navigation.findNavController(getView()).navigate(R.id.mainToServerSelector);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ public class NowPlayingFragment extends Fragment {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Navigation.findNavController(getView()).navigate(R.id.playerFragment);
|
||||
Navigation.findNavController(getActivity(), R.id.nav_host_fragment).navigate(R.id.playerFragment);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package org.moire.ultrasonic.fragment;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
@ -39,7 +38,6 @@ import com.mobeta.android.dslv.DragSortListView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.koin.java.KoinJavaComponent;
|
||||
import org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.activity.EqualizerActivity;
|
||||
import org.moire.ultrasonic.audiofx.EqualizerController;
|
||||
import org.moire.ultrasonic.audiofx.VisualizerController;
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider;
|
||||
@ -960,7 +958,7 @@ public class PlayerFragment extends Fragment implements GestureDetector.OnGestur
|
||||
Util.toast(getContext(), R.string.download_menu_shuffle_notification);
|
||||
return true;
|
||||
case R.id.menu_item_equalizer:
|
||||
startActivity(new Intent(getContext(), EqualizerActivity.class));
|
||||
Navigation.findNavController(getView()).navigate(R.id.playerToEqualizer);
|
||||
return true;
|
||||
case R.id.menu_item_visualizer:
|
||||
final boolean active = !visualizerView.isActive();
|
||||
|
@ -2,7 +2,6 @@ package org.moire.ultrasonic.fragment;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@ -10,7 +9,7 @@ import android.provider.SearchRecentSuggestions;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.preference.CheckBoxPreference;
|
||||
import androidx.preference.EditTextPreference;
|
||||
import androidx.preference.ListPreference;
|
||||
@ -24,8 +23,6 @@ import android.view.View;
|
||||
|
||||
import org.koin.java.KoinJavaComponent;
|
||||
import org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.activity.ServerSelectorActivity;
|
||||
import org.moire.ultrasonic.activity.SubsonicTabActivity;
|
||||
import org.moire.ultrasonic.featureflags.Feature;
|
||||
import org.moire.ultrasonic.featureflags.FeatureStorage;
|
||||
import org.moire.ultrasonic.filepicker.FilePickerDialog;
|
||||
@ -42,7 +39,7 @@ import java.io.File;
|
||||
import kotlin.Lazy;
|
||||
|
||||
import static org.koin.java.KoinJavaComponent.inject;
|
||||
import static org.moire.ultrasonic.activity.ServerSelectorActivity.SERVER_SELECTOR_MANAGE_MODE;
|
||||
import static org.moire.ultrasonic.fragment.ServerSelectorFragment.SERVER_SELECTOR_MANAGE_MODE;
|
||||
|
||||
/**
|
||||
* Shows main app settings.
|
||||
@ -152,8 +149,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
// After API26 foreground services must be used for music playback, and they must have a notification
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
PreferenceCategory notificationsCategory = findPreference(Constants.PREFERENCES_KEY_CATEGORY_NOTIFICATIONS);
|
||||
notificationsCategory.removePreference(findPreference(Constants.PREFERENCES_KEY_SHOW_NOTIFICATION));
|
||||
notificationsCategory.removePreference(findPreference(Constants.PREFERENCES_KEY_ALWAYS_SHOW_NOTIFICATION));
|
||||
Preference preferenceToRemove = findPreference(Constants.PREFERENCES_KEY_SHOW_NOTIFICATION);
|
||||
if (preferenceToRemove != null) notificationsCategory.removePreference(preferenceToRemove);
|
||||
preferenceToRemove = findPreference(Constants.PREFERENCES_KEY_ALWAYS_SHOW_NOTIFICATION);
|
||||
if (preferenceToRemove != null) notificationsCategory.removePreference(preferenceToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,9 +415,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
addServerPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
final Intent intent = new Intent(getActivity(), ServerSelectorActivity.class);
|
||||
intent.putExtra(SERVER_SELECTOR_MANAGE_MODE, true);
|
||||
startActivityForResult(intent, 0);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(SERVER_SELECTOR_MANAGE_MODE, true);
|
||||
Navigation.findNavController(getView()).navigate(R.id.settingsToServerSelector, bundle);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@ -470,15 +469,11 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
}
|
||||
|
||||
private void setImageLoaderConcurrency(int concurrency) {
|
||||
SubsonicTabActivity instance = SubsonicTabActivity.getInstance();
|
||||
ImageLoader imageLoaderInstance = imageLoader.getValue().getImageLoader();
|
||||
|
||||
if (instance != null) {
|
||||
ImageLoader imageLoaderInstance = imageLoader.getValue().getImageLoader();
|
||||
|
||||
if (imageLoaderInstance != null) {
|
||||
imageLoaderInstance.stopImageLoader();
|
||||
imageLoaderInstance.setConcurrency(concurrency);
|
||||
}
|
||||
if (imageLoaderInstance != null) {
|
||||
imageLoaderInstance.stopImageLoader();
|
||||
imageLoaderInstance.setConcurrency(concurrency);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ import androidx.core.app.NotificationManagerCompat;
|
||||
import org.koin.java.KoinJavaComponent;
|
||||
import org.moire.ultrasonic.R;
|
||||
import org.moire.ultrasonic.activity.NavigationActivity;
|
||||
import org.moire.ultrasonic.activity.SubsonicTabActivity;
|
||||
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||
import org.moire.ultrasonic.domain.PlayerState;
|
||||
import org.moire.ultrasonic.domain.RepeatMode;
|
||||
|
@ -28,7 +28,6 @@ import android.text.TextUtils;
|
||||
import kotlin.Lazy;
|
||||
import timber.log.Timber;
|
||||
|
||||
import org.moire.ultrasonic.activity.SubsonicTabActivity;
|
||||
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||
import org.moire.ultrasonic.subsonic.ImageLoaderProvider;
|
||||
|
||||
@ -156,18 +155,14 @@ public class FileUtil
|
||||
|
||||
File avatarFile = getAvatarFile(context, username);
|
||||
|
||||
SubsonicTabActivity subsonicTabActivity = SubsonicTabActivity.getInstance();
|
||||
Bitmap bitmap = null;
|
||||
ImageLoader imageLoader = null;
|
||||
|
||||
if (subsonicTabActivity != null)
|
||||
{
|
||||
imageLoader = imageLoaderProvider.getValue().getImageLoader();
|
||||
imageLoader = imageLoaderProvider.getValue().getImageLoader();
|
||||
|
||||
if (imageLoader != null)
|
||||
{
|
||||
bitmap = imageLoader.getImageBitmap(username, size);
|
||||
}
|
||||
if (imageLoader != null)
|
||||
{
|
||||
bitmap = imageLoader.getImageBitmap(username, size);
|
||||
}
|
||||
|
||||
if (bitmap != null)
|
||||
@ -226,18 +221,14 @@ public class FileUtil
|
||||
|
||||
File albumArtFile = getAlbumArtFile(context, entry);
|
||||
|
||||
SubsonicTabActivity subsonicTabActivity = SubsonicTabActivity.getInstance();
|
||||
Bitmap bitmap = null;
|
||||
ImageLoader imageLoader = null;
|
||||
|
||||
if (subsonicTabActivity != null)
|
||||
{
|
||||
imageLoader = imageLoaderProvider.getValue().getImageLoader();
|
||||
imageLoader = imageLoaderProvider.getValue().getImageLoader();
|
||||
|
||||
if (imageLoader != null)
|
||||
{
|
||||
bitmap = imageLoader.getImageBitmap(entry, true, size);
|
||||
}
|
||||
if (imageLoader != null)
|
||||
{
|
||||
bitmap = imageLoader.getImageBitmap(entry, true, size);
|
||||
}
|
||||
|
||||
if (bitmap != null)
|
||||
|
@ -2,14 +2,9 @@ package org.moire.ultrasonic.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import org.moire.ultrasonic.activity.SubsonicTabActivity;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
|
@ -31,6 +31,7 @@ import org.koin.android.viewmodel.ext.android.viewModel
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
||||
import org.moire.ultrasonic.domain.PlayerState
|
||||
import org.moire.ultrasonic.fragment.ServerSettingsModel
|
||||
import org.moire.ultrasonic.provider.SearchSuggestionProvider
|
||||
import org.moire.ultrasonic.service.DownloadFile
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
@ -111,7 +112,7 @@ class NavigationActivity : AppCompatActivity() {
|
||||
if (currentFragmentId == R.id.playerFragment) {
|
||||
hideNowPlaying()
|
||||
} else {
|
||||
showNowPlaying()
|
||||
if (!nowPlayingHidden) showNowPlaying()
|
||||
}
|
||||
|
||||
// TODO: Maybe we can find a better place for theme change. Currently the change occurs when navigating between fragments
|
||||
@ -136,7 +137,6 @@ class NavigationActivity : AppCompatActivity() {
|
||||
|
||||
nowPlayingEventListener = object : NowPlayingEventListener {
|
||||
override fun onDismissNowPlaying() {
|
||||
// TODO: When will it be set back to false?
|
||||
nowPlayingHidden = true;
|
||||
hideNowPlaying();
|
||||
}
|
||||
@ -164,11 +164,8 @@ class NavigationActivity : AppCompatActivity() {
|
||||
// Lifecycle support's constructor registers some event receivers so it should be created early
|
||||
lifecycleSupport.onCreate()
|
||||
|
||||
if (!nowPlayingHidden) {
|
||||
showNowPlaying()
|
||||
} else {
|
||||
hideNowPlaying()
|
||||
}
|
||||
if (!nowPlayingHidden) showNowPlaying()
|
||||
else hideNowPlaying()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@ -297,11 +294,14 @@ class NavigationActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun showNowPlaying() {
|
||||
if (!Util.getShowNowPlayingPreference(this) || nowPlayingHidden) {
|
||||
if (!Util.getShowNowPlayingPreference(this)) {
|
||||
hideNowPlaying()
|
||||
return
|
||||
}
|
||||
|
||||
// The logic for nowPlayingHidden is that the user can dismiss NowPlaying with a gesture,
|
||||
// and when the MediaPlayerService requests that it should be shown, it returns
|
||||
nowPlayingHidden = false;
|
||||
// Do not show for Player fragment
|
||||
if (currentFragmentId == R.id.playerFragment) {
|
||||
hideNowPlaying()
|
||||
|
@ -5,11 +5,9 @@ import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.android.viewmodel.dsl.viewModel
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
import org.moire.ultrasonic.activity.ServerSettingsModel
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.fragment.ServerSettingsModel
|
||||
import org.moire.ultrasonic.data.AppDatabase
|
||||
import org.moire.ultrasonic.data.MIGRATION_1_2
|
||||
import org.moire.ultrasonic.subsonic.ImageLoaderProvider
|
||||
import org.moire.ultrasonic.util.Util
|
||||
|
||||
const val SP_NAME = "Default_SP"
|
||||
|
@ -8,7 +8,7 @@ import org.koin.android.viewmodel.dsl.viewModel
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
import org.moire.ultrasonic.BuildConfig
|
||||
import org.moire.ultrasonic.activity.ArtistListModel
|
||||
import org.moire.ultrasonic.fragment.ArtistListModel
|
||||
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
|
||||
import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
|
||||
import org.moire.ultrasonic.api.subsonic.SubsonicClientConfiguration
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
Copyright 2020 (C) Jozsef Varga
|
||||
*/
|
||||
package org.moire.ultrasonic.activity
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
@ -16,7 +16,7 @@
|
||||
|
||||
Copyright 2020 (C) Jozsef Varga
|
||||
*/
|
||||
package org.moire.ultrasonic.activity
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuInflater
|
@ -1,6 +0,0 @@
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
class DownloadFragment: Fragment() {
|
||||
}
|
@ -1,16 +1,16 @@
|
||||
package org.moire.ultrasonic.activity
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.viewmodel.ext.android.viewModel
|
||||
import org.moire.ultrasonic.BuildConfig
|
||||
@ -20,21 +20,17 @@ import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
|
||||
import org.moire.ultrasonic.api.subsonic.SubsonicClientConfiguration
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.data.ServerSetting
|
||||
import org.moire.ultrasonic.service.ApiCallResponseChecker.Companion.checkResponseSuccessful
|
||||
import org.moire.ultrasonic.service.ApiCallResponseChecker
|
||||
import org.moire.ultrasonic.service.MusicServiceFactory
|
||||
import org.moire.ultrasonic.util.Constants
|
||||
import org.moire.ultrasonic.util.ErrorDialog
|
||||
import org.moire.ultrasonic.util.ModalBackgroundTask
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import timber.log.Timber
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* This Activity provides a Form which can be used to edit the properties of a Server Setting.
|
||||
* It can also be used to create a Server Setting from scratch.
|
||||
* Contains functions for testing the configured Server Setting
|
||||
*/
|
||||
internal class EditServerActivity : AppCompatActivity() {
|
||||
|
||||
class EditServerFragment: Fragment() {
|
||||
companion object {
|
||||
const val EDIT_SERVER_INTENT_INDEX = "index"
|
||||
}
|
||||
@ -55,32 +51,41 @@ internal class EditServerActivity : AppCompatActivity() {
|
||||
private var testButton: Button? = null
|
||||
private var isInstanceStateSaved: Boolean = false
|
||||
|
||||
@Override
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Util.applyTheme(this.context)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
Util.applyTheme(this)
|
||||
if (savedInstanceState == null) configureActionBar()
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.server_edit, container, false)
|
||||
}
|
||||
|
||||
setContentView(R.layout.server_edit)
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
serverNameEditText = findViewById(R.id.edit_server_name)
|
||||
serverAddressEditText = findViewById(R.id.edit_server_address)
|
||||
userNameEditText = findViewById(R.id.edit_server_username)
|
||||
passwordEditText = findViewById(R.id.edit_server_password)
|
||||
selfSignedSwitch = findViewById(R.id.edit_self_signed)
|
||||
ldapSwitch = findViewById(R.id.edit_ldap)
|
||||
jukeboxSwitch = findViewById(R.id.edit_jukebox)
|
||||
saveButton = findViewById(R.id.edit_save)
|
||||
testButton = findViewById(R.id.edit_test)
|
||||
serverNameEditText = view.findViewById(R.id.edit_server_name)
|
||||
serverAddressEditText = view.findViewById(R.id.edit_server_address)
|
||||
userNameEditText = view.findViewById(R.id.edit_server_username)
|
||||
passwordEditText = view.findViewById(R.id.edit_server_password)
|
||||
selfSignedSwitch = view.findViewById(R.id.edit_self_signed)
|
||||
ldapSwitch = view.findViewById(R.id.edit_ldap)
|
||||
jukeboxSwitch = view.findViewById(R.id.edit_jukebox)
|
||||
saveButton = view.findViewById(R.id.edit_save)
|
||||
testButton = view.findViewById(R.id.edit_test)
|
||||
|
||||
val index = intent.getIntExtra(EDIT_SERVER_INTENT_INDEX, -1)
|
||||
val index = arguments?.getInt(
|
||||
EDIT_SERVER_INTENT_INDEX,
|
||||
-1
|
||||
) ?: -1
|
||||
|
||||
if (index != -1) {
|
||||
// Editing an existing server
|
||||
setTitle(R.string.server_editor_label)
|
||||
FragmentTitle.setTitle(this, R.string.server_editor_label)
|
||||
val serverSetting = serverSettingsModel.getServerSetting(index)
|
||||
serverSetting.observe(
|
||||
this,
|
||||
viewLifecycleOwner,
|
||||
Observer { t ->
|
||||
if (t != null) {
|
||||
currentServerSetting = t
|
||||
@ -110,18 +115,18 @@ internal class EditServerActivity : AppCompatActivity() {
|
||||
) {
|
||||
MusicServiceFactory.resetMusicService()
|
||||
}
|
||||
finish()
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Creating a new server
|
||||
setTitle(R.string.server_editor_new_label)
|
||||
FragmentTitle.setTitle(this, R.string.server_editor_new_label)
|
||||
currentServerSetting = ServerSetting()
|
||||
saveButton!!.setOnClickListener {
|
||||
if (getFields()) {
|
||||
serverSettingsModel.saveNewItem(currentServerSetting)
|
||||
finish()
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -162,8 +167,10 @@ internal class EditServerActivity : AppCompatActivity() {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
||||
super.onViewStateRestored(savedInstanceState)
|
||||
|
||||
if (savedInstanceState == null) return
|
||||
|
||||
serverNameEditText!!.editText?.setText(
|
||||
savedInstanceState.getString(::serverNameEditText.name)
|
||||
@ -183,26 +190,6 @@ internal class EditServerActivity : AppCompatActivity() {
|
||||
isInstanceStateSaved = savedInstanceState.getBoolean(::isInstanceStateSaved.name)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == android.R.id.home) {
|
||||
finishActivity()
|
||||
return true
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
finishActivity()
|
||||
}
|
||||
|
||||
private fun configureActionBar() {
|
||||
val actionBar: ActionBar? = supportActionBar
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowHomeEnabled(true)
|
||||
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the values of the Form from the current Server Setting instance
|
||||
*/
|
||||
@ -299,7 +286,7 @@ internal class EditServerActivity : AppCompatActivity() {
|
||||
*/
|
||||
private fun testConnection() {
|
||||
val task: ModalBackgroundTask<Boolean> = object : ModalBackgroundTask<Boolean>(
|
||||
this,
|
||||
activity,
|
||||
false
|
||||
) {
|
||||
|
||||
@ -331,10 +318,10 @@ internal class EditServerActivity : AppCompatActivity() {
|
||||
|
||||
// Execute a ping to check the authentication, now using the correct API version.
|
||||
pingResponse = subsonicApiClient.api.ping().execute()
|
||||
checkResponseSuccessful(pingResponse)
|
||||
ApiCallResponseChecker.checkResponseSuccessful(pingResponse)
|
||||
|
||||
val licenseResponse = subsonicApiClient.api.getLicense().execute()
|
||||
checkResponseSuccessful(licenseResponse)
|
||||
ApiCallResponseChecker.checkResponseSuccessful(licenseResponse)
|
||||
return licenseResponse.body()!!.license.valid
|
||||
}
|
||||
|
||||
@ -367,20 +354,20 @@ internal class EditServerActivity : AppCompatActivity() {
|
||||
*/
|
||||
private fun finishActivity() {
|
||||
if (areFieldsChanged()) {
|
||||
AlertDialog.Builder(this)
|
||||
AlertDialog.Builder(context)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(R.string.common_confirm)
|
||||
.setMessage(R.string.server_editor_leave_confirmation)
|
||||
.setPositiveButton(R.string.common_ok) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
finish()
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
.setNegativeButton(R.string.common_cancel) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
finish()
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,9 +15,6 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.viewmodel.ext.android.viewModel
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.activity.ArtistListModel
|
||||
import org.moire.ultrasonic.activity.ArtistRowAdapter
|
||||
import org.moire.ultrasonic.activity.ServerSettingsModel
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.domain.Artist
|
||||
import org.moire.ultrasonic.domain.MusicFolder
|
||||
@ -40,9 +37,6 @@ class SelectArtistFragment : Fragment() {
|
||||
private lateinit var viewManager: RecyclerView.LayoutManager
|
||||
private lateinit var viewAdapter: ArtistRowAdapter
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Util.applyTheme(this.context)
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.moire.ultrasonic.activity
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
@ -1,14 +1,15 @@
|
||||
package org.moire.ultrasonic.activity
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ListView
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
@ -16,21 +17,13 @@ import kotlinx.coroutines.withContext
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.viewmodel.ext.android.viewModel
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.activity.EditServerActivity.Companion.EDIT_SERVER_INTENT_INDEX
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.fragment.EditServerFragment.Companion.EDIT_SERVER_INTENT_INDEX
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* This Activity can be used to display all the configured Server Setting items.
|
||||
* It also contains a FAB to add a new server.
|
||||
* It has a Manage Mode and a Select Mode. In Select Mode, clicking the List Items will select
|
||||
* the server, and a server can be edited using the context menu. In Manage Mode the default
|
||||
* action when a List Item is clicked is to edit the server.
|
||||
*/
|
||||
internal class ServerSelectorActivity : AppCompatActivity() {
|
||||
|
||||
class ServerSelectorFragment: Fragment() {
|
||||
companion object {
|
||||
const val SERVER_SELECTOR_MANAGE_MODE = "manageMode"
|
||||
}
|
||||
@ -41,24 +34,33 @@ internal class ServerSelectorActivity : AppCompatActivity() {
|
||||
private val activeServerProvider: ActiveServerProvider by inject()
|
||||
private var serverRowAdapter: ServerRowAdapter? = null
|
||||
|
||||
@Override
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Util.applyTheme(this.context)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
Util.applyTheme(this)
|
||||
if (savedInstanceState == null) configureActionBar()
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.server_selector, container, false)
|
||||
}
|
||||
|
||||
setContentView(R.layout.server_selector)
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val manageMode = intent.getBooleanExtra(SERVER_SELECTOR_MANAGE_MODE, false)
|
||||
val manageMode = arguments?.getBoolean(
|
||||
SERVER_SELECTOR_MANAGE_MODE,
|
||||
false
|
||||
) ?: false
|
||||
if (manageMode) {
|
||||
setTitle(R.string.settings_server_manage_servers)
|
||||
FragmentTitle.setTitle(this, R.string.settings_server_manage_servers)
|
||||
} else {
|
||||
setTitle(R.string.server_selector_label)
|
||||
FragmentTitle.setTitle(this, R.string.server_selector_label)
|
||||
}
|
||||
|
||||
listView = findViewById(R.id.server_list)
|
||||
listView = view.findViewById(R.id.server_list)
|
||||
serverRowAdapter = ServerRowAdapter(
|
||||
this,
|
||||
view.context,
|
||||
arrayOf(),
|
||||
serverSettingsModel,
|
||||
activeServerProvider,
|
||||
@ -81,24 +83,16 @@ internal class ServerSelectorActivity : AppCompatActivity() {
|
||||
editServer(position + 1)
|
||||
} else {
|
||||
setActiveServer(position)
|
||||
finish()
|
||||
findNavController().navigateUp()
|
||||
}
|
||||
}
|
||||
|
||||
val fab = findViewById<FloatingActionButton>(R.id.server_add_fab)
|
||||
val fab = view.findViewById<FloatingActionButton>(R.id.server_add_fab)
|
||||
fab.setOnClickListener {
|
||||
editServer(-1)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == android.R.id.home) {
|
||||
finish()
|
||||
return true
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
val serverList = serverSettingsModel.getServerList()
|
||||
@ -110,14 +104,6 @@ internal class ServerSelectorActivity : AppCompatActivity() {
|
||||
)
|
||||
}
|
||||
|
||||
private fun configureActionBar() {
|
||||
val actionBar: ActionBar? = supportActionBar
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowHomeEnabled(true)
|
||||
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active server when a list item is clicked
|
||||
*/
|
||||
@ -141,7 +127,7 @@ internal class ServerSelectorActivity : AppCompatActivity() {
|
||||
* This Callback handles the deletion of a Server Setting
|
||||
*/
|
||||
private fun onServerDeleted(index: Int) {
|
||||
AlertDialog.Builder(this)
|
||||
AlertDialog.Builder(context)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(R.string.server_menu_delete)
|
||||
.setMessage(R.string.server_selector_delete_confirmation)
|
||||
@ -162,11 +148,11 @@ internal class ServerSelectorActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the Edit Server Activity to edit the details of a server
|
||||
* Starts the Edit Server Fragment to edit the details of a server
|
||||
*/
|
||||
private fun editServer(index: Int) {
|
||||
val intent = Intent(this, EditServerActivity::class.java)
|
||||
intent.putExtra(EDIT_SERVER_INTENT_INDEX, index)
|
||||
startActivityForResult(intent, 0)
|
||||
val bundle = Bundle()
|
||||
bundle.putInt(EDIT_SERVER_INTENT_INDEX, index)
|
||||
findNavController().navigate(R.id.serverSelectorToEditServer, bundle)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.moire.ultrasonic.activity
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
@ -13,6 +13,9 @@
|
||||
<action
|
||||
android:id="@+id/mainToSelectGenre"
|
||||
app:destination="@id/selectGenreFragment" />
|
||||
<action
|
||||
android:id="@+id/mainToServerSelector"
|
||||
app:destination="@id/serverSelectorFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/selectArtistFragment"
|
||||
@ -62,7 +65,11 @@
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/settingsFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.SettingsFragment" />
|
||||
android:name="org.moire.ultrasonic.fragment.SettingsFragment" >
|
||||
<action
|
||||
android:id="@+id/settingsToServerSelector"
|
||||
app:destination="@id/serverSelectorFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/aboutFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.AboutFragment" />
|
||||
@ -78,8 +85,24 @@
|
||||
<action
|
||||
android:id="@+id/playerToLyrics"
|
||||
app:destination="@id/lyricsFragment" />
|
||||
<action
|
||||
android:id="@+id/playerToEqualizer"
|
||||
app:destination="@id/equalizerFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/lyricsFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.LyricsFragment" />
|
||||
<fragment
|
||||
android:id="@+id/equalizerFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.EqualizerFragment" />
|
||||
<fragment
|
||||
android:id="@+id/serverSelectorFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.ServerSelectorFragment" >
|
||||
<action
|
||||
android:id="@+id/serverSelectorToEditServer"
|
||||
app:destination="@id/editServerFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/editServerFragment"
|
||||
android:name="org.moire.ultrasonic.fragment.EditServerFragment" />
|
||||
</navigation>
|
Loading…
x
Reference in New Issue
Block a user