mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Compare commits
20 Commits
beta-0.16.
...
beta-0.16.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9437f7985 | ||
|
|
8141a97fc9 | ||
|
|
db842bd7e4 | ||
|
|
6dbec3a864 | ||
|
|
29f658cf4d | ||
|
|
ca83744a84 | ||
|
|
d91a9e2be4 | ||
|
|
8408c3f467 | ||
|
|
544c83a64c | ||
|
|
3800cd5e4f | ||
|
|
259f2cd419 | ||
|
|
20eb022c36 | ||
|
|
531e555b52 | ||
|
|
a9024aa34b | ||
|
|
d4e3b7842c | ||
|
|
167fddfbcc | ||
|
|
a48d642648 | ||
|
|
9a70f054c7 | ||
|
|
ca43d13bd6 | ||
|
|
5b71004179 |
@@ -54,6 +54,7 @@ public class BrambleCoreModule {
|
||||
c.inject(new IdentityModule.EagerSingletons());
|
||||
c.inject(new LifecycleModule.EagerSingletons());
|
||||
c.inject(new PluginModule.EagerSingletons());
|
||||
c.inject(new PropertiesModule.EagerSingletons());
|
||||
c.inject(new SyncModule.EagerSingletons());
|
||||
c.inject(new SystemModule.EagerSingletons());
|
||||
c.inject(new TransportModule.EagerSingletons());
|
||||
|
||||
@@ -78,8 +78,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 22
|
||||
versionCode 1602
|
||||
versionName "0.16.2"
|
||||
versionCode 1605
|
||||
versionName "0.16.5"
|
||||
applicationId "org.briarproject.briar.beta"
|
||||
resValue "string", "app_package", "org.briarproject.briar.beta"
|
||||
buildConfigField "String", "GitHash", "\"${getGitHash()}\""
|
||||
|
||||
@@ -2,6 +2,9 @@ package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.StrictMode;
|
||||
import android.os.StrictMode.ThreadPolicy;
|
||||
import android.os.StrictMode.VmPolicy;
|
||||
|
||||
import org.acra.ACRA;
|
||||
import org.acra.ReportingInteractionMode;
|
||||
@@ -33,6 +36,8 @@ import static org.acra.ReportField.REPORT_ID;
|
||||
import static org.acra.ReportField.STACK_TRACE;
|
||||
import static org.acra.ReportField.USER_APP_START_DATE;
|
||||
import static org.acra.ReportField.USER_CRASH_DATE;
|
||||
import static org.briarproject.briar.android.TestingConstants.DEFAULT_LOG_LEVEL;
|
||||
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||
|
||||
@ReportsCrashes(
|
||||
reportPrimerClass = BriarReportPrimer.class,
|
||||
@@ -72,6 +77,9 @@ public class BriarApplicationImpl extends Application
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
if (IS_DEBUG_BUILD) enableStrictMode();
|
||||
Logger.getLogger("").setLevel(DEFAULT_LOG_LEVEL);
|
||||
LOG.info("Created");
|
||||
|
||||
applicationComponent = DaggerAndroidComponent.builder()
|
||||
@@ -85,6 +93,17 @@ public class BriarApplicationImpl extends Application
|
||||
AndroidEagerSingletons.initEagerSingletons(applicationComponent);
|
||||
}
|
||||
|
||||
private void enableStrictMode() {
|
||||
ThreadPolicy.Builder threadPolicy = new ThreadPolicy.Builder();
|
||||
threadPolicy.detectAll();
|
||||
threadPolicy.penaltyLog();
|
||||
StrictMode.setThreadPolicy(threadPolicy.build());
|
||||
VmPolicy.Builder vmPolicy = new VmPolicy.Builder();
|
||||
vmPolicy.detectAll();
|
||||
vmPolicy.penaltyLog();
|
||||
StrictMode.setVmPolicy(vmPolicy.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AndroidComponent getApplicationComponent() {
|
||||
return applicationComponent;
|
||||
|
||||
@@ -10,13 +10,21 @@ import static java.util.logging.Level.OFF;
|
||||
public interface TestingConstants {
|
||||
|
||||
/**
|
||||
* Whether this is an alpha or beta build. This should be set to false for
|
||||
* Whether this is a debug build.
|
||||
*/
|
||||
boolean IS_DEBUG_BUILD = BuildConfig.DEBUG;
|
||||
|
||||
/**
|
||||
* Whether this is a beta build. This should be set to false for final
|
||||
* release builds.
|
||||
*/
|
||||
boolean TESTING = BuildConfig.DEBUG;
|
||||
boolean IS_BETA_BUILD = true;
|
||||
|
||||
/** Default log level. */
|
||||
Level DEFAULT_LOG_LEVEL = TESTING ? INFO : OFF;
|
||||
/**
|
||||
* Default log level. Disable logging for final release builds.
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
Level DEFAULT_LOG_LEVEL = IS_DEBUG_BUILD || IS_BETA_BUILD ? INFO : OFF;
|
||||
|
||||
/**
|
||||
* Whether to prevent screenshots from being taken. Setting this to true
|
||||
@@ -24,5 +32,5 @@ public interface TestingConstants {
|
||||
* Unfortunately this also prevents the user from taking screenshots
|
||||
* intentionally.
|
||||
*/
|
||||
boolean PREVENT_SCREENSHOTS = !TESTING;
|
||||
boolean PREVENT_SCREENSHOTS = !IS_DEBUG_BUILD;
|
||||
}
|
||||
|
||||
@@ -60,8 +60,7 @@ abstract class BasePostFragment extends BaseFragment {
|
||||
false);
|
||||
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
ui = new BlogPostViewHolder(view);
|
||||
ui.setOnBlogPostClickListener(new OnBlogPostClickListener() {
|
||||
ui = new BlogPostViewHolder(view, true, new OnBlogPostClickListener() {
|
||||
@Override
|
||||
public void onBlogPostClick(BlogPostItem post) {
|
||||
// We're already there
|
||||
|
||||
@@ -106,7 +106,7 @@ class BlogControllerImpl extends BaseControllerImpl
|
||||
BlogInvitationResponseReceivedEvent b =
|
||||
(BlogInvitationResponseReceivedEvent) e;
|
||||
InvitationResponse r = b.getResponse();
|
||||
if (r.getGroupId().equals(groupId) && r.wasAccepted()) {
|
||||
if (r.getShareableId().equals(groupId) && r.wasAccepted()) {
|
||||
LOG.info("Blog invitation accepted");
|
||||
onBlogInvitationAccepted(b.getContactId());
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ class BlogPostAdapter
|
||||
int viewType) {
|
||||
View v = LayoutInflater.from(ctx).inflate(
|
||||
R.layout.list_item_blog_post, parent, false);
|
||||
BlogPostViewHolder ui = new BlogPostViewHolder(v);
|
||||
ui.setOnBlogPostClickListener(listener);
|
||||
BlogPostViewHolder ui = new BlogPostViewHolder(v, false, listener);
|
||||
return ui;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,16 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
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.inject.Inject;
|
||||
|
||||
@UiThread
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class BlogPostFragment extends BasePostFragment {
|
||||
public class BlogPostFragment extends BasePostFragment implements BlogListener {
|
||||
|
||||
private static final String TAG = BlogPostFragment.class.getName();
|
||||
|
||||
@@ -40,6 +42,7 @@ public class BlogPostFragment extends BasePostFragment {
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
blogController.setBlogListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,4 +62,15 @@ public class BlogPostFragment extends BasePostFragment {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlogPostAdded(BlogPostHeader header, boolean local) {
|
||||
// doesn't matter here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlogRemoved() {
|
||||
finish();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.ActivityOptionsCompat;
|
||||
@@ -47,12 +48,16 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
private final ImageView reblogButton;
|
||||
private final TextView body;
|
||||
private final ViewGroup commentContainer;
|
||||
private final boolean fullText;
|
||||
|
||||
@Nullable
|
||||
private OnBlogPostClickListener listener;
|
||||
@NonNull
|
||||
private final OnBlogPostClickListener listener;
|
||||
|
||||
BlogPostViewHolder(View v) {
|
||||
BlogPostViewHolder(View v, boolean fullText,
|
||||
@NonNull OnBlogPostClickListener listener) {
|
||||
super(v);
|
||||
this.fullText = fullText;
|
||||
this.listener = listener;
|
||||
|
||||
ctx = v.getContext();
|
||||
layout = (ViewGroup) v.findViewById(R.id.postLayout);
|
||||
@@ -64,10 +69,6 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
(ViewGroup) v.findViewById(R.id.commentContainer);
|
||||
}
|
||||
|
||||
void setOnBlogPostClickListener(OnBlogPostClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
void setVisibility(int visibility) {
|
||||
layout.setVisibility(visibility);
|
||||
}
|
||||
@@ -92,7 +93,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
if (item == null) return;
|
||||
|
||||
setTransitionName(item.getId());
|
||||
if (listener != null) {
|
||||
if (!fullText) {
|
||||
layout.setClickable(true);
|
||||
layout.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
@@ -111,7 +112,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
author.setPersona(
|
||||
item.isRssFeed() ? AuthorView.RSS_FEED : AuthorView.NORMAL);
|
||||
// TODO make author clickable more often #624
|
||||
if (listener != null && item.getHeader().getType() == POST) {
|
||||
if (!fullText && item.getHeader().getType() == POST) {
|
||||
author.setAuthorClickable(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -124,7 +125,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
// post body
|
||||
Spanned bodyText = getSpanned(item.getBody());
|
||||
if (listener == null) {
|
||||
if (fullText) {
|
||||
body.setText(bodyText);
|
||||
body.setTextIsSelectable(true);
|
||||
makeLinksClickable(body);
|
||||
@@ -170,7 +171,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
reblogger.setAuthor(item.getAuthor());
|
||||
reblogger.setAuthorStatus(item.getAuthorStatus());
|
||||
reblogger.setDate(item.getTimestamp());
|
||||
if (listener != null) {
|
||||
if (!fullText) {
|
||||
reblogger.setAuthorClickable(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -200,7 +201,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
// TODO make author clickable #624
|
||||
|
||||
body.setText(c.getComment());
|
||||
if (listener == null) body.setTextIsSelectable(true);
|
||||
if (fullText) body.setTextIsSelectable(true);
|
||||
|
||||
commentContainer.addView(v);
|
||||
}
|
||||
|
||||
@@ -161,7 +161,18 @@ public class ReblogFragment extends BaseFragment implements TextInputListener {
|
||||
private ViewHolder(View v) {
|
||||
scrollView = (ScrollView) v.findViewById(R.id.scrollView);
|
||||
progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
|
||||
post = new BlogPostViewHolder(v.findViewById(R.id.postLayout));
|
||||
post = new BlogPostViewHolder(v.findViewById(R.id.postLayout),
|
||||
true, new OnBlogPostClickListener() {
|
||||
@Override
|
||||
public void onBlogPostClick(BlogPostItem post) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthorClick(BlogPostItem post) {
|
||||
// probably don't want to allow author clicks here
|
||||
}
|
||||
});
|
||||
input = (TextInputView) v.findViewById(R.id.inputText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.briarproject.briar.android.forum;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
@@ -43,10 +44,10 @@ public class CreateForumActivity extends BriarActivity {
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(CreateForumActivity.class.getName());
|
||||
|
||||
private TextInputLayout nameEntryLayout;
|
||||
private EditText nameEntry;
|
||||
private Button createForumButton;
|
||||
private ProgressBar progress;
|
||||
private TextView feedback;
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject
|
||||
@@ -58,6 +59,8 @@ public class CreateForumActivity extends BriarActivity {
|
||||
|
||||
setContentView(R.layout.activity_create_forum);
|
||||
|
||||
nameEntryLayout =
|
||||
(TextInputLayout) findViewById(R.id.createForumNameLayout);
|
||||
nameEntry = (EditText) findViewById(R.id.createForumNameEntry);
|
||||
nameEntry.addTextChangedListener(new TextWatcher() {
|
||||
|
||||
@@ -85,8 +88,6 @@ public class CreateForumActivity extends BriarActivity {
|
||||
}
|
||||
});
|
||||
|
||||
feedback = (TextView) findViewById(R.id.createForumFeedback);
|
||||
|
||||
createForumButton = (Button) findViewById(R.id.createForumButton);
|
||||
createForumButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
@@ -118,10 +119,10 @@ public class CreateForumActivity extends BriarActivity {
|
||||
String name = nameEntry.getText().toString();
|
||||
int length = StringUtils.toUtf8(name).length;
|
||||
if (length > MAX_FORUM_NAME_LENGTH) {
|
||||
feedback.setText(R.string.name_too_long);
|
||||
nameEntryLayout.setError(getString(R.string.name_too_long));
|
||||
return false;
|
||||
}
|
||||
feedback.setText("");
|
||||
nameEntryLayout.setError(null);
|
||||
return length > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ class ForumControllerImpl extends
|
||||
(ForumInvitationResponseReceivedEvent) e;
|
||||
ForumInvitationResponse r =
|
||||
(ForumInvitationResponse) f.getResponse();
|
||||
if (r.getGroupId().equals(getGroupId()) && r.wasAccepted()) {
|
||||
if (r.getShareableId().equals(getGroupId()) && r.wasAccepted()) {
|
||||
LOG.info("Forum invitation was accepted");
|
||||
onForumInvitationAccepted(r.getContactId());
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ class GroupControllerImpl extends
|
||||
(GroupInvitationResponseReceivedEvent) e;
|
||||
final GroupInvitationResponse r =
|
||||
(GroupInvitationResponse) g.getResponse();
|
||||
if (getGroupId().equals(r.getGroupId()) && r.wasAccepted()) {
|
||||
if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.briarproject.briar.android.privategroup.creation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
@@ -11,6 +12,7 @@ import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
@@ -19,6 +21,8 @@ import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
|
||||
|
||||
public class CreateGroupFragment extends BaseFragment {
|
||||
@@ -28,7 +32,8 @@ public class CreateGroupFragment extends BaseFragment {
|
||||
private CreateGroupListener listener;
|
||||
private EditText nameEntry;
|
||||
private Button createGroupButton;
|
||||
private TextView feedback;
|
||||
private TextInputLayout nameLayout;
|
||||
private ProgressBar progress;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
@@ -69,7 +74,7 @@ public class CreateGroupFragment extends BaseFragment {
|
||||
}
|
||||
});
|
||||
|
||||
feedback = (TextView) v.findViewById(R.id.feedback);
|
||||
nameLayout = (TextInputLayout) v.findViewById(R.id.nameLayout);
|
||||
|
||||
createGroupButton = (Button) v.findViewById(R.id.button);
|
||||
createGroupButton.setOnClickListener(new OnClickListener() {
|
||||
@@ -79,6 +84,8 @@ public class CreateGroupFragment extends BaseFragment {
|
||||
}
|
||||
});
|
||||
|
||||
progress = (ProgressBar) v.findViewById(R.id.progressBar);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -107,16 +114,18 @@ public class CreateGroupFragment extends BaseFragment {
|
||||
String name = nameEntry.getText().toString();
|
||||
int length = StringUtils.toUtf8(name).length;
|
||||
if (length > MAX_GROUP_NAME_LENGTH) {
|
||||
feedback.setText(R.string.name_too_long);
|
||||
nameLayout.setError(getString(R.string.name_too_long));
|
||||
return false;
|
||||
}
|
||||
feedback.setText("");
|
||||
nameLayout.setError(null);
|
||||
return length > 0;
|
||||
}
|
||||
|
||||
private void createGroup() {
|
||||
if (!validateName()) return;
|
||||
listener.hideSoftKeyboard(nameEntry);
|
||||
createGroupButton.setVisibility(GONE);
|
||||
progress.setVisibility(VISIBLE);
|
||||
listener.onGroupNameChosen(nameEntry.getText().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@ import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.StrictMode;
|
||||
import android.os.StrictMode.ThreadPolicy;
|
||||
import android.os.StrictMode.VmPolicy;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
import android.transition.Fade;
|
||||
|
||||
@@ -23,8 +20,6 @@ import java.util.logging.Logger;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE;
|
||||
import static org.briarproject.briar.android.TestingConstants.DEFAULT_LOG_LEVEL;
|
||||
import static org.briarproject.briar.android.TestingConstants.TESTING;
|
||||
|
||||
public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
@@ -36,11 +31,6 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
@Inject
|
||||
protected AndroidExecutor androidExecutor;
|
||||
|
||||
public SplashScreenActivity() {
|
||||
Logger.getLogger("").setLevel(DEFAULT_LOG_LEVEL);
|
||||
enableStrictMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
super.onCreate(state);
|
||||
@@ -81,19 +71,6 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void enableStrictMode() {
|
||||
if (TESTING) {
|
||||
ThreadPolicy.Builder threadPolicy = new ThreadPolicy.Builder();
|
||||
threadPolicy.detectAll();
|
||||
threadPolicy.penaltyLog();
|
||||
StrictMode.setThreadPolicy(threadPolicy.build());
|
||||
VmPolicy.Builder vmPolicy = new VmPolicy.Builder();
|
||||
vmPolicy.detectAll();
|
||||
vmPolicy.penaltyLog();
|
||||
StrictMode.setVmPolicy(vmPolicy.build());
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreferencesDefaults() {
|
||||
androidExecutor.runOnBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -104,8 +104,9 @@ public class EmojiPageView extends FrameLayout {
|
||||
emojiSize + 2 * pad));
|
||||
view = emojiView;
|
||||
}
|
||||
String emoji = model.getEmoji()[position];
|
||||
view.setEmoji(emoji);
|
||||
|
||||
view.setEmoji(model.getEmoji()[position]);
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class RecentEmojiPageModel implements EmojiPageModel {
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(RecentEmojiPageModel.class.getName());
|
||||
|
||||
private static final String EMOJI_LRU_PREFERENCE = "pref_emoji_recent";
|
||||
private static final String EMOJI_LRU_PREFERENCE = "pref_emoji_recent2";
|
||||
private static final int EMOJI_LRU_SIZE = 50;
|
||||
|
||||
private final LinkedHashSet<String> recentlyUsed; // UI thread
|
||||
@@ -98,12 +98,12 @@ public class RecentEmojiPageModel implements EmojiPageModel {
|
||||
}
|
||||
|
||||
private String serialize(LinkedHashSet<String> emojis) {
|
||||
return StringUtils.join(emojis, ";");
|
||||
return StringUtils.join(emojis, "\t");
|
||||
}
|
||||
|
||||
private LinkedHashSet<String> deserialize(@Nullable String serialized) {
|
||||
if (serialized == null) return new LinkedHashSet<>();
|
||||
String[] list = serialized.split(";");
|
||||
String[] list = serialized.split("\t");
|
||||
LinkedHashSet<String> result = new LinkedHashSet<>(list.length);
|
||||
Collections.addAll(result, list);
|
||||
return result;
|
||||
|
||||
@@ -1,37 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
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="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="@dimen/margin_large">
|
||||
android:padding="@dimen/margin_large">
|
||||
|
||||
<EditText
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/createForumNameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/createForumNameEntry"
|
||||
android:maxLines="1"
|
||||
android:inputType="text|textCapSentences"
|
||||
android:hint="@string/choose_forum_hint" />
|
||||
app:errorEnabled="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/createForumFeedback"
|
||||
android:gravity="center" />
|
||||
<EditText
|
||||
android:id="@+id/createForumNameEntry"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/choose_forum_hint"
|
||||
android:inputType="text|textCapSentences"
|
||||
android:maxLines="1"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<Button
|
||||
style="@style/BriarButton"
|
||||
android:id="@+id/createForumButton"
|
||||
style="@style/BriarButton"
|
||||
android:enabled="false"
|
||||
android:text="@string/create_forum_button" />
|
||||
android:text="@string/create_forum_button"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/createForumProgressBar"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone" />
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,30 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
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="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="@dimen/margin_large">
|
||||
android:padding="@dimen/margin_large">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/name"
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/nameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:inputType="text|textCapSentences"
|
||||
android:hint="@string/groups_create_group_hint"/>
|
||||
app:errorEnabled="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/feedback"
|
||||
android:gravity="center" />
|
||||
<EditText
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/groups_create_group_hint"
|
||||
android:inputType="text|textCapSentences"
|
||||
android:maxLines="1"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<Button
|
||||
style="@style/BriarButton"
|
||||
android:id="@+id/button"
|
||||
style="@style/BriarButton"
|
||||
android:enabled="false"
|
||||
android:text="@string/groups_create_group_button"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -59,6 +59,7 @@ import okhttp3.Dns;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
@@ -334,7 +335,9 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
|
||||
private SyndFeed fetchSyndFeed(String url)
|
||||
throws FeedException, IOException {
|
||||
// fetch feed
|
||||
SyndFeed f = getSyndFeed(getFeedInputStream(url));
|
||||
InputStream stream = getFeedInputStream(url);
|
||||
SyndFeed f = getSyndFeed(stream);
|
||||
stream.close();
|
||||
|
||||
if (f.getEntries().size() == 0)
|
||||
throw new FeedException("Feed has no entries");
|
||||
@@ -387,7 +390,9 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
|
||||
|
||||
// Execute Request
|
||||
Response response = client.newCall(request).execute();
|
||||
return response.body().byteStream();
|
||||
ResponseBody body = response.body();
|
||||
if (body != null) return body.byteStream();
|
||||
throw new IOException("Empty response body");
|
||||
}
|
||||
|
||||
private SyndFeed getSyndFeed(InputStream stream)
|
||||
@@ -433,7 +438,6 @@ class FeedManagerImpl implements FeedManager, Client, EventListener,
|
||||
|
||||
// build post body
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("<h3>").append(feed.getTitle()).append("</h3>");
|
||||
|
||||
if (!StringUtils.isNullOrEmpty(entry.getTitle())) {
|
||||
b.append("<h1>").append(entry.getTitle()).append("</h1>");
|
||||
|
||||
@@ -5,7 +5,6 @@ import net.jodah.concurrentunit.Waiter;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.NoSuchGroupException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -493,26 +492,6 @@ public class BlogSharingIntegrationTest
|
||||
// 1 can again share blog 1 with 0
|
||||
assertTrue(
|
||||
blogSharingManager1.canBeShared(blog1.getId(), contact0From1));
|
||||
|
||||
// re-create local state (simulates sign-out and sign-in)
|
||||
Transaction txn0 = db0.startTransaction(false);
|
||||
((BlogSharingManagerImpl) blogSharingManager0).createLocalState(txn0);
|
||||
db0.commitTransaction(txn0);
|
||||
db0.endTransaction(txn0);
|
||||
Transaction txn1 = db1.startTransaction(false);
|
||||
((BlogSharingManagerImpl) blogSharingManager1).createLocalState(txn1);
|
||||
db1.commitTransaction(txn1);
|
||||
db1.endTransaction(txn1);
|
||||
|
||||
// ensure there's no error with the sessions by checking shareability
|
||||
assertFalse(
|
||||
blogSharingManager0.canBeShared(blog1.getId(), contact1From0));
|
||||
assertTrue(
|
||||
blogSharingManager1.canBeShared(blog1.getId(), contact0From1));
|
||||
|
||||
// contacts should still be able to remove each other without errors
|
||||
contactManager0.removeContact(contactId1From0);
|
||||
contactManager1.removeContact(contactId0From1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
package org.briarproject.briar.sharing;
|
||||
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfEntry;
|
||||
import org.briarproject.bramble.api.data.MetadataParser;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Metadata;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
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.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.briar.api.blog.BlogSharingManager.CLIENT_ID;
|
||||
import static org.briarproject.briar.sharing.SharingConstants.GROUP_KEY_CONTACT_ID;
|
||||
|
||||
public class BlogSharingManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
private final Mockery context = new Mockery();
|
||||
private final BlogSharingManagerImpl blogSharingManager;
|
||||
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
private final IdentityManager identityManager =
|
||||
context.mock(IdentityManager.class);
|
||||
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
|
||||
private final SessionEncoder sessionEncoder =
|
||||
context.mock(SessionEncoder.class);
|
||||
private final SessionParser sessionParser =
|
||||
context.mock(SessionParser.class);
|
||||
private final ContactGroupFactory contactGroupFactory =
|
||||
context.mock(ContactGroupFactory.class);
|
||||
private final BlogManager blogManager = context.mock(BlogManager.class);
|
||||
|
||||
private final AuthorId localAuthorId = new AuthorId(getRandomId());
|
||||
private final ContactId contactId = new ContactId(0);
|
||||
private final AuthorId authorId = new AuthorId(getRandomId());
|
||||
private final Author author = new Author(authorId, "Author",
|
||||
getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
|
||||
private final Contact contact =
|
||||
new Contact(contactId, author, localAuthorId, true, true);
|
||||
private final Collection<Contact> contacts =
|
||||
Collections.singletonList(contact);
|
||||
private final Group contactGroup =
|
||||
new Group(new GroupId(getRandomId()), CLIENT_ID,
|
||||
getRandomBytes(42));
|
||||
private final Group blogGroup =
|
||||
new Group(new GroupId(getRandomId()), BlogManager.CLIENT_ID,
|
||||
getRandomBytes(42));
|
||||
private final Blog blog = new Blog(blogGroup, author, false);
|
||||
@SuppressWarnings("unchecked")
|
||||
private final ProtocolEngine<Blog> engine =
|
||||
context.mock(ProtocolEngine.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public BlogSharingManagerImplTest() {
|
||||
MetadataParser metadataParser = context.mock(MetadataParser.class);
|
||||
MessageTracker messageTracker = context.mock(MessageTracker.class);
|
||||
MessageParser<Blog> messageParser = context.mock(MessageParser.class);
|
||||
InvitationFactory<Blog, BlogInvitationResponse> invitationFactory =
|
||||
context.mock(InvitationFactory.class);
|
||||
blogSharingManager =
|
||||
new BlogSharingManagerImpl(db, clientHelper, metadataParser,
|
||||
messageParser, sessionEncoder, sessionParser,
|
||||
messageTracker, contactGroupFactory,
|
||||
engine, invitationFactory, identityManager,
|
||||
blogManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingContactFreshState() throws Exception {
|
||||
Map<MessageId, BdfDictionary> sessions =
|
||||
new HashMap<MessageId, BdfDictionary>(0);
|
||||
testAddingContact(sessions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingContactExistingState() throws Exception {
|
||||
Map<MessageId, BdfDictionary> sessions =
|
||||
new HashMap<MessageId, BdfDictionary>(1);
|
||||
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
|
||||
testAddingContact(sessions);
|
||||
}
|
||||
|
||||
@Test(expected = DbException.class)
|
||||
public void testAddingContactMultipleSessions() throws Exception {
|
||||
Map<MessageId, BdfDictionary> sessions =
|
||||
new HashMap<MessageId, BdfDictionary>(2);
|
||||
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
|
||||
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
|
||||
testAddingContact(sessions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovingBlogFreshState() throws Exception {
|
||||
Map<MessageId, BdfDictionary> sessions =
|
||||
new HashMap<MessageId, BdfDictionary>(0);
|
||||
testRemovingBlog(sessions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovingBlogExistingState() throws Exception {
|
||||
Map<MessageId, BdfDictionary> sessions =
|
||||
new HashMap<MessageId, BdfDictionary>(1);
|
||||
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
|
||||
testRemovingBlog(sessions);
|
||||
}
|
||||
|
||||
@Test(expected = DbException.class)
|
||||
public void testRemovingBlogMultipleSessions() throws Exception {
|
||||
Map<MessageId, BdfDictionary> sessions =
|
||||
new HashMap<MessageId, BdfDictionary>(2);
|
||||
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
|
||||
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
|
||||
testRemovingBlog(sessions);
|
||||
}
|
||||
|
||||
private void testAddingContact(final Map<MessageId, BdfDictionary> sessions)
|
||||
throws Exception {
|
||||
final Transaction txn = new Transaction(null, false);
|
||||
final LocalAuthor localAuthor =
|
||||
new LocalAuthor(localAuthorId, "Local Author",
|
||||
getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
||||
getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
|
||||
System.currentTimeMillis());
|
||||
final BdfDictionary meta = BdfDictionary
|
||||
.of(new BdfEntry(GROUP_KEY_CONTACT_ID, contactId.getInt()));
|
||||
final Group localBlogGroup =
|
||||
new Group(new GroupId(getRandomId()), BlogManager.CLIENT_ID,
|
||||
getRandomBytes(42));
|
||||
final Blog localBlog = new Blog(localBlogGroup, localAuthor, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(contacts));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(db).containsGroup(txn, contactGroup.getId());
|
||||
will(returnValue(false));
|
||||
oneOf(db).addGroup(txn, contactGroup);
|
||||
oneOf(db).setGroupVisibility(txn, contactId, contactGroup.getId(),
|
||||
SHARED);
|
||||
oneOf(clientHelper)
|
||||
.mergeGroupMetadata(txn, contactGroup.getId(), meta);
|
||||
oneOf(identityManager).getLocalAuthor(txn);
|
||||
will(returnValue(localAuthor));
|
||||
oneOf(blogManager).getPersonalBlog(localAuthor);
|
||||
will(returnValue(localBlog));
|
||||
oneOf(blogManager).getPersonalBlog(author);
|
||||
will(returnValue(blog));
|
||||
}});
|
||||
expectPreShareShareable(txn, contact, localBlog, sessions);
|
||||
expectPreShareShareable(txn, contact, blog, sessions);
|
||||
|
||||
blogSharingManager.createLocalState(txn);
|
||||
}
|
||||
|
||||
private void expectPreShareShareable(final Transaction txn,
|
||||
final Contact contact, final Blog blog,
|
||||
final Map<MessageId, BdfDictionary> sessions) throws Exception {
|
||||
final Group contactGroup =
|
||||
new Group(new GroupId(getRandomId()), CLIENT_ID,
|
||||
getRandomBytes(42));
|
||||
final BdfDictionary sessionDict = new BdfDictionary();
|
||||
final Message message =
|
||||
new Message(new MessageId(getRandomId()), contactGroup.getId(),
|
||||
42L, getRandomBytes(1337));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory)
|
||||
.createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(sessionParser)
|
||||
.getSessionQuery(new SessionId(blog.getId().getBytes()));
|
||||
will(returnValue(sessionDict));
|
||||
oneOf(clientHelper)
|
||||
.getMessageMetadataAsDictionary(txn, contactGroup.getId(),
|
||||
sessionDict);
|
||||
will(returnValue(sessions));
|
||||
if (sessions.size() == 0) {
|
||||
oneOf(db).addGroup(txn, blog.getGroup());
|
||||
oneOf(db).setGroupVisibility(txn, contact.getId(),
|
||||
blog.getGroup().getId(), SHARED);
|
||||
oneOf(clientHelper)
|
||||
.createMessageForStoringMetadata(contactGroup.getId());
|
||||
will(returnValue(message));
|
||||
oneOf(db).addLocalMessage(txn, message, new Metadata(), false);
|
||||
oneOf(sessionEncoder).encodeSession(with(any(Session.class)));
|
||||
will(returnValue(sessionDict));
|
||||
oneOf(clientHelper).mergeMessageMetadata(txn, message.getId(),
|
||||
sessionDict);
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
||||
private void testRemovingBlog(final Map<MessageId, BdfDictionary> sessions)
|
||||
throws Exception {
|
||||
final Transaction txn = new Transaction(null, false);
|
||||
final BdfDictionary sessionDict = new BdfDictionary();
|
||||
final Session session = new Session(contactGroup.getId(), blog.getId());
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(contacts));
|
||||
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||
will(returnValue(contactGroup));
|
||||
oneOf(sessionParser)
|
||||
.getSessionQuery(new SessionId(blog.getId().getBytes()));
|
||||
will(returnValue(sessionDict));
|
||||
oneOf(clientHelper)
|
||||
.getMessageMetadataAsDictionary(txn, contactGroup.getId(),
|
||||
sessionDict);
|
||||
will(returnValue(sessions));
|
||||
if (sessions.size() == 1) {
|
||||
oneOf(sessionParser)
|
||||
.parseSession(contactGroup.getId(), sessionDict);
|
||||
will(returnValue(session));
|
||||
oneOf(engine).onLeaveAction(txn, session);
|
||||
will(returnValue(session));
|
||||
oneOf(sessionEncoder).encodeSession(session);
|
||||
will(returnValue(sessionDict));
|
||||
oneOf(clientHelper).mergeMessageMetadata(txn,
|
||||
sessions.keySet().iterator().next(), sessionDict);
|
||||
}
|
||||
}});
|
||||
blogSharingManager.removingBlog(txn, blog);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user