diff --git a/briar-android/artwork/bluetooth.svg b/briar-android/artwork/bluetooth.svg new file mode 100644 index 0000000000000000000000000000000000000000..951fa966c154b7db67e7c34fe53f8203532e2e96 --- /dev/null +++ b/briar-android/artwork/bluetooth.svg @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="140.89767mm" + height="49.528343mm" + viewBox="0 0 499.24373 175.49413" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="bluetooth.svg" + inkscape:export-filename="bluetooth.png" + inkscape:export-xdpi="194.87476" + inkscape:export-ydpi="194.87476"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.98994949" + inkscape:cx="435.00934" + inkscape:cy="91.353462" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" + inkscape:window-width="1920" + inkscape:window-height="1012" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-72.369616,-444.3511)"> + <path + style="fill:#000000" + d="m 532.17899,615.51093 -4.32657,-4.3343 -7.06956,-2.42737 c -3.88825,-1.33505 -8.72285,-2.99587 -10.74354,-3.6907 l -3.674,-1.26333 3.524,-0.1726 c 8.24183,-0.40367 12.98778,-4.00671 14.33634,-10.88389 0.79628,-4.06078 1.12887,-17.29805 0.83016,-33.04122 -0.15338,-8.08375 -0.16617,-15.41641 -0.0284,-16.29481 0.13775,-0.8784 0.53527,-2.42011 0.88339,-3.42602 1.22247,-3.53243 0.33996,-11.90828 -1.8577,-17.63146 -0.34848,-0.9075 -1.93434,-4.215 -3.52415,-7.35 -4.15849,-8.2003 -4.50458,-8.94188 -4.89292,-10.4841 -0.45865,-1.82145 -0.21161,-5.43531 0.4625,-6.7659 0.66625,-1.31505 2.15695,-2.91616 3.24622,-3.48662 1.29885,-0.68024 2.61568,0.12202 4.6864,2.85512 3.42153,4.51599 14.00135,19.44095 15.73191,22.19301 3.74551,5.95636 5.95558,11.16496 7.9722,18.78849 0.6547,2.475 1.88525,6.9975 2.73456,10.05 0.84931,3.0525 2.71404,10.15792 4.14385,15.78983 l 2.59964,10.23983 4.65,5.19319 c 2.5575,2.85626 5.7975,6.46371 7.2,8.01657 1.4025,1.55286 2.55,2.97543 2.55,3.16127 0,0.33546 -34.49955,29.29931 -34.89913,29.29931 -0.11475,0 -2.15559,-1.95044 -4.5352,-4.3343 z m -93.86507,-16.38777 c -1.25762,-0.62844 -2.20557,-1.3788 -2.91402,-2.30663 -2.08931,-2.73629 -1.95034,2.36868 -1.86433,-68.48249 l 0.0777,-64.03881 0.66066,-1.23494 c 1.0152,-1.89767 1.99201,-2.91087 3.73952,-3.87887 l 1.59982,-0.88619 37.78387,-0.0796 c 42.45592,-0.0894 39.40239,-0.2483 42.11646,2.19188 0.87544,0.78709 1.75715,1.95946 2.18393,2.90385 0.71264,1.57698 0.71613,1.63839 0.80561,14.20405 l 0.0899,12.62022 -1.79817,-0.13007 c -1.42577,-0.10313 -2.08143,0.007 -3.16601,0.5321 -2.01294,0.97445 -3.93993,2.89871 -5.11476,5.10753 l -1.03717,1.95 -0.007,-12.825 -0.007,-12.825 -33.6,0 -33.6,0 0,51.3 0,51.3 33.59873,0 33.59874,0 0.0763,-34.425 c 0.073,-32.96021 0.0982,-34.36117 0.59098,-32.925 0.28309,0.825 1.80562,3.9975 3.3834,7.05 5.49252,10.62624 5.40494,9.86009 5.39597,47.20335 -0.007,27.62122 -0.12358,29.95084 -1.66204,33.10906 -1.07144,2.19949 -2.71143,3.71042 -5.05823,4.66019 l -1.67381,0.6774 -36.1677,0.0797 -36.16769,0.0797 -1.864,-0.93145 z m 42.39939,-5.03813 c 2.87119,-1.30885 4.45771,-3.6784 4.43003,-6.61652 -0.0388,-4.11587 -3.1088,-7.22328 -7.1364,-7.22328 -2.11956,0 -3.56727,0.60889 -5.16364,2.17177 -2.24518,2.19807 -2.75398,5.43897 -1.30101,8.28704 0.71312,1.39782 2.52137,3.00905 3.96214,3.53045 1.49707,0.54176 3.84003,0.47454 5.20888,-0.14946 z" + id="path4201" + inkscape:connector-curvature="0" + sodipodi:nodetypes="scsscssscssssscssssscssssscsscsscsssscscscccccccccscscsscccccsssssss" /> + <path + style="fill:#000000" + d="m 111.80395,615.51093 4.32657,-4.3343 7.06956,-2.42737 c 3.88825,-1.33505 8.72285,-2.99587 10.74354,-3.6907 l 3.674,-1.26333 -3.524,-0.1726 c -8.24183,-0.40367 -12.98778,-4.00671 -14.33634,-10.88389 -0.79628,-4.06078 -1.12887,-17.29805 -0.83016,-33.04122 0.15338,-8.08375 0.16617,-15.41641 0.0284,-16.29481 -0.13775,-0.8784 -0.53527,-2.42011 -0.88339,-3.42602 -1.22247,-3.53243 -0.33996,-11.90828 1.8577,-17.63146 0.34848,-0.9075 1.93434,-4.215 3.52415,-7.35 4.15849,-8.2003 4.50458,-8.94188 4.89292,-10.4841 0.45865,-1.82145 0.21161,-5.43531 -0.4625,-6.7659 -0.66625,-1.31505 -2.15695,-2.91616 -3.24622,-3.48662 -1.29885,-0.68024 -2.61568,0.12202 -4.6864,2.85512 -3.42153,4.51599 -14.00135,19.44095 -15.73191,22.19301 -3.74551,5.95636 -5.955584,11.16496 -7.972204,18.78849 -0.6547,2.475 -1.88525,6.9975 -2.73456,10.05 -0.84931,3.0525 -2.71404,10.15792 -4.14385,15.78983 l -2.59964,10.23983 -4.65,5.19319 c -2.5575,2.85626 -5.7975,6.46371 -7.2,8.01657 -1.4025,1.55286 -2.55,2.97543 -2.55,3.16127 0,0.33546 34.499554,29.29931 34.899134,29.29931 0.11475,0 2.15559,-1.95044 4.53519,-4.3343 z m 93.86506,-16.38777 c 1.25762,-0.62844 2.20557,-1.3788 2.91402,-2.30663 2.08931,-2.73629 1.95034,2.36868 1.86433,-68.48249 l -0.0777,-64.03881 -0.66066,-1.23494 c -1.0152,-1.89767 -1.99201,-2.91087 -3.73952,-3.87887 l -1.59982,-0.88619 -37.78386,-0.0796 c -42.45592,-0.0894 -39.40239,-0.2483 -42.11646,2.19188 -0.87544,0.78709 -1.75715,1.95946 -2.18393,2.90385 -0.71264,1.57698 -0.71613,1.63839 -0.80561,14.20405 l -0.0899,12.62022 1.79817,-0.13007 c 1.42577,-0.10313 2.08143,0.007 3.16601,0.5321 2.01294,0.97445 3.93993,2.89871 5.11476,5.10753 l 1.03717,1.95 0.007,-12.825 0.007,-12.825 33.6,0 33.59999,0 0,51.3 0,51.3 -33.59872,0 -33.59874,0 -0.0763,-34.425 c -0.073,-32.96021 -0.0982,-34.36117 -0.59098,-32.925 -0.28309,0.825 -1.80562,3.9975 -3.3834,7.05 -5.49252,10.62624 -5.40494,9.86009 -5.39597,47.20335 0.007,27.62122 0.12358,29.95084 1.66204,33.10906 1.07144,2.19949 2.71143,3.71042 5.05823,4.66019 l 1.67381,0.6774 36.1677,0.0797 36.16768,0.0797 1.864,-0.93145 z m -42.39938,-5.03813 c -2.87119,-1.30885 -4.45771,-3.6784 -4.43003,-6.61652 0.0388,-4.11587 3.1088,-7.22328 7.1364,-7.22328 2.11956,0 3.56727,0.60889 5.16364,2.17177 2.24518,2.19807 2.75398,5.43897 1.30101,8.28704 -0.71312,1.39782 -2.52137,3.00905 -3.96214,3.53045 -1.49707,0.54176 -3.84003,0.47454 -5.20888,-0.14946 z" + id="path4201-1" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccsscssscssssscssssscsssscccsscsscsssscscscccccccccscscsscccccsssssss" /> + <g + id="g4838" + transform="matrix(0.08166146,0,0,0.08166146,285.28364,535.81196)"> + <rect + id="rect4270" + width="640" + height="976" + ry="291" + style="fill:#0a3d91" + x="129.51247" + y="-189.58334" /> + <path + id="path4272" + d="m 286.51248,140.41666 305,307.00003 -147,178 0,-636.000027 147,169.999997 -305,299.00003" + style="fill:none;stroke:#ffffff;stroke-width:53" + inkscape:connector-curvature="0" /> + </g> + <path + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0a3d91;stroke-width:7.55;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:7.55,22.65;stroke-dashoffset:0;stroke-opacity:1" + d="m 219.05071,474.19795 c 70.76376,46.48067 139.93534,38.03285 208.24431,-0.1739" + id="path4844" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + </g> +</svg> diff --git a/briar-android/res/drawable/bluetooth.png b/briar-android/res/drawable/bluetooth.png new file mode 100644 index 0000000000000000000000000000000000000000..f99091e6726ba462096b3b4abe568e86e874ece6 Binary files /dev/null and b/briar-android/res/drawable/bluetooth.png differ diff --git a/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml b/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml new file mode 100644 index 0000000000000000000000000000000000000000..bf0d3ee68aefc16e31c2130c14d1aefe27798a9d --- /dev/null +++ b/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="@dimen/margin_activity_vertical" + android:paddingEnd="@dimen/margin_activity_horizontal" + android:paddingRight="@dimen/margin_activity_horizontal" + android:paddingStart="@dimen/margin_activity_horizontal" + android:paddingLeft="@dimen/margin_activity_horizontal" + android:paddingTop="@dimen/margin_activity_vertical"> + + <TextView + android:id="@+id/stepView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:padding="@dimen/margin_medium" + tools:text="Step 3/3" + android:layout_alignParentTop="true" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true"/> + + <TextView + android:id="@+id/connectedView" + style="@style/BriarTextTitle" + android:textSize="@dimen/text_size_large" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/connected_to_contact" + android:padding="@dimen/margin_medium" + android:layout_below="@+id/stepView" + android:layout_centerHorizontal="true" + android:drawableLeft="@drawable/navigation_accept" + android:drawableStart="@drawable/navigation_accept" + android:gravity="center_vertical"/> + + <TextView + android:id="@+id/yourConfirmationCodeView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/your_confirmation_code" + android:padding="@dimen/margin_medium" + android:layout_below="@+id/connectedView" + android:layout_centerHorizontal="true"/> + + <TextView + android:id="@+id/codeView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="@dimen/margin_medium" + android:textSize="50sp" + android:layout_below="@+id/yourConfirmationCodeView" + android:layout_centerHorizontal="true" + tools:text="1337"/> + + <TextView + android:id="@+id/waitingView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/searching_format" + android:layout_gravity="center_horizontal" + android:padding="@dimen/margin_medium" + android:layout_below="@+id/codeView" + android:layout_centerHorizontal="true" + android:visibility="gone" + android:gravity="center_horizontal"/> + + <ProgressBar + android:id="@+id/progressBar" + style="?android:attr/progressBarStyleLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:indeterminate="true" + android:layout_below="@+id/waitingView" + android:layout_centerHorizontal="true" + android:visibility="gone"/> + + <TextView + android:id="@+id/enterCodeTextView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/enter_confirmation_code" + android:layout_gravity="center_horizontal" + android:padding="@dimen/margin_medium" + android:layout_below="@+id/codeView" + android:layout_centerHorizontal="true"/> + + <include + android:id="@+id/codeEntryView" + layout="@layout/view_code_entry" + android:layout_below="@+id/enterCodeTextView" + android:layout_centerHorizontal="true" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="@dimen/margin_medium"/> + + <Button + android:id="@+id/continueButton" + style="@style/BriarButton.Default" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/continue_button" + android:layout_gravity="center_horizontal" + android:enabled="false" + android:layout_below="@+id/codeEntryView" + android:layout_centerHorizontal="true" + android:layout_margin="@dimen/margin_medium"/> + + </RelativeLayout> +</ScrollView> \ No newline at end of file diff --git a/briar-android/res/layout/invitation_bluetooth_invitation_code.xml b/briar-android/res/layout/invitation_bluetooth_invitation_code.xml new file mode 100644 index 0000000000000000000000000000000000000000..875a58d08aefd46951721cce332e8671fe33e792 --- /dev/null +++ b/briar-android/res/layout/invitation_bluetooth_invitation_code.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?> +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="@dimen/margin_activity_vertical" + android:paddingEnd="@dimen/margin_activity_horizontal" + android:paddingRight="@dimen/margin_activity_horizontal" + android:paddingStart="@dimen/margin_activity_horizontal" + android:paddingLeft="@dimen/margin_activity_horizontal" + android:paddingTop="@dimen/margin_activity_vertical"> + + <TextView + android:id="@+id/stepView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:layout_marginTop="@dimen/margin_medium" + tools:text="Step 2/3" + android:layout_alignParentTop="true" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true"/> + + <TextView + android:id="@+id/yourCodeView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/your_invitation_code" + android:layout_marginTop="@dimen/margin_medium" + android:layout_below="@+id/stepView" + android:layout_centerHorizontal="true"/> + + <TextView + android:id="@+id/codeView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/margin_medium" + android:textSize="50sp" + android:layout_below="@+id/yourCodeView" + android:layout_centerHorizontal="true" + tools:text="1337"/> + + <TextView + android:id="@+id/waitingView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/searching_format" + android:layout_gravity="center_horizontal" + android:layout_marginTop="@dimen/margin_medium" + android:layout_below="@+id/codeView" + android:layout_centerHorizontal="true" + android:visibility="gone" + android:gravity="center_horizontal"/> + + <ProgressBar + android:id="@+id/progressBar" + style="?android:attr/progressBarStyleLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:indeterminate="true" + android:layout_below="@+id/waitingView" + android:layout_centerHorizontal="true" + android:visibility="gone"/> + + <TextView + android:id="@+id/enterCodeTextView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/enter_invitation_code" + android:layout_gravity="center_horizontal" + android:padding="@dimen/margin_medium" + android:layout_below="@+id/codeView" + android:layout_centerHorizontal="true"/> + + <include + android:id="@+id/codeEntryView" + layout="@layout/view_code_entry" + android:layout_below="@+id/enterCodeTextView" + android:layout_centerHorizontal="true" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="@dimen/margin_medium"/> + + <Button + android:id="@+id/continueButton" + style="@style/BriarButton.Default" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/continue_button" + android:layout_gravity="center_horizontal" + android:enabled="false" + android:layout_below="@+id/codeEntryView" + android:layout_centerHorizontal="true" + android:layout_margin="@dimen/margin_medium"/> + + </RelativeLayout> +</ScrollView> \ No newline at end of file diff --git a/briar-android/res/layout/invitation_bluetooth_start.xml b/briar-android/res/layout/invitation_bluetooth_start.xml new file mode 100644 index 0000000000000000000000000000000000000000..9198f7537fba193244d028c2c5c68d7e0f5e6f3d --- /dev/null +++ b/briar-android/res/layout/invitation_bluetooth_start.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="@dimen/margin_activity_vertical" + android:paddingEnd="@dimen/margin_activity_horizontal" + android:paddingRight="@dimen/margin_activity_horizontal" + android:paddingStart="@dimen/margin_activity_horizontal" + android:paddingLeft="@dimen/margin_activity_horizontal" + android:paddingTop="@dimen/margin_activity_vertical"> + + <TextView + android:id="@+id/stepView" + style="@style/BriarTextBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + tools:text="Step 1/3"/> + + <TextView + android:id="@+id/yourNicknameView" + style="@style/BriarTextBody" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/your_nickname" + android:layout_marginTop="@dimen/margin_medium"/> + + <Spinner + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/spinner" + android:spinnerMode="dropdown" + android:layout_marginTop="@dimen/margin_medium"/> + + <ImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/imageView" + android:src="@drawable/bluetooth" + android:scaleType="fitCenter" + android:adjustViewBounds="true" + android:layout_marginTop="@dimen/margin_medium"/> + + <TextView + android:id="@+id/faceToFaceView" + style="@style/BriarTextBody" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/face_to_face" + android:layout_marginTop="@dimen/margin_medium"/> + + <Button + android:id="@+id/continueButton" + style="@style/BriarButton.Default" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/continue_button" + android:layout_gravity="center_horizontal" + android:layout_marginTop="@dimen/margin_medium"/> + </LinearLayout> + +</ScrollView> \ No newline at end of file diff --git a/briar-android/res/layout/invitation_error.xml b/briar-android/res/layout/invitation_error.xml new file mode 100644 index 0000000000000000000000000000000000000000..e1c94c393620793a72c963a3cc8300e818119866 --- /dev/null +++ b/briar-android/res/layout/invitation_error.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingBottom="@dimen/margin_activity_vertical" + android:paddingEnd="@dimen/margin_activity_horizontal" + android:paddingStart="@dimen/margin_activity_horizontal" + android:paddingTop="@dimen/margin_activity_vertical"> + + <TextView + android:id="@+id/errorTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/connection_failed" + android:layout_gravity="center_horizontal" + android:textSize="@dimen/text_size_large" + android:drawableStart="@drawable/alerts_and_states_error" + android:drawableLeft="@drawable/alerts_and_states_error" + android:gravity="center_vertical" + android:padding="@dimen/margin_medium"/> + + <TextView + android:id="@+id/explanationTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/interfering" + android:layout_gravity="center_horizontal" + android:padding="@dimen/margin_medium"/> + + <Button + android:id="@+id/tryAgainButton" + style="@style/BriarButton.Default" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/try_again_button" + android:layout_gravity="center_horizontal" + android:layout_margin="@dimen/margin_medium"/> + +</LinearLayout> \ No newline at end of file diff --git a/briar-android/res/layout/view_code_entry.xml b/briar-android/res/layout/view_code_entry.xml new file mode 100644 index 0000000000000000000000000000000000000000..018915876e8e147e3a5a04fb6aac062e5b74a13f --- /dev/null +++ b/briar-android/res/layout/view_code_entry.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<EditText + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/codeEntryView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:inputType="number" + android:layout_gravity="center_horizontal" + android:textSize="@dimen/text_size_xlarge" + android:ems="4" + android:maxLines="1" + android:maxLength="6" + android:layout_margin="@dimen/margin_medium" + android:imeOptions="actionGo" + tools:text="123456"/> \ No newline at end of file diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 6532d77d8a105c55ee96a9684282b88ab136f3fe..1df0b4897ad53800926576f5c861e6c86ecbc1f1 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -36,12 +36,12 @@ <string name="contact_list_title">Contacts</string> <string name="no_contacts">No contacts</string> <string name="add_contact_title">Add a Contact</string> - <string name="your_nickname">Your nickname: </string> - <string name="face_to_face">For security reasons you must be face-to-face with the person you want to add as a contact.\n\nThis will prevent anyone from impersonating you or reading your messages in future.</string> + <string name="your_nickname">Please select the identity you want to use:</string> + <string name="face_to_face">You must be face-to-face with the person you want to add as a contact. This will prevent anyone from impersonating you or reading your messages in future.</string> <string name="continue_button">Continue</string> <string name="your_invitation_code">Your invitation code is</string> <string name="enter_invitation_code">Please enter your contact\'s invitation code:</string> - <string name="searching_format">Searching for %06d\u2026</string> + <string name="searching_format">Searching for contact with invitation code %06d\u2026</string> <string name="connection_failed">Connection failed</string> <string name="could_not_find_contact">Briar could not find your contact nearby</string> <string name="try_again_button">Try Again</string> @@ -110,8 +110,9 @@ <string name="notify_sound_setting_default">Default ringtone</string> <string name="notify_sound_setting_disabled">None</string> <string name="choose_ringtone_title">Choose ringtone</string> + <string name="step">Step %1$d/%2$d</string> <!-- Dialogs --> <string name="dialog_title_lost_password">Lost password</string> <string name="dialog_message_lost_password">Password recovery is not possible. Do you wish to delete your user, all contacts, and re-register ?</string> -</resources> \ No newline at end of file +</resources> diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java index eb0a52e9da0649d590fc7c526e52788d2a8fb498..ab318363be0286c52ac208e57f751e183f3ed78e 100644 --- a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java +++ b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java @@ -1,13 +1,9 @@ package org.briarproject.android.invitation; -import static android.widget.Toast.LENGTH_LONG; -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; - -import java.util.Collection; -import java.util.logging.Logger; - -import javax.inject.Inject; +import android.bluetooth.BluetoothAdapter; +import android.content.Intent; +import android.os.Bundle; +import android.widget.Toast; import org.briarproject.R; import org.briarproject.android.BriarActivity; @@ -24,10 +20,17 @@ import org.briarproject.api.invitation.InvitationState; import org.briarproject.api.invitation.InvitationTask; import org.briarproject.api.invitation.InvitationTaskFactory; -import android.bluetooth.BluetoothAdapter; -import android.content.Intent; -import android.os.Bundle; -import android.widget.Toast; +import java.util.Collection; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import static android.widget.Toast.LENGTH_LONG; +import static java.util.logging.Level.INFO; +import static java.util.logging.Level.WARNING; +import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.CONNECTED; +import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.WAIT_FOR_CONTACT; +import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.DETAILS; public class AddContactActivity extends BriarActivity implements InvitationListener { @@ -86,9 +89,10 @@ implements InvitationListener { } else if (remoteInvitationCode == -1) { setView(new InvitationCodeView(this)); } else if (connectionFailed) { - setView(new ConnectionFailedView(this)); + setView(new ErrorView(this, R.string.connection_failed, + R.string.could_not_find_contact)); } else if (contactName == null) { - setView(new CodesDoNotMatchView(this)); + setView(new ErrorView(this, R.string.codes_do_not_match, R.string.interfering)); } else { showToastAndFinish(); return; @@ -113,24 +117,25 @@ implements InvitationListener { } else if (remoteInvitationCode == -1) { setView(new InvitationCodeView(this)); } else if (connectionFailed) { - setView(new ConnectionFailedView(this)); + setView(new ErrorView(AddContactActivity.this, R.string.connection_failed, + R.string.could_not_find_contact)); } else if (connected && localConfirmationCode == -1) { - setView(new ConnectedView(this)); + setView(new ConfirmationCodeView(this, CONNECTED)); } else if (localConfirmationCode == -1) { - setView(new ConnectionView(this)); + setView(new InvitationCodeView(this, true)); } else if (!localCompared) { setView(new ConfirmationCodeView(this)); } else if (!remoteCompared) { - setView(new WaitForContactView(this)); + setView(new ConfirmationCodeView(this, WAIT_FOR_CONTACT)); } else if (localMatched && remoteMatched) { if (contactName == null) { - setView(new ContactDetailsView(this)); + setView(new ConfirmationCodeView(this, DETAILS)); } else { showToastAndFinish(); return; } } else { - setView(new CodesDoNotMatchView(this)); + setView(new ErrorView(this, R.string.codes_do_not_match, R.string.interfering)); } } } @@ -276,7 +281,10 @@ implements InvitationListener { if (localAuthorId == null) throw new IllegalStateException(); if (localInvitationCode == -1) throw new IllegalStateException(); remoteInvitationCode = code; - setView(new ConnectionView(this)); + + // change UI to show a progress indicator + setView(new InvitationCodeView(this, true)); + task = invitationTaskFactory.createTask(localAuthorId, localInvitationCode, code, enableBluetooth); taskHandle = referenceManager.putReference(task, InvitationTask.class); @@ -295,13 +303,14 @@ implements InvitationListener { localCompared = true; if (code == remoteConfirmationCode) { localMatched = true; - if (remoteMatched) setView(new ContactDetailsView(this)); - else if (remoteCompared) setView(new CodesDoNotMatchView(this)); - else setView(new WaitForContactView(this)); + if (remoteMatched) setView(new ConfirmationCodeView(this, DETAILS)); + else if (remoteCompared) setView(new ErrorView(this, R.string.codes_do_not_match, + R.string.interfering)); + else setView(new ConfirmationCodeView(this, WAIT_FOR_CONTACT)); task.localConfirmationSucceeded(); } else { localMatched = false; - setView(new CodesDoNotMatchView(this)); + setView(new ErrorView(this, R.string.codes_do_not_match, R.string.interfering)); task.localConfirmationFailed(); } } @@ -314,7 +323,7 @@ implements InvitationListener { runOnUiThread(new Runnable() { public void run() { connected = true; - setView(new ConnectedView(AddContactActivity.this)); + setView(new ConfirmationCodeView(AddContactActivity.this, CONNECTED)); } }); } @@ -323,7 +332,8 @@ implements InvitationListener { runOnUiThread(new Runnable() { public void run() { connectionFailed = true; - setView(new ConnectionFailedView(AddContactActivity.this)); + setView(new ErrorView(AddContactActivity.this, R.string.connection_failed, + R.string.could_not_find_contact)); } }); } @@ -343,7 +353,8 @@ implements InvitationListener { runOnUiThread(new Runnable() { public void run() { connectionFailed = true; - setView(new ConnectionFailedView(AddContactActivity.this)); + setView(new ErrorView(AddContactActivity.this, R.string.connection_failed, + R.string.could_not_find_contact)); } }); } @@ -354,7 +365,7 @@ implements InvitationListener { remoteCompared = true; remoteMatched = true; if (localMatched) - setView(new ContactDetailsView(AddContactActivity.this)); + setView(new ConfirmationCodeView(AddContactActivity.this, DETAILS)); } }); } @@ -365,7 +376,8 @@ implements InvitationListener { remoteCompared = true; remoteMatched = false; if (localMatched) - setView(new CodesDoNotMatchView(AddContactActivity.this)); + setView(new ErrorView(AddContactActivity.this, R.string.codes_do_not_match, + R.string.interfering)); } }); } @@ -382,7 +394,8 @@ implements InvitationListener { public void pseudonymExchangeFailed() { runOnUiThread(new Runnable() { public void run() { - setView(new ConnectionFailedView(AddContactActivity.this)); + setView(new ErrorView(AddContactActivity.this, R.string.connection_failed, + R.string.could_not_find_contact)); } }); } diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactView.java b/briar-android/src/org/briarproject/android/invitation/AddContactView.java index 2a6b978493557988f47b2663a44a9c018dfda631..6a6b300be31f4e03f0ebc459df86f5d073bede7a 100644 --- a/briar-android/src/org/briarproject/android/invitation/AddContactView.java +++ b/briar-android/src/org/briarproject/android/invitation/AddContactView.java @@ -1,31 +1,22 @@ package org.briarproject.android.invitation; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH; - -import org.briarproject.android.util.LayoutUtils; - import android.content.Context; import android.widget.LinearLayout; abstract class AddContactView extends LinearLayout { - protected final int pad; - + static final public int CODE_LEN = 6; protected AddContactActivity container = null; AddContactView(Context ctx) { super(ctx); - pad = LayoutUtils.getPadding(ctx); } void init(AddContactActivity container) { this.container = container; - setLayoutParams(MATCH_MATCH); - setOrientation(VERTICAL); - setGravity(CENTER_HORIZONTAL); populate(); } abstract void populate(); + } diff --git a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java index 5ecd1898fadb719cd74b7ff691af18c64d8da260..f609eb93f2d00b015e1fa4ac8a7ec856f814efe4 100644 --- a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java +++ b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java @@ -21,6 +21,7 @@ import org.briarproject.api.LocalAuthor; import android.content.Context; import android.content.Intent; +import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; @@ -35,7 +36,6 @@ implements OnItemSelectedListener, OnClickListener { private LocalAuthorSpinnerAdapter adapter = null; private Spinner spinner = null; - private Button continueButton = null; ChooseIdentityView(Context ctx) { super(ctx); @@ -45,34 +45,22 @@ implements OnItemSelectedListener, OnClickListener { removeAllViews(); Context ctx = getContext(); - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setLayoutParams(MATCH_WRAP); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); + LayoutInflater inflater = (LayoutInflater) ctx.getSystemService + (Context.LAYOUT_INFLATER_SERVICE); + View view = inflater.inflate(R.layout.invitation_bluetooth_start, this); - TextView yourNickname = new TextView(ctx); - yourNickname.setTextSize(18); - yourNickname.setPadding(pad, pad, pad, pad); - yourNickname.setText(R.string.your_nickname); - innerLayout.addView(yourNickname); + // current step + // TODO this could go into the ActionBar eventually + TextView step = (TextView) view.findViewById(R.id.stepView); + step.setText(String.format(ctx.getString(R.string.step), 1, 3)); adapter = new LocalAuthorSpinnerAdapter(ctx, false); - spinner = new Spinner(ctx); + spinner = (Spinner) view.findViewById(R.id.spinner); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); - innerLayout.addView(spinner); - addView(innerLayout); - TextView faceToFace = new TextView(ctx); - faceToFace.setPadding(pad, pad, pad, pad); - faceToFace.setText(R.string.face_to_face); - addView(faceToFace); - - continueButton = new Button(ctx); - continueButton.setLayoutParams(WRAP_WRAP); - continueButton.setText(R.string.continue_button); + Button continueButton = (Button) view.findViewById(R.id.continueButton); continueButton.setOnClickListener(this); - addView(continueButton); container.loadLocalAuthors(); } diff --git a/briar-android/src/org/briarproject/android/invitation/CodeEntryListener.java b/briar-android/src/org/briarproject/android/invitation/CodeEntryListener.java deleted file mode 100644 index e63c8b177797eedd09d2e081fb6b7df42519bce9..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/invitation/CodeEntryListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.briarproject.android.invitation; - -interface CodeEntryListener { - - void codeEntered(int remoteCode); -} diff --git a/briar-android/src/org/briarproject/android/invitation/CodeEntryView.java b/briar-android/src/org/briarproject/android/invitation/CodeEntryView.java deleted file mode 100644 index d15bfdab37232a801d991765d1de003421170cc4..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/invitation/CodeEntryView.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.briarproject.android.invitation; - -import static android.content.Context.INPUT_METHOD_SERVICE; -import static android.text.InputType.TYPE_CLASS_NUMBER; -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY; -import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP; - -import org.briarproject.R; -import org.briarproject.android.util.LayoutUtils; - -import android.content.Context; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.inputmethod.InputMethodManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.TextView.OnEditorActionListener; - -class CodeEntryView extends LinearLayout -implements OnEditorActionListener, OnClickListener { - - private final int pad; - - private CodeEntryListener listener = null; - private EditText codeEntry = null; - private Button continueButton = null; - - public CodeEntryView(Context ctx) { - super(ctx); - pad = LayoutUtils.getPadding(ctx); - } - - void init(CodeEntryListener listener, String prompt) { - this.listener = listener; - setOrientation(VERTICAL); - setGravity(CENTER_HORIZONTAL); - - Context ctx = getContext(); - TextView enterCode = new TextView(ctx); - enterCode.setGravity(CENTER_HORIZONTAL); - enterCode.setPadding(pad, pad, pad, 0); - enterCode.setText(prompt); - addView(enterCode); - - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - codeEntry = new EditText(ctx) { - @Override - protected void onTextChanged(CharSequence text, int start, - int lengthBefore, int lengthAfter) { - if (continueButton != null) - continueButton.setEnabled(getText().length() == 6); - } - }; - codeEntry.setId(1); // FIXME: State is not saved and restored - codeEntry.setTextSize(26); - codeEntry.setOnEditorActionListener(this); - codeEntry.setMinEms(5); - codeEntry.setMaxEms(5); - codeEntry.setMaxLines(1); - codeEntry.setInputType(TYPE_CLASS_NUMBER); - innerLayout.addView(codeEntry); - - continueButton = new Button(ctx); - continueButton.setLayoutParams(WRAP_WRAP); - continueButton.setText(R.string.continue_button); - continueButton.setEnabled(false); - continueButton.setOnClickListener(this); - innerLayout.addView(continueButton); - addView(innerLayout); - } - - public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { - if (!validateAndReturnCode()) codeEntry.setText(""); - return true; - } - - public void onClick(View view) { - if (!validateAndReturnCode()) codeEntry.setText(""); - } - - private boolean validateAndReturnCode() { - String remoteCodeString = codeEntry.getText().toString(); - int remoteCode; - try { - remoteCode = Integer.parseInt(remoteCodeString); - } catch (NumberFormatException e) { - return false; - } - // Hide the soft keyboard - Object o = getContext().getSystemService(INPUT_METHOD_SERVICE); - ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0); - listener.codeEntered(remoteCode); - return true; - } -} diff --git a/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java b/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java index 7c52cd880b0e1395a8e025e4953699d2f995e742..118744cc928162f3a7db100299932eba5b838065 100644 --- a/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java +++ b/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java @@ -1,60 +1,126 @@ package org.briarproject.android.invitation; -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; +import android.content.Context; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; import org.briarproject.R; -import android.content.Context; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; +import static android.content.Context.INPUT_METHOD_SERVICE; +import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY; + +class ConfirmationCodeView extends AddContactView { -class ConfirmationCodeView extends AddContactView implements CodeEntryListener { + public enum ConfirmationState { CONNECTED, ENTER_CODE, WAIT_FOR_CONTACT, DETAILS } + private ConfirmationState state; ConfirmationCodeView(Context ctx) { super(ctx); + this.state = ConfirmationState.ENTER_CODE; + } + + ConfirmationCodeView(Context ctx, ConfirmationState state) { + super(ctx); + this.state = state; } void populate() { removeAllViews(); Context ctx = getContext(); - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(ctx); - icon.setImageResource(R.drawable.navigation_accept); - innerLayout.addView(icon); - - TextView connected = new TextView(ctx); - connected.setTextSize(22); - connected.setPadding(pad, pad, pad, pad); - connected.setText(R.string.connected_to_contact); - innerLayout.addView(connected); - addView(innerLayout); - - TextView yourCode = new TextView(ctx); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setPadding(pad, pad, pad, pad); - yourCode.setText(R.string.your_confirmation_code); - addView(yourCode); - - TextView code = new TextView(ctx); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setPadding(pad, 0, pad, pad); + + LayoutInflater inflater = (LayoutInflater) ctx.getSystemService + (Context.LAYOUT_INFLATER_SERVICE); + View view = inflater.inflate(R.layout.invitation_bluetooth_confirmation_code, this); + + // current step + // TODO this could go into the ActionBar eventually + TextView step = (TextView) view.findViewById(R.id.stepView); + step.setText(String.format(ctx.getString(R.string.step), 3, 3)); + + // local confirmation code + TextView code = (TextView) view.findViewById(R.id.codeView); int localCode = container.getLocalConfirmationCode(); code.setText(String.format("%06d", localCode)); - addView(code); - CodeEntryView codeEntry = new CodeEntryView(ctx); - String enter = container.getString(R.string.enter_confirmation_code); - codeEntry.init(this, enter); - addView(codeEntry); + if (state != ConfirmationState.ENTER_CODE) { + // hide views we no longer need + view.findViewById(R.id.enterCodeTextView).setVisibility(View.GONE); + view.findViewById(R.id.codeEntryView).setVisibility(View.GONE); + view.findViewById(R.id.continueButton).setVisibility(View.GONE); + + // show progress indicator + view.findViewById(R.id.progressBar).setVisibility(View.VISIBLE); + + // show what we are waiting for + TextView connecting = (TextView) view.findViewById(R.id.waitingView); + int textId; + if (state == ConfirmationState.CONNECTED) { + textId = R.string.calculating_confirmation_code; + view.findViewById(R.id.yourConfirmationCodeView).setVisibility(View.GONE); + view.findViewById(R.id.codeView).setVisibility(View.GONE); + } else if (state == ConfirmationState.WAIT_FOR_CONTACT) { + textId = R.string.waiting_for_contact; + } else { + textId = R.string.exchanging_contact_details; + } + connecting.setText(ctx.getString(textId)); + connecting.setVisibility(View.VISIBLE); + } + else { + // handle click on continue button + final EditText codeEntry = (EditText) view.findViewById(R.id.codeEntryView); + final Button continueButton = (Button) view.findViewById(R.id.continueButton); + continueButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + send(codeEntry); + } + }); + + // activate continue button only when we have a 6 digit (CODE_LEN) code + codeEntry.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + continueButton.setEnabled(codeEntry.getText().length() == CODE_LEN); + } + + @Override + public void afterTextChanged(Editable s) { + } + }); + + codeEntry.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_GO && v.getText().length() == CODE_LEN) { + send(v); + return true; + } + return false; + } + }); + } } - public void codeEntered(int remoteCode) { - container.remoteConfirmationCodeEntered(remoteCode); + private void send(TextView codeEntry) { + int code = Integer.parseInt(codeEntry.getText().toString()); + container.remoteConfirmationCodeEntered(code); + + // Hide the soft keyboard + Object o = getContext().getSystemService(INPUT_METHOD_SERVICE); + ((InputMethodManager) o).hideSoftInputFromWindow(codeEntry.getWindowToken(), 0); } + } diff --git a/briar-android/src/org/briarproject/android/invitation/ConnectedView.java b/briar-android/src/org/briarproject/android/invitation/ConnectedView.java deleted file mode 100644 index b9a51abec686244cf8044856933bcc958b16cfdb..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/invitation/ConnectedView.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.briarproject.android.invitation; - -import static android.view.Gravity.CENTER; - -import org.briarproject.R; - -import android.content.Context; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - -class ConnectedView extends AddContactView { - - ConnectedView(Context ctx) { - super(ctx); - } - - void populate() { - removeAllViews(); - Context ctx = getContext(); - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(ctx); - icon.setImageResource(R.drawable.navigation_accept); - innerLayout.addView(icon); - - TextView connected = new TextView(ctx); - connected.setTextSize(22); - connected.setPadding(pad, pad, pad, pad); - connected.setText(R.string.connected_to_contact); - innerLayout.addView(connected); - addView(innerLayout); - - innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ProgressBar progress = new ProgressBar(ctx); - progress.setIndeterminate(true); - progress.setPadding(pad, pad, pad, pad); - innerLayout.addView(progress); - - TextView connecting = new TextView(ctx); - connecting.setText(R.string.calculating_confirmation_code); - innerLayout.addView(connecting); - addView(innerLayout); - } -} diff --git a/briar-android/src/org/briarproject/android/invitation/ConnectionFailedView.java b/briar-android/src/org/briarproject/android/invitation/ConnectionFailedView.java deleted file mode 100644 index 346d9788c41d9b1c89623727b35c92831873384f..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/invitation/ConnectionFailedView.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.briarproject.android.invitation; - -import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE; -import static android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION; -import static android.view.Gravity.CENTER; -import static org.briarproject.android.invitation.AddContactActivity.REQUEST_BLUETOOTH; -import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP; - -import org.briarproject.R; - -import android.content.Context; -import android.content.Intent; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -class ConnectionFailedView extends AddContactView implements OnClickListener { - - private Button tryAgainButton = null; - - ConnectionFailedView(Context ctx) { - super(ctx); - } - - void populate() { - removeAllViews(); - Context ctx = getContext(); - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(ctx); - icon.setImageResource(R.drawable.alerts_and_states_error); - innerLayout.addView(icon); - - TextView failed = new TextView(ctx); - failed.setTextSize(22); - failed.setPadding(pad, pad, pad, pad); - failed.setText(R.string.connection_failed); - innerLayout.addView(failed); - addView(innerLayout); - - TextView couldNotFind = new TextView(ctx); - couldNotFind.setGravity(CENTER); - couldNotFind.setPadding(pad, 0, pad, pad); - couldNotFind.setText(R.string.could_not_find_contact); - addView(couldNotFind); - - tryAgainButton = new Button(ctx); - tryAgainButton.setLayoutParams(WRAP_WRAP); - tryAgainButton.setText(R.string.try_again_button); - tryAgainButton.setOnClickListener(this); - addView(tryAgainButton); - } - - public void onClick(View view) { - Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE); - i.putExtra(EXTRA_DISCOVERABLE_DURATION, 120); - container.startActivityForResult(i, REQUEST_BLUETOOTH); - } -} diff --git a/briar-android/src/org/briarproject/android/invitation/ConnectionView.java b/briar-android/src/org/briarproject/android/invitation/ConnectionView.java deleted file mode 100644 index e85b100c0cf0a26c3d843bf09603f01afd7deebc..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/invitation/ConnectionView.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.briarproject.android.invitation; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; - -import org.briarproject.R; - -import android.content.Context; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - -class ConnectionView extends AddContactView { - - ConnectionView(Context ctx) { - super(ctx); - } - - void populate() { - removeAllViews(); - Context ctx = getContext(); - TextView yourCode = new TextView(ctx); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setPadding(pad, pad, pad, pad); - yourCode.setText(R.string.your_invitation_code); - addView(yourCode); - - TextView code = new TextView(ctx); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setPadding(pad, 0, pad, pad); - int localCode = container.getLocalInvitationCode(); - code.setText(String.format("%06d", localCode)); - addView(code); - - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ProgressBar progress = new ProgressBar(ctx); - progress.setPadding(pad, pad, pad, pad); - progress.setIndeterminate(true); - innerLayout.addView(progress); - - TextView connecting = new TextView(ctx); - int remoteCode = container.getRemoteInvitationCode(); - String format = container.getString(R.string.searching_format); - connecting.setText(String.format(format, remoteCode)); - innerLayout.addView(connecting); - - addView(innerLayout); - } -} diff --git a/briar-android/src/org/briarproject/android/invitation/ContactDetailsView.java b/briar-android/src/org/briarproject/android/invitation/ContactDetailsView.java deleted file mode 100644 index 9e8a83f78c4b838a69052efdc13569134bed527a..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/invitation/ContactDetailsView.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.briarproject.android.invitation; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; - -import org.briarproject.R; - -import android.content.Context; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - -class ContactDetailsView extends AddContactView { - - ContactDetailsView(Context ctx) { - super(ctx); - } - - void populate() { - removeAllViews(); - Context ctx = getContext(); - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(ctx); - icon.setImageResource(R.drawable.navigation_accept); - innerLayout.addView(icon); - - TextView connected = new TextView(ctx); - connected.setTextSize(22); - connected.setPadding(pad, pad, pad, pad); - connected.setText(R.string.connected_to_contact); - innerLayout.addView(connected); - addView(innerLayout); - - TextView yourCode = new TextView(ctx); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setPadding(pad, 0, pad, pad); - yourCode.setText(R.string.your_confirmation_code); - addView(yourCode); - - TextView code = new TextView(ctx); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setPadding(pad, 0, pad, pad); - int localCode = container.getLocalConfirmationCode(); - code.setText(String.format("%06d", localCode)); - addView(code); - - innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ProgressBar progress = new ProgressBar(ctx); - progress.setIndeterminate(true); - progress.setPadding(pad, pad, pad, pad); - innerLayout.addView(progress); - - TextView connecting = new TextView(ctx); - connecting.setText(R.string.exchanging_contact_details); - innerLayout.addView(connecting); - addView(innerLayout); - } -} diff --git a/briar-android/src/org/briarproject/android/invitation/CodesDoNotMatchView.java b/briar-android/src/org/briarproject/android/invitation/ErrorView.java similarity index 52% rename from briar-android/src/org/briarproject/android/invitation/CodesDoNotMatchView.java rename to briar-android/src/org/briarproject/android/invitation/ErrorView.java index ea800ccfc8cd4c2028bf074fd82da482062938c5..0f17a4ebf02fbf7020577daa1a7c5e1094b60a5c 100644 --- a/briar-android/src/org/briarproject/android/invitation/CodesDoNotMatchView.java +++ b/briar-android/src/org/briarproject/android/invitation/ErrorView.java @@ -10,6 +10,7 @@ import org.briarproject.R; import android.content.Context; import android.content.Intent; +import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; @@ -17,41 +18,39 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -class CodesDoNotMatchView extends AddContactView implements OnClickListener { +class ErrorView extends AddContactView implements OnClickListener { - CodesDoNotMatchView(Context ctx) { + private final int error; + private final int explanation; + + ErrorView(Context ctx) { + super(ctx); + this.error = R.string.connection_failed; + this.explanation = R.string.could_not_find_contact; + } + + ErrorView(Context ctx, int error, int explanation) { super(ctx); + this.error = error; + this.explanation = explanation; } void populate() { removeAllViews(); Context ctx = getContext(); - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(ctx); - icon.setImageResource(R.drawable.alerts_and_states_error); - innerLayout.addView(icon); - - TextView failed = new TextView(ctx); - failed.setTextSize(22); - failed.setPadding(pad, pad, pad, pad); - failed.setText(R.string.codes_do_not_match); - innerLayout.addView(failed); - addView(innerLayout); - - TextView interfering = new TextView(ctx); - interfering.setGravity(CENTER); - interfering.setPadding(pad, 0, pad, pad); - interfering.setText(R.string.interfering); - addView(interfering); - - Button tryAgainButton = new Button(ctx); - tryAgainButton.setLayoutParams(WRAP_WRAP); - tryAgainButton.setText(R.string.try_again_button); + + LayoutInflater inflater = (LayoutInflater) ctx.getSystemService + (Context.LAYOUT_INFLATER_SERVICE); + View view = inflater.inflate(R.layout.invitation_error, this); + + TextView errorView = (TextView) view.findViewById(R.id.errorTextView); + errorView.setText(ctx.getString(error)); + + TextView explanationView = (TextView) view.findViewById(R.id.explanationTextView); + explanationView.setText(ctx.getString(explanation)); + + Button tryAgainButton = (Button) view.findViewById(R.id.tryAgainButton); tryAgainButton.setOnClickListener(this); - addView(tryAgainButton); } public void onClick(View view) { diff --git a/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java b/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java index 1f014fc0c9c09536ef78433c96927155011cf72c..ebd6fcc13eaf79c53a2dd9b64193999877c2b63f 100644 --- a/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java +++ b/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java @@ -1,42 +1,116 @@ package org.briarproject.android.invitation; -import static android.view.Gravity.CENTER_HORIZONTAL; +import android.content.Context; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; import org.briarproject.R; -import android.content.Context; -import android.widget.TextView; +import static android.content.Context.INPUT_METHOD_SERVICE; +import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY; -class InvitationCodeView extends AddContactView implements CodeEntryListener { +class InvitationCodeView extends AddContactView { - InvitationCodeView(Context ctx) { + private boolean waiting; + + InvitationCodeView(Context ctx, boolean waiting) { super(ctx); + this.waiting = waiting; + } + + InvitationCodeView(Context ctx) { + this(ctx, false); } void populate() { removeAllViews(); Context ctx = getContext(); - TextView yourCode = new TextView(ctx); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setPadding(pad, pad, pad, pad); - yourCode.setText(R.string.your_invitation_code); - addView(yourCode); - - TextView code = new TextView(ctx); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setPadding(pad, 0, pad, pad); + + LayoutInflater inflater = (LayoutInflater) ctx.getSystemService + (Context.LAYOUT_INFLATER_SERVICE); + View view = inflater.inflate(R.layout.invitation_bluetooth_invitation_code, this); + + // current step + // TODO this could go into the ActionBar eventually + TextView step = (TextView) view.findViewById(R.id.stepView); + step.setText(String.format(ctx.getString(R.string.step), 2, 3)); + + // local invitation code + TextView code = (TextView) view.findViewById(R.id.codeView); int localCode = container.getLocalInvitationCode(); code.setText(String.format("%06d", localCode)); - addView(code); - CodeEntryView codeEntry = new CodeEntryView(ctx); - String enter = container.getString(R.string.enter_invitation_code); - codeEntry.init(this, enter); - addView(codeEntry); + if (waiting) { + // hide views we no longer need + view.findViewById(R.id.enterCodeTextView).setVisibility(View.GONE); + view.findViewById(R.id.codeEntryView).setVisibility(View.GONE); + view.findViewById(R.id.continueButton).setVisibility(View.GONE); + + // show progress indicator + view.findViewById(R.id.progressBar).setVisibility(View.VISIBLE); + + // show which code we are waiting for + TextView connecting = (TextView) view.findViewById(R.id.waitingView); + int remoteCode = container.getRemoteInvitationCode(); + String format = container.getString(R.string.searching_format); + connecting.setText(String.format(format, remoteCode)); + connecting.setVisibility(View.VISIBLE); + } + else { + // handle click on continue button + final EditText codeEntry = (EditText) view.findViewById(R.id.codeEntryView); + final Button continueButton = (Button) view.findViewById(R.id.continueButton); + continueButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + send(codeEntry); + } + }); + + // activate continue button only when we have a 6 digit (CODE_LEN) code + codeEntry.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + continueButton.setEnabled(codeEntry.getText().length() == CODE_LEN); + } + + @Override + public void afterTextChanged(Editable s) { + } + }); + + codeEntry.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_GO && v.getText().length() == CODE_LEN) { + send(v); + return true; + } + return false; + } + }); + } } - public void codeEntered(int remoteCode) { - container.remoteInvitationCodeEntered(remoteCode); + private void send(TextView codeEntry) { + int code = Integer.parseInt(codeEntry.getText().toString()); + container.remoteInvitationCodeEntered(code); + + // Hide the soft keyboard + Object o = getContext().getSystemService(INPUT_METHOD_SERVICE); + ((InputMethodManager) o).hideSoftInputFromWindow(codeEntry.getWindowToken(), 0); } + } diff --git a/briar-android/src/org/briarproject/android/invitation/WaitForContactView.java b/briar-android/src/org/briarproject/android/invitation/WaitForContactView.java deleted file mode 100644 index f417dd113940a72861d448a07fde7ddc12c9bbc3..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/invitation/WaitForContactView.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.briarproject.android.invitation; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; - -import org.briarproject.R; - -import android.content.Context; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - -class WaitForContactView extends AddContactView { - - WaitForContactView(Context ctx) { - super(ctx); - } - - void populate() { - removeAllViews(); - Context ctx = getContext(); - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(ctx); - icon.setImageResource(R.drawable.navigation_accept); - innerLayout.addView(icon); - - TextView connected = new TextView(ctx); - connected.setTextSize(22); - connected.setPadding(pad, pad, pad, pad); - connected.setText(R.string.connected_to_contact); - innerLayout.addView(connected); - addView(innerLayout); - - TextView yourCode = new TextView(ctx); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setPadding(pad, 0, pad, pad); - yourCode.setText(R.string.your_confirmation_code); - addView(yourCode); - - TextView code = new TextView(ctx); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setPadding(pad, 0, pad, pad); - int localCode = container.getLocalConfirmationCode(); - code.setText(String.format("%06d", localCode)); - addView(code); - - innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ProgressBar progress = new ProgressBar(ctx); - progress.setIndeterminate(true); - progress.setPadding(pad, pad, pad, pad); - innerLayout.addView(progress); - - TextView connecting = new TextView(ctx); - connecting.setText(R.string.waiting_for_contact); - innerLayout.addView(connecting); - addView(innerLayout); - } -}