Add state holder for message activity

This commit is contained in:
Jannis Mattheis
2018-11-02 14:04:48 +01:00
parent 907d11cdbc
commit ec78979011
7 changed files with 326 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
package com.github.gotify.messages.provider;
import android.app.Activity;
import com.github.gotify.Utils;
import com.github.gotify.api.Api;
import com.github.gotify.client.ApiClient;
import com.github.gotify.client.ApiException;
import com.github.gotify.client.api.TokenApi;
import com.github.gotify.client.model.Application;
import java.util.Collections;
import java.util.List;
public class ApplicationHolder {
private List<Application> state;
private Runnable onUpdate;
private Activity activity;
private ApiClient client;
public ApplicationHolder(Activity activity, ApiClient client) {
this.activity = activity;
this.client = client;
}
public void requestIfMissing() {
if (state == null) {
request();
}
}
public void request() {
TokenApi tokenApi = new TokenApi(client);
Api.withLogging(tokenApi::getAppsAsync)
.handleInUIThread(activity, this::onReceiveApps, this::onFailedApps);
}
private void onReceiveApps(List<Application> apps) {
state = apps;
onUpdate.run();
}
private void onFailedApps(ApiException e) {
Utils.showSnackBar(activity, "Could not request applications, see logs.");
}
public List<Application> get() {
return state == null ? Collections.emptyList() : state;
}
public void onUpdate(Runnable runnable) {
this.onUpdate = runnable;
}
}

View File

@@ -0,0 +1,71 @@
package com.github.gotify.messages.provider;
import com.github.gotify.client.api.MessageApi;
import com.github.gotify.client.model.Message;
import com.github.gotify.client.model.PagedMessages;
import java.util.List;
public class MessageFacade {
private final ApplicationHolder applicationHolder;
private final MessageRequester requester;
private final MessageStateHolder state;
private final MessageImageCombiner combiner;
public MessageFacade(MessageApi api, ApplicationHolder applicationHolder) {
this.applicationHolder = applicationHolder;
this.requester = new MessageRequester(api);
this.combiner = new MessageImageCombiner();
this.state = new MessageStateHolder();
}
public List<MessageWithImage> get(Integer appId) {
return combiner.combine(state.state(appId).messages, applicationHolder.get());
}
public void addMessages(List<Message> messages) {
for (Message message : messages) {
state.newMessage(message);
}
}
public List<MessageWithImage> loadMore(Integer appId) {
MessageState state = this.state.state(appId);
if (state.hasNext || !state.loaded) {
PagedMessages pagedMessages = requester.loadMore(state);
this.state.newMessages(appId, pagedMessages);
}
return get(appId);
}
public List<MessageWithImage> getOrLoadMore(Integer appId) {
MessageState state = this.state.state(appId);
if (state.loaded) {
return get(appId);
}
return loadMore(appId);
}
public void clear() {
this.state.clear();
}
public int getLastReceivedMessage() {
return state.getLastReceivedMessage();
}
public void delete(Message message) {
this.requester.asyncRemoveMessage(message);
this.state.removeMessage(message);
}
public boolean deleteAll(Integer appId) {
boolean success = this.requester.deleteAll(appId);
this.state.deleteAll(appId);
return success;
}
public boolean canLoadMore(Integer appId) {
return state.state(appId).hasNext;
}
}

View File

@@ -0,0 +1,37 @@
package com.github.gotify.messages.provider;
import com.github.gotify.client.model.Application;
import com.github.gotify.client.model.Message;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class MessageImageCombiner {
List<MessageWithImage> combine(List<Message> messages, List<Application> applications) {
Map<Integer, String> appIdToImage = appIdToImage(applications);
List<MessageWithImage> result = new ArrayList<>();
for (Message message : messages) {
MessageWithImage messageWithImage = new MessageWithImage();
messageWithImage.message = message;
messageWithImage.image = appIdToImage.get(message.getAppid());
result.add(messageWithImage);
}
return result;
}
private Map<Integer, String> appIdToImage(List<Application> applications) {
Map<Integer, String> map = new HashMap<>();
for (Application app : applications) {
map.put(app.getId(), app.getImage());
}
return map;
}
}

View File

