~singpolyma/cheogram-android

7a3ba3e375bb7ef1f3fe20d57237554c27362106 — Daniel Gultsch 5 years ago f10f373
created enter phone number activity
M build.gradle => build.gradle +2 -0
@@ 23,6 23,7 @@ configurations {
    compatImplementation
    fullFreeCompatImplementation
    quickFreeCompatImplementation
    quickImplementation
}

ext {


@@ 59,6 60,7 @@ dependencies {
    implementation 'org.osmdroid:osmdroid-android:6.0.1'
    implementation 'org.hsluv:hsluv:0.2'
    implementation 'org.conscrypt:conscrypt-android:1.3.0'
    quickImplementation 'io.michaelrocks:libphonenumber-android:8.9.14'
}

ext {

M src/main/res/values/strings.xml => src/main/res/values/strings.xml +8 -0
@@ 750,4 750,12 @@
    <string name="cancelled">cancelled</string>
    <string name="already_drafting_message">You are already drafting a message.</string>
    <string name="feature_not_implemented">Feature not implemented</string>
    <string name="invalid_country_code">Invalid country code</string>
    <string name="choose_a_country">Choose a country</string>
    <string name="phone_number">phone number</string>
    <string name="verify_your_phone_number">Verify your phone number</string>
    <string name="enter_country_code_and_phone_number">Quick Conversations will send an SMS message (carrier charges may apply) to verify your phone number. Enter your country code and phone number:</string>
    <string name="we_will_be_verifying"><![CDATA[We will be verifying the phone number<br/><br/><b>%s</b><br/><br/>Is this OK, or would you like to edit the number?]]></string>
    <string name="not_a_valid_phone_number">%s is not a valid phone number.</string>
    <string name="please_enter_your_phone_number">Please enter your phone number.</string>
</resources>

A src/quick/AndroidManifest.xml => src/quick/AndroidManifest.xml +13 -0
@@ 0,0 1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="eu.siacs.conversations">

    <application tools:ignore="GoogleAppIndexingWarning">
        <activity
            android:name=".ui.EnterPhoneNumberActivity"
            android:label="@string/verify_your_phone_number"
            android:launchMode="singleTask" />

    </application>
</manifest>

A src/quick/java/eu/siacs/conversations/ui/EnterPhoneNumberActivity.java => src/quick/java/eu/siacs/conversations/ui/EnterPhoneNumberActivity.java +107 -0
@@ 0,0 1,107 @@
package eu.siacs.conversations.ui;

import android.app.AlertDialog;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.Html;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;

import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ActivityEnterNumberBinding;
import eu.siacs.conversations.ui.drawable.TextDrawable;
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
import io.michaelrocks.libphonenumber.android.NumberParseException;
import io.michaelrocks.libphonenumber.android.PhoneNumberUtil;
import io.michaelrocks.libphonenumber.android.Phonenumber;

public class EnterPhoneNumberActivity extends AppCompatActivity {

    private ActivityEnterNumberBinding binding;
    private String region = null;
    private final TextWatcher countryCodeTextWatcher = 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) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            final String text = editable.toString();
            try {
                final int code = Integer.parseInt(text);
                region = PhoneNumberUtilWrapper.getInstance(EnterPhoneNumberActivity.this).getRegionCodeForCountryCode(code);
                if ("ZZ".equals(region)) {
                    binding.country.setText(TextUtils.isEmpty(text) ? R.string.choose_a_country : R.string.invalid_country_code);
                } else {
                    binding.number.requestFocus();
                    binding.country.setText(PhoneNumberUtilWrapper.getCountryForCode(region));
                }
            } catch (NumberFormatException e) {
                binding.country.setText(TextUtils.isEmpty(text) ? R.string.choose_a_country : R.string.invalid_country_code);
            }
        }
    };

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.binding = DataBindingUtil.setContentView(this, R.layout.activity_enter_number);
        this.binding.countryCode.setCompoundDrawables(new TextDrawable(this.binding.countryCode, "+"), null, null, null);
        this.binding.country.setOnClickListener(this::onSelectCountryClick);
        this.binding.next.setOnClickListener(this::onNextClick);
        setSupportActionBar((Toolbar) this.binding.toolbar);


        this.binding.countryCode.addTextChangedListener(this.countryCodeTextWatcher);
        this.region = PhoneNumberUtilWrapper.getUserCountry(this);
        this.binding.countryCode.setText(String.valueOf(PhoneNumberUtilWrapper.getInstance(this).getCountryCodeForRegion(this.region)));
    }

    private void onNextClick(View v) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        try {
            final Editable number = this.binding.number.getText();
            final String input = number.toString();
            final Phonenumber.PhoneNumber phoneNumber = PhoneNumberUtilWrapper.getInstance(this).parse(input, region);
            this.binding.countryCode.setText(String.valueOf(phoneNumber.getCountryCode()));
            number.clear();
            number.append(String.valueOf(phoneNumber.getNationalNumber()));
            final String formattedPhoneNumber = PhoneNumberUtilWrapper.getInstance(this).format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL);

            if (PhoneNumberUtilWrapper.getInstance(this).isValidNumber(phoneNumber)) {
                builder.setMessage(Html.fromHtml(getString(R.string.we_will_be_verifying, formattedPhoneNumber)));
                builder.setNegativeButton(R.string.edit, null);
                builder.setPositiveButton(R.string.ok, (dialog, which) -> onPhoneNumberEntered(phoneNumber));
            } else {
                builder.setMessage(getString(R.string.not_a_valid_phone_number, formattedPhoneNumber));
                builder.setPositiveButton(R.string.ok, null);
            }
            Log.d(Config.LOGTAG, phoneNumber.toString());
        } catch (NumberParseException e) {
            builder.setMessage(R.string.please_enter_your_phone_number);
            builder.setPositiveButton(R.string.ok, null);
        }
        builder.create().show();
    }

    private void onSelectCountryClick(View view) {

    }

    private void onPhoneNumberEntered(Phonenumber.PhoneNumber phoneNumber) {

    }

}

