mirror of
https://github.com/badaix/snapcast.git
synced 2025-04-29 18:27:12 +02:00
undo delete client
This commit is contained in:
parent
d014e79ad0
commit
dd020b0b6d
8 changed files with 133 additions and 85 deletions
|
@ -41,10 +41,7 @@ public class ClientInfoItem extends LinearLayout implements SeekBar.OnSeekBarCha
|
|||
}
|
||||
|
||||
private void update() {
|
||||
if (!clientInfo.getName().isEmpty())
|
||||
title.setText(clientInfo.getName());
|
||||
else
|
||||
title.setText(clientInfo.getHost());
|
||||
title.setText(clientInfo.getVisibleName());
|
||||
title.setEnabled(clientInfo.isConnected());
|
||||
volumeSeekBar.setProgress(clientInfo.getVolume().getPercent());
|
||||
if (clientInfo.getVolume().isMuted())
|
||||
|
|
|
@ -5,8 +5,6 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
import android.net.nsd.NsdManager;
|
||||
|
@ -14,6 +12,9 @@ import android.net.nsd.NsdServiceInfo;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.Snackbar.Callback;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
|
@ -26,7 +27,6 @@ import android.widget.CheckBox;
|
|||
import android.widget.CompoundButton;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.appindexing.Action;
|
||||
import com.google.android.gms.appindexing.AppIndex;
|
||||
|
@ -40,9 +40,6 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
|
||||
private static final String TAG = "Main";
|
||||
boolean bound = false;
|
||||
private TextView tvInfo;
|
||||
private CheckBox cbScreenWakelock;
|
||||
private ListView lvClient;
|
||||
private MenuItem miStartStop = null;
|
||||
private NsdManager.DiscoveryListener mDiscoveryListener;
|
||||
private NsdManager mNsdManager = null;
|
||||
|
@ -82,8 +79,8 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
tvInfo = (TextView) findViewById(R.id.tvInfo);
|
||||
cbScreenWakelock = (CheckBox) findViewById(R.id.cbScreenWakelock);
|
||||
TextView tvInfo = (TextView) findViewById(R.id.tvInfo);
|
||||
CheckBox cbScreenWakelock = (CheckBox) findViewById(R.id.cbScreenWakelock);
|
||||
cbScreenWakelock.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
|
||||
|
@ -94,8 +91,6 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
}
|
||||
});
|
||||
|
||||
lvClient = (ListView) findViewById(R.id.lvClient);
|
||||
|
||||
AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
String rate = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
|
||||
|
@ -104,6 +99,7 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
}
|
||||
|
||||
clientInfoAdapter = new ClientInfoAdapter(this, this);
|
||||
ListView lvClient = (ListView) findViewById(R.id.lvClient);
|
||||
lvClient.setAdapter(clientInfoAdapter);
|
||||
getSupportActionBar().setSubtitle("Host: no Snapserver found");
|
||||
|
||||
|
@ -175,6 +171,7 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
i.putExtra(SnapclientService.EXTRA_HOST, host);
|
||||
i.putExtra(SnapclientService.EXTRA_PORT, port);
|
||||
i.setAction(SnapclientService.ACTION_START);
|
||||
|
||||
startService(i);
|
||||
}
|
||||
|
@ -209,7 +206,9 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
MainActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getSupportActionBar().setSubtitle(text);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null)
|
||||
actionBar.setSubtitle(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -361,9 +360,31 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onDeleteClicked(ClientInfoItem clientInfoItem) {
|
||||
remoteControl.delete(clientInfoItem.getClientInfo());
|
||||
clientInfoAdapter.removeClient(clientInfoItem.getClientInfo());
|
||||
public void onDeleteClicked(final ClientInfoItem clientInfoItem) {
|
||||
final ClientInfo clientInfo = clientInfoItem.getClientInfo();
|
||||
clientInfo.setDeleted(true);
|
||||
clientInfoAdapter.update();
|
||||
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout),
|
||||
getString(R.string.client_deleted, clientInfo.getVisibleName()),
|
||||
Snackbar.LENGTH_SHORT);
|
||||
mySnackbar.setAction(R.string.undo_string, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clientInfo.setDeleted(false);
|
||||
clientInfoAdapter.update();
|
||||
}
|
||||
});
|
||||
mySnackbar.setCallback(new Callback() {
|
||||
@Override
|
||||
public void onDismissed(Snackbar snackbar, int event) {
|
||||
super.onDismissed(snackbar, event);
|
||||
if (event != DISMISS_EVENT_ACTION) {
|
||||
remoteControl.delete(clientInfo);
|
||||
clientInfoAdapter.removeClient(clientInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
mySnackbar.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -409,7 +430,7 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
|
||||
@Override
|
||||
public void onServerInfo(RemoteControl remoteControl, ServerInfo serverInfo) {
|
||||
clientInfoAdapter.update(serverInfo);
|
||||
clientInfoAdapter.updateServer(serverInfo);
|
||||
}
|
||||
|
||||
private class ClientInfoAdapter extends ArrayAdapter<ClientInfo> {
|
||||
|
@ -440,29 +461,36 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
return clientInfoItem;
|
||||
}
|
||||
|
||||
public void updateClient(final ClientInfo clientInfo) {
|
||||
if (serverInfo.addClient(clientInfo))
|
||||
update(null);
|
||||
}
|
||||
|
||||
public void removeClient(final ClientInfo clientInfo) {
|
||||
Log.d(TAG, "removeClient: " + clientInfo.getMac());
|
||||
if (serverInfo.removeClient(clientInfo)) {
|
||||
if ((clientInfo != null) && serverInfo.removeClient(clientInfo)) {
|
||||
Log.d(TAG, "removeClient 1: " + clientInfo.getMac());
|
||||
update(null);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(final ServerInfo serverInfo) {
|
||||
if (serverInfo != null)
|
||||
public void updateClient(final ClientInfo clientInfo) {
|
||||
Log.d(TAG, "updateClient: " + clientInfo.getHost() + " " + clientInfo.isDeleted());
|
||||
if (serverInfo.updateClient(clientInfo)) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateServer(final ServerInfo serverInfo) {
|
||||
if (serverInfo != null) {
|
||||
ClientInfoAdapter.this.serverInfo = serverInfo;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void update() {
|
||||
|
||||
MainActivity.this.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clear();
|
||||
for (ClientInfo clientInfo : ClientInfoAdapter.this.serverInfo.getClientInfos()) {
|
||||
if ((clientInfo != null) && (!hideOffline || clientInfo.isConnected()))
|
||||
if ((clientInfo != null) && (!hideOffline || clientInfo.isConnected()) && !clientInfo.isDeleted())
|
||||
add(clientInfo);
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
|
@ -478,7 +506,7 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl
|
|||
if (this.hideOffline == hideOffline)
|
||||
return;
|
||||
this.hideOffline = hideOffline;
|
||||
update(null);
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import android.os.Looper;
|
|||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
|
@ -32,6 +31,8 @@ public class SnapclientService extends Service {
|
|||
|
||||
public static final String EXTRA_HOST = "EXTRA_HOST";
|
||||
public static final String EXTRA_PORT = "EXTRA_PORT";
|
||||
public static final String ACTION_START = "ACTION_START";
|
||||
public static final String ACTION_STOP = "ACTION_STOP";
|
||||
private final IBinder mBinder = new LocalBinder();
|
||||
private java.lang.Process process = null;
|
||||
private PowerManager.WakeLock wakeLock = null;
|
||||
|
@ -50,57 +51,57 @@ public class SnapclientService extends Service {
|
|||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
if (intent.getAction() == "ACTION_STOP") {
|
||||
if (intent == null)
|
||||
return START_NOT_STICKY;
|
||||
|
||||
if (intent.getAction() == ACTION_STOP) {
|
||||
stopService();
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
|
||||
} else if (intent.getAction() == ACTION_START) {
|
||||
Intent stopIntent = new Intent(this, SnapclientService.class);
|
||||
stopIntent.setAction(ACTION_STOP);
|
||||
PendingIntent piStop = PendingIntent.getService(this, 0, stopIntent, 0);
|
||||
|
||||
Intent stopIntent = new Intent(this, SnapclientService.class);
|
||||
stopIntent.setAction("ACTION_STOP");
|
||||
PendingIntent piStop = PendingIntent.getService(this, 0, stopIntent, 0);
|
||||
NotificationCompat.Builder builder =
|
||||
new NotificationCompat.Builder(this)
|
||||
.setSmallIcon(R.drawable.ic_media_play)
|
||||
.setTicker(getText(R.string.ticker_text))
|
||||
.setContentTitle(getText(R.string.notification_title))
|
||||
.setContentText(getText(R.string.notification_text))
|
||||
.setContentInfo(getText(R.string.notification_info))
|
||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(getText(R.string.notification_text)))
|
||||
.addAction(R.drawable.ic_media_stop, getString(R.string.stop), piStop);
|
||||
|
||||
NotificationCompat.Builder builder =
|
||||
new NotificationCompat.Builder(this)
|
||||
.setSmallIcon(R.drawable.ic_media_play)
|
||||
.setTicker(getText(R.string.ticker_text))
|
||||
.setContentTitle(getText(R.string.notification_title))
|
||||
.setContentText(getText(R.string.notification_text))
|
||||
.setContentInfo(getText(R.string.notification_info))
|
||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(getText(R.string.notification_text)))
|
||||
.addAction(R.drawable.ic_media_stop, getString(R.string.stop), piStop);
|
||||
Intent resultIntent = new Intent(this, MainActivity.class);
|
||||
|
||||
Intent resultIntent = new Intent(this, MainActivity.class);
|
||||
|
||||
// The stack builder object will contain an artificial back stack for the
|
||||
// started Activity.
|
||||
// This ensures that navigating backward from the Activity leads out of
|
||||
// your application to the Home screen.
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
|
||||
// Adds the back stack for the Intent (but not the Intent itself)
|
||||
stackBuilder.addParentStack(MainActivity.class);
|
||||
// Adds the Intent that starts the Activity to the top of the stack
|
||||
stackBuilder.addNextIntent(resultIntent);
|
||||
PendingIntent resultPendingIntent =
|
||||
stackBuilder.getPendingIntent(
|
||||
0,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
builder.setContentIntent(resultPendingIntent);
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
// mId allows you to update the notification later on.
|
||||
final Notification notification = builder.build();
|
||||
// The stack builder object will contain an artificial back stack for the
|
||||
// started Activity.
|
||||
// This ensures that navigating backward from the Activity leads out of
|
||||
// your application to the Home screen.
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
|
||||
// Adds the back stack for the Intent (but not the Intent itself)
|
||||
stackBuilder.addParentStack(MainActivity.class);
|
||||
// Adds the Intent that starts the Activity to the top of the stack
|
||||
stackBuilder.addNextIntent(resultIntent);
|
||||
PendingIntent resultPendingIntent =
|
||||
stackBuilder.getPendingIntent(
|
||||
0,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
builder.setContentIntent(resultPendingIntent);
|
||||
NotificationManager mNotificationManager =
|
||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
// mId allows you to update the notification later on.
|
||||
final Notification notification = builder.build();
|
||||
// mNotificationManager.notify(123, notification);
|
||||
startForeground(123, notification);
|
||||
startForeground(123, notification);
|
||||
|
||||
|
||||
String host = intent.getStringExtra(EXTRA_HOST);
|
||||
int port = intent.getIntExtra(EXTRA_PORT, 1704);
|
||||
start(host, port);
|
||||
|
||||
// If we get killed, after returning from here, restart
|
||||
return START_STICKY;
|
||||
String host = intent.getStringExtra(EXTRA_HOST);
|
||||
int port = intent.getIntExtra(EXTRA_PORT, 1704);
|
||||
start(host, port);
|
||||
return START_STICKY;
|
||||
}
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,7 @@ public class ClientInfo implements JsonSerialisable {
|
|||
private Time_t lastSeen;
|
||||
private boolean connected;
|
||||
private int latency = 0;
|
||||
private boolean deleted = false;
|
||||
|
||||
public ClientInfo(JSONObject json) {
|
||||
fromJson(json);
|
||||
|
@ -114,6 +115,12 @@ public class ClientInfo implements JsonSerialisable {
|
|||
return name;
|
||||
}
|
||||
|
||||
public String getVisibleName() {
|
||||
if ((name != null) && !name.isEmpty())
|
||||
return name;
|
||||
return getHost();
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -134,6 +141,14 @@ public class ClientInfo implements JsonSerialisable {
|
|||
this.connected = connected;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClientInfo{" +
|
||||
|
@ -157,6 +172,7 @@ public class ClientInfo implements JsonSerialisable {
|
|||
ClientInfo that = (ClientInfo) o;
|
||||
|
||||
if (connected != that.connected) return false;
|
||||
if (deleted != that.deleted) return false;
|
||||
if (latency != that.latency) return false;
|
||||
if (mac != null ? !mac.equals(that.mac) : that.mac != null) return false;
|
||||
if (ip != null ? !ip.equals(that.ip) : that.ip != null) return false;
|
||||
|
@ -176,6 +192,7 @@ public class ClientInfo implements JsonSerialisable {
|
|||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
result = 31 * result + (volume != null ? volume.hashCode() : 0);
|
||||
result = 31 * result + (connected ? 1 : 0);
|
||||
result = 31 * result + (deleted ? 1 : 0);
|
||||
result = 31 * result + latency;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public class RemoteControl implements TcpClient.TcpClientListener {
|
|||
JSONArray clients = json.getJSONObject("result").getJSONArray("clients");
|
||||
for (int i = 0; i < clients.length(); i++) {
|
||||
final ClientInfo clientInfo = new ClientInfo(clients.getJSONObject(i));
|
||||
serverInfo.addClient(clientInfo);
|
||||
serverInfo.updateClient(clientInfo);
|
||||
}
|
||||
if (listener != null)
|
||||
listener.onServerInfo(this, serverInfo);
|
||||
|
|
|
@ -26,7 +26,7 @@ public class ServerInfo {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean addClient(ClientInfo client) {
|
||||
public boolean updateClient(ClientInfo client) {
|
||||
if (client == null)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/myCoordinatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
tools:context="de.badaix.snapcast.MainActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
@ -14,7 +12,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_centerHorizontal="true">
|
||||
android:layout_centerHorizontal="true"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -48,4 +50,5 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
||||
|
|
|
@ -26,5 +26,7 @@
|
|||
<string name="client_latency">Latency</string>
|
||||
<string name="online">online</string>
|
||||
<string name="action_play_stop">Play/Stop</string>
|
||||
<string name="client_deleted">Client %1$s deleted</string>
|
||||
<string name="undo_string">undo</string>
|
||||
</resources>
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue