diff --git a/briar-android/res/drawable/ic_info_white.xml b/briar-android/res/drawable/ic_info_white.xml new file mode 100644 index 0000000000000000000000000000000000000000..7c4d881ba07a28b17decfc68fcb644a73013ffd3 --- /dev/null +++ b/briar-android/res/drawable/ic_info_white.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/> +</vector> diff --git a/briar-android/res/menu/group_reveal_actions.xml b/briar-android/res/menu/group_reveal_actions.xml new file mode 100644 index 0000000000000000000000000000000000000000..8612c943633ad0057c3ac7d3493f0f7bb260f174 --- /dev/null +++ b/briar-android/res/menu/group_reveal_actions.xml @@ -0,0 +1,12 @@ +<?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_group_reveal_onboarding" + android:icon="@drawable/ic_info_white" + android:title="@string/show_onboarding" + app:showAsAction="always"/> + +</menu> diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 0c5274d171f303b10c7490fe63ab946924f672f3..cc6f0f7d64c1be12b2ecfbb9dd4901e25f1c50ac 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -80,6 +80,7 @@ <string name="no_data">No data</string> <string name="ellipsis">…</string> <string name="text_too_long">The entered text is too long</string> + <string name="show_onboarding">Show Help Dialog</string> <!-- Contacts and Private Conversations--> <string name="no_contacts">It seems that you are new here and have no contacts yet.\n\nTap the + icon at the top and follow the instructions to add some friends to your list.\n\nPlease remember: You can only add new contacts face-to-face to prevent anyone from impersonating you or reading your messages in the future.</string> @@ -196,6 +197,7 @@ <!-- Private Groups Revealing Contacts --> <string name="groups_reveal_contacts">Reveal Contacts</string> + <string name="groups_reveal_dialog_message">You can choose whether to reveal contacts to all current and future members of this group.\n\nRevealing contacts makes your connection to the group faster and more reliable, because you can communicate with revealed contacts even when the creator of the group is offline.</string> <string name="groups_reveal_visible">Your relationship is visible to the group</string> <string name="groups_reveal_visible_revealed_by_us">Your relationship is visible to the group (revealed by you)</string> <string name="groups_reveal_visible_revealed_by_contact">Your relationship is visible to the group (revealed by contact)</string> diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsActivity.java b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsActivity.java index f76d514fd72853a39bae8dcfc152bb9ee881231a..cae47760bf4ae9a0c9e1ae15d0f4213a297b39ed 100644 --- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsActivity.java +++ b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsActivity.java @@ -1,9 +1,13 @@ package org.briarproject.android.privategroup.reveal; +import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; +import android.support.v7.app.AlertDialog; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; @@ -13,6 +17,7 @@ import org.briarproject.R; import org.briarproject.android.ActivityComponent; import org.briarproject.android.contactselection.ContactSelectorActivity; import org.briarproject.android.controller.handler.UiExceptionHandler; +import org.briarproject.android.controller.handler.UiResultExceptionHandler; import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DbException; import org.briarproject.api.nullsafety.MethodsNotNullByDefault; @@ -67,17 +72,75 @@ public class RevealContactsActivity extends ContactSelectorActivity return R.layout.activity_reveal_contacts; } + @Override + public void onStart() { + super.onStart(); + controller.isOnboardingNeeded( + new UiResultExceptionHandler<Boolean, DbException>(this) { + @Override + public void onResultUi(Boolean show) { + if (show) showOnboardingDialog(); + } + + @Override + public void onExceptionUi(DbException exception) { + // TODO proper error handling + finish(); + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.group_reveal_actions, menu); + return super.onCreateOptionsMenu(menu); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; + case R.id.action_group_reveal_onboarding: + showOnboardingDialog(); + return true; default: return super.onOptionsItemSelected(item); } } + private void showOnboardingDialog() { + new AlertDialog.Builder(this, R.style.BriarDialogTheme) + .setMessage(getString(R.string.groups_reveal_dialog_message)) + .setPositiveButton(R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int which) { + dialog.cancel(); + } + }) + .setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + onboardingShown(); + } + }) + .show(); + } + + private void onboardingShown() { + controller.onboardingShown( + new UiExceptionHandler<DbException>(this) { + @Override + public void onExceptionUi(DbException exception) { + // TODO proper error handling + } + }); + } + @Override public void contactsSelected(Collection<ContactId> contacts) { super.contactsSelected(contacts); diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsController.java b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsController.java index 9c14e20a06bfbdc399d587910e31d06301078135..dcc67f6aabb01344049418903a300d1592eef6bb 100644 --- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsController.java +++ b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsController.java @@ -2,6 +2,7 @@ package org.briarproject.android.privategroup.reveal; import org.briarproject.android.contactselection.ContactSelectorController; import org.briarproject.android.controller.handler.ExceptionHandler; +import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.api.contact.ContactId; import org.briarproject.api.db.DbException; import org.briarproject.api.nullsafety.NotNullByDefault; @@ -13,6 +14,11 @@ import java.util.Collection; public interface RevealContactsController extends ContactSelectorController<RevealableContactItem> { + void isOnboardingNeeded( + ResultExceptionHandler<Boolean, DbException> handler); + + void onboardingShown(ExceptionHandler<DbException> handler); + void reveal(GroupId g, Collection<ContactId> contacts, ExceptionHandler<DbException> handler); diff --git a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsControllerImpl.java index 40ddff92d0f6291c683da0b6862cbf5ab53150f6..d0b89a0e2441149751f5d51d68d4ab41ea86eca9 100644 --- a/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsControllerImpl.java +++ b/briar-android/src/org/briarproject/android/privategroup/reveal/RevealContactsControllerImpl.java @@ -14,6 +14,8 @@ import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.privategroup.GroupMember; import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.privategroup.invitation.GroupInvitationManager; +import org.briarproject.api.settings.Settings; +import org.briarproject.api.settings.SettingsManager; import org.briarproject.api.sync.GroupId; import java.util.ArrayList; @@ -26,6 +28,7 @@ import javax.inject.Inject; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static org.briarproject.android.fragment.SettingsFragment.SETTINGS_NAMESPACE; import static org.briarproject.api.privategroup.Visibility.INVISIBLE; @Immutable @@ -35,20 +38,24 @@ public class RevealContactsControllerImpl extends DbControllerImpl private static final Logger LOG = Logger.getLogger(RevealContactsControllerImpl.class.getName()); + private static final String SHOW_ONBOARDING_REVEAL_CONTACTS = + "showOnboardingRevealContacts"; private final PrivateGroupManager groupManager; private final GroupInvitationManager groupInvitationManager; private final ContactManager contactManager; + private final SettingsManager settingsManager; @Inject public RevealContactsControllerImpl(@DatabaseExecutor Executor dbExecutor, LifecycleManager lifecycleManager, PrivateGroupManager groupManager, GroupInvitationManager groupInvitationManager, - ContactManager contactManager) { + ContactManager contactManager, SettingsManager settingsManager) { super(dbExecutor, lifecycleManager); this.groupManager = groupManager; this.groupInvitationManager = groupInvitationManager; this.contactManager = contactManager; + this.settingsManager = settingsManager; } @Override @@ -95,6 +102,45 @@ public class RevealContactsControllerImpl extends DbControllerImpl return items; } + @Override + public void isOnboardingNeeded( + final ResultExceptionHandler<Boolean, DbException> handler) { + runOnDbThread(new Runnable() { + @Override + public void run() { + try { + Settings settings = + settingsManager.getSettings(SETTINGS_NAMESPACE); + handler.onResult( + settings.getBoolean(SHOW_ONBOARDING_REVEAL_CONTACTS, + true)); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + handler.onException(e); + } + + } + }); + } + + @Override + public void onboardingShown(ExceptionHandler<DbException> handler) { + runOnDbThread(new Runnable() { + @Override + public void run() { + try { + Settings settings = new Settings(); + settings.putBoolean(SHOW_ONBOARDING_REVEAL_CONTACTS, false); + settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); + } catch (DbException e) { + if (LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } + } + }); + } + @Override public void reveal(final GroupId g, final Collection<ContactId> contacts, final ExceptionHandler<DbException> handler) {