A src/quick/java/eu/siacs/conversations/ui/drawable/TextDrawable.java => src/quick/java/eu/siacs/conversations/ui/drawable/TextDrawable.java +240 -0
@@ 0,0 1,240 @@
package eu.siacs.conversations.ui.drawable; /**
 * Copyright 2016 Ali Muzaffar
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.TextView;

import java.lang.ref.WeakReference;

public class TextDrawable extends Drawable implements TextWatcher {
    private WeakReference<TextView> ref;
    private String mText;
    private Paint mPaint;
    private Rect mHeightBounds;
    private boolean mBindToViewPaint = false;
    private float mPrevTextSize = 0;
    private boolean mInitFitText = false;
    private boolean mFitTextEnabled = false;

    /**
     * Create a TextDrawable using the given paint object and string
     *
     * @param paint
     * @param s
     */
    public TextDrawable(Paint paint, String s) {
        mText = s;
        mPaint = new Paint(paint);
        mHeightBounds = new Rect();
        init();
    }

    /**
     * Create a TextDrawable. This uses the given TextView to initialize paint and has initial text
     * that will be drawn. Initial text can also be useful for reserving space that may otherwise
     * not be available when setting compound drawables.
     *
     * @param tv               The TextView / EditText using to initialize this drawable
     * @param initialText      Optional initial text to display
     * @param bindToViewsText  Should this drawable mirror the text in the TextView
     * @param bindToViewsPaint Should this drawable mirror changes to Paint in the TextView, like textColor, typeface, alpha etc.
     *                         Note, this will override any changes made using setColorFilter or setAlpha.
     */
    public TextDrawable(TextView tv, String initialText, boolean bindToViewsText, boolean bindToViewsPaint) {
        this(tv.getPaint(), initialText);
        ref = new WeakReference<>(tv);
        if (bindToViewsText || bindToViewsPaint) {
            if (bindToViewsText) {
                tv.addTextChangedListener(this);
            }
            mBindToViewPaint = bindToViewsPaint;
        }
    }

    /**
     * Create a TextDrawable. This uses the given TextView to initialize paint and the text that
     * will be drawn.
     *
     * @param tv               The TextView / EditText using to initialize this drawable
     * @param bindToViewsText  Should this drawable mirror the text in the TextView
     * @param bindToViewsPaint Should this drawable mirror changes to Paint in the TextView, like textColor, typeface, alpha etc.
     *                         Note, this will override any changes made using setColorFilter or setAlpha.
     */
    public TextDrawable(TextView tv, boolean bindToViewsText, boolean bindToViewsPaint) {
        this(tv, tv.getText().toString(), false, false);
    }

    /**
     * Use the provided TextView/EditText to initialize the drawable.
     * The Drawable will copy the Text and the Paint properties, however it will from that
     * point on be independant of the TextView.
     *
     * @param tv a TextView or EditText or any of their children.
     */
    public TextDrawable(TextView tv) {
        this(tv, false, false);
    }

    /**
     * Use the provided TextView/EditText to initialize the drawable.
     * The Drawable will copy the Paint properties, and use the provided text to initialise itself.
     *
     * @param tv a TextView or EditText or any of their children.
     * @param s  The String to draw
     */
    public TextDrawable(TextView tv, String s) {
        this(tv, s, false, false);
    }

    @Override
    public void draw(Canvas canvas) {
        if (mBindToViewPaint && ref.get() != null) {
            Paint p = ref.get().getPaint();
            canvas.drawText(mText, 0, getBounds().height(), p);
        } else {
            if (mInitFitText) {
                fitTextAndInit();
            }
            canvas.drawText(mText, 0, getBounds().height(), mPaint);
        }
    }

    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        int alpha = mPaint.getAlpha();
        if (alpha == 0) {
            return PixelFormat.TRANSPARENT;
        } else if (alpha == 255) {
            return PixelFormat.OPAQUE;
        } else {
            return PixelFormat.TRANSLUCENT;
        }
    }

    private void init() {
        Rect bounds = getBounds();
        //We want to use some character to determine the max height of the text.
        //Otherwise if we draw something like "..." they will appear centered
        //Here I'm just going to use the entire alphabet to determine max height.
        mPaint.getTextBounds("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+", 0, 1, mHeightBounds);
        //This doesn't account for leading or training white spaces.
        //mPaint.getTextBounds(mText, 0, mText.length(), bounds);
        float width = mPaint.measureText(mText);
        bounds.top = mHeightBounds.top;
        bounds.bottom = mHeightBounds.bottom;
        bounds.right = (int) width;
        bounds.left = 0;
        setBounds(bounds);
    }

    public void setPaint(Paint paint) {
        mPaint = new Paint(paint);
        //Since this can change the font used, we need to recalculate bounds.
        if (mFitTextEnabled && !mInitFitText) {
            fitTextAndInit();
        } else {
            init();
        }
        invalidateSelf();
    }

    public Paint getPaint() {
        return mPaint;
    }

    public void setText(String text) {
        mText = text;
        //Since this can change the bounds of the text, we need to recalculate.
        if (mFitTextEnabled && !mInitFitText) {
            fitTextAndInit();
        } else {
            init();
        }
        invalidateSelf();
    }

    public String getText() {
        return mText;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        setText(s.toString());
    }

    /**
     * Make the TextDrawable match the width of the View it's associated with.
     * <p/>
     * Note: While this option will not work if bindToViewPaint is true.
     *
     * @param fitText
     */
    public void setFillText(boolean fitText) {
        mFitTextEnabled = fitText;
        if (fitText) {
            mPrevTextSize = mPaint.getTextSize();
            if (ref.get() != null) {
                if (ref.get().getWidth() > 0) {
                    fitTextAndInit();
                } else {
                    mInitFitText = true;
                }
            }
        } else {
            if (mPrevTextSize > 0) {
                mPaint.setTextSize(mPrevTextSize);
            }
            init();
        }
    }

    private void fitTextAndInit() {
        float fitWidth = ref.get().getWidth();
        float textWidth = mPaint.measureText(mText);
        float multi = fitWidth / textWidth;
        mPaint.setTextSize(mPaint.getTextSize() * multi);
        mInitFitText = false;
        init();
    }

}
\ No newline at end of file

A src/quick/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java => src/quick/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java +53 -0
@@ 0,0 1,53 @@
package eu.siacs.conversations.utils;

import android.content.Context;
import android.telephony.TelephonyManager;

import java.util.Locale;

import io.michaelrocks.libphonenumber.android.PhoneNumberUtil;

public class PhoneNumberUtilWrapper {

    private static volatile PhoneNumberUtil instance;


    public static String getCountryForCode(String code) {
        Locale locale = new Locale("", code);
        return locale.getDisplayCountry();
    }

    public static String getUserCountry(Context context) {
        try {
            final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            final String simCountry = tm.getSimCountryIso();
            if (simCountry != null && simCountry.length() == 2) { // SIM country code is available
                return simCountry.toUpperCase(Locale.US);
            } else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) { // device is not 3G (would be unreliable)
                String networkCountry = tm.getNetworkCountryIso();
                if (networkCountry != null && networkCountry.length() == 2) { // network country code is available
                    return networkCountry.toUpperCase(Locale.US);
                }
            }
        } catch (Exception e) {
            // fallthrough
        }
        Locale locale = Locale.getDefault();
        return locale.getCountry();
    }

    public static PhoneNumberUtil getInstance(final Context context) {
        PhoneNumberUtil localInstance = instance;
        if (localInstance == null) {
            synchronized (PhoneNumberUtilWrapper.class){
                localInstance = instance;
                if (localInstance == null) {
                    instance = localInstance = PhoneNumberUtil.createInstance(context);
                }

            }
        }
        return localInstance;
    }

}

M src/quick/java/eu/siacs/conversations/utils/SignupUtils.java => src/quick/java/eu/siacs/conversations/utils/SignupUtils.java +8 -2
@@ 2,16 2,22 @@ package eu.siacs.conversations.utils;

import android.app.Activity;
import android.content.Intent;
import android.util.Log;

import eu.siacs.conversations.Config;
import eu.siacs.conversations.ui.ConversationsActivity;
import eu.siacs.conversations.ui.EnterPhoneNumberActivity;

public class SignupUtils {

    public static Intent getSignUpIntent(Activity activity) {
        return null;
        final Intent intent = new Intent(activity, EnterPhoneNumberActivity.class);
        return intent;
    }

    public static Intent getRedirectionIntent(ConversationsActivity activity) {
        return null;
        final Intent intent = getSignUpIntent(activity);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        return intent;
    }
}
\ No newline at end of file

A src/quick/res/drawable-hdpi/ic_arrow_drop_down_black_18dp.png => src/quick/res/drawable-hdpi/ic_arrow_drop_down_black_18dp.png +0 -0
A src/quick/res/drawable-mdpi/ic_arrow_drop_down_black_18dp.png => src/quick/res/drawable-mdpi/ic_arrow_drop_down_black_18dp.png +0 -0
A src/quick/res/drawable-xhdpi/ic_arrow_drop_down_black_18dp.png => src/quick/res/drawable-xhdpi/ic_arrow_drop_down_black_18dp.png +0 -0
A src/quick/res/drawable-xxhdpi/ic_arrow_drop_down_black_18dp.png => src/quick/res/drawable-xxhdpi/ic_arrow_drop_down_black_18dp.png +0 -0
A src/quick/res/drawable-xxxhdpi/ic_arrow_drop_down_black_18dp.png => src/quick/res/drawable-xxxhdpi/ic_arrow_drop_down_black_18dp.png +0 -0
A src/quick/res/layout/activity_enter_number.xml => src/quick/res/layout/activity_enter_number.xml +91 -0
@@ 0,0 1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include android:id="@+id/toolbar" layout="@layout/toolbar" />

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:id="@+id/instructions"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:padding="16dp"
                    android:gravity="center_horizontal"
                    android:textAppearance="@style/TextAppearance.Conversations.Body1"
                    android:text="@string/enter_country_code_and_phone_number"/>

                <LinearLayout
                    android:id="@+id/phone_number_box"
                    android:layout_width="256dp"
                    android:layout_height="match_parent"
                    android:layout_above="@+id/next"
                    android:layout_below="@+id/instructions"
                    android:layout_centerHorizontal="true"
                    android:orientation="vertical">

                    <EditText
                        android:id="@+id/country"
                        style="@style/Widget.Conversations.EditText"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:cursorVisible="false"
                        android:drawableRight="@drawable/ic_arrow_drop_down_black_18dp"
                        android:focusable="false"
                        android:gravity="bottom|center_horizontal"
                        android:longClickable="false" />

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">

                        <EditText
                            android:id="@+id/country_code"
                            style="@style/Widget.Conversations.EditText"
                            android:layout_width="0dp"
                            android:layout_height="wrap_content"
                            android:layout_weight="1"
                            android:gravity="bottom|center_horizontal"
                            android:inputType="number"
                            android:longClickable="false"
                            android:maxLength="3"
                            android:maxLines="1" />

                        <EditText
                            android:id="@+id/number"
                            style="@style/Widget.Conversations.EditText"
                            android:layout_width="0dp"
                            android:layout_height="wrap_content"
                            android:layout_weight="3"
                            android:hint="@string/phone_number"
                            android:inputType="number"
                            android:gravity="bottom|start"
                            android:longClickable="false"
                            android:maxLines="1" />
                    </LinearLayout>
                </LinearLayout>
                <Button
                    android:id="@+id/next"
                    android:layout_alignParentBottom="true"
                    android:layout_alignParentEnd="true"
                    style="@style/Widget.Conversations.Button.Borderless"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/next"
                    android:textColor="?colorAccent"/>
            </RelativeLayout>
        </ScrollView>
    </LinearLayout>
</layout>