mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 22:29:53 +01:00
Migrate BlogController to BlogViewModel
This commit is contained in:
@@ -1,48 +0,0 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
|
||||||
import org.briarproject.briar.android.controller.handler.ExceptionHandler;
|
|
||||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
|
||||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import androidx.annotation.UiThread;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
interface BaseController {
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
void onStart();
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
void onStop();
|
|
||||||
|
|
||||||
void loadBlogPosts(GroupId g,
|
|
||||||
ResultExceptionHandler<List<BlogPostItem>, DbException> handler);
|
|
||||||
|
|
||||||
void loadBlogPost(BlogPostHeader header,
|
|
||||||
ResultExceptionHandler<BlogPostItem, DbException> handler);
|
|
||||||
|
|
||||||
void loadBlogPost(GroupId g, MessageId m,
|
|
||||||
ResultExceptionHandler<BlogPostItem, DbException> handler);
|
|
||||||
|
|
||||||
void repeatPost(BlogPostItem item, @Nullable String comment,
|
|
||||||
ExceptionHandler<DbException> handler);
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
interface BlogListener {
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
void onBlogPostAdded(BlogPostHeader header, boolean local);
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
void onBlogRemoved();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,61 +1,28 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
|
||||||
import org.briarproject.briar.android.controller.DbControllerImpl;
|
import org.briarproject.briar.android.controller.DbControllerImpl;
|
||||||
import org.briarproject.briar.android.controller.handler.ExceptionHandler;
|
|
||||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.blog.Blog;
|
|
||||||
import org.briarproject.briar.api.blog.BlogCommentHeader;
|
|
||||||
import org.briarproject.briar.api.blog.BlogManager;
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
|
||||||
import org.briarproject.briar.util.HtmlUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import androidx.annotation.CallSuper;
|
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.now;
|
|
||||||
import static org.briarproject.briar.util.HtmlUtils.ARTICLE;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
abstract class BaseControllerImpl extends DbControllerImpl
|
abstract class BaseControllerImpl extends DbControllerImpl
|
||||||
implements BaseController, EventListener {
|
implements EventListener {
|
||||||
|
|
||||||
private static final Logger LOG =
|
|
||||||
Logger.getLogger(BaseControllerImpl.class.getName());
|
|
||||||
|
|
||||||
protected final EventBus eventBus;
|
protected final EventBus eventBus;
|
||||||
protected final AndroidNotificationManager notificationManager;
|
protected final AndroidNotificationManager notificationManager;
|
||||||
protected final IdentityManager identityManager;
|
protected final IdentityManager identityManager;
|
||||||
protected final BlogManager blogManager;
|
protected final BlogManager blogManager;
|
||||||
|
|
||||||
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
|
||||||
private final Map<MessageId, BlogPostHeader> headerCache =
|
|
||||||
new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
BaseControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
BaseControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||||
LifecycleManager lifecycleManager, EventBus eventBus,
|
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||||
AndroidNotificationManager notificationManager,
|
AndroidNotificationManager notificationManager,
|
||||||
@@ -67,144 +34,4 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
|||||||
this.blogManager = blogManager;
|
this.blogManager = blogManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@CallSuper
|
|
||||||
public void onStart() {
|
|
||||||
eventBus.addListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@CallSuper
|
|
||||||
public void onStop() {
|
|
||||||
eventBus.removeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadBlogPosts(GroupId groupId,
|
|
||||||
ResultExceptionHandler<List<BlogPostItem>, DbException> handler) {
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
List<BlogPostItem> items = loadItems(groupId);
|
|
||||||
handler.onResult(items);
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
handler.onException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
List<BlogPostItem> loadItems(GroupId groupId) throws DbException {
|
|
||||||
long start = now();
|
|
||||||
Collection<BlogPostHeader> headers =
|
|
||||||
blogManager.getPostHeaders(groupId);
|
|
||||||
logDuration(LOG, "Loading headers", start);
|
|
||||||
List<BlogPostItem> items = new ArrayList<>(headers.size());
|
|
||||||
start = now();
|
|
||||||
for (BlogPostHeader h : headers) {
|
|
||||||
headerCache.put(h.getId(), h);
|
|
||||||
BlogPostItem item = getItem(h);
|
|
||||||
items.add(item);
|
|
||||||
}
|
|
||||||
logDuration(LOG, "Loading bodies", start);
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadBlogPost(BlogPostHeader header,
|
|
||||||
ResultExceptionHandler<BlogPostItem, DbException> handler) {
|
|
||||||
|
|
||||||
String text = textCache.get(header.getId());
|
|
||||||
if (text != null) {
|
|
||||||
LOG.info("Loaded text from cache");
|
|
||||||
handler.onResult(new BlogPostItem(header, text));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
long start = now();
|
|
||||||
BlogPostItem item = getItem(header);
|
|
||||||
logDuration(LOG, "Loading text", start);
|
|
||||||
handler.onResult(item);
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
handler.onException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadBlogPost(GroupId g, MessageId m,
|
|
||||||
ResultExceptionHandler<BlogPostItem, DbException> handler) {
|
|
||||||
|
|
||||||
BlogPostHeader header = headerCache.get(m);
|
|
||||||
if (header != null) {
|
|
||||||
LOG.info("Loaded header from cache");
|
|
||||||
loadBlogPost(header, handler);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
long start = now();
|
|
||||||
BlogPostHeader header1 = getPostHeader(g, m);
|
|
||||||
BlogPostItem item = getItem(header1);
|
|
||||||
logDuration(LOG, "Loading post", start);
|
|
||||||
handler.onResult(item);
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
handler.onException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void repeatPost(BlogPostItem item, @Nullable String comment,
|
|
||||||
ExceptionHandler<DbException> handler) {
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
LocalAuthor a = identityManager.getLocalAuthor();
|
|
||||||
Blog b = blogManager.getPersonalBlog(a);
|
|
||||||
BlogPostHeader h = item.getHeader();
|
|
||||||
blogManager.addLocalComment(a, b.getId(), comment, h);
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
handler.onException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private BlogPostHeader getPostHeader(GroupId g, MessageId m)
|
|
||||||
throws DbException {
|
|
||||||
BlogPostHeader header = headerCache.get(m);
|
|
||||||
if (header == null) {
|
|
||||||
header = blogManager.getPostHeader(g, m);
|
|
||||||
headerCache.put(m, header);
|
|
||||||
}
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
@DatabaseExecutor
|
|
||||||
private BlogPostItem getItem(BlogPostHeader h) throws DbException {
|
|
||||||
String text;
|
|
||||||
if (h instanceof BlogCommentHeader) {
|
|
||||||
BlogCommentHeader c = (BlogCommentHeader) h;
|
|
||||||
BlogCommentItem item = new BlogCommentItem(c);
|
|
||||||
text = getPostText(item.getPostHeader().getId());
|
|
||||||
item.setText(text);
|
|
||||||
return item;
|
|
||||||
} else {
|
|
||||||
text = getPostText(h.getId());
|
|
||||||
return new BlogPostItem(h, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DatabaseExecutor
|
|
||||||
private String getPostText(MessageId m) throws DbException {
|
|
||||||
String text = textCache.get(m);
|
|
||||||
if (text == null) {
|
|
||||||
text = HtmlUtils.clean(blogManager.getPostText(m), ARTICLE);
|
|
||||||
textCache.put(m, text);
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.app.Application;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.NoSuchMessageException;
|
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.db.TransactionManager;
|
import org.briarproject.bramble.api.db.TransactionManager;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
@@ -19,6 +18,7 @@ import org.briarproject.bramble.api.sync.MessageId;
|
|||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.briar.android.viewmodel.DbViewModel;
|
import org.briarproject.briar.android.viewmodel.DbViewModel;
|
||||||
import org.briarproject.briar.android.viewmodel.LiveResult;
|
import org.briarproject.briar.android.viewmodel.LiveResult;
|
||||||
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.blog.Blog;
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
import org.briarproject.briar.api.blog.BlogCommentHeader;
|
import org.briarproject.briar.api.blog.BlogCommentHeader;
|
||||||
import org.briarproject.briar.api.blog.BlogManager;
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
@@ -26,6 +26,7 @@ import org.briarproject.briar.api.blog.BlogPostHeader;
|
|||||||
import org.briarproject.briar.util.HtmlUtils;
|
import org.briarproject.briar.util.HtmlUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@@ -35,11 +36,10 @@ import java.util.logging.Logger;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.annotation.UiThread;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.Transformations;
|
|
||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
@@ -50,20 +50,23 @@ import static org.briarproject.briar.util.HtmlUtils.ARTICLE;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class BaseViewModel extends DbViewModel implements EventListener {
|
public class BaseViewModel extends DbViewModel implements EventListener {
|
||||||
|
|
||||||
private static Logger LOG = getLogger(BaseViewModel.class.getName());
|
private static final Logger LOG = getLogger(BaseViewModel.class.getName());
|
||||||
|
|
||||||
protected final TransactionManager db;
|
protected final TransactionManager db;
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
protected final IdentityManager identityManager;
|
protected final IdentityManager identityManager;
|
||||||
|
protected final AndroidNotificationManager notificationManager;
|
||||||
protected final BlogManager blogManager;
|
protected final BlogManager blogManager;
|
||||||
|
|
||||||
protected final MutableLiveData<LiveResult<List<BlogPostItem>>> blogPosts =
|
private final MutableLiveData<LiveResult<List<BlogPostItem>>> blogPosts =
|
||||||
new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
|
|
||||||
// TODO do we still need those caches?
|
// TODO do we still need those caches?
|
||||||
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
||||||
private final Map<MessageId, BlogPostHeader> headerCache =
|
private final Map<MessageId, BlogPostHeader> headerCache =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
|
@Nullable
|
||||||
|
private Boolean postAddedWasLocal = null;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
BaseViewModel(Application application,
|
BaseViewModel(Application application,
|
||||||
@@ -73,11 +76,13 @@ public class BaseViewModel extends DbViewModel implements EventListener {
|
|||||||
AndroidExecutor androidExecutor,
|
AndroidExecutor androidExecutor,
|
||||||
EventBus eventBus,
|
EventBus eventBus,
|
||||||
IdentityManager identityManager,
|
IdentityManager identityManager,
|
||||||
|
AndroidNotificationManager notificationManager,
|
||||||
BlogManager blogManager) {
|
BlogManager blogManager) {
|
||||||
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
|
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.identityManager = identityManager;
|
this.identityManager = identityManager;
|
||||||
|
this.notificationManager = notificationManager;
|
||||||
this.blogManager = blogManager;
|
this.blogManager = blogManager;
|
||||||
|
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
@@ -93,10 +98,6 @@ public class BaseViewModel extends DbViewModel implements EventListener {
|
|||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadItems(GroupId groupId) {
|
|
||||||
loadList(txn -> loadBlogPosts(txn, groupId), blogPosts::setValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
protected List<BlogPostItem> loadBlogPosts(Transaction txn, GroupId groupId)
|
protected List<BlogPostItem> loadBlogPosts(Transaction txn, GroupId groupId)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -148,9 +149,9 @@ public class BaseViewModel extends DbViewModel implements EventListener {
|
|||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
BlogPostHeader header1 = getPostHeader(g, m);
|
BlogPostHeader header = getPostHeader(g, m);
|
||||||
BlogPostItem item = db.transactionWithResult(true, txn ->
|
BlogPostItem item = db.transactionWithResult(true, txn ->
|
||||||
getItem(txn, header1)
|
getItem(txn, header)
|
||||||
);
|
);
|
||||||
logDuration(LOG, "Loading post", start);
|
logDuration(LOG, "Loading post", start);
|
||||||
result.postValue(new LiveResult<>(item));
|
result.postValue(new LiveResult<>(item));
|
||||||
@@ -173,6 +174,31 @@ public class BaseViewModel extends DbViewModel implements EventListener {
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
protected void updateBlogPosts(LiveResult<List<BlogPostItem>> posts) {
|
||||||
|
blogPosts.setValue(posts);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onBlogPostAdded(BlogPostHeader header, boolean local) {
|
||||||
|
postAddedWasLocal = local;
|
||||||
|
runOnDbThread(() -> {
|
||||||
|
try {
|
||||||
|
db.transaction(true, txn -> {
|
||||||
|
BlogPostItem item = getItem(txn, header);
|
||||||
|
txn.attach(() -> {
|
||||||
|
List<BlogPostItem> items = addListItem(blogPosts, item);
|
||||||
|
if (items != null) {
|
||||||
|
Collections.sort(items);
|
||||||
|
blogPosts.setValue(new LiveResult<>(items));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void repeatPost(BlogPostItem item, @Nullable String comment) {
|
void repeatPost(BlogPostItem item, @Nullable String comment) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
@@ -186,34 +212,17 @@ public class BaseViewModel extends DbViewModel implements EventListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LiveData<LiveResult<List<BlogPostItem>>> getAllBlogPosts() {
|
LiveData<LiveResult<List<BlogPostItem>>> getBlogPosts() {
|
||||||
return blogPosts;
|
return blogPosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
LiveData<LiveResult<List<BlogPostItem>>> getBlogPosts(GroupId g) {
|
@UiThread
|
||||||
return Transformations.map(blogPosts, result -> {
|
@Nullable
|
||||||
List<BlogPostItem> allPosts = result.getResultOrNull();
|
Boolean getPostAddedWasLocalAndReset() {
|
||||||
if (allPosts == null) return result;
|
if (postAddedWasLocal == null) return null;
|
||||||
List<BlogPostItem> groupPosts = new ArrayList<>();
|
boolean wasLocal = postAddedWasLocal;
|
||||||
for (BlogPostItem item : allPosts) {
|
postAddedWasLocal = null;
|
||||||
if (item.getGroupId().equals(g)) groupPosts.add(item);
|
return wasLocal;
|
||||||
}
|
|
||||||
return new LiveResult<>(groupPosts);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
LiveData<LiveResult<BlogPostItem>> getBlogPost(MessageId m) {
|
|
||||||
return Transformations.map(blogPosts, result -> {
|
|
||||||
List<BlogPostItem> allPosts = result.getResultOrNull();
|
|
||||||
if (allPosts == null) {
|
|
||||||
Exception e = requireNonNull(result.getException());
|
|
||||||
return new LiveResult<>(e);
|
|
||||||
}
|
|
||||||
for (BlogPostItem item : allPosts) {
|
|
||||||
if (item.getId().equals(m)) return new LiveResult<>(item);
|
|
||||||
}
|
|
||||||
return new LiveResult<>(new NoSuchMessageException());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,15 +16,27 @@ import javax.annotation.Nullable;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class BlogActivity extends BriarActivity
|
public class BlogActivity extends BriarActivity
|
||||||
implements BaseFragmentListener {
|
implements BaseFragmentListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
@Inject
|
@Inject
|
||||||
BlogController blogController;
|
BlogController blogController;
|
||||||
|
|
||||||
|
private BlogViewModel viewModel;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectActivity(ActivityComponent component) {
|
||||||
|
component.inject(this);
|
||||||
|
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||||
|
.get(BlogViewModel.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
@@ -35,6 +47,7 @@ public class BlogActivity extends BriarActivity
|
|||||||
if (b == null) throw new IllegalStateException("No group ID in intent");
|
if (b == null) throw new IllegalStateException("No group ID in intent");
|
||||||
GroupId groupId = new GroupId(b);
|
GroupId groupId = new GroupId(b);
|
||||||
blogController.setGroupId(groupId);
|
blogController.setGroupId(groupId);
|
||||||
|
viewModel.setGroupId(groupId);
|
||||||
|
|
||||||
setContentView(R.layout.activity_fragment_container_toolbar);
|
setContentView(R.layout.activity_fragment_container_toolbar);
|
||||||
Toolbar toolbar = setUpCustomToolbar(false);
|
Toolbar toolbar = setUpCustomToolbar(false);
|
||||||
@@ -54,9 +67,4 @@ public class BlogActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void injectActivity(ActivityComponent component) {
|
|
||||||
component.inject(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,44 +4,16 @@ import org.briarproject.bramble.api.contact.ContactId;
|
|||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
|
||||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import androidx.annotation.UiThread;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public interface BlogController extends BaseController {
|
public interface BlogController {
|
||||||
|
|
||||||
void setGroupId(GroupId g);
|
void setGroupId(GroupId g);
|
||||||
|
|
||||||
@UiThread
|
|
||||||
void setBlogSharingListener(BlogSharingListener listener);
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
void unsetBlogSharingListener(BlogSharingListener listener);
|
|
||||||
|
|
||||||
void loadBlogPosts(
|
|
||||||
ResultExceptionHandler<List<BlogPostItem>, DbException> handler);
|
|
||||||
|
|
||||||
void loadBlogPost(MessageId m,
|
|
||||||
ResultExceptionHandler<BlogPostItem, DbException> handler);
|
|
||||||
|
|
||||||
void loadBlog(ResultExceptionHandler<BlogItem, DbException> handler);
|
|
||||||
|
|
||||||
void deleteBlog(ResultExceptionHandler<Void, DbException> handler);
|
|
||||||
|
|
||||||
void loadSharingContacts(
|
void loadSharingContacts(
|
||||||
ResultExceptionHandler<Collection<ContactId>, DbException> handler);
|
ResultExceptionHandler<Collection<ContactId>, DbException> handler);
|
||||||
|
|
||||||
interface BlogSharingListener extends BlogListener {
|
|
||||||
@UiThread
|
|
||||||
void onBlogInvitationAccepted(ContactId c);
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
void onBlogLeft(ContactId c);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,38 +10,25 @@ import org.briarproject.bramble.api.event.Event;
|
|||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
|
||||||
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
|
||||||
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
||||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.blog.Blog;
|
|
||||||
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
|
||||||
import org.briarproject.briar.api.blog.BlogManager;
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
import org.briarproject.briar.api.blog.BlogSharingManager;
|
import org.briarproject.briar.api.blog.BlogSharingManager;
|
||||||
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
|
|
||||||
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
|
||||||
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.LogUtils.now;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -53,10 +40,6 @@ class BlogControllerImpl extends BaseControllerImpl
|
|||||||
|
|
||||||
private final BlogSharingManager blogSharingManager;
|
private final BlogSharingManager blogSharingManager;
|
||||||
|
|
||||||
// UI thread
|
|
||||||
@Nullable
|
|
||||||
private BlogSharingListener listener;
|
|
||||||
|
|
||||||
private volatile GroupId groupId = null;
|
private volatile GroupId groupId = null;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -76,15 +59,10 @@ class BlogControllerImpl extends BaseControllerImpl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityStart() {
|
public void onActivityStart() {
|
||||||
super.onStart();
|
|
||||||
notificationManager.blockNotification(groupId);
|
|
||||||
notificationManager.clearBlogPostNotification(groupId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityStop() {
|
public void onActivityStop() {
|
||||||
super.onStop();
|
|
||||||
notificationManager.unblockNotification(groupId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -96,99 +74,9 @@ class BlogControllerImpl extends BaseControllerImpl
|
|||||||
groupId = g;
|
groupId = g;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlogSharingListener(BlogSharingListener listener) {
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unsetBlogSharingListener(BlogSharingListener listener) {
|
|
||||||
if (this.listener == listener) this.listener = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
if (groupId == null || listener == null)
|
|
||||||
throw new IllegalStateException();
|
|
||||||
if (e instanceof BlogPostAddedEvent) {
|
|
||||||
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
|
|
||||||
if (b.getGroupId().equals(groupId)) {
|
|
||||||
LOG.info("Blog post added");
|
|
||||||
listener.onBlogPostAdded(b.getHeader(), b.isLocal());
|
|
||||||
}
|
|
||||||
} else if (e instanceof BlogInvitationResponseReceivedEvent) {
|
|
||||||
BlogInvitationResponseReceivedEvent b =
|
|
||||||
(BlogInvitationResponseReceivedEvent) e;
|
|
||||||
BlogInvitationResponse r = b.getMessageHeader();
|
|
||||||
if (r.getShareableId().equals(groupId) && r.wasAccepted()) {
|
|
||||||
LOG.info("Blog invitation accepted");
|
|
||||||
listener.onBlogInvitationAccepted(b.getContactId());
|
|
||||||
}
|
|
||||||
} else if (e instanceof ContactLeftShareableEvent) {
|
|
||||||
ContactLeftShareableEvent s = (ContactLeftShareableEvent) e;
|
|
||||||
if (s.getGroupId().equals(groupId)) {
|
|
||||||
LOG.info("Blog left by contact");
|
|
||||||
listener.onBlogLeft(s.getContactId());
|
|
||||||
}
|
|
||||||
} else if (e instanceof GroupRemovedEvent) {
|
|
||||||
GroupRemovedEvent g = (GroupRemovedEvent) e;
|
|
||||||
if (g.getGroup().getId().equals(groupId)) {
|
|
||||||
LOG.info("Blog removed");
|
|
||||||
listener.onBlogRemoved();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadBlogPosts(
|
|
||||||
ResultExceptionHandler<List<BlogPostItem>, DbException> handler) {
|
|
||||||
if (groupId == null) throw new IllegalStateException();
|
|
||||||
loadBlogPosts(groupId, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadBlogPost(MessageId m,
|
|
||||||
ResultExceptionHandler<BlogPostItem, DbException> handler) {
|
|
||||||
if (groupId == null) throw new IllegalStateException();
|
|
||||||
loadBlogPost(groupId, m, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadBlog(
|
|
||||||
ResultExceptionHandler<BlogItem, DbException> handler) {
|
|
||||||
if (groupId == null) throw new IllegalStateException();
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
long start = now();
|
|
||||||
LocalAuthor a = identityManager.getLocalAuthor();
|
|
||||||
Blog b = blogManager.getBlog(groupId);
|
|
||||||
boolean ours = a.getId().equals(b.getAuthor().getId());
|
|
||||||
boolean removable = blogManager.canBeRemoved(b);
|
|
||||||
BlogItem blog = new BlogItem(b, ours, removable);
|
|
||||||
logDuration(LOG, "Loading blog", start);
|
|
||||||
handler.onResult(blog);
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
handler.onException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteBlog(ResultExceptionHandler<Void, DbException> handler) {
|
|
||||||
if (groupId == null) throw new IllegalStateException();
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
long start = now();
|
|
||||||
Blog b = blogManager.getBlog(groupId);
|
|
||||||
blogManager.removeBlog(b);
|
|
||||||
logDuration(LOG, "Removing blog", start);
|
|
||||||
handler.onResult(null);
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
handler.onException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
@@ -21,7 +20,6 @@ import org.briarproject.bramble.api.sync.GroupId;
|
|||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
import org.briarproject.briar.android.blog.BlogController.BlogSharingListener;
|
|
||||||
import org.briarproject.briar.android.controller.SharingController;
|
import org.briarproject.briar.android.controller.SharingController;
|
||||||
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
@@ -30,7 +28,6 @@ import org.briarproject.briar.android.sharing.ShareBlogActivity;
|
|||||||
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
||||||
import org.briarproject.briar.android.view.BriarRecyclerView;
|
import org.briarproject.briar.android.view.BriarRecyclerView;
|
||||||
import org.briarproject.briar.android.widget.LinkDialogFragment;
|
import org.briarproject.briar.android.widget.LinkDialogFragment;
|
||||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -41,6 +38,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView.LayoutManager;
|
import androidx.recyclerview.widget.RecyclerView.LayoutManager;
|
||||||
|
|
||||||
@@ -57,11 +55,12 @@ import static org.briarproject.briar.android.controller.SharingController.Sharin
|
|||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class BlogFragment extends BaseFragment
|
public class BlogFragment extends BaseFragment
|
||||||
implements BlogSharingListener, SharingListener,
|
implements SharingListener, OnBlogPostClickListener {
|
||||||
OnBlogPostClickListener {
|
|
||||||
|
|
||||||
private final static String TAG = BlogFragment.class.getName();
|
private final static String TAG = BlogFragment.class.getName();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
@Inject
|
@Inject
|
||||||
BlogController blogController;
|
BlogController blogController;
|
||||||
@Inject
|
@Inject
|
||||||
@@ -70,11 +69,10 @@ public class BlogFragment extends BaseFragment
|
|||||||
private Parcelable layoutManagerState;
|
private Parcelable layoutManagerState;
|
||||||
|
|
||||||
private GroupId groupId;
|
private GroupId groupId;
|
||||||
|
private BlogViewModel viewModel;
|
||||||
private final BlogPostAdapter adapter = new BlogPostAdapter(this);
|
private final BlogPostAdapter adapter = new BlogPostAdapter(this);
|
||||||
private LayoutManager layoutManager;
|
private LayoutManager layoutManager;
|
||||||
private BriarRecyclerView list;
|
private BriarRecyclerView list;
|
||||||
private MenuItem writeButton, deleteButton;
|
|
||||||
private boolean isMyBlog = false, canDeleteBlog = false;
|
|
||||||
|
|
||||||
static BlogFragment newInstance(GroupId groupId) {
|
static BlogFragment newInstance(GroupId groupId) {
|
||||||
BlogFragment f = new BlogFragment();
|
BlogFragment f = new BlogFragment();
|
||||||
@@ -89,7 +87,8 @@ public class BlogFragment extends BaseFragment
|
|||||||
@Override
|
@Override
|
||||||
public void injectFragment(ActivityComponent component) {
|
public void injectFragment(ActivityComponent component) {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
blogController.setBlogSharingListener(this);
|
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||||
|
.get(BlogViewModel.class);
|
||||||
sharingController.setSharingListener(this);
|
sharingController.setSharingListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +111,14 @@ public class BlogFragment extends BaseFragment
|
|||||||
list.showProgressBar();
|
list.showProgressBar();
|
||||||
list.setEmptyText(getString(R.string.blogs_other_blog_empty_state));
|
list.setEmptyText(getString(R.string.blogs_other_blog_empty_state));
|
||||||
|
|
||||||
|
viewModel.getBlogPosts().observe(getViewLifecycleOwner(), result ->
|
||||||
|
result.onError(this::handleException)
|
||||||
|
.onSuccess(this::onBlogPostsLoaded)
|
||||||
|
);
|
||||||
|
viewModel.getBlogRemoved().observe(getViewLifecycleOwner(), removed -> {
|
||||||
|
if (removed) finish();
|
||||||
|
});
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
layoutManagerState =
|
layoutManagerState =
|
||||||
savedInstanceState.getParcelable("layoutManager");
|
savedInstanceState.getParcelable("layoutManager");
|
||||||
@@ -123,16 +130,17 @@ public class BlogFragment extends BaseFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
viewModel.blockNotifications();
|
||||||
|
viewModel.clearBlogPostNotifications();
|
||||||
sharingController.onStart();
|
sharingController.onStart();
|
||||||
loadBlog();
|
|
||||||
loadSharedContacts();
|
loadSharedContacts();
|
||||||
loadBlogPosts(false);
|
|
||||||
list.startPeriodicUpdate();
|
list.startPeriodicUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
|
viewModel.unblockNotifications();
|
||||||
sharingController.onStop();
|
sharingController.onStop();
|
||||||
list.stopPeriodicUpdate();
|
list.stopPeriodicUpdate();
|
||||||
}
|
}
|
||||||
@@ -140,7 +148,6 @@ public class BlogFragment extends BaseFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
blogController.unsetBlogSharingListener(this);
|
|
||||||
sharingController.unsetSharingListener(this);
|
sharingController.unsetSharingListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,42 +163,43 @@ public class BlogFragment extends BaseFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.blogs_blog_actions, menu);
|
inflater.inflate(R.menu.blogs_blog_actions, menu);
|
||||||
writeButton = menu.findItem(R.id.action_write_blog_post);
|
MenuItem writeButton = menu.findItem(R.id.action_write_blog_post);
|
||||||
if (isMyBlog) writeButton.setVisible(true);
|
MenuItem deleteButton = menu.findItem(R.id.action_blog_delete);
|
||||||
deleteButton = menu.findItem(R.id.action_blog_delete);
|
viewModel.getBlog().observe(getViewLifecycleOwner(), blog -> {
|
||||||
if (canDeleteBlog) deleteButton.setEnabled(true);
|
setToolbarTitle(blog.getBlog().getAuthor());
|
||||||
|
if (blog.isOurs()) writeButton.setVisible(true);
|
||||||
|
if (blog.canBeRemoved()) deleteButton.setEnabled(true);
|
||||||
|
});
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
int itemId = item.getItemId();
|
||||||
case R.id.action_write_blog_post:
|
if (itemId == R.id.action_write_blog_post) {
|
||||||
Intent i = new Intent(getActivity(),
|
Intent i = new Intent(getActivity(),
|
||||||
WriteBlogPostActivity.class);
|
WriteBlogPostActivity.class);
|
||||||
i.putExtra(GROUP_ID, groupId.getBytes());
|
i.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
startActivityForResult(i, REQUEST_WRITE_BLOG_POST);
|
startActivityForResult(i, REQUEST_WRITE_BLOG_POST);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_blog_share:
|
} else if (itemId == R.id.action_blog_share) {
|
||||||
Intent i2 = new Intent(getActivity(), ShareBlogActivity.class);
|
Intent i2 = new Intent(getActivity(), ShareBlogActivity.class);
|
||||||
i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
i2.putExtra(GROUP_ID, groupId.getBytes());
|
i2.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
startActivityForResult(i2, REQUEST_SHARE_BLOG);
|
startActivityForResult(i2, REQUEST_SHARE_BLOG);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_blog_sharing_status:
|
} else if (itemId == R.id.action_blog_sharing_status) {
|
||||||
Intent i3 = new Intent(getActivity(),
|
Intent i3 = new Intent(getActivity(),
|
||||||
BlogSharingStatusActivity.class);
|
BlogSharingStatusActivity.class);
|
||||||
i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
i3.putExtra(GROUP_ID, groupId.getBytes());
|
i3.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
startActivity(i3);
|
startActivity(i3);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_blog_delete:
|
} else if (itemId == R.id.action_blog_delete) {
|
||||||
showDeleteDialog();
|
showDeleteDialog();
|
||||||
return true;
|
return true;
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -201,7 +209,7 @@ public class BlogFragment extends BaseFragment
|
|||||||
|
|
||||||
if (request == REQUEST_WRITE_BLOG_POST && result == RESULT_OK) {
|
if (request == REQUEST_WRITE_BLOG_POST && result == RESULT_OK) {
|
||||||
displaySnackbar(R.string.blogs_blog_post_created, true);
|
displaySnackbar(R.string.blogs_blog_post_created, true);
|
||||||
loadBlogPosts(true);
|
viewModel.loadBlogPosts(groupId);
|
||||||
} else if (request == REQUEST_SHARE_BLOG && result == RESULT_OK) {
|
} else if (request == REQUEST_SHARE_BLOG && result == RESULT_OK) {
|
||||||
displaySnackbar(R.string.blogs_sharing_snackbar, false);
|
displaySnackbar(R.string.blogs_sharing_snackbar, false);
|
||||||
}
|
}
|
||||||
@@ -212,30 +220,25 @@ public class BlogFragment extends BaseFragment
|
|||||||
return TAG;
|
return TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void onBlogPostsLoaded(List<BlogPostItem> items) {
|
||||||
public void onBlogPostAdded(BlogPostHeader header, boolean local) {
|
adapter.submitList(items, () -> {
|
||||||
blogController.loadBlogPost(header,
|
Boolean wasLocal = viewModel.getPostAddedWasLocalAndReset();
|
||||||
new UiResultExceptionHandler<BlogPostItem, DbException>(
|
if (wasLocal != null && wasLocal) {
|
||||||
this) {
|
list.scrollToPosition(0);
|
||||||
@Override
|
displaySnackbar(R.string.blogs_blog_post_created,
|
||||||
public void onResultUi(BlogPostItem post) {
|
false);
|
||||||
// adapter.add(post);
|
} else if (wasLocal != null) {
|
||||||
if (local) {
|
displaySnackbar(R.string.blogs_blog_post_received,
|
||||||
list.scrollToPosition(0);
|
true);
|
||||||
displaySnackbar(R.string.blogs_blog_post_created,
|
}
|
||||||
false);
|
list.showData();
|
||||||
} else {
|
if (layoutManagerState == null) {
|
||||||
displaySnackbar(R.string.blogs_blog_post_received,
|
list.scrollToPosition(0);
|
||||||
true);
|
} else {
|
||||||
}
|
layoutManager.onRestoreInstanceState(
|
||||||
}
|
layoutManagerState);
|
||||||
|
}
|
||||||
@Override
|
});
|
||||||
public void onExceptionUi(DbException exception) {
|
|
||||||
handleException(exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -262,53 +265,8 @@ public class BlogFragment extends BaseFragment
|
|||||||
f.show(getParentFragmentManager(), f.getUniqueTag());
|
f.show(getParentFragmentManager(), f.getUniqueTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadBlogPosts(boolean reload) {
|
|
||||||
blogController.loadBlogPosts(
|
|
||||||
new UiResultExceptionHandler<List<BlogPostItem>,
|
|
||||||
DbException>(this) {
|
|
||||||
@Override
|
|
||||||
public void onResultUi(List<BlogPostItem> posts) {
|
|
||||||
if (posts.isEmpty()) {
|
|
||||||
list.showData();
|
|
||||||
} else {
|
|
||||||
adapter.submitList(posts);
|
|
||||||
if (reload || layoutManagerState == null) {
|
|
||||||
list.scrollToPosition(0);
|
|
||||||
} else {
|
|
||||||
layoutManager.onRestoreInstanceState(
|
|
||||||
layoutManagerState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExceptionUi(DbException exception) {
|
|
||||||
handleException(exception);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadBlog() {
|
|
||||||
blogController.loadBlog(
|
|
||||||
new UiResultExceptionHandler<BlogItem, DbException>(this) {
|
|
||||||
@Override
|
|
||||||
public void onResultUi(BlogItem blog) {
|
|
||||||
setToolbarTitle(blog.getBlog().getAuthor());
|
|
||||||
if (blog.isOurs())
|
|
||||||
showWriteButton();
|
|
||||||
if (blog.canBeRemoved())
|
|
||||||
enableDeleteButton();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExceptionUi(DbException exception) {
|
|
||||||
handleException(exception);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setToolbarTitle(Author a) {
|
private void setToolbarTitle(Author a) {
|
||||||
getActivity().setTitle(a.getName());
|
requireActivity().setTitle(a.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSharedContacts() {
|
private void loadSharedContacts() {
|
||||||
@@ -329,20 +287,6 @@ public class BlogFragment extends BaseFragment
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBlogInvitationAccepted(ContactId c) {
|
|
||||||
sharingController.add(c);
|
|
||||||
setToolbarSubTitle(sharingController.getTotalCount(),
|
|
||||||
sharingController.getOnlineCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBlogLeft(ContactId c) {
|
|
||||||
sharingController.remove(c);
|
|
||||||
setToolbarSubTitle(sharingController.getTotalCount(),
|
|
||||||
sharingController.getOnlineCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharingInfoUpdated(int total, int online) {
|
public void onSharingInfoUpdated(int total, int online) {
|
||||||
setToolbarSubTitle(total, online);
|
setToolbarSubTitle(total, online);
|
||||||
@@ -350,25 +294,13 @@ public class BlogFragment extends BaseFragment
|
|||||||
|
|
||||||
private void setToolbarSubTitle(int total, int online) {
|
private void setToolbarSubTitle(int total, int online) {
|
||||||
ActionBar actionBar =
|
ActionBar actionBar =
|
||||||
((BriarActivity) getActivity()).getSupportActionBar();
|
((BriarActivity) requireActivity()).getSupportActionBar();
|
||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setSubtitle(
|
actionBar.setSubtitle(
|
||||||
getString(R.string.shared_with, total, online));
|
getString(R.string.shared_with, total, online));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showWriteButton() {
|
|
||||||
isMyBlog = true;
|
|
||||||
if (writeButton != null)
|
|
||||||
writeButton.setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableDeleteButton() {
|
|
||||||
canDeleteBlog = true;
|
|
||||||
if (deleteButton != null)
|
|
||||||
deleteButton.setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displaySnackbar(int stringId, boolean scroll) {
|
private void displaySnackbar(int stringId, boolean scroll) {
|
||||||
BriarSnackbarBuilder sb = new BriarSnackbarBuilder();
|
BriarSnackbarBuilder sb = new BriarSnackbarBuilder();
|
||||||
if (scroll) {
|
if (scroll) {
|
||||||
@@ -379,38 +311,21 @@ public class BlogFragment extends BaseFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showDeleteDialog() {
|
private void showDeleteDialog() {
|
||||||
DialogInterface.OnClickListener okListener =
|
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
|
||||||
(dialog, which) -> deleteBlog();
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),
|
|
||||||
R.style.BriarDialogTheme);
|
R.style.BriarDialogTheme);
|
||||||
builder.setTitle(getString(R.string.blogs_remove_blog));
|
builder.setTitle(getString(R.string.blogs_remove_blog));
|
||||||
builder.setMessage(
|
builder.setMessage(
|
||||||
getString(R.string.blogs_remove_blog_dialog_message));
|
getString(R.string.blogs_remove_blog_dialog_message));
|
||||||
builder.setPositiveButton(R.string.cancel, null);
|
builder.setPositiveButton(R.string.cancel, null);
|
||||||
builder.setNegativeButton(R.string.blogs_remove_blog_ok, okListener);
|
builder.setNegativeButton(R.string.blogs_remove_blog_ok,
|
||||||
|
(dialog, which) -> deleteBlog());
|
||||||
builder.show();
|
builder.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteBlog() {
|
private void deleteBlog() {
|
||||||
blogController.deleteBlog(
|
viewModel.deleteBlog();
|
||||||
new UiResultExceptionHandler<Void, DbException>(this) {
|
Toast.makeText(getActivity(), R.string.blogs_blog_removed, LENGTH_SHORT)
|
||||||
@Override
|
.show();
|
||||||
public void onResultUi(Void result) {
|
|
||||||
Toast.makeText(getActivity(),
|
|
||||||
R.string.blogs_blog_removed, LENGTH_SHORT)
|
|
||||||
.show();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExceptionUi(DbException exception) {
|
|
||||||
handleException(exception);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBlogRemoved() {
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ public class BlogModule {
|
|||||||
@IntoMap
|
@IntoMap
|
||||||
@ViewModelKey(FeedViewModel.class)
|
@ViewModelKey(FeedViewModel.class)
|
||||||
abstract ViewModel bindFeedViewModel(FeedViewModel feedViewModel);
|
abstract ViewModel bindFeedViewModel(FeedViewModel feedViewModel);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(BlogViewModel.class)
|
||||||
|
abstract ViewModel bindBlogViewModel(BlogViewModel blogViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
|
|||||||
@@ -1,30 +1,35 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.blog.BaseController.BlogListener;
|
|
||||||
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
|
||||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class BlogPostFragment extends BasePostFragment implements BlogListener {
|
public class BlogPostFragment extends BasePostFragment {
|
||||||
|
|
||||||
private static final String TAG = BlogPostFragment.class.getName();
|
private static final String TAG = BlogPostFragment.class.getName();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
@Inject
|
@Inject
|
||||||
BlogController blogController;
|
BlogController blogController;
|
||||||
|
|
||||||
|
private BlogViewModel viewModel;
|
||||||
|
|
||||||
static BlogPostFragment newInstance(MessageId postId) {
|
static BlogPostFragment newInstance(MessageId postId) {
|
||||||
BlogPostFragment f = new BlogPostFragment();
|
BlogPostFragment f = new BlogPostFragment();
|
||||||
|
|
||||||
@@ -35,42 +40,29 @@ public class BlogPostFragment extends BasePostFragment implements BlogListener {
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectFragment(ActivityComponent component) {
|
||||||
|
component.inject(this);
|
||||||
|
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||||
|
.get(BlogViewModel.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUniqueTag() {
|
public String getUniqueTag() {
|
||||||
return TAG;
|
return TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public void injectFragment(ActivityComponent component) {
|
public View onCreateView(LayoutInflater inflater,
|
||||||
component.inject(this);
|
@Nullable ViewGroup container,
|
||||||
}
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
View v = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
@Override
|
viewModel.loadBlogPost(postId).observe(getViewLifecycleOwner(), res ->
|
||||||
public void onStart() {
|
res.onError(this::handleException)
|
||||||
super.onStart();
|
.onSuccess(this::onBlogPostLoaded)
|
||||||
blogController.loadBlogPost(postId,
|
);
|
||||||
new UiResultExceptionHandler<BlogPostItem, DbException>(
|
return v;
|
||||||
this) {
|
|
||||||
@Override
|
|
||||||
public void onResultUi(BlogPostItem post) {
|
|
||||||
onBlogPostLoaded(post);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExceptionUi(DbException exception) {
|
|
||||||
handleException(exception);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBlogPostAdded(BlogPostHeader header, boolean local) {
|
|
||||||
// doesn't matter here
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBlogRemoved() {
|
|
||||||
finish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.TransactionManager;
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
||||||
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
|
import org.briarproject.briar.android.viewmodel.LiveResult;
|
||||||
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
|
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
||||||
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
|
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
||||||
|
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class BlogViewModel extends BaseViewModel {
|
||||||
|
|
||||||
|
private static final Logger LOG = getLogger(BlogViewModel.class.getName());
|
||||||
|
|
||||||
|
// implicitly non-null
|
||||||
|
private volatile GroupId groupId = null;
|
||||||
|
|
||||||
|
private final MutableLiveData<BlogItem> blog = new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> blogRemoved =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
BlogViewModel(Application application,
|
||||||
|
@DatabaseExecutor Executor dbExecutor,
|
||||||
|
LifecycleManager lifecycleManager,
|
||||||
|
TransactionManager db,
|
||||||
|
AndroidExecutor androidExecutor,
|
||||||
|
EventBus eventBus,
|
||||||
|
IdentityManager identityManager,
|
||||||
|
AndroidNotificationManager notificationManager,
|
||||||
|
BlogManager blogManager) {
|
||||||
|
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
|
||||||
|
eventBus, identityManager, notificationManager, blogManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventOccurred(Event e) {
|
||||||
|
if (e instanceof BlogPostAddedEvent) {
|
||||||
|
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
|
||||||
|
if (b.getGroupId().equals(groupId)) {
|
||||||
|
LOG.info("Blog post added");
|
||||||
|
onBlogPostAdded(b.getHeader(), b.isLocal());
|
||||||
|
}
|
||||||
|
} else if (e instanceof BlogInvitationResponseReceivedEvent) {
|
||||||
|
BlogInvitationResponseReceivedEvent b =
|
||||||
|
(BlogInvitationResponseReceivedEvent) e;
|
||||||
|
BlogInvitationResponse r = b.getMessageHeader();
|
||||||
|
if (r.getShareableId().equals(groupId) && r.wasAccepted()) {
|
||||||
|
LOG.info("Blog invitation accepted");
|
||||||
|
// TODO
|
||||||
|
// onBlogInvitationAccepted(b.getContactId());
|
||||||
|
// sharingController.add(c);
|
||||||
|
}
|
||||||
|
} else if (e instanceof ContactLeftShareableEvent) {
|
||||||
|
ContactLeftShareableEvent s = (ContactLeftShareableEvent) e;
|
||||||
|
if (s.getGroupId().equals(groupId)) {
|
||||||
|
LOG.info("Blog left by contact");
|
||||||
|
// TODO
|
||||||
|
// onBlogLeft(s.getContactId());
|
||||||
|
// sharingController.remove(c);
|
||||||
|
}
|
||||||
|
} else if (e instanceof GroupRemovedEvent) {
|
||||||
|
GroupRemovedEvent g = (GroupRemovedEvent) e;
|
||||||
|
if (g.getGroup().getId().equals(groupId)) {
|
||||||
|
LOG.info("Blog removed");
|
||||||
|
blogRemoved.setValue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this before calling any other methods.
|
||||||
|
*/
|
||||||
|
public void setGroupId(GroupId groupId) {
|
||||||
|
this.groupId = groupId;
|
||||||
|
loadBlog(groupId);
|
||||||
|
loadBlogPosts(groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadBlog(GroupId groupId) {
|
||||||
|
runOnDbThread(() -> {
|
||||||
|
try {
|
||||||
|
long start = now();
|
||||||
|
LocalAuthor a = identityManager.getLocalAuthor();
|
||||||
|
Blog b = blogManager.getBlog(groupId);
|
||||||
|
boolean ours = a.getId().equals(b.getAuthor().getId());
|
||||||
|
boolean removable = blogManager.canBeRemoved(b);
|
||||||
|
blog.postValue(new BlogItem(b, ours, removable));
|
||||||
|
logDuration(LOG, "Loading blog", start);
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void blockNotifications() {
|
||||||
|
notificationManager.blockNotification(groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearBlogPostNotifications() {
|
||||||
|
notificationManager.clearBlogPostNotification(groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unblockNotifications() {
|
||||||
|
notificationManager.unblockNotification(groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadBlogPosts(GroupId groupId) {
|
||||||
|
loadList(txn -> loadBlogPosts(txn, groupId), this::updateBlogPosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteBlog() {
|
||||||
|
runOnDbThread(() -> {
|
||||||
|
try {
|
||||||
|
long start = now();
|
||||||
|
Blog b = blogManager.getBlog(groupId);
|
||||||
|
blogManager.removeBlog(b);
|
||||||
|
logDuration(LOG, "Removing blog", start);
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<LiveResult<BlogPostItem>> loadBlogPost(MessageId m) {
|
||||||
|
return loadBlogPost(groupId, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<BlogItem> getBlog() {
|
||||||
|
return blog;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> getBlogRemoved() {
|
||||||
|
return blogRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -63,8 +63,7 @@ public class FeedFragment extends BaseFragment
|
|||||||
@Override
|
@Override
|
||||||
public void injectFragment(ActivityComponent component) {
|
public void injectFragment(ActivityComponent component) {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
// TODO don't use NavDrawerActivity scope here
|
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||||
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
|
||||||
.get(FeedViewModel.class);
|
.get(FeedViewModel.class);
|
||||||
// TODO ideally we only do this once when the ViewModel gets created
|
// TODO ideally we only do this once when the ViewModel gets created
|
||||||
viewModel.loadPersonalBlog();
|
viewModel.loadPersonalBlog();
|
||||||
@@ -88,7 +87,7 @@ public class FeedFragment extends BaseFragment
|
|||||||
list.setEmptyText(R.string.blogs_feed_empty_state);
|
list.setEmptyText(R.string.blogs_feed_empty_state);
|
||||||
list.setEmptyAction(R.string.blogs_feed_empty_state_action);
|
list.setEmptyAction(R.string.blogs_feed_empty_state_action);
|
||||||
|
|
||||||
viewModel.getAllBlogPosts().observe(getViewLifecycleOwner(), result ->
|
viewModel.getBlogPosts().observe(getViewLifecycleOwner(), result ->
|
||||||
result
|
result
|
||||||
.onError(this::handleException)
|
.onError(this::handleException)
|
||||||
.onSuccess(this::onBlogPostsLoaded)
|
.onSuccess(this::onBlogPostsLoaded)
|
||||||
@@ -135,6 +134,7 @@ public class FeedFragment extends BaseFragment
|
|||||||
} else if (wasLocal != null) {
|
} else if (wasLocal != null) {
|
||||||
showSnackBar(R.string.blogs_blog_post_received);
|
showSnackBar(R.string.blogs_blog_post_received);
|
||||||
}
|
}
|
||||||
|
list.showData();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,9 @@ import org.briarproject.bramble.api.sync.GroupId;
|
|||||||
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
|
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
|
||||||
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.briar.android.viewmodel.LiveResult;
|
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.blog.Blog;
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
import org.briarproject.briar.api.blog.BlogManager;
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
|
||||||
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -30,10 +28,8 @@ import java.util.List;
|
|||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.UiThread;
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
@@ -49,11 +45,7 @@ class FeedViewModel extends BaseViewModel {
|
|||||||
|
|
||||||
private static final Logger LOG = getLogger(FeedViewModel.class.getName());
|
private static final Logger LOG = getLogger(FeedViewModel.class.getName());
|
||||||
|
|
||||||
protected final AndroidNotificationManager notificationManager;
|
|
||||||
|
|
||||||
private final MutableLiveData<Blog> personalBlog = new MutableLiveData<>();
|
private final MutableLiveData<Blog> personalBlog = new MutableLiveData<>();
|
||||||
@Nullable
|
|
||||||
private Boolean postAddedWasLocal = null;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FeedViewModel(Application application,
|
FeedViewModel(Application application,
|
||||||
@@ -63,11 +55,10 @@ class FeedViewModel extends BaseViewModel {
|
|||||||
AndroidExecutor androidExecutor,
|
AndroidExecutor androidExecutor,
|
||||||
EventBus eventBus,
|
EventBus eventBus,
|
||||||
IdentityManager identityManager,
|
IdentityManager identityManager,
|
||||||
BlogManager blogManager,
|
AndroidNotificationManager notificationManager,
|
||||||
AndroidNotificationManager notificationManager) {
|
BlogManager blogManager) {
|
||||||
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
|
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
|
||||||
eventBus, identityManager, blogManager);
|
eventBus, identityManager, notificationManager, blogManager);
|
||||||
this.notificationManager = notificationManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -122,7 +113,7 @@ class FeedViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loadAllBlogPosts() {
|
void loadAllBlogPosts() {
|
||||||
loadList(this::loadAllBlogPosts, blogPosts::setValue);
|
loadList(this::loadAllBlogPosts, this::updateBlogPosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -142,33 +133,4 @@ class FeedViewModel extends BaseViewModel {
|
|||||||
return posts;
|
return posts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBlogPostAdded(BlogPostHeader header, boolean local) {
|
|
||||||
postAddedWasLocal = local;
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
db.transaction(true, txn -> {
|
|
||||||
BlogPostItem item = getItem(txn, header);
|
|
||||||
txn.attach(() -> {
|
|
||||||
List<BlogPostItem> items = addListItem(blogPosts, item);
|
|
||||||
if (items != null) {
|
|
||||||
Collections.sort(items);
|
|
||||||
blogPosts.setValue(new LiveResult<>(items));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
@Nullable
|
|
||||||
Boolean getPostAddedWasLocalAndReset() {
|
|
||||||
if (postAddedWasLocal == null) return null;
|
|
||||||
boolean wasLocal = postAddedWasLocal;
|
|
||||||
postAddedWasLocal = null;
|
|
||||||
return wasLocal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user