Add MessagesActivity
This commit is contained in:
@@ -0,0 +1,107 @@
|
|||||||
|
package com.github.gotify.messages;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.github.gotify.R;
|
||||||
|
import com.github.gotify.Utils;
|
||||||
|
import com.github.gotify.client.model.Message;
|
||||||
|
import com.github.gotify.messages.provider.MessageWithImage;
|
||||||
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
public class ListMessageAdapter extends BaseAdapter {
|
||||||
|
|
||||||
|
private Context content;
|
||||||
|
private List<MessageWithImage> items;
|
||||||
|
private Delete delete;
|
||||||
|
|
||||||
|
ListMessageAdapter(Context context, List<MessageWithImage> items, Delete delete) {
|
||||||
|
super();
|
||||||
|
this.content = context;
|
||||||
|
this.items = items;
|
||||||
|
this.delete = delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
void items(List<MessageWithImage> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageWithImage getItem(int position) {
|
||||||
|
return items.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return getItem(position).message.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
final View view;
|
||||||
|
if (convertView == null) {
|
||||||
|
view = LayoutInflater.from(content).inflate(R.layout.message_item, parent, false);
|
||||||
|
} else {
|
||||||
|
view = convertView;
|
||||||
|
}
|
||||||
|
ViewHolder holder = new ViewHolder(view);
|
||||||
|
final MessageWithImage message = items.get(position);
|
||||||
|
holder.message.setText(message.message.getMessage());
|
||||||
|
holder.title.setText(message.message.getTitle());
|
||||||
|
Picasso.get()
|
||||||
|
.load(message.image)
|
||||||
|
.error(R.drawable.ic_alarm)
|
||||||
|
.placeholder(R.drawable.ic_placeholder)
|
||||||
|
.into(holder.image);
|
||||||
|
holder.date.setText(
|
||||||
|
message.message.getDate() != null
|
||||||
|
? Utils.dateToRelative(message.message.getDate())
|
||||||
|
: "?");
|
||||||
|
holder.delete.setOnClickListener((ignored) -> delete.delete(message.message));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
@BindView(R.id.message_image)
|
||||||
|
ImageView image;
|
||||||
|
|
||||||
|
@BindView(R.id.message_text)
|
||||||
|
TextView message;
|
||||||
|
|
||||||
|
@BindView(R.id.message_title)
|
||||||
|
TextView title;
|
||||||
|
|
||||||
|
@BindView(R.id.message_date)
|
||||||
|
TextView date;
|
||||||
|
|
||||||
|
@BindView(R.id.message_delete)
|
||||||
|
ImageButton delete;
|
||||||
|
|
||||||
|
ViewHolder(final View view) {
|
||||||
|
super(view);
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Delete {
|
||||||
|
void delete(Message message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,457 @@
|
|||||||
|
package com.github.gotify.messages;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AbsListView;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.github.gotify.MissedMessageUtil;
|
||||||
|
import com.github.gotify.R;
|
||||||
|
import com.github.gotify.Settings;
|
||||||
|
import com.github.gotify.Utils;
|
||||||
|
import com.github.gotify.api.ClientFactory;
|
||||||
|
import com.github.gotify.client.ApiClient;
|
||||||
|
import com.github.gotify.client.ApiException;
|
||||||
|
import com.github.gotify.client.api.MessageApi;
|
||||||
|
import com.github.gotify.client.api.TokenApi;
|
||||||
|
import com.github.gotify.client.model.Application;
|
||||||
|
import com.github.gotify.client.model.Client;
|
||||||
|
import com.github.gotify.client.model.Message;
|
||||||
|
import com.github.gotify.init.InitializationActivity;
|
||||||
|
import com.github.gotify.log.Log;
|
||||||
|
import com.github.gotify.log.LogsActivity;
|
||||||
|
import com.github.gotify.login.LoginActivity;
|
||||||
|
import com.github.gotify.messages.provider.ApplicationHolder;
|
||||||
|
import com.github.gotify.messages.provider.MessageFacade;
|
||||||
|
import com.github.gotify.messages.provider.MessageState;
|
||||||
|
import com.github.gotify.messages.provider.MessageWithImage;
|
||||||
|
import com.github.gotify.service.WebSocketService;
|
||||||
|
import com.google.android.material.navigation.NavigationView;
|
||||||
|
import com.squareup.okhttp.HttpUrl;
|
||||||
|
import com.squareup.picasso.Picasso;
|
||||||
|
import com.squareup.picasso.Target;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.core.view.GravityCompat;
|
||||||
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
|
||||||
|
public class MessagesActivity extends AppCompatActivity
|
||||||
|
implements NavigationView.OnNavigationItemSelectedListener, AbsListView.OnScrollListener {
|
||||||
|
|
||||||
|
private BroadcastReceiver receiver =
|
||||||
|
new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String messageJson = intent.getStringExtra("message");
|
||||||
|
Message message = Utils.json().deserialize(messageJson, Message.class);
|
||||||
|
new NewSingleMessage().execute(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private int APPLICATION_ORDER = 1;
|
||||||
|
|
||||||
|
@BindView(R.id.toolbar)
|
||||||
|
Toolbar toolbar;
|
||||||
|
|
||||||
|
@BindView(R.id.drawer_layout)
|
||||||
|
DrawerLayout drawer;
|
||||||
|
|
||||||
|
@BindView(R.id.nav_view)
|
||||||
|
NavigationView navigationView;
|
||||||
|
|
||||||
|
@BindView(R.id.messages_view)
|
||||||
|
ListView messagesView;
|
||||||
|
|
||||||
|
@BindView(R.id.swipe_refresh)
|
||||||
|
SwipeRefreshLayout swipeRefreshLayout;
|
||||||
|
|
||||||
|
private MessageFacade messages;
|
||||||
|
|
||||||
|
private ApiClient client;
|
||||||
|
private Settings settings;
|
||||||
|
protected ApplicationHolder appsHolder;
|
||||||
|
|
||||||
|
private int appId = MessageState.ALL_MESSAGES;
|
||||||
|
|
||||||
|
private boolean isLoadMore = false;
|
||||||
|
private Integer selectAppIdOnDrawerClose = null;
|
||||||
|
|
||||||
|
// we need to keep the target references otherwise they get gc'ed before they can be called.
|
||||||
|
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||||
|
private final List<Target> targetReferences = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_messages);
|
||||||
|
ButterKnife.bind(this);
|
||||||
|
Log.i("Entering " + getClass().getSimpleName());
|
||||||
|
settings = new Settings(this);
|
||||||
|
|
||||||
|
client = ClientFactory.clientToken(settings.url(), settings.token());
|
||||||
|
appsHolder = new ApplicationHolder(this, client);
|
||||||
|
appsHolder.onUpdate(() -> onUpdateApps(appsHolder.get()));
|
||||||
|
appsHolder.request();
|
||||||
|
initDrawer();
|
||||||
|
|
||||||
|
messages = new MessageFacade(new MessageApi(client), appsHolder);
|
||||||
|
|
||||||
|
messagesView.setOnScrollListener(this);
|
||||||
|
messagesView.setAdapter(new ListMessageAdapter(this, emptyList(), this::delete));
|
||||||
|
|
||||||
|
swipeRefreshLayout.setOnRefreshListener(this::onRefresh);
|
||||||
|
drawer.addDrawerListener(
|
||||||
|
new DrawerLayout.SimpleDrawerListener() {
|
||||||
|
@Override
|
||||||
|
public void onDrawerClosed(View drawerView) {
|
||||||
|
if (selectAppIdOnDrawerClose != null) {
|
||||||
|
appId = selectAppIdOnDrawerClose;
|
||||||
|
new SelectApplicationAndUpdateMessages(true)
|
||||||
|
.execute(selectAppIdOnDrawerClose);
|
||||||
|
selectAppIdOnDrawerClose = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
new SelectApplicationAndUpdateMessages(true).execute(appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRefreshAll(View view) {
|
||||||
|
startActivity(new Intent(this, InitializationActivity.class));
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onRefresh() {
|
||||||
|
messages.clear();
|
||||||
|
new LoadMore().execute(appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(Message message) {
|
||||||
|
new DeleteMessage().execute(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onUpdateApps(List<Application> applications) {
|
||||||
|
Menu menu = navigationView.getMenu();
|
||||||
|
menu.removeGroup(R.id.apps);
|
||||||
|
targetReferences.clear();
|
||||||
|
updateMessagesAndStopLoading(messages.get(appId));
|
||||||
|
for (Application app : applications) {
|
||||||
|
MenuItem item = menu.add(R.id.apps, app.getId(), APPLICATION_ORDER, app.getName());
|
||||||
|
item.setCheckable(true);
|
||||||
|
Target t = Utils.toDrawable(getResources(), item::setIcon);
|
||||||
|
targetReferences.add(t);
|
||||||
|
Picasso.get()
|
||||||
|
.load(app.getImage())
|
||||||
|
.error(R.drawable.ic_alarm)
|
||||||
|
.placeholder(R.drawable.ic_placeholder)
|
||||||
|
.resize(100, 100)
|
||||||
|
.into(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDrawer() {
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
navigationView.setItemIconTintList(null);
|
||||||
|
ActionBarDrawerToggle toggle =
|
||||||
|
new ActionBarDrawerToggle(
|
||||||
|
this,
|
||||||
|
drawer,
|
||||||
|
toolbar,
|
||||||
|
R.string.navigation_drawer_open,
|
||||||
|
R.string.navigation_drawer_close);
|
||||||
|
drawer.addDrawerListener(toggle);
|
||||||
|
toggle.syncState();
|
||||||
|
|
||||||
|
navigationView.setNavigationItemSelectedListener(this);
|
||||||
|
View headerView = navigationView.getHeaderView(0);
|
||||||
|
TextView header = headerView.findViewById(R.id.header_username);
|
||||||
|
String host = HttpUrl.parse(settings.url()).host();
|
||||||
|
header.setText(getString(R.string.connection, settings.user().getName(), host));
|
||||||
|
|
||||||
|
TextView version = headerView.findViewById(R.id.header_versions);
|
||||||
|
version.setText(getString(R.string.server_version, settings.serverVersion()));
|
||||||
|
ImageButton refreshAll = headerView.findViewById(R.id.refresh_all);
|
||||||
|
refreshAll.setOnClickListener(this::onRefreshAll);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||||
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
|
} else {
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
|
@Override
|
||||||
|
public boolean onNavigationItemSelected(MenuItem item) {
|
||||||
|
// Handle navigation view item clicks here.
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
if (item.getGroupId() == R.id.apps) {
|
||||||
|
selectAppIdOnDrawerClose = id;
|
||||||
|
startLoading();
|
||||||
|
toolbar.setSubtitle(item.getTitle());
|
||||||
|
} else if (id == R.id.nav_all_messages) {
|
||||||
|
selectAppIdOnDrawerClose = MessageState.ALL_MESSAGES;
|
||||||
|
startLoading();
|
||||||
|
toolbar.setSubtitle("");
|
||||||
|
} else if (id == R.id.logout) {
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.logout)
|
||||||
|
.setMessage(getString(R.string.logout_confirm))
|
||||||
|
.setPositiveButton(R.string.yes, this::doLogout)
|
||||||
|
.setNegativeButton(R.string.cancel, (a, b) -> {})
|
||||||
|
.show();
|
||||||
|
} else if (id == R.id.nav_logs) {
|
||||||
|
startActivity(new Intent(this, LogsActivity.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doLogout(DialogInterface dialog, int which) {
|
||||||
|
setContentView(R.layout.splash);
|
||||||
|
new DeleteClientAndNavigateToLogin().execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLoading() {
|
||||||
|
swipeRefreshLayout.setRefreshing(true);
|
||||||
|
messagesView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopLoading() {
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
messagesView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(WebSocketService.NEW_MESSAGE_BROADCAST);
|
||||||
|
registerReceiver(receiver, filter);
|
||||||
|
new UpdateMissedMessages().execute(messages.getLastReceivedMessage());
|
||||||
|
navigationView
|
||||||
|
.getMenu()
|
||||||
|
.findItem(appId == MessageState.ALL_MESSAGES ? R.id.nav_all_messages : appId)
|
||||||
|
.setChecked(true);
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
unregisterReceiver(receiver);
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScrollStateChanged(AbsListView view, int scrollState) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScroll(
|
||||||
|
AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||||
|
if (firstVisibleItem + visibleItemCount > totalItemCount - 15
|
||||||
|
&& totalItemCount != 0
|
||||||
|
&& messages.canLoadMore(appId)) {
|
||||||
|
if (!isLoadMore) {
|
||||||
|
isLoadMore = true;
|
||||||
|
new LoadMore().execute(appId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UpdateMissedMessages extends AsyncTask<Integer, Void, Boolean> {
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(Integer... ids) {
|
||||||
|
Integer id = first(ids);
|
||||||
|
if (id == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Message> newMessages = new MissedMessageUtil(client).missingMessages(id);
|
||||||
|
messages.addMessages(newMessages);
|
||||||
|
return !newMessages.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean update) {
|
||||||
|
if (update) {
|
||||||
|
new SelectApplicationAndUpdateMessages(true).execute(appId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.messages_action, menu);
|
||||||
|
return super.onCreateOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
if (item.getItemId() == R.id.action_delete_all) {
|
||||||
|
new DeleteMessages().execute(appId);
|
||||||
|
}
|
||||||
|
return super.onContextItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LoadMore extends AsyncTask<Integer, Void, List<MessageWithImage>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<MessageWithImage> doInBackground(Integer... appId) {
|
||||||
|
return messages.loadMore(first(appId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(List<MessageWithImage> messageWithImages) {
|
||||||
|
updateMessagesAndStopLoading(messageWithImages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SelectApplicationAndUpdateMessages
|
||||||
|
extends AsyncTask<Integer, Void, List<MessageWithImage>> {
|
||||||
|
|
||||||
|
private SelectApplicationAndUpdateMessages(boolean withLoadingSpinner) {
|
||||||
|
if (withLoadingSpinner) {
|
||||||
|
startLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<MessageWithImage> doInBackground(Integer... appIds) {
|
||||||
|
return messages.getOrLoadMore(appIds[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(List<MessageWithImage> messageWithImages) {
|
||||||
|
updateMessagesAndStopLoading(messageWithImages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NewSingleMessage extends AsyncTask<Message, Void, Void> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Message... newMessages) {
|
||||||
|
messages.addMessages(Arrays.asList(newMessages));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void data) {
|
||||||
|
new SelectApplicationAndUpdateMessages(false).execute(appId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeleteMessage extends AsyncTask<Message, Void, Void> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Message... messages) {
|
||||||
|
MessagesActivity.this.messages.delete(first(messages));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void data) {
|
||||||
|
new SelectApplicationAndUpdateMessages(false).execute(appId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeleteMessages extends AsyncTask<Integer, Void, Boolean> {
|
||||||
|
|
||||||
|
DeleteMessages() {
|
||||||
|
startLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(Integer... appId) {
|
||||||
|
return messages.deleteAll(first(appId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean success) {
|
||||||
|
if (!success) {
|
||||||
|
Utils.showSnackBar(MessagesActivity.this, "Delete failed :(");
|
||||||
|
}
|
||||||
|
new SelectApplicationAndUpdateMessages(false).execute(appId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeleteClientAndNavigateToLogin extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... ignore) {
|
||||||
|
TokenApi api =
|
||||||
|
new TokenApi(ClientFactory.clientToken(settings.url(), settings.token()));
|
||||||
|
stopService(new Intent(MessagesActivity.this, WebSocketService.class));
|
||||||
|
try {
|
||||||
|
List<Client> clients = api.getClients();
|
||||||
|
|
||||||
|
Client currentClient = null;
|
||||||
|
for (Client client : clients) {
|
||||||
|
if (client.getToken().equals(settings.token())) {
|
||||||
|
currentClient = client;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentClient != null) {
|
||||||
|
Log.i("Delete client with id " + currentClient.getId());
|
||||||
|
api.deleteClient(currentClient.getId());
|
||||||
|
} else {
|
||||||
|
Log.e("Could not delete client, client does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (ApiException e) {
|
||||||
|
Log.e("Could not delete client", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
settings.clear();
|
||||||
|
startActivity(new Intent(MessagesActivity.this, LoginActivity.class));
|
||||||
|
finish();
|
||||||
|
super.onPostExecute(aVoid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateMessagesAndStopLoading(List<MessageWithImage> messageWithImages) {
|
||||||
|
isLoadMore = false;
|
||||||
|
stopLoading();
|
||||||
|
ListMessageAdapter adapter = (ListMessageAdapter) messagesView.getAdapter();
|
||||||
|
adapter.items(messageWithImages);
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T first(T[] data) {
|
||||||
|
if (data.length != 1) {
|
||||||
|
throw new IllegalArgumentException("must be one element");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
43
app/src/main/res/layout/activity_messages.xml
Normal file
43
app/src/main/res/layout/activity_messages.xml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/drawer_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
tools:openDrawer="start">
|
||||||
|
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipe_refresh"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/messages_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/app_bar_drawer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.navigation.NavigationView
|
||||||
|
android:id="@+id/nav_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="start"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
app:headerLayout="@layout/nav_header_drawer"
|
||||||
|
app:menu="@menu/messages_menu" />
|
||||||
|
|
||||||
|
</androidx.drawerlayout.widget.DrawerLayout>
|
||||||
18
app/src/main/res/layout/app_bar_drawer.xml
Normal file
18
app/src/main/res/layout/app_bar_drawer.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.google.android.material.appbar.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="@style/AppTheme.AppBarOverlay"
|
||||||
|
tools:context=".messages.MessagesActivity">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
65
app/src/main/res/layout/message_item.xml
Normal file
65
app/src/main/res/layout/message_item.xml
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="75dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="5dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/message_date"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:text=""
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/message_delete"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/message_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="23dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:maxLength="30"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text=""
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/message_image"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/message_image"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:contentDescription="@string/message_image_desc"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/message_text"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/message_image"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/message_title" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/message_delete"
|
||||||
|
style="@style/Widget.AppCompat.Button.Borderless"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:contentDescription="@string/delete_message"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/ic_delete" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
59
app/src/main/res/layout/nav_header_drawer.xml
Normal file
59
app/src/main/res/layout/nav_header_drawer.xml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/nav_header_height"
|
||||||
|
android:layout_alignParentBottom="false"
|
||||||
|
android:background="@drawable/side_nav_bar"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.Dark">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="83dp"
|
||||||
|
android:layout_height="75dp"
|
||||||
|
android:contentDescription="@string/nav_header_desc"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/header_versions"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:srcCompat="@drawable/gotify" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/header_versions"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||||
|
android:text="Gotify v1.0.0"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/header_username"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/header_username"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="admin@your.domain.de"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/refresh_all"
|
||||||
|
style="@style/Widget.AppCompat.Button.Borderless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:contentDescription="@string/refresh_all"
|
||||||
|
android:scaleType="fitEnd"
|
||||||
|
android:tint="@android:color/white"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/imageView"
|
||||||
|
app:srcCompat="@drawable/ic_refresh" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
6
app/src/main/res/menu/messages_action.xml
Normal file
6
app/src/main/res/menu/messages_action.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
<item
|
||||||
|
android:title="@string/delete_all"
|
||||||
|
android:id="@+id/action_delete_all"
|
||||||
|
android:orderInCategory="100"/>
|
||||||
|
</menu>
|
||||||
30
app/src/main/res/menu/messages_menu.xml
Normal file
30
app/src/main/res/menu/messages_menu.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:showIn="navigation_view">
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
<item
|
||||||
|
android:orderInCategory="0"
|
||||||
|
android:icon="@drawable/ic_dashboard"
|
||||||
|
android:id="@+id/nav_all_messages"
|
||||||
|
android:title="@string/all_messages" />
|
||||||
|
</group>
|
||||||
|
<group
|
||||||
|
android:id="@+id/apps"
|
||||||
|
android:checkableBehavior="single">
|
||||||
|
|
||||||
|
</group>
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
<item
|
||||||
|
android:icon="@drawable/ic_power_setting"
|
||||||
|
android:orderInCategory="2"
|
||||||
|
android:id="@+id/logout"
|
||||||
|
android:title="@string/logout" />
|
||||||
|
<item
|
||||||
|
android:orderInCategory="2"
|
||||||
|
android:icon="@drawable/ic_bug_report"
|
||||||
|
android:id="@+id/nav_logs"
|
||||||
|
android:title="@string/logs" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</menu>
|
||||||
Reference in New Issue
Block a user