@@ -0,0 +1,52 @@
package com.github.gotify.messages.provider;
import com.github.gotify.api.Api;
import com.github.gotify.client.ApiException;
import com.github.gotify.client.api.MessageApi;
import com.github.gotify.client.model.Message;
import com.github.gotify.client.model.PagedMessages;
import com.github.gotify.log.Log;
class MessageRequester {
private static final Integer LIMIT = 100;
private MessageApi messageApi;
MessageRequester(MessageApi messageApi) {
this.messageApi = messageApi;
}
PagedMessages loadMore(MessageState state) {
try {
Log.i("Loading more messages for " + state.appId);
if (MessageState.ALL_MESSAGES == state.appId) {
return messageApi.getMessages(LIMIT, state.nextSince);
} else {
return messageApi.getAppMessages(state.appId, LIMIT, state.nextSince);
}
} catch (ApiException apiException) {
Log.e("failed requesting messages", apiException);
return null;
}
}
void asyncRemoveMessage(Message message) {
Log.i("Removing message with id " + message.getId());
Api.<Void>withLogging((cb) -> messageApi.deleteMessageAsync(message.getId(), cb))
.handle((a) -> {}, (e) -> {});
}
boolean deleteAll(Integer appId) {
try {
Log.i("Deleting all messages for " + appId);
if (MessageState.ALL_MESSAGES == appId) {
messageApi.deleteMessages();
} else {
messageApi.deleteAppMessages(appId);
}
return true;
} catch (ApiException e) {
Log.e("Could not delete messages", e);
return false;
}
}
}

View File

@@ -0,0 +1,16 @@
package com.github.gotify.messages.provider;
import com.github.gotify.client.model.Message;
import java.util.ArrayList;
import java.util.List;
public class MessageState {
public static final int ALL_MESSAGES = -1;
int appId;
boolean loaded;
boolean hasNext;
int nextSince = 0;
List<Message> messages = new ArrayList<>();
}

View File

@@ -0,0 +1,88 @@
package com.github.gotify.messages.provider;
import com.github.gotify.client.model.Message;
import com.github.gotify.client.model.PagedMessages;
import java.util.HashMap;
import java.util.Map;
class MessageStateHolder {
private int lastReceivedMessage = -1;
private Map<Integer, MessageState> states = new HashMap<>();
synchronized void clear() {
states = new HashMap<>();
}
synchronized void newMessages(Integer appId, PagedMessages pagedMessages) {
MessageState state = state(appId);
if (!state.loaded && pagedMessages.getMessages().size() > 0) {
lastReceivedMessage =
Math.max(pagedMessages.getMessages().get(0).getId(), lastReceivedMessage);
}
state.loaded = true;
state.messages.addAll(pagedMessages.getMessages());
state.hasNext = pagedMessages.getPaging().getNext() != null;
state.nextSince = pagedMessages.getPaging().getSince();
state.appId = appId;
states.put(appId, state);
}
synchronized void newMessage(Message message) {
MessageState allMessages = state(MessageState.ALL_MESSAGES);
MessageState appMessages = state(message.getAppid());
if (allMessages.loaded) {
allMessages.messages.add(0, message);
}
if (appMessages.loaded) {
appMessages.messages.add(0, message);
}
lastReceivedMessage = message.getId();
}
synchronized MessageState state(Integer appId) {
MessageState state = states.get(appId);
if (state == null) {
return emptyState(appId);
}
return state;
}
void deleteAll(Integer appId) {
clear();
MessageState state = state(appId);
state.loaded = true;
states.put(appId, state);
}
private MessageState emptyState(Integer appId) {
MessageState emptyState = new MessageState();
emptyState.loaded = false;
emptyState.hasNext = false;
emptyState.nextSince = 0;
emptyState.appId = appId;
return emptyState;
}
synchronized int getLastReceivedMessage() {
return lastReceivedMessage;
}
void removeMessage(Message message) {
MessageState allMessages = state(MessageState.ALL_MESSAGES);
MessageState appMessages = state(message.getAppid());
if (allMessages.loaded) {
allMessages.messages.remove(message);
}
if (appMessages.loaded) {
appMessages.messages.remove(message);
}
}
}

View File

@@ -0,0 +1,8 @@
package com.github.gotify.messages.provider;
import com.github.gotify.client.model.Message;
public class MessageWithImage {
public Message message;
public String image;
}