Unverified Commit 6d7e0aab authored by Torsten Grote's avatar Torsten Grote Committed by akwizgran

Reblogging and Comment UI

parent da080724
......@@ -32,7 +32,6 @@ import org.briarproject.lifecycle.LifecycleModule;
import org.briarproject.properties.PropertiesModule;
import org.briarproject.sync.SyncModule;
import org.briarproject.transport.TransportModule;
import org.briarproject.util.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
......@@ -60,7 +59,6 @@ import static org.briarproject.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.api.sync.ValidationManager.State.INVALID;
import static org.briarproject.api.sync.ValidationManager.State.PENDING;
import static org.briarproject.api.sync.ValidationManager.State.VALID;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
......@@ -193,8 +191,7 @@ public class BlogManagerTest {
assertEquals(1, headers0.size());
// check that body is there
assertArrayEquals(StringUtils.toUtf8(body),
blogManager0.getPostBody(p.getMessage().getId()));
assertEquals(body, blogManager0.getPostBody(p.getMessage().getId()));
// make sure that blog0 at author1 doesn't have the post yet
Collection<BlogPostHeader> headers1 =
......@@ -211,8 +208,7 @@ public class BlogManagerTest {
assertEquals(POST, headers1.iterator().next().getType());
// check that body is there
assertArrayEquals(StringUtils.toUtf8(body),
blogManager1.getPostBody(p.getMessage().getId()));
assertEquals(body, blogManager1.getPostBody(p.getMessage().getId()));
stopLifecycles();
}
......@@ -334,8 +330,7 @@ public class BlogManagerTest {
assertEquals(author0, h.getParent().getAuthor());
// ensure that body can be retrieved from wrapped post
assertArrayEquals(StringUtils.toUtf8(body),
blogManager0.getPostBody(h.getParentId()));
assertEquals(body, blogManager0.getPostBody(h.getParentId()));
// 1 has only their own comment in their blog
headers1 = blogManager1.getPostHeaders(blog1.getId());
......@@ -375,6 +370,13 @@ public class BlogManagerTest {
Collection<BlogPostHeader> headers1 =
blogManager1.getPostHeaders(blog0.getId());
assertEquals(2, headers1.size());
for (BlogPostHeader h : headers1) {
if (h.getType() == POST) {
assertEquals(body, blogManager1.getPostBody(h.getId()));
} else {
assertEquals(comment, ((BlogCommentHeader)h).getComment());
}
}
stopLifecycles();
}
......
......@@ -211,6 +211,17 @@
/>
</activity>
<activity
android:name=".android.blogs.ReblogActivity"
android:label="@string/blogs_reblog_button"
android:parentActivityName=".android.blogs.BlogActivity"
android:windowSoftInputMode="stateHidden">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.blogs.BlogActivity"
/>
</activity>
<activity
android:name=".android.blogs.RssFeedImportActivity"
android:label="@string/blogs_rss_feeds_import"
......
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="@dimen/unread_bubble_size"/>
<solid
android:color="@color/briar_text_primary_inverse"/>
<stroke
android:color="@color/briar_text_primary"
android:width="1dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/introductionContainer"
android:id="@+id/fragmentContainer"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
\ No newline at end of file
......@@ -7,11 +7,25 @@
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/avatar"
style="@style/BriarAvatar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_width="@dimen/blogs_avatar_normal_size"
android:layout_height="@dimen/blogs_avatar_normal_size"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/margin_medium"
tools:src="@drawable/ic_launcher"/>
<ImageView
android:id="@+id/avatarIcon"
android:layout_width="@dimen/blogs_avatar_icon_size"
android:layout_height="@dimen/blogs_avatar_icon_size"
android:layout_alignBottom="@+id/avatar"
android:layout_alignRight="@+id/avatar"
android:background="@drawable/bubble_white"
android:padding="2dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_repeat"
android:visibility="invisible"
tools:ignore="ContentDescription"/>
<TextView
android:id="@+id/authorName"
android:layout_width="wrap_content"
......@@ -20,7 +34,7 @@
android:layout_toEndOf="@+id/avatar"
android:layout_toRightOf="@+id/avatar"
android:textColor="@color/briar_text_primary"
android:textSize="@dimen/text_size_tiny"
android:textSize="@dimen/text_size_small"
tools:text="Author Name"/>
<org.briarproject.android.util.TrustIndicatorView
......@@ -42,7 +56,7 @@
android:layout_toEndOf="@+id/avatar"
android:layout_toRightOf="@+id/avatar"
android:gravity="bottom"
android:textColor="@color/briar_text_primary"
android:textColor="@color/briar_text_secondary"
android:textSize="@dimen/text_size_tiny"
tools:text="yesterday"/>
......
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:id="@+id/scrollView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/window_background">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/margin_small">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
<include
android:id="@+id/postLayout"
layout="@layout/list_item_blog_post"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="@+id/inputText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/postLayout"
android:layout_margin="@dimen/listitem_vertical_margin"
android:gravity="bottom"
android:hint="@string/blogs_reblog_comment_hint"
android:inputType="textShortMessage|textMultiLine|textCapSentences|textAutoCorrect"/>
<Button
android:id="@+id/publishButton"
style="@style/BriarButton"
android:layout_below="@+id/inputText"
android:enabled="false"
android:text="@string/blogs_reblog_button"/>
</RelativeLayout>
</ScrollView>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:showIn="@layout/list_item_blog_post">
<View
android:id="@+id/inputDivider"
style="@style/Divider.Horizontal"/>
<org.briarproject.android.util.AuthorView
android:id="@+id/authorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:padding="@dimen/listitem_vertical_margin"
app:persona="commenter"/>
<TextView
android:id="@+id/bodyView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/authorView"
android:paddingBottom="@dimen/listitem_vertical_margin"
android:paddingLeft="@dimen/listitem_vertical_margin"
android:paddingRight="@dimen/listitem_vertical_margin"
android:textColor="@color/briar_text_secondary"
android:textIsSelectable="true"
android:textSize="@dimen/text_size_small"
tools:text="This is a comment that appears below a blog post. Usually, it is expected to be rather short. Not much longer than this one."/>
</RelativeLayout>
......@@ -2,41 +2,77 @@
<android.support.v7.widget.CardView
style="@style/BriarCard"
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">
<RelativeLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical">
<org.briarproject.android.util.AuthorView
android:id="@+id/authorView"
android:layout_width="wrap_content"
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="@dimen/listitem_vertical_margin"
android:layout_toLeftOf="@+id/commentView"/>
<ImageView
android:id="@+id/commentView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:padding="@dimen/margin_small"
android:src="@drawable/ic_repeat"/>
<TextView
android:id="@+id/bodyView"
android:layout_width="wrap_content"
android:padding="@dimen/listitem_vertical_margin">
<org.briarproject.android.util.AuthorView
android:id="@+id/rebloggerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="@dimen/listitem_horizontal_margin"
android:layout_toLeftOf="@+id/commentView"
app:persona="reblogger"/>
<org.briarproject.android.util.AuthorView
android:id="@+id/authorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/rebloggerView"
android:layout_marginBottom="@dimen/listitem_vertical_margin"
android:layout_toLeftOf="@+id/commentView"/>
<ImageView
android:id="@+id/commentView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:contentDescription="@string/blogs_reblog_comment_hint"
android:padding="@dimen/margin_small"
android:src="@drawable/ic_repeat"/>
<TextView
android:id="@+id/bodyView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/authorView"
android:textColor="@color/briar_text_secondary"
android:textIsSelectable="true"
android:textSize="@dimen/text_size_medium"
tools:text="This is a body text that shows the content of a blog post.\n\nThis one is not short, but it is also not too long."/>
</RelativeLayout>
<LinearLayout
android:id="@+id/commentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/authorView"
android:textColor="@color/briar_text_secondary"
android:textSize="@dimen/text_size_medium"
tools:text="This is a body text that shows the content of a blog post.\n\nThis one is not short, but it is also not too long."/>
android:orientation="vertical">
<include
layout="@layout/list_item_blog_comment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
\ No newline at end of file
</android.support.v7.widget.CardView>
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/action_write_blog_post"
android:icon="@drawable/forum_item_create_white"
android:title="@string/blogs_write_blog_post"
android:visible="false"
app:showAsAction="ifRoom"
tools:visible="true"/>
<item
android:id="@+id/action_blog_share"
......@@ -18,6 +27,8 @@
android:id="@+id/action_blog_delete"
android:icon="@drawable/action_delete_white"
android:title="@string/blogs_remove_blog"
app:showAsAction="never"/>
android:visible="false"
app:showAsAction="never"
tools:visible="true"/>
</menu>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_write_blog_post"
android:icon="@drawable/forum_item_create_white"
android:title="@string/blogs_write_blog_post"
app:showAsAction="ifRoom"/>
</menu>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BriarRecyclerView">
<attr name="scrollToEnd" format="boolean" />
<attr name="emptyText" format="string" />
</declare-styleable>
<declare-styleable name="AuthorView">
<attr name="persona" format="enum">
<enum name="normal" value="0"/>
<enum name="reblogger" value="1"/>
<enum name="commenter" value="2"/>
</attr>
</declare-styleable>
</resources>
\ No newline at end of file
......@@ -43,4 +43,8 @@
<dimen name="forum_nested_indicator">24dp</dimen>
<dimen name="forum_avatar_size">20dp</dimen>
<dimen name="blogs_avatar_normal_size">30dp</dimen>
<dimen name="blogs_avatar_icon_size">15dp</dimen>
<dimen name="blogs_avatar_comment_size">20dp</dimen>
</resources>
......@@ -35,7 +35,7 @@
<string name="nav_drawer_close_description">Close the navigation drawer</string>
<string name="contact_list_button">Contacts</string>
<string name="forums_button">Forums</string>
<string name="blogs_button">Micro Blogs</string>
<string name="blogs_button">Blogs</string>
<string name="settings_button">Settings</string>
<string name="sign_out_button">Sign Out</string>
......@@ -207,7 +207,6 @@
<string name="blogs_my_blogs_create_hint_desc">A short description of your new blog</string>
<string name="blogs_my_blogs_create_hint_desc_explanation">Potential readers may or may not subscribe to your blog based on the content of the description.</string>
<string name="blogs_my_blogs_empty_state">You don\'t have any blogs.\n\nWhy don\'t you create one now by clicking the plus in the top right screen corner?</string>
<string name="blogs_my_blogs_blog_empty_state">This is the place for content of your blog.\n\nIt seems like you haven\'t written anything yet.\n\nPlease tap the pen icon to compose a new blog post.\n\nDon\'t forget to go public and share your blog.</string>
<string name="blogs_my_blogs_created">Blog created</string>
<string name="blogs_blog_is_empty">This blog is empty</string>
<string name="blogs_other_blog_empty_state">This blog is currently empty.\n\nEither the author hasn\'t written anything yet, or the person who shared this blog with you needs to come online, so posts can be synchronized.</string>
......@@ -227,6 +226,8 @@
<string name="blogs_remove_blog_dialog_message">Are you sure that you want to remove this blog and all posts?\nNote that this will not remove the blog from other people\'s devices.</string>
<string name="blogs_remove_blog_ok">Remove Blog</string>
<string name="blogs_blog_removed">Blog Removed</string>
<string name="blogs_reblog_comment_hint">Add an optional comment</string>
<string name="blogs_reblog_button">Reblog</string>
<string name="blogs_blog_list">Blog List</string>
<string name="blogs_available_blogs">Available Blogs</string>
......
......@@ -126,7 +126,6 @@
<style name="BriarCard" parent="CardView">
<item name="cardUseCompatPadding">true</item>
<item name="contentPadding">@dimen/listitem_vertical_margin</item>
<item name="android:layout_margin">@dimen/margin_small</item>
</style>
......
......@@ -6,10 +6,10 @@ import org.briarproject.android.blogs.BlogActivity;
import org.briarproject.android.blogs.BlogFragment;
import org.briarproject.android.blogs.BlogListFragment;
import org.briarproject.android.blogs.BlogPostFragment;
import org.briarproject.android.blogs.BlogsFragment;
import org.briarproject.android.blogs.CreateBlogActivity;
import org.briarproject.android.blogs.FeedFragment;
import org.briarproject.android.blogs.MyBlogsFragment;
import org.briarproject.android.blogs.ReblogActivity;
import org.briarproject.android.blogs.ReblogFragment;
import org.briarproject.android.blogs.RssFeedImportActivity;
import org.briarproject.android.blogs.RssFeedManageActivity;
import org.briarproject.android.blogs.WriteBlogPostActivity;
......@@ -93,6 +93,10 @@ public interface ActivityComponent {
void inject(BlogPostFragment fragment);
void inject(ReblogFragment fragment);
void inject(ReblogActivity activity);
void inject(SettingsActivity activity);
void inject(ChangePasswordActivity activity);
......@@ -106,10 +110,8 @@ public interface ActivityComponent {
// Fragments
void inject(ContactListFragment fragment);
void inject(ForumListFragment fragment);
void inject(BlogsFragment fragment);
void inject(BlogListFragment fragment);
void inject(FeedFragment fragment);
void inject(MyBlogsFragment fragment);
void inject(IntroFragment fragment);
void inject(ShowQrCodeFragment fragment);
void inject(ContactChooserFragment fragment);
......
......@@ -7,7 +7,7 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import org.briarproject.R;
import org.briarproject.android.blogs.BlogsFragment;
import org.briarproject.android.blogs.FeedFragment;
import org.briarproject.android.contact.ContactListFragment;
import org.briarproject.android.forum.ForumListFragment;
import org.briarproject.android.fragment.BaseFragment;
......@@ -27,7 +27,7 @@ public abstract class BriarFragmentActivity extends BriarActivity {
actionBar.setTitle(R.string.contact_list_button);
} else if (fragmentTag.equals(ForumListFragment.TAG)) {
actionBar.setTitle(R.string.forums_button);
} else if (fragmentTag.equals(BlogsFragment.TAG)) {
} else if (fragmentTag.equals(FeedFragment.TAG)) {
actionBar.setTitle(R.string.blogs_button);
}
}
......
......@@ -21,7 +21,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.blogs.BlogsFragment;
import org.briarproject.android.blogs.FeedFragment;
import org.briarproject.android.contact.ContactListFragment;
import org.briarproject.android.controller.NavDrawerController;
import org.briarproject.android.controller.TransportStateListener;
......@@ -82,7 +82,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
startFragment(ContactListFragment.newInstance());
}
else if (intent.getBooleanExtra(INTENT_BLOGS, false)) {
startFragment(BlogsFragment.newInstance());
startFragment(FeedFragment.newInstance());
}
setIntent(null);
}
......@@ -186,7 +186,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
startFragment(ForumListFragment.newInstance());
break;
case R.id.nav_btn_blogs:
startFragment(BlogsFragment.newInstance());
startFragment(FeedFragment.newInstance());
break;
case R.id.nav_btn_settings:
startActivity(new Intent(this, SettingsActivity.class));
......
package org.briarproject.android.blogs;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.api.blogs.BlogPostHeader;
import org.briarproject.api.db.DbException;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
import java.util.Collection;
public interface BaseController {
void onStart();
void onStop();
void loadBlogPosts(GroupId g,
ResultExceptionHandler<Collection<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,
ResultExceptionHandler<Void, DbException> resultHandler);
void setOnBlogPostAddedListener(OnBlogPostAddedListener listener);
interface OnBlogPostAddedListener {
@UiThread
void onBlogPostAdded(BlogPostHeader header, boolean local);
}
}
package org.briarproject.android.blogs;
import android.app.Activity;
import android.support.annotation.CallSuper;
import android.support.annotation.Nullable;
import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.controller.DbControllerImpl;
import org.briarproject.android.controller.handler.ResultExceptionHandler;
import org.briarproject.api.blogs.Blog;
import org.briarproject.api.blogs.BlogCommentHeader;
import org.briarproject.api.blogs.BlogManager;
import org.briarproject.api.blogs.BlogPostHeader;
import org.briarproject.api.db.DbException;
import org.briarproject.api.event.BlogPostAddedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;