diff --git a/.travis.yml b/.travis.yml index 136b29158e..ac9f7ea3ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,13 @@ android: components: - platform-tools - tools + - build-tools-28.0.3 + - build-tools-28.0.2 - build-tools-27.0.3 - build-tools-26.0.2 - build-tools-25.0.2 - build-tools-25.0.0 + - android-28 - android-27 - android-26 - android-25 diff --git a/build.gradle b/build.gradle index 68b6820911..840551871e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,11 +6,11 @@ buildscript { maven { url 'https://maven.fabric.io/public' } } dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'com.android.tools.build:gradle:3.2.1' classpath "io.realm:realm-gradle-plugin:3.1.1" classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'com.frogermcs.androiddevmetrics:androiddevmetrics-plugin:0.4' - classpath 'io.fabric.tools:gradle:1.+' + classpath 'io.fabric.tools:gradle:1.25.4' classpath 'com.google.gms:google-services:3.1.1' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fa8d4bdd8f..012557694c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Oct 26 14:17:31 YEKT 2017 +#Tue Sep 25 11:30:28 YEKT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/xabber/build.gradle b/xabber/build.gradle index 753ae70da8..2243a22f2b 100644 --- a/xabber/build.gradle +++ b/xabber/build.gradle @@ -4,14 +4,14 @@ apply plugin: 'com.frogermcs.androiddevmetrics' apply plugin: 'io.fabric' android { - compileSdkVersion 27 - buildToolsVersion '27.0.3' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { minSdkVersion 15 - targetSdkVersion 27 - versionCode 501 - versionName '2.4.1(501)' + targetSdkVersion 28 + versionCode 533 + versionName '2.5(533)' } lintOptions { @@ -83,12 +83,10 @@ android { 'proguard-rules.pro' // enable crashlytics buildConfigField "boolean", "USE_CRASHLYTICS", "true" - ext.enableCrashlytics = true } debug { // disable crashlytics buildConfigField "boolean", "USE_CRASHLYTICS", "false" - ext.enableCrashlytics = false } } @@ -139,7 +137,7 @@ if (build_param == "dev") { ext { smackVersion = '4.2.1-SNAPSHOT' - supportVersion = '27.0.2' + supportVersion = '28.0.0' } dependencies { @@ -153,7 +151,11 @@ dependencies { implementation "com.android.support:design:$supportVersion" implementation "com.android.support:support-v13:$supportVersion" - implementation 'com.android.support:multidex:1.0.1' + implementation "com.android.support:customtabs:$supportVersion" + implementation 'com.android.support:multidex:1.0.3' + + // firebase + compile 'com.google.firebase:firebase-messaging:11.4.0' implementation 'com.github.Str4tocaster:otr4j:custom-SNAPSHOT' implementation 'com.google.zxing:android-integration:3.3.0' @@ -168,7 +170,8 @@ dependencies { implementation 'io.reactivex:rxandroid:1.1.0' implementation 'io.reactivex:rxjava:1.1.0' - //social + // social + implementation 'com.google.android.gms:play-services-safetynet:11.4.0' implementation 'com.facebook.android:facebook-android-sdk:4.31.0' implementation 'com.twitter.sdk.android:twitter:3.0.0' implementation 'com.google.android.gms:play-services-auth:11.4.0' @@ -187,11 +190,11 @@ dependencies { implementation 'ru.egslava:MaskedEditText:1.0.5' implementation 'eu.davidea:flexible-adapter:5.0.0-rc4' implementation 'com.soundcloud.android:android-crop:1.0.1@aar' - implementation 'de.hdodenhof:circleimageview:2.1.0' + implementation 'de.hdodenhof:circleimageview:2.2.0' implementation 'com.melnykov:floatingactionbutton:1.3.0' - implementation('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') { - transitive = true; + implementation('com.crashlytics.sdk.android:crashlytics:2.9.5@aar') { + transitive = true } implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version: '1.58' diff --git a/xabber/emojicon/build.gradle b/xabber/emojicon/build.gradle index 6c3370e61c..9eec85e2ef 100644 --- a/xabber/emojicon/build.gradle +++ b/xabber/emojicon/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 25 - buildToolsVersion '26.0.2' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { - minSdkVersion 14 - targetSdkVersion 25 + minSdkVersion 15 + targetSdkVersion 28 } buildTypes { @@ -18,5 +18,5 @@ android { } dependencies { - compile "com.android.support:support-v13:25.3.0" + implementation "com.android.support:support-v13:28.0.0" } diff --git a/xabber/emojicon/src/main/AndroidManifest.xml b/xabber/emojicon/src/main/AndroidManifest.xml index a07b8e21bf..f44dcdda55 100644 --- a/xabber/emojicon/src/main/AndroidManifest.xml +++ b/xabber/emojicon/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ - + - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/drawable/orca_composer_attach_location_button.xml b/xabber/emojicon/src/main/res/drawable/orca_composer_attach_location_button.xml deleted file mode 100644 index 4971113aae..0000000000 --- a/xabber/emojicon/src/main/res/drawable/orca_composer_attach_location_button.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/drawable/orca_composer_attach_photo_button.xml b/xabber/emojicon/src/main/res/drawable/orca_composer_attach_photo_button.xml deleted file mode 100644 index ca7508dd96..0000000000 --- a/xabber/emojicon/src/main/res/drawable/orca_composer_attach_photo_button.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/drawable/orca_composer_popup_button.xml b/xabber/emojicon/src/main/res/drawable/orca_composer_popup_button.xml deleted file mode 100644 index d43dc26e4d..0000000000 --- a/xabber/emojicon/src/main/res/drawable/orca_composer_popup_button.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/drawable/orca_composer_popup_button_active.xml b/xabber/emojicon/src/main/res/drawable/orca_composer_popup_button_active.xml deleted file mode 100644 index f5e40ef8c2..0000000000 --- a/xabber/emojicon/src/main/res/drawable/orca_composer_popup_button_active.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/drawable/orca_emoji_backspace_front_button.xml b/xabber/emojicon/src/main/res/drawable/orca_emoji_backspace_front_button.xml deleted file mode 100644 index a2d2f5b627..0000000000 --- a/xabber/emojicon/src/main/res/drawable/orca_emoji_backspace_front_button.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/drawable/orca_emoji_more_front_button.xml b/xabber/emojicon/src/main/res/drawable/orca_emoji_more_front_button.xml deleted file mode 100644 index a799d56d95..0000000000 --- a/xabber/emojicon/src/main/res/drawable/orca_emoji_more_front_button.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/drawable/orca_emoji_tab_background.xml b/xabber/emojicon/src/main/res/drawable/orca_emoji_tab_background.xml deleted file mode 100644 index f68e6212b9..0000000000 --- a/xabber/emojicon/src/main/res/drawable/orca_emoji_tab_background.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/drawable/orca_emoji_tab_dark_background.xml b/xabber/emojicon/src/main/res/drawable/orca_emoji_tab_dark_background.xml deleted file mode 100644 index 07ff608c99..0000000000 --- a/xabber/emojicon/src/main/res/drawable/orca_emoji_tab_dark_background.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/xabber/emojicon/src/main/res/values/attrs.xml b/xabber/emojicon/src/main/res/values/attrs.xml index e406440ce9..66556fcb0e 100644 --- a/xabber/emojicon/src/main/res/values/attrs.xml +++ b/xabber/emojicon/src/main/res/values/attrs.xml @@ -26,15 +26,4 @@ 250dp 80dp - - \ No newline at end of file diff --git a/xabber/proguard-rules.pro b/xabber/proguard-rules.pro index 2743f915a8..b818fb83cb 100644 --- a/xabber/proguard-rules.pro +++ b/xabber/proguard-rules.pro @@ -7,6 +7,22 @@ # RxJava -dontwarn rx.internal.util.** +-dontwarn sun.misc.** + +-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { + long producerIndex; + long consumerIndex; +} + +-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { + rx.internal.util.atomic.LinkedQueueNode producerNode; +} + +-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { + rx.internal.util.atomic.LinkedQueueNode consumerNode; +} + +-dontnote rx.internal.util.PlatformDependent # google -keep class com.google.** diff --git a/xabber/src/beta/res/values/application_title.xml b/xabber/src/beta/res/values/application_title.xml index 832b3c1b0a..31e83cbc75 100644 --- a/xabber/src/beta/res/values/application_title.xml +++ b/xabber/src/beta/res/values/application_title.xml @@ -15,5 +15,4 @@ Xabber Xabber Beta https://www.xabber.com/ - xabber.org diff --git a/xabber/src/dev/res/values/social_keys.xml b/xabber/src/dev/res/values/social_keys.xml index ed203d29e9..107a8169d6 100644 --- a/xabber/src/dev/res/values/social_keys.xml +++ b/xabber/src/dev/res/values/social_keys.xml @@ -12,4 +12,6 @@ temp temp + + temp \ No newline at end of file diff --git a/xabber/src/main/AndroidManifest.xml b/xabber/src/main/AndroidManifest.xml index 247bc428a8..d8fa86b6b8 100644 --- a/xabber/src/main/AndroidManifest.xml +++ b/xabber/src/main/AndroidManifest.xml @@ -16,6 +16,8 @@ xmlns:tools="http://schemas.android.com/tools" package="com.xabber.android"> + + @@ -38,6 +40,7 @@ + + + + + + @@ -514,15 +523,23 @@ android:name="android.support.PARENT_ACTIVITY" android:value="com.xabber.android.ui.activity.ChatActivity" /> - + + - + + + + @@ -531,14 +548,8 @@ - - - - + accounts = getAllAccounts(); + for (AccountJid account : accounts) { + if (account.getFullJid().asBareJid().equals(user)) + return true; + } + return false; + } + /** * Save account item to database. */ @@ -344,7 +354,7 @@ private AccountItem addAccount(boolean custom, String host, int port, AccountItem accountItem = new AccountItem(custom, host, port, serverName, userName, resource, storePassword, password, token, color, order, syncNotAllowed, timestamp, priority, statusMode, statusText, enabled, saslEnabled, tlsMode, compression, proxyType, proxyHost, proxyPort, proxyUser, - proxyPassword, syncable, keyPair, lastSync, archiveMode); + proxyPassword, syncable, keyPair, lastSync, archiveMode, true); requestToWriteAccount(accountItem); addAccount(accountItem); @@ -360,7 +370,8 @@ private AccountItem addAccount(boolean custom, String host, int port, * @throws NetworkException if user or server part are invalid. */ public AccountJid addAccount(String user, String password, String token, boolean syncable, - boolean storePassword, boolean xabberSync, boolean useOrbot, boolean registerNewAccount, boolean enabled) + boolean storePassword, boolean xabberSync, boolean useOrbot, + boolean registerNewAccount, boolean enabled, boolean tlsRequired) throws NetworkException { if (user == null) { throw new NetworkException(R.string.EMPTY_USER_NAME); @@ -379,6 +390,9 @@ public AccountJid addAccount(String user, String password, String token, boolean throw new NetworkException(R.string.INCORRECT_USER_NAME); } + if (isAccountExist(user)) + throw new NetworkException(R.string.ACCOUNT_EXIST); + Resourcepart resource = null; String resourceString = XmppStringUtils.parseResource(user).trim(); if (!TextUtils.isEmpty(resourceString)) { @@ -390,24 +404,12 @@ public AccountJid addAccount(String user, String password, String token, boolean } String host = serverName.getDomain().toString(); int port = 5222; - boolean tlsRequired = false; - if (useOrbot) { - tlsRequired = true; - } if (resource == null) { resource = generateResource(); } AccountItem accountItem; - while(true) { - - if (getAccount(AccountJid.from(userName, serverName, resource)) == null) { - break; - } - resource = generateResource(); - } - boolean useCustomHost = application.getResources().getBoolean(R.bool.account_use_custom_host_default); @@ -417,7 +419,7 @@ public AccountJid addAccount(String user, String password, String token, boolean accountItem = addAccount(useCustomHost, host, port, serverName, userName, storePassword, password, token, resource, getNextColorIndex(), getNextOrder(), false, - XabberAccountManager.getInstance().getCurrentTime(), 0, StatusMode.available, + 0, 0, StatusMode.available, SettingsManager.statusText(), enabled, true, tlsRequired ? TLSMode.required : TLSMode.enabled, useCompression, useOrbot ? ProxyType.orbot : ProxyType.none, "localhost", 8080, "", "", syncable, null, null, archiveMode, registerNewAccount); @@ -441,7 +443,7 @@ storePassword, password, token, resource, getNextColorIndex(), getNextOrder(), f @NonNull private Resourcepart generateResource() { try { - return Resourcepart.from(application.getString(R.string.account_resource_default) + "_" + StringUtils.randomString(8)); + return Resourcepart.from(application.getString(R.string.account_resource_default) + "-" + StringUtils.randomString(8)); } catch (XmppStringprepException e) { LogManager.exception(this, e); return Resourcepart.EMPTY; @@ -1182,4 +1184,12 @@ private void removeHistoryOnExit() { } } } + + public void setAllAccountAutoLoginToXabber(boolean autoLogin) { + for (AccountItem accountItem : getAllAccountItems()) { + accountItem.setXabberAutoLoginEnabled(autoLogin); + requestToWriteAccount(accountItem); + } + } + } diff --git a/xabber/src/main/java/com/xabber/android/data/connection/CertificateManager.java b/xabber/src/main/java/com/xabber/android/data/connection/CertificateManager.java index efe6d4495d..6d8539cf6a 100644 --- a/xabber/src/main/java/com/xabber/android/data/connection/CertificateManager.java +++ b/xabber/src/main/java/com/xabber/android/data/connection/CertificateManager.java @@ -16,6 +16,7 @@ public class CertificateManager implements OnAccountRemovedListener { + private Activity currentActivityForBind; private static CertificateManager instance; public static CertificateManager getInstance() { @@ -37,6 +38,7 @@ private CertificateManager() { @NonNull MemorizingTrustManager getNewMemorizingTrustManager(@NonNull final AccountJid accountJid) { MemorizingTrustManager mtm = new MemorizingTrustManager(Application.getInstance()); + if (currentActivityForBind != null) mtm.bindDisplayActivity(currentActivityForBind); memorizingTrustManagerMap.put(accountJid, mtm); return mtm; } @@ -44,6 +46,7 @@ MemorizingTrustManager getNewMemorizingTrustManager(@NonNull final AccountJid ac @NonNull public MemorizingTrustManager getNewFileUploadManager(@NonNull final AccountJid accountJid) { MemorizingTrustManager mtm = new MemorizingTrustManager(Application.getInstance()); + if (currentActivityForBind != null) mtm.bindDisplayActivity(currentActivityForBind); fileUploadMap.put(accountJid, mtm); return mtm; } @@ -56,6 +59,7 @@ public void registerActivity(Activity activity) { for (MemorizingTrustManager memorizingTrustManager : fileUploadMap.values()) { memorizingTrustManager.bindDisplayActivity(activity); } + currentActivityForBind = activity; } public void unregisterActivity(Activity activity) { @@ -66,6 +70,7 @@ public void unregisterActivity(Activity activity) { for (MemorizingTrustManager memorizingTrustManager : fileUploadMap.values()) { memorizingTrustManager.unbindDisplayActivity(activity); } + if (currentActivityForBind == activity) currentActivityForBind = null; } @Override diff --git a/xabber/src/main/java/com/xabber/android/data/database/RealmManager.java b/xabber/src/main/java/com/xabber/android/data/database/RealmManager.java index 6134b13153..82d0804ce1 100644 --- a/xabber/src/main/java/com/xabber/android/data/database/RealmManager.java +++ b/xabber/src/main/java/com/xabber/android/data/database/RealmManager.java @@ -29,7 +29,7 @@ public class RealmManager { private static final String REALM_DATABASE_NAME = "realm_database.realm"; - private static final int REALM_DATABASE_VERSION = 14; + private static final int REALM_DATABASE_VERSION = 17; private static final String LOG_TAG = RealmManager.class.getSimpleName(); private final RealmConfiguration realmConfiguration; @@ -213,6 +213,33 @@ public void migrate(DynamicRealm realm, long oldVersion, long newVersion) { oldVersion++; } + + if (oldVersion == 14) { + RealmObjectSchema xabberAccountSchema = + schema.get(XabberAccountRealm.class.getSimpleName()); + + xabberAccountSchema.addField("domain", String.class); + + oldVersion++; + } + + if (oldVersion == 15) { + RealmObjectSchema accountSchema = + schema.get(AccountRealm.class.getSimpleName()); + + accountSchema.addField("xabberAutoLoginEnabled", boolean.class); + + oldVersion++; + } + + if (oldVersion == 16) { + RealmObjectSchema xabberAccountSchema = + schema.get(XabberAccountRealm.class.getSimpleName()); + + xabberAccountSchema.addField("hasPassword", boolean.class); + + oldVersion++; + } } }) .modules(new RealmDatabaseModule()) diff --git a/xabber/src/main/java/com/xabber/android/data/database/realm/AccountRealm.java b/xabber/src/main/java/com/xabber/android/data/database/realm/AccountRealm.java index 59a2b5c8d8..2fdf0bc842 100644 --- a/xabber/src/main/java/com/xabber/android/data/database/realm/AccountRealm.java +++ b/xabber/src/main/java/com/xabber/android/data/database/realm/AccountRealm.java @@ -59,6 +59,7 @@ public static class Fields { private int timestamp; private int order; private boolean syncNotAllowed; + private boolean xabberAutoLoginEnabled; private int priority; private String statusMode; @@ -208,6 +209,14 @@ public void setSyncNotAllowed(boolean syncNotAllowed) { this.syncNotAllowed = syncNotAllowed; } + public boolean isXabberAutoLoginEnabled() { + return xabberAutoLoginEnabled; + } + + public void setXabberAutoLoginEnabled(boolean xabberAutoLoginEnabled) { + this.xabberAutoLoginEnabled = xabberAutoLoginEnabled; + } + public int getPriority() { return priority; } diff --git a/xabber/src/main/java/com/xabber/android/data/database/realm/XabberAccountRealm.java b/xabber/src/main/java/com/xabber/android/data/database/realm/XabberAccountRealm.java index 10a97ed19f..c0f46f2203 100644 --- a/xabber/src/main/java/com/xabber/android/data/database/realm/XabberAccountRealm.java +++ b/xabber/src/main/java/com/xabber/android/data/database/realm/XabberAccountRealm.java @@ -19,12 +19,14 @@ public class XabberAccountRealm extends RealmObject { private String accountStatus; private String token; private String username; + private String domain; private String firstName; private String lastName; private String registerDate; private String language; private String phone; private boolean needToVerifyPhone; + private boolean hasPassword; private RealmList xmppUsers; private RealmList emails; private RealmList socialBindings; @@ -65,6 +67,14 @@ public void setUsername(String username) { this.username = username; } + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + public String getFirstName() { return firstName; } @@ -136,5 +146,13 @@ public String getPhone() { public void setPhone(String phone) { this.phone = phone; } + + public boolean hasPassword() { + return hasPassword; + } + + public void setHasPassword(boolean hasPassword) { + this.hasPassword = hasPassword; + } } diff --git a/xabber/src/main/java/com/xabber/android/data/database/sqlite/AccountTable.java b/xabber/src/main/java/com/xabber/android/data/database/sqlite/AccountTable.java index a10b9d2993..fc34974e78 100644 --- a/xabber/src/main/java/com/xabber/android/data/database/sqlite/AccountTable.java +++ b/xabber/src/main/java/com/xabber/android/data/database/sqlite/AccountTable.java @@ -458,6 +458,7 @@ private void saveAccountRealm(String id, AccountItem accountItem) { accountRealm.setToken(connectionSettings.getToken()); accountRealm.setOrder(accountItem.getOrder()); accountRealm.setSyncNotAllowed(accountItem.isSyncNotAllowed()); + accountRealm.setXabberAutoLoginEnabled(accountItem.isXabberAutoLoginEnabled()); accountRealm.setTimestamp(accountItem.getTimestamp()); accountRealm.setResource(connectionSettings.getResource().toString()); accountRealm.setColorIndex(accountItem.getColorIndex()); diff --git a/xabber/src/main/java/com/xabber/android/data/extension/avatar/AvatarManager.java b/xabber/src/main/java/com/xabber/android/data/extension/avatar/AvatarManager.java index 1cd740baa7..66543a933e 100644 --- a/xabber/src/main/java/com/xabber/android/data/extension/avatar/AvatarManager.java +++ b/xabber/src/main/java/com/xabber/android/data/extension/avatar/AvatarManager.java @@ -330,6 +330,15 @@ public Drawable getAccountAvatar(AccountJid account) { } } + public Drawable getAccountAvatarForSync(AccountJid account, int color) { + Bitmap value = getBitmap(account.getFullJid().asBareJid()); + if (value != null) { + return new BitmapDrawable(application.getResources(), value); + } else { + return getDefaultAccountAvatarForSync(account, color); + } + } + @NonNull public Drawable getDefaultAccountAvatar(AccountJid account) { String name = AccountManager.getInstance().getVerboseName(account); @@ -337,6 +346,12 @@ public Drawable getDefaultAccountAvatar(AccountJid account) { return generateDefaultAvatar(account.getFullJid().asBareJid().toString(), name, color); } + @NonNull + public Drawable getDefaultAccountAvatarForSync(AccountJid account, int color) { + String name = AccountManager.getInstance().getVerboseName(account); + return generateDefaultAvatar(account.getFullJid().asBareJid().toString(), name, color); + } + /** * Gets avatar for regular user. * diff --git a/xabber/src/main/java/com/xabber/android/data/extension/httpfileupload/ImageCompressor.java b/xabber/src/main/java/com/xabber/android/data/extension/httpfileupload/ImageCompressor.java index 006c470212..55e1ea80e4 100644 --- a/xabber/src/main/java/com/xabber/android/data/extension/httpfileupload/ImageCompressor.java +++ b/xabber/src/main/java/com/xabber/android/data/extension/httpfileupload/ImageCompressor.java @@ -2,12 +2,14 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.media.ExifInterface; import android.util.Log; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; public class ImageCompressor { @@ -93,10 +95,25 @@ public static File compressImage(final File file, String outputDirectory) { fOut.close(); source.recycle(); resizedBmp.recycle(); - return result; + } catch (Exception e) { return null; } + + // copy EXIF orientation from original image + try { + ExifInterface oldExif = new ExifInterface(file.getPath()); + String exifOrientation = oldExif.getAttribute(ExifInterface.TAG_ORIENTATION); + if (exifOrientation != null) { + ExifInterface newExif = new ExifInterface(result.getPath()); + newExif.setAttribute(ExifInterface.TAG_ORIENTATION, exifOrientation); + newExif.saveAttributes(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + return result; } private static Bitmap resizeBitmap(Bitmap source, int maxSizePixels) { diff --git a/xabber/src/main/java/com/xabber/android/data/extension/privatestorage/PrivateStorageManager.java b/xabber/src/main/java/com/xabber/android/data/extension/privatestorage/PrivateStorageManager.java new file mode 100644 index 0000000000..c31fe92a3a --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/data/extension/privatestorage/PrivateStorageManager.java @@ -0,0 +1,113 @@ +package com.xabber.android.data.extension.privatestorage; + +import android.support.annotation.Nullable; + +import com.xabber.android.data.account.AccountItem; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.ui.adapter.XMPPAccountAuthAdapter; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smackx.iqprivate.PrivateDataManager; +import org.jivesoftware.smackx.iqprivate.packet.PrivateData; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +import rx.Single; + +public class PrivateStorageManager { + + private static final String NAMESPACE = "xabber:options"; + private static final String ELEMENT_NAME = "storage"; + private static final String TYPE_BIND = "bind"; + private static final String BIND_TRUE = "1"; + private static final String BIND_FALSE = "0"; + + private static PrivateStorageManager instance; + + static { + PrivateDataManager.addPrivateDataProvider(ELEMENT_NAME, NAMESPACE, + new XabberOptionsPrivateData.Provider()); + } + + public static PrivateStorageManager getInstance() { + if (instance == null) instance = new PrivateStorageManager(); + return instance; + } + + public boolean haveXabberAccountBinding(AccountJid accountJid) { + XabberOptionsPrivateData privateData = (XabberOptionsPrivateData) getPrivateData(accountJid, NAMESPACE, ELEMENT_NAME); + if (privateData == null) return false; + return BIND_TRUE.equals(privateData.getValue(TYPE_BIND)); + } + + public void setXabberAccountBinding(AccountJid accountJid, boolean bind) { + XabberOptionsPrivateData privateData = new XabberOptionsPrivateData(ELEMENT_NAME, NAMESPACE); + privateData.setValue(TYPE_BIND, bind ? BIND_TRUE : BIND_FALSE); + setPrivateData(accountJid, privateData); + } + + @Nullable private PrivateData getPrivateData(AccountJid accountJid, String namespace, String elementName) { + AccountItem accountItem = AccountManager.getInstance().getAccount(accountJid); + if (accountItem == null || !accountItem.isEnabled()) return null; + + XMPPTCPConnection connection = accountItem.getConnection(); + PrivateDataManager privateDataManager = PrivateDataManager.getInstanceFor(connection); + try { + if (!privateDataManager.isSupported()) return null; + return privateDataManager.getPrivateData(elementName, namespace); + } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException + | SmackException.NotConnectedException | InterruptedException + | IllegalArgumentException e) { + e.printStackTrace(); + return null; + } + } + + private void setPrivateData(AccountJid accountJid, PrivateData privateData) { + AccountItem accountItem = AccountManager.getInstance().getAccount(accountJid); + if (accountItem == null || !accountItem.isEnabled()) return; + + XMPPTCPConnection connection = accountItem.getConnection(); + PrivateDataManager privateDataManager = PrivateDataManager.getInstanceFor(connection); + + try { + if (!privateDataManager.isSupported()) return; + privateDataManager.setPrivateData(privateData); + } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException + | SmackException.NotConnectedException | InterruptedException + | IllegalArgumentException e) { + e.printStackTrace(); + } + } + + /** Prepare views */ + + public Single> getAccountViewWithBindings(List accounts) { + return Single.fromCallable(new CallableLoadBindings(accounts)); + } + + private class CallableLoadBindings implements Callable> { + + private List accounts; + + public CallableLoadBindings(List accounts) { + this.accounts = accounts; + } + + @Override + public List call() throws Exception { + List items = new ArrayList<>(); + for (AccountJid accountJid : accounts) { + items.add(new XMPPAccountAuthAdapter.AccountView(accountJid, + haveXabberAccountBinding(accountJid))); + } + return items; + } + } + +} diff --git a/xabber/src/main/java/com/xabber/android/data/extension/privatestorage/XabberOptionsPrivateData.java b/xabber/src/main/java/com/xabber/android/data/extension/privatestorage/XabberOptionsPrivateData.java new file mode 100644 index 0000000000..f714ba4022 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/data/extension/privatestorage/XabberOptionsPrivateData.java @@ -0,0 +1,154 @@ +package com.xabber.android.data.extension.privatestorage; + +import org.jivesoftware.smackx.iqprivate.packet.PrivateData; +import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class XabberOptionsPrivateData implements PrivateData { + + private String elementName; + private String namespace; + private Map map; + + /** + * Creates a new generic private data object. + * + * @param elementName the name of the element of the XML sub-document. + * @param namespace the namespace of the element. + */ + public XabberOptionsPrivateData(String elementName, String namespace) { + this.elementName = elementName; + this.namespace = namespace; + } + + /** + * Returns the XML element name of the private data sub-packet root element. + * + * @return the XML element name of the stanza(/packet) extension. + */ + @Override + public String getElementName() { + return elementName; + } + + /** + * Returns the XML namespace of the private data sub-packet root element. + * + * @return the XML namespace of the stanza(/packet) extension. + */ + @Override + public String getNamespace() { + return namespace; + } + + @Override + public String toXML() { + StringBuilder buf = new StringBuilder(); + buf.append('<').append(elementName).append(" xmlns=\"").append(namespace).append("\">"); + for (String name : getNames()) { + String value = getValue(name); + buf.append(""); + } + buf.append("'); + return buf.toString(); + } + + /** + * Returns a Set of the names that can be used to get + * values of the private data. + * + * @return a Set of the names. + */ + public synchronized Set getNames() { + if (map == null) { + return Collections.emptySet(); + } + return Collections.unmodifiableSet(map.keySet()); + } + + /** + * Returns a value given a name. + * + * @param name the name. + * @return the value. + */ + public synchronized String getValue(String name) { + if (map == null) { + return null; + } + return map.get(name); + } + + /** + * Sets a value given the name. + * + * @param name the name. + * @param value the value. + */ + public synchronized void setValue(String name, String value) { + if (map == null) { + map = new HashMap(); + } + map.put(name, value); + } + + public static class Provider implements PrivateDataProvider { + + public Provider() { + super(); + } + + @Override + public PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserException, IOException { + String elementName = parser.getName(); + String namespace = parser.getNamespace(); + + XabberOptionsPrivateData data = new XabberOptionsPrivateData(elementName, namespace); + boolean finished = false; + int position = 0; + while (!finished) { + int event = parser.next(); + if (event == XmlPullParser.START_TAG) { + + // parse attributes of tag + String type = "type" + position; + if (parser.getAttributeCount() > 0) { + type = parser.getAttributeValue("", "type"); + } + + // If an empty element, set the value with the empty string. + if (parser.isEmptyElementTag()) { + data.setValue(type,""); + } + + // Otherwise, get the the element text. + else { + event = parser.next(); + if (event == XmlPullParser.TEXT) { + String value = parser.getText(); + data.setValue(type, value); + } + } + } + else if (event == XmlPullParser.END_TAG) { + if (parser.getName().equals(elementName)) { + finished = true; + } + } + position++; + } + + return data; + } + } + +} diff --git a/xabber/src/main/java/com/xabber/android/data/message/RegularChat.java b/xabber/src/main/java/com/xabber/android/data/message/RegularChat.java index 59b44a7ba4..d528aa03c1 100644 --- a/xabber/src/main/java/com/xabber/android/data/message/RegularChat.java +++ b/xabber/src/main/java/com/xabber/android/data/message/RegularChat.java @@ -30,6 +30,7 @@ import com.xabber.android.data.extension.otr.OTRUnencryptedException; import com.xabber.android.data.extension.otr.SecurityLevel; import com.xabber.android.data.log.LogManager; +import com.xabber.android.data.xaccount.XMPPAuthManager; import net.java.otr4j.OtrException; @@ -173,6 +174,12 @@ protected boolean onPacket(UserJid bareAddress, Stanza packet, boolean isCarbons if (text == null) return true; + // Xabber service message received + if (message.getType() == Type.headline) { + if (XMPPAuthManager.getInstance().isXabberServiceMessage(message.getStanzaId())) + return true; + } + String thread = message.getThread(); updateThreadId(thread); diff --git a/xabber/src/main/java/com/xabber/android/data/xaccount/AuthManager.java b/xabber/src/main/java/com/xabber/android/data/xaccount/AuthManager.java index fd49d3c639..fed3231c25 100644 --- a/xabber/src/main/java/com/xabber/android/data/xaccount/AuthManager.java +++ b/xabber/src/main/java/com/xabber/android/data/xaccount/AuthManager.java @@ -2,9 +2,13 @@ import android.util.Base64; -import com.google.gson.Gson; +import com.google.firebase.iid.FirebaseInstanceId; import com.xabber.android.BuildConfig; import com.xabber.android.data.SettingsManager; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.extension.privatestorage.PrivateStorageManager; + +import org.jxmpp.stringprep.XmppStringprepException; import java.util.ArrayList; import java.util.HashMap; @@ -24,7 +28,6 @@ public class AuthManager { public static final String PROVIDER_FACEBOOK = "facebook"; public static final String PROVIDER_TWITTER = "twitter"; - public static final String PROVIDER_GITHUB = "github"; public static final String PROVIDER_GOOGLE = "google"; private static final String SOURCE_NAME = "Xabber Android"; @@ -39,7 +42,7 @@ public static Single login(String login, String pass) { return HttpApiManager.getXabberApi().login("Basic " + encodedCredentials, new Source(getSource())); } - public static Single logout(final boolean deleteAccounts) { + public static Single logout() { return HttpApiManager.getXabberApi().logout(getXabberTokenHeader()) .flatMap(new Func1>() { @@ -59,26 +62,20 @@ public Single call(ResponseBody responseBody) { else return Single.error(new Throwable("Realm: xabber account deletion error")); } + }) + .flatMap(new Func1>() { + @Override + public Single call(ResponseBody responseBody) { + return unregisterFCMEndpoint(FirebaseInstanceId.getInstance().getToken()); + } }); } - public static Single loginSocial(String provider, String socialToken) { + public static Single loginSocial(String provider, String credentials) { SettingsManager.setSyncAllAccounts(true); - - Gson gson = new Gson(); - String credentials = gson.toJson(new AccessToken(socialToken)); return HttpApiManager.getXabberApi().loginSocial(new SocialAuthRequest(provider, credentials, getSource())); } - public static Single loginSocialTwitter( - String socialToken, String twitterTokenSecret, String secret, String key) { - SettingsManager.setSyncAllAccounts(true); - - Gson gson = new Gson(); - String credentials = gson.toJson(new TwitterAccessToken(new TwitterTokens(twitterTokenSecret, socialToken), secret, key)); - return HttpApiManager.getXabberApi().loginSocial(new SocialAuthRequest(PROVIDER_TWITTER, credentials, getSource())); - } - public static Single getAccount(final String token) { return HttpApiManager.getXabberApi().getAccount("Token " + token) .flatMap(new Func1>() { @@ -237,29 +234,94 @@ public Single call(XabberAccountDTO xabberAccountDTO) { }); } - public static Single completeRegister(String username, String pass, String confirmPass, - String firstName, String lastName, - String host, String language, boolean createToken) { - return HttpApiManager.getXabberApi().completeRegister(getXabberTokenHeader(), - new CompleteRegister(username, pass, confirmPass, firstName, lastName, host, language, createToken)) + public static Single addEmail(String email) { + return HttpApiManager.getXabberApi().addEmail(getXabberTokenHeader(), new Email(email, getSource())); + } + + public static Single deleteEmail(int emailId) { + return HttpApiManager.getXabberApi().deleteEmail(getXabberTokenHeader(), emailId); + } + + // API v2 + + public static Single requestXMPPCode(String jid) { + return HttpApiManager.getXabberApi().requestXMPPCode(new Jid(jid)); + } + + public static Single confirmXMPP(final String jid, String code) { + SettingsManager.setSyncAllAccounts(true); + return HttpApiManager.getXabberApi().confirmXMPP(new CodeConfirm(code, jid)) .flatMap(new Func1>() { @Override public Single call(XabberAccountDTO xabberAccountDTO) { - return XabberAccountManager.getInstance().saveOrUpdateXabberAccountToRealm(xabberAccountDTO, getXabberToken()); + try { + PrivateStorageManager.getInstance().setXabberAccountBinding(AccountJid.from(jid), true); + } catch (XmppStringprepException e) { + e.printStackTrace(); + } + + return XabberAccountManager.getInstance().saveOrUpdateXabberAccountToRealm(xabberAccountDTO, + xabberAccountDTO.getToken()); } }); } - public static Single addEmail(String email) { - return HttpApiManager.getXabberApi().addEmail(getXabberTokenHeader(), new Email(email, getSource())); + public static Single getHosts() { + return HttpApiManager.getXabberApi().getHosts(); } - public static Single setPhoneNumber(String phoneNumber) { - return HttpApiManager.getXabberApi().setPhoneNumber(getXabberTokenHeader(), new SetPhoneNumber("set", phoneNumber)); + public static Single signupv2(String username, String host, String password, + String captchaToken) { + SettingsManager.setSyncAllAccounts(true); + return HttpApiManager.getXabberApi().signupv2(new SignUpFields(username, host, + password, captchaToken)) + .flatMap(new Func1>() { + @Override + public Single call(XabberAccountDTO xabberAccountDTO) { + return XabberAccountManager.getInstance().saveOrUpdateXabberAccountToRealm(xabberAccountDTO, + xabberAccountDTO.getToken()); + } + }); + } + + public static Single signupv2(String username, String host, String password, + String provider, String credentials) { + SettingsManager.setSyncAllAccounts(true); + return HttpApiManager.getXabberApi().signupv2(new SignUpFields(username, host, + password, provider, credentials)) + .flatMap(new Func1>() { + @Override + public Single call(XabberAccountDTO xabberAccountDTO) { + return XabberAccountManager.getInstance().saveOrUpdateXabberAccountToRealm(xabberAccountDTO, + xabberAccountDTO.getToken()); + } + }); + } + + public static Single bindSocial(String provider, String credentials) { + return HttpApiManager.getXabberApi().bindSocial(getXabberTokenHeader(), + new SocialAuthRequest(provider, credentials, getSource())); + } + + public static Single unbindSocial(String provider) { + return HttpApiManager.getXabberApi().unbindSocial(getXabberTokenHeader(), new Provider(provider)); + } + + public static Single registerFCMEndpoint(String endpoint) { + return HttpApiManager.getXabberApi().registerFCMEndpoint(getXabberTokenHeader(), new Endpoint(endpoint)); + } + + public static Single unregisterFCMEndpoint(String endpoint) { + return HttpApiManager.getXabberApi().unregisterFCMEndpoint(new Endpoint(endpoint)); + } + + public static Single changePassword(String oldPass, String pass, String passConfirm) { + return HttpApiManager.getXabberApi().changePassword(getXabberTokenHeader(), + new ChangePassFields(oldPass, pass, passConfirm)); } - public static Single confirmPhoneNumber(String code) { - return HttpApiManager.getXabberApi().confirmPhoneNumber(getXabberTokenHeader(), new ConfirmPhoneNumber("verify", code)); + public static Single requestResetPassword(String email) { + return HttpApiManager.getXabberApi().requestResetPassword(new ResetPassFields(email)); } // support @@ -279,49 +341,150 @@ private static String getSource() { return SOURCE_NAME + " " + BuildConfig.FLAVOR + " " + BuildConfig.VERSION_NAME; } + public static String getProviderName(String provider) { + switch (provider) { + case AuthManager.PROVIDER_TWITTER: + return "Twitter"; + case AuthManager.PROVIDER_FACEBOOK: + return "Facebook"; + default: + return "Google+"; + } + } + // models - public static class CompleteRegister { - final String username; + public static class ChangePassFields { + final String old_password; final String password; final String confirm_password; - final String first_name; - final String last_name; + + public ChangePassFields(String oldPassword, String password, String confirmPassword) { + this.old_password = oldPassword; + this.password = password; + this.confirm_password = confirmPassword; + } + } + + public static class ResetPassFields { + final String email; + + public ResetPassFields(String email) { + this.email = email; + } + } + + public static class Endpoint { + final String endpoint_key; + + public Endpoint(String endpoint_key) { + this.endpoint_key = endpoint_key; + } + } + + public static class SignUpFields { + final String username; final String host; - final String language; + final String password; + String captcha_token; + String provider; + String credentials; final boolean create_token; + String first_name; + String last_name; + String language; + final String source; + String source_ip; - public CompleteRegister(String username, String password, String confirm_password, - String first_name, String last_name, String host, String language, - boolean create_token) { + public SignUpFields(String username, String host, String password, + String captcha_token) { this.username = username; + this.host = host; this.password = password; - this.confirm_password = confirm_password; - this.first_name = first_name; - this.last_name = last_name; + this.captcha_token = captcha_token; + this.create_token = true; + this.source = getSource(); + } + + public SignUpFields(String username, String host, String password, String provider, + String credentials) { + this.username = username; this.host = host; - this.language = language; - this.create_token = create_token; + this.password = password; + this.provider = provider; + this.credentials = credentials; + this.create_token = true; + this.source = getSource(); } } - public static class SetPhoneNumber { - final String action; - final String phone; + public static class CodeConfirm { + final String code; + final String jid; - public SetPhoneNumber(String action, String phone) { - this.action = action; - this.phone = phone; + public CodeConfirm(String code, String jid) { + this.code = code; + this.jid = jid; } } - public static class ConfirmPhoneNumber { - final String action; - final String code; + public static class HostResponse { + final List results; - public ConfirmPhoneNumber(String action, String code) { - this.action = action; - this.code = code; + public HostResponse(List results) { + this.results = results; + } + + public List getHosts() { + return results; + } + } + + public static class Host { + final String host; + final String description; + final String price; + final boolean is_free; + + public Host(String host, String description, String price, boolean is_free) { + this.host = host; + this.description = description; + this.price = price; + this.is_free = is_free; + } + + public String getHost() { + return host; + } + + public String getDescription() { + return description; + } + + public String getPrice() { + return price; + } + + public boolean isFree() { + return is_free; + } + } + + public static class XMPPCode { + final String request_id; + final String api_jid; + + public XMPPCode(String request_id, String api_jid) { + this.request_id = request_id; + this.api_jid = api_jid; + } + + public String getRequestId() { + return request_id; + } + + public String getApiJid() { + return api_jid; } } @@ -381,6 +544,14 @@ public Email(String email, String source) { } } + public static class Provider { + final String provider; + + public Provider(String provider) { + this.provider = provider; + } + } + public static class SocialAuthRequest { final String provider; final String credentials; diff --git a/xabber/src/main/java/com/xabber/android/data/xaccount/HttpApiManager.java b/xabber/src/main/java/com/xabber/android/data/xaccount/HttpApiManager.java index 12a947debc..b52f991fe1 100644 --- a/xabber/src/main/java/com/xabber/android/data/xaccount/HttpApiManager.java +++ b/xabber/src/main/java/com/xabber/android/data/xaccount/HttpApiManager.java @@ -18,8 +18,9 @@ public class HttpApiManager { public static final String XABBER_FORGOT_PASS_URL = "https://www.xabber.com/account/auth/forgot-password/"; + public static final String XABBER_EMAIL_CONFIRM_URL = "https://www.xabber.com/account/emails/confirmation/"; - public static final String XABBER_API_URL = "https://api.xabber.com/api/v1/"; + public static final String XABBER_API_URL = "https://api.xabber.com/api/v2/"; private static final String XABBER_COM_URL = "https://www.xabber.com/"; private static IXabberApi xabberApi; private static IXabberCom xabberCom; diff --git a/xabber/src/main/java/com/xabber/android/data/xaccount/IXabberApi.java b/xabber/src/main/java/com/xabber/android/data/xaccount/IXabberApi.java index 46bd84cf01..f3b38429e9 100644 --- a/xabber/src/main/java/com/xabber/android/data/xaccount/IXabberApi.java +++ b/xabber/src/main/java/com/xabber/android/data/xaccount/IXabberApi.java @@ -2,11 +2,13 @@ import okhttp3.ResponseBody; import retrofit2.http.Body; +import retrofit2.http.DELETE; import retrofit2.http.GET; import retrofit2.http.HTTP; import retrofit2.http.Header; import retrofit2.http.PATCH; import retrofit2.http.POST; +import retrofit2.http.Path; import rx.Single; /** @@ -33,12 +35,6 @@ public interface IXabberApi { @PATCH("accounts/current/") Single updateAccount(@Header("Authorization") String token, @Body AuthManager.Account account); - @POST("accounts/current/phone/") - Single setPhoneNumber(@Header("Authorization") String token, @Body AuthManager.SetPhoneNumber setPhoneNumber); - - @POST("accounts/current/phone/") - Single confirmPhoneNumber(@Header("Authorization") String token, @Body AuthManager.ConfirmPhoneNumber confirmPhoneNumber); - @GET("accounts/current/client-settings/") Single getClientSettings(@Header("Authorization") String token); @@ -57,11 +53,42 @@ public interface IXabberApi { @POST("accounts/email_confirmation/") Single confirmEmail(@Body AuthManager.Key key); - @POST("accounts/current/complete_registration/") - Single completeRegister(@Header("Authorization") String token, @Body AuthManager.CompleteRegister register); - @POST("accounts/current/email_list/") Single addEmail(@Header("Authorization") String token, @Body AuthManager.Email email); + @DELETE("accounts/current/email_list/{email_id}/") + Single deleteEmail(@Header("Authorization") String token, @Path(value = "email_id", encoded = true) int emailId); + + @POST("fcm/subscription/") + Single registerFCMEndpoint(@Header("Authorization") String token, @Body AuthManager.Endpoint endpoint); + + @HTTP(method = "DELETE", path = "fcm/subscription/", hasBody = true) + Single unregisterFCMEndpoint(@Body AuthManager.Endpoint endpoint); + + @POST("accounts/current/set_password/") + Single changePassword(@Header("Authorization") String token, @Body AuthManager.ChangePassFields fields); + + @POST("accounts/password_reset_request/") + Single requestResetPassword(@Body AuthManager.ResetPassFields fields); + + /* Xabber API v2 */ + + @POST("accounts/xmpp_code_request/") + Single requestXMPPCode(@Body AuthManager.Jid jid); + + @POST("accounts/xmpp_auth/") + Single confirmXMPP(@Body AuthManager.CodeConfirm codeConfirm); + + @GET("accounts/xmpp/hosts/") + Single getHosts(); + + @POST("accounts/signup/") + Single signupv2(@Body AuthManager.SignUpFields fields); + + @POST("accounts/current/social_bind/") + Single bindSocial(@Header("Authorization") String token, @Body AuthManager.SocialAuthRequest body); + + @POST("accounts/current/social_unbind/") + Single unbindSocial(@Header("Authorization") String token, @Body AuthManager.Provider provider); } diff --git a/xabber/src/main/java/com/xabber/android/data/xaccount/XMPPAuthManager.java b/xabber/src/main/java/com/xabber/android/data/xaccount/XMPPAuthManager.java new file mode 100644 index 0000000000..eb88a5e973 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/data/xaccount/XMPPAuthManager.java @@ -0,0 +1,238 @@ +package com.xabber.android.data.xaccount; + +import android.util.Log; + +import com.xabber.android.data.Application; +import com.xabber.android.data.NetworkException; +import com.xabber.android.data.SettingsManager; +import com.xabber.android.data.account.AccountItem; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.connection.ConnectionItem; +import com.xabber.android.data.connection.listeners.OnConnectedListener; +import com.xabber.android.data.connection.listeners.OnPacketListener; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.entity.UserJid; +import com.xabber.android.data.extension.privatestorage.PrivateStorageManager; +import com.xabber.android.data.log.LogManager; +import com.xabber.android.data.roster.PresenceManager; +import com.xabber.android.data.roster.RosterManager; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.StandardExtensionElement; +import org.jivesoftware.smack.packet.Stanza; +import org.jxmpp.stringprep.XmppStringprepException; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; + +public class XMPPAuthManager implements OnPacketListener, OnConnectedListener { + + private static final String LOG_TAG = XMPPAuthManager.class.getSimpleName(); + private static final String EXTENSION_NAMESPACE = "http://jabber.org/protocol/http-auth"; + private static final String ATTRIBUTE_ID = "id"; + + private static XMPPAuthManager instance; + + private Map requests = new HashMap<>(); + + public static XMPPAuthManager getInstance() { + if (instance == null) instance = new XMPPAuthManager(); + return instance; + } + + public void addRequest(String requestId, String apiJid, String clientJid) { + onRequestReceived(new Request(requestId, clientJid, apiJid)); + addContactToRoster(apiJid, clientJid); + } + + /** + * StanzaId is RequestId + * */ + public boolean isXabberServiceMessage(String stanzaId) { + return requests.containsKey(stanzaId); + } + + @Override + public void onStanza(ConnectionItem connection, Stanza packet) { + if (packet instanceof Message && ((Message) packet).getType() == Message.Type.headline) { + Message message = (Message) packet; + + String apiJid = message.getFrom().toString(); + String clientJid = message.getTo().toString(); + String requestId = message.getStanzaId(); + String code = null; + + StandardExtensionElement extensionElement = (StandardExtensionElement) + message.getExtension(EXTENSION_NAMESPACE); + if (extensionElement != null) code = extensionElement.getAttributeValue(ATTRIBUTE_ID); + + if (requestId != null && code != null) + onRequestReceived(new Request(requestId, clientJid, apiJid, code)); + } + } + + @Override + public void onConnected(final ConnectionItem connection) { + + + Application.getInstance().runInBackground(new Runnable() { + @Override + public void run() { + XabberAccount xabberAccount = XabberAccountManager.getInstance().getAccount(); + AccountJid accountJid = connection.getAccount(); + if (xabberAccount == null) { + AccountItem accountItem = AccountManager.getInstance().getAccount(accountJid); + if (accountItem != null && accountItem.isXabberAutoLoginEnabled()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (PrivateStorageManager.getInstance().haveXabberAccountBinding(accountJid)) + requestXMPPAuthCode(accountJid); + } + + } else if (xabberAccount.getFullUsername() + .equals(AccountManager.getInstance().getVerboseName(accountJid))) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + PrivateStorageManager.getInstance().setXabberAccountBinding(accountJid, true); + } + } + }); + } + + private void requestXMPPAuthCode(final AccountJid accountJid) { + Log.d(LOG_TAG, "request XMPP code for account: " + + accountJid.getFullJid().toString()); + AuthManager.requestXMPPCode(accountJid.getFullJid().toString()) + .subscribe(new Action1() { + @Override + public void call(AuthManager.XMPPCode code) { + Log.d(XMPPAuthManager.class.toString(), "xmpp auth code requested successfully"); + addRequest(code.getRequestId(), code.getApiJid(), accountJid.getFullJid().toString()); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + Log.d(XMPPAuthManager.class.toString(), "request XMPP code failed: " + throwable.toString()); + } + }); + } + + private void confirmXMPP(Request request) { + Log.d(LOG_TAG, "confirm account: " + request.clientJid); + AuthManager.confirmXMPP(request.clientJid, request.code) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(XabberAccount account) { + Log.d(XMPPAuthManager.class.toString(), "xabber account authorized successfully"); + updateSettings(); + AccountManager.getInstance().setAllAccountAutoLoginToXabber(true); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + Log.d(XMPPAuthManager.class.toString(), "XMPP authorization failed: " + throwable.toString()); + } + }); + } + + protected void updateSettings() { + AuthManager.patchClientSettings(XabberAccountManager.getInstance().createSettingsList()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1>() { + @Override + public void call(List s) { + Log.d(XMPPAuthManager.class.toString(), + "xabber account settings updated successfully"); + XabberAccountManager.getInstance().registerEndpoint(); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + Log.d(XMPPAuthManager.class.toString(), + "xabber account settings update failed: " + throwable.toString()); + } + }); + } + + private void onRequestReceived(Request request) { + if (requests.containsKey(request.id)) { + if (request.code == null) request.code = requests.get(request.id).code; + confirmXMPP(request); + } else requests.put(request.id, request); + } + + private void addContactToRoster(String apiJid, String clientJid) { + UserJid user; + AccountJid account; + try { + user = UserJid.from(apiJid); + account = AccountJid.from(clientJid); + + RosterManager.getInstance().createContact(account, user, + "xabber", Collections.EMPTY_LIST); + PresenceManager.getInstance().requestSubscription(account, user); + + } catch (UserJid.UserJidCreateException | XmppStringprepException | InterruptedException | + SmackException | NetworkException | XMPPException.XMPPErrorException e) { + LogManager.exception(this, e); + return; + } + } + + class Request { + private String id; + private String clientJid; + private String apiJid; + private String code; + + public Request(String id, String clientJid, String apiJid) { + this.id = id; + this.clientJid = clientJid; + this.apiJid = apiJid; + } + + public Request(String id, String clientJid, String apiJid, String code) { + this.id = id; + this.clientJid = clientJid; + this.apiJid = apiJid; + this.code = code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getId() { + return id; + } + + public String getClientJid() { + return clientJid; + } + + public String getApiJid() { + return apiJid; + } + + public String getCode() { + return code; + } + } +} diff --git a/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccount.java b/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccount.java index 2c6b2dc666..712de8a0ae 100644 --- a/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccount.java +++ b/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccount.java @@ -15,6 +15,7 @@ public class XabberAccount { private int id; private String accountStatus; private String username; + private String domain; private String firstName; private String lastName; private String registerDate; @@ -25,14 +26,16 @@ public class XabberAccount { private String token; private String phone; private boolean needToVerifyPhone; + private boolean hasPassword; - public XabberAccount(int id, String accountStatus, String username, String firstName, + public XabberAccount(int id, String accountStatus, String username, String domain, String firstName, String lastName, String registerDate, String language, List xmppUsers, List emails, List socialBindings, String token, - boolean needToVerifyPhone, String phone) { + boolean needToVerifyPhone, String phone, boolean hasPassword) { this.id = id; this.accountStatus = accountStatus; this.username = username; + this.domain = domain; this.firstName = firstName; this.lastName = lastName; this.registerDate = registerDate; @@ -43,6 +46,7 @@ public XabberAccount(int id, String accountStatus, String username, String first this.token = token; this.needToVerifyPhone = needToVerifyPhone; this.phone = phone; + this.hasPassword = hasPassword; } public String getAccountStatus() { @@ -57,6 +61,14 @@ public String getUsername() { return username; } + public String getDomain() { + return domain; + } + + public String getFullUsername() { + return username + "@" + domain; + } + public String getFirstName() { return firstName; } @@ -96,4 +108,8 @@ public boolean isNeedToVerifyPhone() { public String getPhone() { return phone; } + + public boolean hasPassword() { + return hasPassword; + } } diff --git a/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccountDTO.java b/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccountDTO.java index 0bb6e94078..efdb753dca 100644 --- a/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccountDTO.java +++ b/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccountDTO.java @@ -11,23 +11,27 @@ public class XabberAccountDTO { private int id; private String account_status; private String username; + private String domain; private String first_name; private String last_name; private String registration_date; private String language; private String phone; private boolean need_to_verify_phone; + private String token; + private boolean has_password; private List xmpp_users; private List email_list; private List social_bindings; - public XabberAccountDTO(int id, String account_status, String username, String first_name, + public XabberAccountDTO(int id, String account_status, String username, String domain, String first_name, String last_name, String registration_date, String language, String phone, - boolean need_to_verify_phone, List xmpp_users, + boolean need_to_verify_phone, String token, boolean hasPassword, List xmpp_users, List email_list, List social_bindings) { this.id = id; this.account_status = account_status; this.username = username; + this.domain = domain; this.first_name = first_name; this.last_name = last_name; this.registration_date = registration_date; @@ -37,6 +41,8 @@ public XabberAccountDTO(int id, String account_status, String username, String f this.xmpp_users = xmpp_users; this.email_list = email_list; this.social_bindings = social_bindings; + this.token = token; + this.has_password = hasPassword; } public String getAccountStatus() { @@ -51,6 +57,10 @@ public String getUsername() { return username; } + public String getDomain() { + return domain; + } + public String getFirstName() { return first_name; } @@ -86,5 +96,13 @@ public boolean isNeedToVerifyPhone() { public String getPhone() { return phone; } + + public String getToken() { + return token; + } + + public boolean hasPassword() { + return has_password; + } } diff --git a/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccountManager.java b/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccountManager.java index 38dfe8000a..6094a57da6 100644 --- a/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccountManager.java +++ b/xabber/src/main/java/com/xabber/android/data/xaccount/XabberAccountManager.java @@ -4,6 +4,7 @@ import android.support.annotation.Nullable; import android.util.Log; +import com.google.firebase.iid.FirebaseInstanceId; import com.xabber.android.data.Application; import com.xabber.android.data.NetworkException; import com.xabber.android.data.OnLoadListener; @@ -36,11 +37,13 @@ import io.realm.Realm; import io.realm.RealmList; import io.realm.RealmResults; +import okhttp3.ResponseBody; import rx.Single; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; import rx.schedulers.Schedulers; +import rx.subjects.BehaviorSubject; import rx.subscriptions.CompositeSubscription; /** @@ -53,6 +56,7 @@ public class XabberAccountManager implements OnLoadListener { private static XabberAccountManager instance; private XabberAccount account; + private BehaviorSubject accountSubject = BehaviorSubject.create(); private List xmppAccountsForSync; private List xmppAccountsForCreate; @@ -201,7 +205,7 @@ public void call(Throwable throwable) { @Override public void onLoad() { XabberAccount account = loadXabberAccountFromRealm(); - this.account = account; + setAccount(account); this.lastOrderChangeTimestamp = SettingsManager.getLastOrderChangeTimestamp(); @@ -209,16 +213,16 @@ public void onLoad() { this.accountsSyncState = loadSyncStatesFromRealm(); if (account != null) { - getAccountFromNet(account.getToken()); + getAccountFromNet(account.getToken(), true); } } - private void getAccountFromNet(String token) { + private void getAccountFromNet(String token, final boolean needUpdateSettings) { Subscription getAccountSubscription = AuthManager.getAccount(token) .subscribe(new Action1() { @Override public void call(XabberAccount xabberAccount) { - handleSuccessGetAccount(xabberAccount); + handleSuccessGetAccount(xabberAccount, needUpdateSettings); } }, new Action1() { @Override @@ -229,6 +233,10 @@ public void call(Throwable throwable) { compositeSubscription.add(getAccountSubscription); } + public void updateAccountInfo() { + getAccountFromNet(account.getToken(), false); + } + public void updateAccountSettings() { List list = createSettingsList(); if (list != null && list.size() > 0) { @@ -257,10 +265,10 @@ public void call(Throwable throwable) { } } - private void handleSuccessGetAccount(@NonNull XabberAccount xabberAccount) { + private void handleSuccessGetAccount(@NonNull XabberAccount xabberAccount, boolean needUpdateSettings) { Log.d(LOG_TAG, "Xabber account loading from net: successfully"); - this.account = xabberAccount; - updateAccountSettings(); + setAccount(xabberAccount); + if (needUpdateSettings) updateAccountSettings(); } private void handleErrorGetAccount(Throwable throwable) { @@ -273,13 +281,56 @@ private void handleErrorGetAccount(Throwable throwable) { } } + public void deleteAccountSettings(String jid) { + if (XabberAccountManager.getInstance().getAccountSyncState(jid) != null) { + + Subscription deleteSubscription = AuthManager.deleteClientSettings(jid) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1>() { + @Override + public void call(List settings) { + handleSuccessDelete(settings); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorDelete(throwable); + } + }); + compositeSubscription.add(deleteSubscription); + } + } + + private void handleSuccessDelete(List settings) { + Log.d(LOG_TAG, "Settings deleted successfuly"); + } + + private void handleErrorDelete(Throwable throwable) { + String message = RetrofitErrorConverter.throwableToHttpError(throwable); + if (message != null) { + if (message.equals("Invalid token")) + XabberAccountManager.getInstance().onInvalidToken(); + else Log.d(LOG_TAG, "Error while deleting settings: " + message); + } else Log.d(LOG_TAG, "Error while deleting settings: " + throwable.toString()); + } + @Nullable public XabberAccount getAccount() { return account; } + public BehaviorSubject subscribeForAccount() { + return accountSubject; + } + + private void setAccount(XabberAccount account) { + this.account = account; + accountSubject.onNext(this.account); + } + public void removeAccount() { - this.account = null; + setAccount(null); this.accountsSyncState.clear(); } @@ -290,12 +341,14 @@ public Single saveOrUpdateXabberAccountToRealm(XabberAccountDTO x xabberAccountRealm.setToken(token); xabberAccountRealm.setAccountStatus(xabberAccount.getAccountStatus()); xabberAccountRealm.setUsername(xabberAccount.getUsername()); + xabberAccountRealm.setDomain(xabberAccount.getDomain()); xabberAccountRealm.setFirstName(xabberAccount.getFirstName()); xabberAccountRealm.setLastName(xabberAccount.getLastName()); xabberAccountRealm.setLanguage(xabberAccount.getLanguage()); xabberAccountRealm.setRegisterDate(xabberAccount.getRegistrationDate()); xabberAccountRealm.setNeedToVerifyPhone(xabberAccount.isNeedToVerifyPhone()); xabberAccountRealm.setPhone(xabberAccount.getPhone()); + xabberAccountRealm.setHasPassword(xabberAccount.hasPassword()); RealmList realmUsers = new RealmList<>(); for (XMPPUserDTO user : xabberAccount.getXmppUsers()) { @@ -335,7 +388,7 @@ public Single saveOrUpdateXabberAccountToRealm(XabberAccountDTO x realm.commitTransaction(); realm.close(); - this.account = account; + setAccount(account); return Single.just(account); } @@ -382,6 +435,7 @@ public static XabberAccount xabberAccountRealmToPOJO(XabberAccountRealm accountR Integer.parseInt(accountRealm.getId()), accountRealm.getAccountStatus(), accountRealm.getUsername(), + accountRealm.getDomain(), accountRealm.getFirstName(), accountRealm.getLastName(), accountRealm.getRegisterDate(), @@ -391,7 +445,8 @@ public static XabberAccount xabberAccountRealmToPOJO(XabberAccountRealm accountR socials, accountRealm.getToken(), accountRealm.isNeedToVerifyPhone(), - accountRealm.getPhone() + accountRealm.getPhone(), + accountRealm.hasPassword() ); return xabberAccount; @@ -445,7 +500,9 @@ public void updateLocalAccount(XMPPAccountSettings account) { // create new xmpp-account if (accountJid == null && !account.isDeleted()) { try { - AccountJid jid = AccountManager.getInstance().addAccount(account.getJid(), "", account.getToken(), false, true, true, false, false, true); + AccountJid jid = AccountManager.getInstance().addAccount(account.getJid(), + "", account.getToken(), false, true, + true, false, false, true, false); AccountManager.getInstance().setColor(jid, ColorManager.getInstance().convertColorNameToIndex(account.getColor())); AccountManager.getInstance().setOrder(jid, account.getOrder()); AccountManager.getInstance().setTimestamp(jid, account.getTimestamp()); @@ -533,6 +590,7 @@ public void run() { removeAccount(); } }); + unregisterEndpoint(); } public static class XabberAccountDeletedEvent {} @@ -723,5 +781,41 @@ else if (remoteItem.getTimestamp() > localItem.getTimestamp()) return resultList; } + + public void registerEndpoint() { + compositeSubscription.add( + AuthManager.registerFCMEndpoint(FirebaseInstanceId.getInstance().getToken()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(ResponseBody responseBody) { + Log.d(LOG_TAG, "Endpoint successfully registered"); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + Log.d(LOG_TAG, "Endpoint register failed: " + throwable.toString()); + } + })); + } + + public void unregisterEndpoint() { + compositeSubscription.add( + AuthManager.unregisterFCMEndpoint(FirebaseInstanceId.getInstance().getToken()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(ResponseBody responseBody) { + Log.d(LOG_TAG, "Endpoint successfully unregistered"); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + Log.d(LOG_TAG, "Endpoint unregister failed: " + throwable.toString()); + } + })); + } } diff --git a/xabber/src/main/java/com/xabber/android/presentation/mvp/signup/SignUpRepo.java b/xabber/src/main/java/com/xabber/android/presentation/mvp/signup/SignUpRepo.java new file mode 100644 index 0000000000..e50374d18b --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/presentation/mvp/signup/SignUpRepo.java @@ -0,0 +1,89 @@ +package com.xabber.android.presentation.mvp.signup; + +public class SignUpRepo { + + private String username; + private String host; + private String pass; + private String socialCredentials; + private String socialProvider; + private String captchaToken; + private String lastErrorMessage; + + private static SignUpRepo instance; + + public static SignUpRepo getInstance() { + if (instance == null) instance = new SignUpRepo(); + return instance; + } + + public void clearRepo() { + username = null; + host = null; + pass = null; + socialCredentials = null; + socialProvider = null; + captchaToken = null; + lastErrorMessage = null; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getPass() { + return pass; + } + + public void setPass(String pass) { + this.pass = pass; + } + + public String getSocialCredentials() { + return socialCredentials; + } + + public void setSocialCredentials(String socialCredentials) { + this.socialCredentials = socialCredentials; + } + + public String getSocialProvider() { + return socialProvider; + } + + public void setSocialProvider(String socialProvider) { + this.socialProvider = socialProvider; + } + + public String getCaptchaToken() { + return captchaToken; + } + + public void setCaptchaToken(String captchaToken) { + this.captchaToken = captchaToken; + } + + public String getLastErrorMessage() { + return lastErrorMessage; + } + + public void setLastErrorMessage(String lastErrorMessage) { + this.lastErrorMessage = lastErrorMessage; + } + + public boolean isCompleted() { + return username != null && pass != null && host != null; + } +} diff --git a/xabber/src/main/java/com/xabber/android/service/DownloadService.java b/xabber/src/main/java/com/xabber/android/service/DownloadService.java index 8b80aadd67..f28f1e6c7c 100644 --- a/xabber/src/main/java/com/xabber/android/service/DownloadService.java +++ b/xabber/src/main/java/com/xabber/android/service/DownloadService.java @@ -8,24 +8,16 @@ import android.support.annotation.Nullable; import android.util.Log; -import com.xabber.android.data.connection.CertificateManager; import com.xabber.android.data.database.MessageDatabaseManager; import com.xabber.android.data.database.messagerealm.Attachment; import com.xabber.android.data.entity.AccountJid; import com.xabber.android.data.extension.file.FileManager; +import com.xabber.android.utils.HttpClientWithMTM; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.X509TrustManager; - -import de.duenndns.ssl.MemorizingTrustManager; import io.realm.Realm; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -68,7 +60,7 @@ protected void onHandleIntent(@Nullable Intent intent) { AccountJid accountJid = intent.getParcelableExtra(KEY_ACCOUNT_JID); // build http client - OkHttpClient client = createHttpClient(accountJid); + OkHttpClient client = HttpClientWithMTM.getClient(accountJid); // start download if (client != null) requestFileDownload(fileName, fileSize, url, client); @@ -81,32 +73,6 @@ public void onDestroy() { needStop = true; } - private static OkHttpClient createHttpClient(AccountJid accountJid) { - // create ssl verification - SSLSocketFactory sslSocketFactory = null; - MemorizingTrustManager mtm = CertificateManager.getInstance().getNewFileUploadManager(accountJid); - - final SSLContext sslContext; - try { - sslContext = SSLContext.getInstance("SSL"); - sslContext.init(null, new X509TrustManager[]{mtm}, new java.security.SecureRandom()); - sslSocketFactory = sslContext.getSocketFactory(); - } catch (NoSuchAlgorithmException | KeyManagementException e) { - return null; - } - - // build http client - final OkHttpClient client = new OkHttpClient().newBuilder() - .sslSocketFactory(sslSocketFactory) - .hostnameVerifier(mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier())) - .writeTimeout(5, TimeUnit.MINUTES) - .connectTimeout(5, TimeUnit.MINUTES) - .readTimeout(5, TimeUnit.MINUTES) - .build(); - - return client; - } - private void requestFileDownload(final String fileName, final long fileSize, String url, OkHttpClient client) { Request request = new Request.Builder().url(url).build(); try { diff --git a/xabber/src/main/java/com/xabber/android/service/PushService.java b/xabber/src/main/java/com/xabber/android/service/PushService.java new file mode 100644 index 0000000000..0d6414fc54 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/service/PushService.java @@ -0,0 +1,103 @@ +package com.xabber.android.service; + +import android.util.Base64; +import android.util.Log; + +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; +import com.google.gson.Gson; +import com.xabber.android.data.xaccount.XabberAccount; +import com.xabber.android.data.xaccount.XabberAccountManager; + +import java.util.Map; + +public class PushService extends FirebaseMessagingService { + + private static final String FIELD_TARGET_TYPE = "target_type"; + private static final String FIELD_TARGET = "target"; + private static final String FIELD_BODY = "body"; + + private static final String ACTION_SETTINGS_UPDATED = "settings_updated"; + private static final String ACTION_ACCOUNT_UPDATED = "account_updated"; + private static final String TARGET_TYPE_XACCOUNT = "xaccount"; + private static final String TARGET_TYPE_NODE = "node"; + + Gson gson = new Gson(); + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + + // Check if message contains a data payload. + if (remoteMessage.getData().size() > 0) { + Map data = remoteMessage.getData(); + String targetType = data.get(FIELD_TARGET_TYPE); + String target = data.get(FIELD_TARGET); + String encodedBody = data.get(FIELD_BODY); + + if (targetType != null && target != null && encodedBody != null) { + String decodedBody = new String(Base64.decode(encodedBody, Base64.NO_WRAP)); + + switch (targetType) { + case TARGET_TYPE_XACCOUNT: + onXAccountPushReceived(target, decodedBody); + break; + case TARGET_TYPE_NODE: + onXMPPPushReceived(target, decodedBody); + break; + default: + Log.d(PushService.class.getSimpleName(), "Unexpected target type - " + targetType); + } + } + } + } + + private void onXAccountPushReceived(String target, String body) { + XabberAccount xabberAccount = XabberAccountManager.getInstance().getAccount(); + if (xabberAccount != null && xabberAccount.getFullUsername().equals(target)) { + XAccountPushData data = gson.fromJson(body, XAccountPushData.class); + + if (data != null && xabberAccount.getFullUsername().equals(data.getUsername()) + && !xabberAccount.getToken().equals(data.getFromToken())) { + switch (data.getAction()) { + case ACTION_SETTINGS_UPDATED: + XabberAccountManager.getInstance().updateAccountSettings(); + break; + case ACTION_ACCOUNT_UPDATED: + XabberAccountManager.getInstance().updateAccountInfo(); + break; + default: + Log.d(PushService.class.getSimpleName(), + "Unexpected action in Xabber Account push - " + data.getAction()); + } + } + } + } + + private void onXMPPPushReceived(String target, String body) { + /** Will be used for XMPP pushes */ + } + + private static class XAccountPushData { + private final String action; + private final String username; + private final String from_token; + + public XAccountPushData(String action, String username, String from_token) { + this.action = action; + this.username = username; + this.from_token = from_token; + } + + public String getAction() { + return action; + } + + public String getUsername() { + return username; + } + + public String getFromToken() { + return from_token; + } + } +} diff --git a/xabber/src/main/java/com/xabber/android/service/UploadService.java b/xabber/src/main/java/com/xabber/android/service/UploadService.java index dc1ba308f4..289a0c5ab2 100644 --- a/xabber/src/main/java/com/xabber/android/service/UploadService.java +++ b/xabber/src/main/java/com/xabber/android/service/UploadService.java @@ -13,7 +13,6 @@ import com.xabber.android.data.account.AccountItem; import com.xabber.android.data.account.AccountManager; -import com.xabber.android.data.connection.CertificateManager; import com.xabber.android.data.entity.AccountJid; import com.xabber.android.data.entity.UserJid; import com.xabber.android.data.extension.file.FileManager; @@ -21,6 +20,7 @@ import com.xabber.android.data.extension.httpfileupload.ImageCompressor; import com.xabber.android.data.log.LogManager; import com.xabber.android.data.message.MessageManager; +import com.xabber.android.utils.HttpClientWithMTM; import com.xabber.xmpp.httpfileupload.Slot; import org.apache.commons.io.FilenameUtils; @@ -45,13 +45,7 @@ import java.util.HashMap; import java.util.List; import java.util.UUID; -import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.X509TrustManager; - -import de.duenndns.ssl.MemorizingTrustManager; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -312,25 +306,15 @@ private I sendIqRequestAndWaitForResponse(AbstractXMPPConnection private Response uploadFileToSlot(final AccountJid account, final Slot slot, final File file) throws IOException, NoSuchAlgorithmException, KeyManagementException { - MemorizingTrustManager mtm = CertificateManager.getInstance().getNewFileUploadManager(account); - SSLContext sslContext = SSLContext.getInstance("SSL"); - sslContext.init(null, new X509TrustManager[]{mtm}, new java.security.SecureRandom()); - SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); - - OkHttpClient client = new OkHttpClient().newBuilder() - .sslSocketFactory(sslSocketFactory) - .hostnameVerifier(mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier())) - .writeTimeout(5, TimeUnit.MINUTES) - .connectTimeout(5, TimeUnit.MINUTES) - .readTimeout(5, TimeUnit.MINUTES) - .build(); + OkHttpClient client = HttpClientWithMTM.getClient(account); Request request = new Request.Builder() .url(slot.getPutUrl()) .put(RequestBody.create(CONTENT_TYPE, file)) .build(); - return client.newCall(request).execute(); + if (client != null) return client.newCall(request).execute(); + else throw new IOException("Upload failed: failed to create httpclient"); } private static String getCompressedDirPath() { diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/BaseLoginActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/BaseLoginActivity.java index e6d1b09c4a..3c5e898c6b 100644 --- a/xabber/src/main/java/com/xabber/android/ui/activity/BaseLoginActivity.java +++ b/xabber/src/main/java/com/xabber/android/ui/activity/BaseLoginActivity.java @@ -1,6 +1,5 @@ package com.xabber.android.ui.activity; -import android.app.AlertDialog; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; @@ -22,6 +21,7 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.gson.Gson; import com.twitter.sdk.android.core.Callback; import com.twitter.sdk.android.core.DefaultLogger; import com.twitter.sdk.android.core.Result; @@ -33,14 +33,23 @@ import com.twitter.sdk.android.core.identity.TwitterAuthClient; import com.xabber.android.R; import com.xabber.android.data.Application; +import com.xabber.android.data.SettingsManager; +import com.xabber.android.data.account.AccountManager; import com.xabber.android.data.xaccount.AuthManager; -import com.xabber.android.data.xaccount.XAccountTokenDTO; +import com.xabber.android.data.xaccount.XMPPAccountSettings; import com.xabber.android.data.xaccount.XabberAccount; +import com.xabber.android.data.xaccount.XabberAccountManager; +import com.xabber.android.ui.dialog.AddEmailDialogFragment; +import com.xabber.android.ui.dialog.ConfirmEmailDialogFragment; +import com.xabber.android.ui.fragment.XAccountLinksFragment; +import com.xabber.android.ui.helper.OnSocialBindListener; import com.xabber.android.utils.RetrofitErrorConverter; import java.io.IOException; import java.util.Collections; +import java.util.List; +import okhttp3.ResponseBody; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; @@ -51,9 +60,11 @@ * Created by valery.miller on 31.07.17. */ -public abstract class BaseLoginActivity extends ManagedActivity implements GoogleApiClient.OnConnectionFailedListener { +public abstract class BaseLoginActivity extends ManagedActivity implements + GoogleApiClient.OnConnectionFailedListener, XAccountLinksFragment.Listener, + AddEmailDialogFragment.Listener, ConfirmEmailDialogFragment.Listener, OnSocialBindListener { - private final static String TAG = BaseLoginActivity.class.getSimpleName(); + private final static String LOG_TAG = BaseLoginActivity.class.getSimpleName(); // facebook auth private CallbackManager callbackManager; @@ -67,6 +78,7 @@ public abstract class BaseLoginActivity extends ManagedActivity implements Googl private static final int RC_SIGN_IN = 9001; private static final String GOOGLE_TOKEN_SERVER = "https://www.googleapis.com/oauth2/v4/token"; + private Gson gson = new Gson(); protected CompositeSubscription compositeSubscription = new CompositeSubscription(); @Override @@ -114,15 +126,6 @@ public void loginTwitter() { twitterAuthClient.authorize(this, twitterSessionCallback); } - public void loginGithub() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setMessage(R.string.github_alert) - .setTitle("GitHub") - .setPositiveButton(R.string.ok, null); - AlertDialog dialog = builder.create(); - dialog.show(); - } - private void initGoogleAuth() { GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestServerAuthCode(getString(R.string.SOCIAL_AUTH_GOOGLE_KEY), false) @@ -159,7 +162,8 @@ public void run() { Application.getInstance().runOnUiThread(new Runnable() { @Override public void run() { - loginSocial(AuthManager.PROVIDER_GOOGLE, token); + String credentials = gson.toJson(new AuthManager.AccessToken(token)); + onSocialAuthSuccess(AuthManager.PROVIDER_GOOGLE, credentials); } }); } catch (IOException e) { @@ -168,7 +172,7 @@ public void run() { } }); } - } else Toast.makeText(this, "google error", Toast.LENGTH_LONG).show(); + } else Toast.makeText(this, R.string.auth_google_error, Toast.LENGTH_LONG).show(); } private void initFacebookAuth() { @@ -177,18 +181,20 @@ private void initFacebookAuth() { @Override public void onSuccess(LoginResult loginResult) { String token = loginResult.getAccessToken().getToken(); - if (token != null) - loginSocial(AuthManager.PROVIDER_FACEBOOK, token); + if (token != null) { + String credentials = gson.toJson(new AuthManager.AccessToken(token)); + onSocialAuthSuccess(AuthManager.PROVIDER_FACEBOOK, credentials); + } } @Override public void onCancel() { - Toast.makeText(BaseLoginActivity.this, "fcb cancel", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseLoginActivity.this, R.string.auth_facebook_cancel, Toast.LENGTH_SHORT).show(); } @Override public void onError(FacebookException error) { - Toast.makeText(BaseLoginActivity.this, "fcb error", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseLoginActivity.this, R.string.auth_facebook_error, Toast.LENGTH_SHORT).show(); } }); } @@ -208,193 +214,334 @@ private void initTwitterAuth() { public void success(Result result) { String token = result.data.getAuthToken().token; String secret = result.data.getAuthToken().secret; - if (token != null && secret != null) - loginSocialTwitter(token, secret, + if (token != null && secret != null) { + String credentials = gson.toJson(new AuthManager.TwitterAccessToken( + new AuthManager.TwitterTokens(secret, token), getResources().getString(R.string.SOCIAL_AUTH_TWITTER_SECRET), - getResources().getString(R.string.SOCIAL_AUTH_TWITTER_KEY)); + getResources().getString(R.string.SOCIAL_AUTH_TWITTER_KEY))); + onSocialAuthSuccess(AuthManager.PROVIDER_TWITTER, credentials); + } } @Override public void failure(TwitterException exception) { - Toast.makeText(BaseLoginActivity.this, "twitter error", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseLoginActivity.this, R.string.auth_twitter_error, Toast.LENGTH_SHORT).show(); } }; } - private void loginSocial(String provider, String token) { - showProgress(getString(R.string.progress_title_login)); - Subscription loginSocialSubscription = AuthManager.loginSocial(provider, token) + protected abstract void onSocialAuthSuccess(final String provider, final String credentials); + + protected abstract void showProgress(String title); + + protected abstract void hideProgress(); + + protected void handleError(Throwable throwable, String errorContext, String logTag) { + String message = RetrofitErrorConverter.throwableToHttpError(throwable); + if (message != null) { + Log.d(logTag, errorContext + message); + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + } else { + Log.d(logTag, errorContext + throwable.toString()); + Toast.makeText(this, errorContext + throwable.toString(), + Toast.LENGTH_LONG).show(); + } + } + + /** SYNCHRONIZATION */ + + protected void synchronize(boolean needGoToMainActivity) { + XabberAccount account = XabberAccountManager.getInstance().getAccount(); + if (account != null && account.getToken() != null) { + showProgress(getResources().getString(R.string.progress_title_sync)); + getAccountWithUpdate(account.getToken(), needGoToMainActivity); + } else { + Toast.makeText(BaseLoginActivity.this, R.string.sync_fail, Toast.LENGTH_SHORT).show(); + } + } + + protected void getAccountWithUpdate(String token, final boolean needGoToMainActivity) { + Subscription loadAccountsSubscription = AuthManager.getAccount(token) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { + .subscribe(new Action1() { @Override - public void call(XAccountTokenDTO s) { - handleSuccessLogin(s); + public void call(XabberAccount s) { + Log.d(LOG_TAG, "Xabber account loading from net: successfully"); + updateAccountInfo(s); + + // if exist local accounts + if (AccountManager.getInstance().getAllAccountItems().size() > 0) + updateSettings(needGoToMainActivity); + else getSettings(needGoToMainActivity); + } }, new Action1() { @Override public void call(Throwable throwable) { - handleErrorSocialLogin(throwable); + Log.d(LOG_TAG, "Xabber account loading from net: error: " + throwable.toString()); + String message = RetrofitErrorConverter.throwableToHttpError(throwable); + if (message != null && message.equals("Invalid token")) { + XabberAccountManager.getInstance().onInvalidToken(); + //showLoginFragment(); + } + + hideProgress(); + Toast.makeText(BaseLoginActivity.this, R.string.sync_fail, Toast.LENGTH_SHORT).show(); } }); - compositeSubscription.add(loginSocialSubscription); + compositeSubscription.add(loadAccountsSubscription); } - private void loginSocialTwitter(String token, String twitterTokenSecret, String secret, String key) { - showProgress(getString(R.string.progress_title_login)); - Subscription loginSocialSubscription = AuthManager.loginSocialTwitter(token, twitterTokenSecret, secret, key) + protected void updateSettings(final boolean needGoToMainActivity) { + Subscription getSettingsSubscription = AuthManager.patchClientSettings(XabberAccountManager.getInstance().createSettingsList()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { + .subscribe(new Action1>() { @Override - public void call(XAccountTokenDTO s) { - handleSuccessLogin(s); + public void call(List s) { + Log.d(LOG_TAG, "XMPP accounts loading from net: successfully"); + hideProgress(); + updateLastSyncTime(); + onSynchronized(); + //Toast.makeText(BaseLoginActivity.this, R.string.sync_success, Toast.LENGTH_SHORT).show(); + if (needGoToMainActivity) goToMainActivity(); } }, new Action1() { @Override public void call(Throwable throwable) { - handleErrorSocialLogin(throwable); + Log.d(LOG_TAG, "XMPP accounts loading from net: error: " + throwable.toString()); + hideProgress(); + Toast.makeText(BaseLoginActivity.this, R.string.sync_fail, Toast.LENGTH_SHORT).show(); } }); - compositeSubscription.add(loginSocialSubscription); + compositeSubscription.add(getSettingsSubscription); } - public void login(String login, String pass) { - showProgress(getString(R.string.progress_title_login)); - Subscription loginSubscription = AuthManager.login(login, pass) + protected void getSettings(final boolean needGoToMainActivity) { + Subscription getSettingsSubscription = AuthManager.getClientSettings() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { + .subscribe(new Action1>() { @Override - public void call(XAccountTokenDTO s) { - handleSuccessLogin(s); + public void call(List settings) { + Log.d(LOG_TAG, "XMPP accounts loading from net: successfully"); + XabberAccountManager.getInstance().setXmppAccountsForCreate(settings); + hideProgress(); + // update last synchronization time + SettingsManager.setLastSyncDate(XabberAccountManager.getCurrentTimeString()); + onSynchronized(); + //Toast.makeText(BaseLoginActivity.this, R.string.sync_success, Toast.LENGTH_SHORT).show(); + if (needGoToMainActivity) goToMainActivity(); } }, new Action1() { @Override public void call(Throwable throwable) { - handleErrorLogin(throwable); + Log.d(LOG_TAG, "XMPP accounts loading from net: error: " + throwable.toString()); + hideProgress(); } }); - compositeSubscription.add(loginSubscription); + compositeSubscription.add(getSettingsSubscription); } - private void handleSuccessLogin(@NonNull XAccountTokenDTO response) { - getAccount(response.getToken()); + protected void updateAccountInfo(XabberAccount account) {} + + protected void updateLastSyncTime() {} + + protected void goToMainActivity() { + Intent intent = ContactListActivity.createIntent(BaseLoginActivity.this); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + finish(); + startActivity(intent); } - private void handleErrorLogin(Throwable throwable) { - hideProgress(); + protected abstract void onSynchronized(); - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - Log.d(TAG, "Error while login: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } else { - Log.d(TAG, "Error while login: " + throwable.toString()); - Toast.makeText(this, "Error while login: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } + /** ADD EMAIL */ + + protected void resendConfirmEmail(String email) { + showProgress(getResources().getString(R.string.progress_title_resend)); + Subscription resendEmailSubscription = AuthManager.addEmail(email) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(ResponseBody s) { + handleSuccessResendEmail(s); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorResendEmail(throwable); + } + }); + compositeSubscription.add(resendEmailSubscription); + } + + private void handleSuccessResendEmail(ResponseBody response) { + hideProgress(); + Toast.makeText(this, R.string.resend_success, Toast.LENGTH_SHORT).show(); + synchronize(false); } - private void handleErrorSocialLogin(Throwable throwable) { - Log.d(TAG, "Error while social login request: " + throwable.toString()); - Toast.makeText(this, R.string.social_auth_fail, Toast.LENGTH_LONG).show(); + private void handleErrorResendEmail(Throwable throwable) { hideProgress(); + handleError(throwable, "Error while send verification email: ", LOG_TAG); } - private void getAccount(String token) { - Subscription getAccountSubscription = AuthManager.getAccount(token) + /** CONFIRM EMAIL */ + + protected void confirmEmail(String code) { + showProgress(getResources().getString(R.string.progress_title_confirm)); + Subscription confirmSubscription = AuthManager.confirmEmail(code) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1() { @Override - public void call(XabberAccount xabberAccount) { - handleSuccessGetAccount(xabberAccount); + public void call(XabberAccount s) { + handleSuccessConfirm(s); } }, new Action1() { @Override public void call(Throwable throwable) { - handleErrorLogin(throwable); + handleErrorConfirm(throwable); } }); - compositeSubscription.add(getAccountSubscription); - } - - private void handleSuccessGetAccount(@NonNull XabberAccount xabberAccount) { - if (!XabberAccount.STATUS_REGISTERED.equals(xabberAccount.getAccountStatus())) - handleSuccessGetAccountAfterSignUp(xabberAccount); - else { - Intent intent = XabberAccountInfoActivity.createIntent(this); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - intent.putExtra(XabberAccountInfoActivity.CALL_FROM, XabberAccountInfoActivity.CALL_FROM_LOGIN); - finish(); - startActivity(intent); - } + compositeSubscription.add(confirmSubscription); } - public void signup(String email) { - showProgress(getString(R.string.progress_title_signup)); - Subscription signupSubscription = AuthManager.signup(email) + private void handleSuccessConfirm(XabberAccount response) { + hideProgress(); + Toast.makeText(this, R.string.confirm_success, Toast.LENGTH_SHORT).show(); + synchronize(false); + } + + private void handleErrorConfirm(Throwable throwable) { + hideProgress(); + handleError(throwable, "Error while confirming email: ", LOG_TAG); + } + + /** DELETE EMAIL */ + + protected void deleteEmail(int emailId) { + showProgress(getResources().getString(R.string.progress_title_delete)); + Subscription deleteSubscription = AuthManager.deleteEmail(emailId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { + .subscribe(new Action1() { @Override - public void call(XAccountTokenDTO s) { - handleSuccessSignUp(s); + public void call(ResponseBody s) { + handleSuccessDelete(s); } }, new Action1() { @Override public void call(Throwable throwable) { - handleErrorSignUp(throwable); + handleErrorDelete(throwable); } }); - compositeSubscription.add(signupSubscription); + compositeSubscription.add(deleteSubscription); } - private void handleSuccessSignUp(XAccountTokenDTO s) { - getAccountAfterSignUp(s.getToken()); + private void handleSuccessDelete(ResponseBody response) { + hideProgress(); + Toast.makeText(this, R.string.delete_success, Toast.LENGTH_SHORT).show(); + synchronize(false); } - private void handleErrorSignUp(Throwable throwable) { + private void handleErrorDelete(Throwable throwable) { hideProgress(); + handleError(throwable, "Error while deleting email: ", LOG_TAG); + } - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - Log.d(TAG, "Error while registration: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } else { - Log.d(TAG, "Error while registration: " + throwable.toString()); - Toast.makeText(this, "Error while registration: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } + /** SOCIAL BIND / UNBIND */ + + protected void bindSocial(String provider, String credentials) { + showProgress(getResources().getString(R.string.progress_title_bind_social)); + Subscription loginSocialSubscription = AuthManager.bindSocial(provider, credentials) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(ResponseBody s) { + hideProgress(); + Toast.makeText(BaseLoginActivity.this, + R.string.social_bind_success, Toast.LENGTH_SHORT).show(); + synchronize(false); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + hideProgress(); + Toast.makeText(BaseLoginActivity.this, + R.string.social_bind_fail, Toast.LENGTH_SHORT).show(); + } + }); + compositeSubscription.add(loginSocialSubscription); } - private void getAccountAfterSignUp(String token) { - Subscription getAccountSubscription = AuthManager.getAccount(token) + protected void unbindSocial(String provider) { + showProgress(getResources().getString(R.string.progress_title_unbind_social)); + Subscription unbindSocialSubscription = AuthManager.unbindSocial(provider) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { + .subscribe(new Action1() { @Override - public void call(XabberAccount xabberAccount) { - handleSuccessGetAccountAfterSignUp(xabberAccount); + public void call(ResponseBody responseBody) { + hideProgress(); + Toast.makeText(BaseLoginActivity.this, + R.string.social_unbind_success, Toast.LENGTH_SHORT).show(); + synchronize(false); } }, new Action1() { @Override public void call(Throwable throwable) { - handleErrorSignUp(throwable); + hideProgress(); + Toast.makeText(BaseLoginActivity.this, + R.string.social_unbind_fail, Toast.LENGTH_SHORT).show(); } }); - compositeSubscription.add(getAccountSubscription); + compositeSubscription.add(unbindSocialSubscription); } - private void handleSuccessGetAccountAfterSignUp(XabberAccount account) { - hideProgress(); + /** XABBER ACCOUNT LINKS LISTENER */ - Intent intent = XabberAccountInfoActivity.createIntent(this); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - finish(); - startActivity(intent); + @Override + public void onBindClick(String provider) { + switch (provider) { + case AuthManager.PROVIDER_GOOGLE: + loginGoogle(); + break; + case AuthManager.PROVIDER_FACEBOOK: + loginFacebook(); + break; + case AuthManager.PROVIDER_TWITTER: + loginTwitter(); + break; + } } - protected abstract void showProgress(String title); + @Override + public void onSocialUnbindClick(String provider) { + unbindSocial(provider); + } - protected abstract void hideProgress(); + @Override + public void onAddEmailClick(String email) { + resendConfirmEmail(email); + } + + @Override + public void onDeleteEmailClick(int emailId) { + deleteEmail(emailId); + } + + @Override + public void onResendCodeClick(String email) { + resendConfirmEmail(email); + } + + @Override + public void onConfirmClick(String email, String code) { + confirmEmail(code); + } } diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/ChatActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/ChatActivity.java index cd1fc17255..cea45b9a5a 100644 --- a/xabber/src/main/java/com/xabber/android/ui/activity/ChatActivity.java +++ b/xabber/src/main/java/com/xabber/android/ui/activity/ChatActivity.java @@ -519,7 +519,6 @@ private void selectChatPage(BaseEntity chat, boolean smoothScroll) { if (chatFragment != null) { chatFragment.saveInputState(); - chatFragment.saveScrollState(); chatFragment.setChat(chat.getAccount(), chat.getUser()); } @@ -645,6 +644,8 @@ private void insertExtraText() { @Override public void onChatSelected(AccountJid accountJid, UserJid userJid) { + if (chatFragment != null) + chatFragment.saveScrollState(); selectChat(accountJid, userJid); } diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/ContactListActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/ContactListActivity.java index 8f2e17bac3..e2324affc6 100644 --- a/xabber/src/main/java/com/xabber/android/ui/activity/ContactListActivity.java +++ b/xabber/src/main/java/com/xabber/android/ui/activity/ContactListActivity.java @@ -58,7 +58,6 @@ import com.xabber.android.data.roster.RosterContact; import com.xabber.android.data.roster.RosterManager; import com.xabber.android.data.xaccount.XMPPAccountSettings; -import com.xabber.android.data.xaccount.XabberAccount; import com.xabber.android.data.xaccount.XabberAccountManager; import com.xabber.android.presentation.mvp.contactlist.ContactListPresenter; import com.xabber.android.presentation.ui.contactlist.ContactListFragment; @@ -83,6 +82,8 @@ import java.util.List; import java.util.Locale; +import rx.subscriptions.CompositeSubscription; + /** * Main application activity. * @@ -90,8 +91,7 @@ */ public class ContactListActivity extends ManagedActivity implements OnAccountChangedListener, View.OnClickListener, OnChooseListener, ContactListFragment.ContactListFragmentListener, - ContactListDrawerFragment.ContactListDrawerListener, - BottomMenu.OnClickListener { + ContactListDrawerFragment.ContactListDrawerListener, BottomMenu.OnClickListener { /** * Select contact to be invited to the room was requested. @@ -129,6 +129,8 @@ public class ContactListActivity extends ManagedActivity implements OnAccountCha private View showcaseView; private Button btnShowcaseGotIt; + private CompositeSubscription compositeSubscription = new CompositeSubscription(); + public static Intent createPersistentIntent(Context context) { Intent intent = new Intent(context, ContactListActivity.class); intent.setAction("android.intent.action.MAIN"); @@ -221,6 +223,12 @@ public void onClick(View v) { }); } + @Override + protected void onDestroy() { + super.onDestroy(); + compositeSubscription.clear(); + } + @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); @@ -307,12 +315,13 @@ protected void onResume() { super.onResume(); if (!AccountManager.getInstance().hasAccounts() && XabberAccountManager.getInstance().getAccount() == null) { - startActivity(IntroActivity.createIntent(this)); + startActivity(TutorialActivity.createIntent(this)); finish(); return; } rebuildAccountToggle(); + setStatusBarColor(); Application.getInstance().addUIListener(OnAccountChangedListener.class, this); if (action != null) { @@ -457,7 +466,9 @@ public void showPassDialogs() { // create account if exist token try { AccountJid accountJid = AccountManager.getInstance().addAccount(item.getJid(), - "", item.getToken(), false, true, true, false, false, true); + "", item.getToken(), false, true, + true, false, false, + true, false); AccountManager.getInstance().setColor(accountJid, ColorManager.getInstance().convertColorNameToIndex(item.getColor())); AccountManager.getInstance().setOrder(accountJid, item.getOrder()); AccountManager.getInstance().setTimestamp(accountJid, item.getTimestamp()); @@ -672,6 +683,7 @@ private void createShortcut(AbstractContact abstractContact) { @Override public void onAccountsChanged(Collection accounts) { rebuildAccountToggle(); + setStatusBarColor(); } @Override @@ -701,10 +713,7 @@ public void onContactListDrawerListener(int viewId) { startActivity(PreferenceEditor.createIntent(this)); break; case R.id.drawer_header_action_xabber_account: - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null) - startActivity(XabberAccountInfoActivity.createIntent(this)); - else startActivity(TutorialActivity.createIntent(this)); + onXabberAccountClick(); break; case R.id.drawer_action_patreon: startActivity(PatreonAppealActivity.createIntent(this)); @@ -755,6 +764,10 @@ public void onSearchClick() { } else showContactListFragment(null); } + private void onXabberAccountClick() { + startActivity(XabberAccountActivity.createIntent(this)); + } + private void showBottomNavigation() { if (!isFinishing()) { if (bottomMenu == null) diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/DeepLinkActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/DeepLinkActivity.java new file mode 100644 index 0000000000..c0cbcbc22f --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/activity/DeepLinkActivity.java @@ -0,0 +1,103 @@ +package com.xabber.android.ui.activity; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.widget.Toast; + +import com.xabber.android.R; +import com.xabber.android.data.xaccount.AuthManager; +import com.xabber.android.data.xaccount.HttpApiManager; +import com.xabber.android.data.xaccount.XabberAccount; +import com.xabber.android.data.xaccount.XabberAccountManager; + +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; + +public class DeepLinkActivity extends BaseLoginActivity { + + protected CompositeSubscription compositeSubscription = new CompositeSubscription(); + private final static String LOG_TAG = DeepLinkActivity.class.getSimpleName(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_deeplink); + } + + @Override + protected void onResume() { + super.onResume(); + handleIntent(getIntent()); + } + + @Override + protected void onPause() { + super.onPause(); + compositeSubscription.clear(); + } + + @Override + protected void onSocialAuthSuccess(String provider, String credentials) { } + + @Override + protected void showProgress(String title) { } + + @Override + protected void hideProgress() { } + + @Override + protected void onSynchronized() { + + } + + private void handleIntent(Intent intent) { + if (intent == null) return; + + String appLinkAction = intent.getAction(); + Uri appLinkData = intent.getData(); + if (Intent.ACTION_VIEW.equals(appLinkAction) && appLinkData != null) { + String uri = appLinkData.toString(); + String key = uri.replace(HttpApiManager.XABBER_EMAIL_CONFIRM_URL, ""); + key = key.replace("/", ""); + + XabberAccount account = XabberAccountManager.getInstance().getAccount(); + if (account != null) confirmEmailWithKey(key); + } + } + + /** CONFIRM EMAIL */ + + protected void confirmEmailWithKey(String key) { + showProgress(getResources().getString(R.string.progress_title_confirm)); + Subscription confirmSubscription = AuthManager.confirmEmailWithKey(key) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(XabberAccount s) { + handleSuccessConfirm(s); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorConfirm(throwable); + } + }); + compositeSubscription.add(confirmSubscription); + } + + private void handleSuccessConfirm(XabberAccount response) { + Toast.makeText(this, R.string.confirm_success, Toast.LENGTH_SHORT).show(); + synchronize(false); + finish(); + } + + private void handleErrorConfirm(Throwable throwable) { + handleError(throwable, "Error while confirming email: ", LOG_TAG); + finish(); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/IntroActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/IntroActivity.java deleted file mode 100644 index 0ba2112214..0000000000 --- a/xabber/src/main/java/com/xabber/android/ui/activity/IntroActivity.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.xabber.android.ui.activity; - -import android.app.SearchManager; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.View; -import android.widget.Button; - -import com.xabber.android.R; -import com.xabber.android.data.account.AccountManager; -import com.xabber.android.data.log.LogManager; -import com.xabber.android.data.xaccount.XabberAccountManager; - -public class IntroActivity extends ManagedActivity { - - private static final String LOG_TAG = IntroActivity.class.getSimpleName(); - - public static Intent createIntent(Context context) { - return new Intent(context, IntroActivity.class); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (isFinishing()) { - return; - } - - setContentView(R.layout.activity_intro); - -// ((TextView) findViewById(R.id.intro_faq_text)) -// .setMovementMethod(LinkMovementMethod.getInstance()); - - Button btnBasicXmpp = (Button) findViewById(R.id.btnBasicXmpp); - Button btnLoginXabber = (Button) findViewById(R.id.btnLoginXabber); - - btnLoginXabber.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - startActivity(TutorialActivity.createIntent(IntroActivity.this)); - } - }); - - btnBasicXmpp.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - startActivity(AccountAddActivity.createIntent(IntroActivity.this)); - } - }); - -// registerAccountButton.setOnClickListener(new View.OnClickListener() { -// @Override -// public void onClick(View v) { -// searchHowToRegister(); -// } -// }); - } - - private void searchHowToRegister() { - String searchQuery = getString(R.string.intro_web_search_register_xmpp); - - if (!startWebSearchActivity(searchQuery)) { - if (!startSearchGoogleActivity(searchQuery)) { - LogManager.w(LOG_TAG, "Could not find web search or browser activity"); - } - } - } - - private boolean startSearchGoogleActivity(String searchQuery) { - Uri uri = Uri.parse("http://www.google.com/#q=" + searchQuery); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - try { - startActivity(intent); - return true; - } catch (ActivityNotFoundException e) { - LogManager.exception(LOG_TAG, e); - return false; - } - - } - - private boolean startWebSearchActivity(String searchQuery) { - Intent intent = new Intent(Intent.ACTION_WEB_SEARCH ); - intent.putExtra(SearchManager.QUERY, searchQuery); - try { - startActivity(intent); - return true; - } catch (ActivityNotFoundException e) { - LogManager.exception(LOG_TAG, e); - return false; - } - } - - @Override - protected void onResume() { - super.onResume(); - - if (AccountManager.getInstance().hasAccounts() || XabberAccountManager.getInstance().getAccount() != null) { - Intent intent = ContactListActivity.createIntent(this); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - finish(); - startActivity(intent); - } - } - -} diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/TutorialActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/TutorialActivity.java index dc0c0a8d68..5e67113d21 100644 --- a/xabber/src/main/java/com/xabber/android/ui/activity/TutorialActivity.java +++ b/xabber/src/main/java/com/xabber/android/ui/activity/TutorialActivity.java @@ -6,11 +6,12 @@ import android.support.annotation.Nullable; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; -import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import com.xabber.android.R; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.xaccount.XabberAccountManager; import com.xabber.android.ui.adapter.TutorialAdapter; import me.relex.circleindicator.CircleIndicator; @@ -19,7 +20,7 @@ * Created by valery.miller on 14.09.17. */ -public class TutorialActivity extends AppCompatActivity { +public class TutorialActivity extends ManagedActivity { private Button btnLogin; private Button btnRegister; @@ -32,6 +33,10 @@ public static Intent createIntent(Context context) { protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (isFinishing()) { + return; + } + setContentView(R.layout.activity_tutorial); overridePendingTransition(R.anim.fade_in, R.anim.fade_out); @@ -48,7 +53,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - startActivity(XabberLoginActivity.createIntent(TutorialActivity.this)); + startActivity(XabberLoginActivity.createIntent(TutorialActivity.this, XabberLoginActivity.FRAGMENT_LOGIN)); } }); @@ -56,13 +61,23 @@ public void onClick(View v) { btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent intent = XabberAccountInfoActivity.createIntent(TutorialActivity.this); - intent.putExtra(XabberAccountInfoActivity.CALL_FROM, XabberAccountInfoActivity.CALL_FROM_LOGIN); - startActivity(intent); + startActivity(XabberLoginActivity.createIntent(TutorialActivity.this, XabberLoginActivity.FRAGMENT_SIGNUP_STEP1)); } }); } + @Override + protected void onResume() { + super.onResume(); + + if (AccountManager.getInstance().hasAccounts() || XabberAccountManager.getInstance().getAccount() != null) { + Intent intent = ContactListActivity.createIntent(this); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + finish(); + startActivity(intent); + } + } + @Override public void onBackPressed() { super.onBackPressed(); diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/XAChangePassActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/XAChangePassActivity.java new file mode 100644 index 0000000000..90278e885b --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/activity/XAChangePassActivity.java @@ -0,0 +1,177 @@ +package com.xabber.android.ui.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.TextInputLayout; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.Toast; + +import com.xabber.android.R; +import com.xabber.android.data.connection.NetworkManager; +import com.xabber.android.data.xaccount.AuthManager; +import com.xabber.android.ui.color.BarPainter; + +import okhttp3.ResponseBody; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; + +public class XAChangePassActivity extends ManagedActivity { + + private Toolbar toolbar; + + private EditText edtOldPass; + private TextInputLayout tilOldPass; + private EditText edtPass; + private TextInputLayout tilPass; + private EditText edtConfirmPass; + private TextInputLayout tilConfirmPass; + private Button btnChange; + private ProgressBar progressBar; + + protected CompositeSubscription compositeSubscription = new CompositeSubscription(); + + @NonNull + public static Intent createIntent(Context context) { + return new Intent(context, XAChangePassActivity.class); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(R.style.Theme_LightToolbar); + setContentView(R.layout.activity_change_xa_pass); + + toolbar = (Toolbar) findViewById(R.id.toolbar_default); + toolbar.setNavigationIcon(R.drawable.ic_arrow_left); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + toolbar.setTitleTextColor(getResources().getColor(R.color.black_text)); + toolbar.setTitle(R.string.button_change_pass); + BarPainter barPainter = new BarPainter(this, toolbar); + barPainter.setLiteGrey(); + + progressBar = findViewById(R.id.progressBar); + edtOldPass = findViewById(R.id.edtOldPass); + tilOldPass = findViewById(R.id.tilOldPass); + edtPass = findViewById(R.id.edtPass); + tilPass = findViewById(R.id.tilPass); + edtConfirmPass = findViewById(R.id.edtConfirmPass); + tilConfirmPass = findViewById(R.id.tilConfirmPass); + btnChange = findViewById(R.id.btnChange); + btnChange.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onChangePassClick(edtOldPass, edtPass, edtConfirmPass); + } + }); + } + + @Override + protected void onPause() { + super.onPause(); + compositeSubscription.clear(); + } + + public void onChangePassClick(EditText edtOldPass, EditText edtPass, EditText edtConfirmPass) { + String oldPass = edtOldPass.getText().toString(); + oldPass = oldPass.trim(); + + String pass = edtPass.getText().toString(); + pass = pass.trim(); + + String confirmPass = edtConfirmPass.getText().toString(); + confirmPass = confirmPass.trim(); + + if (oldPass.isEmpty()) { + tilOldPass.setError(getString(R.string.empty_field)); + return; + } else tilOldPass.setError(null); + + if (oldPass.length() < 4) { + tilOldPass.setError(getString(R.string.pass_too_short)); + return; + } else tilOldPass.setError(null); + + if (pass.isEmpty()) { + tilPass.setError(getString(R.string.empty_field)); + return; + } else tilPass.setError(null); + + if (pass.length() < 4) { + tilPass.setError(getString(R.string.pass_too_short)); + return; + } else tilPass.setError(null); + + if (confirmPass.isEmpty()) { + tilConfirmPass.setError(getString(R.string.empty_field)); + return; + } else tilConfirmPass.setError(null); + + if (confirmPass.length() < 4) { + tilConfirmPass.setError(getString(R.string.pass_too_short)); + return; + } else tilConfirmPass.setError(null); + + if (!pass.equals(confirmPass)) { + tilConfirmPass.setError(getString(R.string.passwords_not_match)); + return; + } else tilConfirmPass.setError(null); + + if (checkInternetOrShowError()) changePass(oldPass, pass, confirmPass); + } + + private void changePass(String oldPass, String pass, String confirmPass) { + showProgress(true); + compositeSubscription.add(AuthManager.changePassword(oldPass, pass, confirmPass) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(ResponseBody s) { + handleSuccessChangePass(); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorChangePass(); + } + })); + } + + private void handleSuccessChangePass() { + Toast.makeText(this, R.string.password_changed_success, Toast.LENGTH_SHORT).show(); + showProgress(false); + finish(); + } + + private void handleErrorChangePass() { + Toast.makeText(this, R.string.password_changed_fail, Toast.LENGTH_SHORT).show(); + showProgress(false); + } + + private boolean checkInternetOrShowError() { + if (NetworkManager.isNetworkAvailable()) return true; + else { + Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); + return false; + } + } + + private void showProgress(boolean show) { + progressBar.setVisibility(show ? View.VISIBLE : View.GONE); + btnChange.setEnabled(!show); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/XabberAccountActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/XabberAccountActivity.java new file mode 100644 index 0000000000..40dfac04de --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/activity/XabberAccountActivity.java @@ -0,0 +1,406 @@ +package com.xabber.android.ui.activity; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.CheckBox; +import android.widget.Toast; + +import com.xabber.android.R; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.connection.NetworkManager; +import com.xabber.android.data.xaccount.AuthManager; +import com.xabber.android.data.xaccount.EmailDTO; +import com.xabber.android.data.xaccount.XMPPAuthManager; +import com.xabber.android.data.xaccount.XabberAccount; +import com.xabber.android.data.xaccount.XabberAccountManager; +import com.xabber.android.ui.color.BarPainter; +import com.xabber.android.ui.fragment.XAccountXMPPLoginFragment; +import com.xabber.android.ui.fragment.XabberAccountInfoFragment; +import com.xabber.android.utils.RetrofitErrorConverter; + +import okhttp3.ResponseBody; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; + +public class XabberAccountActivity extends BaseLoginActivity + implements Toolbar.OnMenuItemClickListener, XAccountXMPPLoginFragment.Listener { + + private final static String LOG_TAG = XabberAccountActivity.class.getSimpleName(); + private final static String FRAGMENT_INFO = "fragment_info"; + private final static String FRAGMENT_LOGIN = "fragment_login"; + + private FragmentTransaction fTrans; + private Fragment fragmentInfo; + private Fragment fragmentLogin; + + private Toolbar toolbar; + private BarPainter barPainter; + + private Dialog dialog; + private boolean dialogShowed; + + @NonNull + public static Intent createIntent(Context context) { + return new Intent(context, XabberAccountActivity.class); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(R.style.Theme_LightToolbar); + setContentView(R.layout.activity_xabber_account_info); + + toolbar = (Toolbar) findViewById(R.id.toolbar_default); + toolbar.setOnMenuItemClickListener(this); + toolbar.setNavigationIcon(R.drawable.ic_arrow_left); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + toolbar.inflateMenu(R.menu.toolbar_xabber_account_info); + toolbar.setTitleTextColor(getResources().getColor(R.color.black_text)); + barPainter = new BarPainter(this, toolbar); + } + + @Override + protected void onResume() { + super.onResume(); + onPrepareOptionsMenu(toolbar.getMenu()); + subscribeForXabberAccount(); + } + + @Override + protected void onPause() { + super.onPause(); + if (dialog != null) + dialog.dismiss(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + compositeSubscription.clear(); + } + + @Override + public boolean onMenuItemClick(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_set_pass: + onResetPassClick(); + return true; + case R.id.action_reset_pass: + onResetPassClick(); + return true; + case R.id.action_change_pass: + startActivity(XAChangePassActivity.createIntent(this)); + return true; + case R.id.action_quit: + if (!dialogShowed) { + dialogShowed = true; + showLogoutDialog(); + } + return true; + case R.id.action_sync: + onSyncClick(false); + return true; + default: + return false; + } + } + + @Override + protected void showProgress(String title) { + if (fragmentInfo != null) + ((XabberAccountInfoFragment)fragmentInfo).showProgressInAccount(true); + } + + @Override + protected void hideProgress() { + if (fragmentInfo != null) + ((XabberAccountInfoFragment)fragmentInfo).showProgressInAccount(false); + } + + private boolean checkInternetOrShowError() { + if (NetworkManager.isNetworkAvailable()) return true; + else { + Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); + return false; + } + } + + private void subscribeForXabberAccount() { + compositeSubscription.add(XabberAccountManager.getInstance().subscribeForAccount() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(new Action1() { + @Override + public void call(XabberAccount account) { + if (account != null) showInfoFragment(); + else showLoginFragment(); + } + }).subscribe()); + } + + @Override + protected void onSynchronized() { + XabberAccountInfoFragment fragment = (XabberAccountInfoFragment) getFragmentManager().findFragmentByTag(FRAGMENT_INFO); + if (fragment != null && fragment.isVisible()) + ((XabberAccountInfoFragment) fragmentInfo).getSettings(); + } + + /** Social Auth */ + + @Override + protected void onSocialAuthSuccess(String provider, String credentials) { + bindSocial(provider, credentials); + } + + /** XMPP-login */ + + @Override + public void onAccountClick(String jid) { + loginXabberAccountViaXMPP(jid); + } + + public void loginXabberAccountViaXMPP(String accountJid) { + if (checkInternetOrShowError()) requestXMPPCode(accountJid); + } + + private void requestXMPPCode(final String jid) { + + // ! show progress ! + + Subscription requestXMPPCodeSubscription = AuthManager.requestXMPPCode(jid) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(AuthManager.XMPPCode code) { + handleSuccessRequestXMPPCode(code, jid); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorRequestXMPPCode(throwable); + } + }); + compositeSubscription.add(requestXMPPCodeSubscription); + } + + private void handleSuccessRequestXMPPCode(AuthManager.XMPPCode code, String jid) { + + // ! hide progress ! + + XMPPAuthManager.getInstance().addRequest(code.getRequestId(), code.getApiJid(), jid); + } + + private void handleErrorRequestXMPPCode(Throwable throwable) { + // ! hide progress ! + // TODO: 07.09.18 сделать корректную обработку ошибок + Toast.makeText(this, "Error while xmpp-auth: " + throwable.toString(), Toast.LENGTH_LONG).show(); + } + + /** Xabber Account Info */ + + public void onLogoutClick(boolean deleteAccounts) { + if (checkInternetOrShowError()) logout(deleteAccounts); + } + + public void onSyncClick(boolean needGoToMainActivity) { + if (checkInternetOrShowError()) synchronize(needGoToMainActivity); + } + + private void showInfoFragment() { + if (fragmentInfo == null) + fragmentInfo = XabberAccountInfoFragment.newInstance(); + + fTrans = getFragmentManager().beginTransaction(); + fTrans.replace(R.id.container, fragmentInfo, FRAGMENT_INFO); + fTrans.commitAllowingStateLoss(); + + toolbar.setTitle(R.string.title_xabber_account); + barPainter.setLiteGrey(); + setupMenu(true); + } + + private void showLoginFragment() { + if (fragmentLogin == null) + fragmentLogin = XAccountXMPPLoginFragment.newInstance(); + + fTrans = getFragmentManager().beginTransaction(); + fTrans.replace(R.id.container, fragmentLogin, FRAGMENT_LOGIN); + fTrans.commit(); + + toolbar.setTitle(R.string.title_login_xabber_account); + barPainter.setLiteGrey(); + setupMenu(false); + } + + private void setupMenu(boolean show) { + Menu menu = toolbar.getMenu(); + menu.setGroupVisible(R.id.group1, show); + + XabberAccount account = XabberAccountManager.getInstance().getAccount(); + if (account != null) { + if (account.hasPassword()) + menu.findItem(R.id.action_set_pass).setVisible(false); + else { + menu.findItem(R.id.action_change_pass).setVisible(false); + menu.findItem(R.id.action_reset_pass).setVisible(false); + } + + } + } + + @Override + protected void updateAccountInfo(XabberAccount account) { + if (account != null) { + XabberAccountInfoFragment fragment = (XabberAccountInfoFragment) getFragmentManager().findFragmentByTag(FRAGMENT_INFO); + if (fragment != null && fragment.isVisible()) + ((XabberAccountInfoFragment) fragmentInfo).updateData(account); + } + } + + @Override + protected void updateLastSyncTime() { + XabberAccountInfoFragment fragment = (XabberAccountInfoFragment) getFragmentManager().findFragmentByTag(FRAGMENT_INFO); + if (fragment != null && fragment.isVisible()) + ((XabberAccountInfoFragment) fragmentInfo).updateLastSyncTime(); + } + + /** LOGOUT */ + + private void showLogoutDialog() { + LayoutInflater inflater = getLayoutInflater(); + View view = inflater.inflate(R.layout.dialog_logout_xabber_account, null); + final CheckBox chbDeleteAccounts = (CheckBox) view.findViewById(R.id.chbDeleteAccounts); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.progress_title_quit) + .setMessage(R.string.logout_summary) + .setView(view) + .setPositiveButton(R.string.button_quit, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onLogoutClick(chbDeleteAccounts.isChecked()); + } + }) + .setNegativeButton(R.string.cancel, null); + dialog = builder.create(); + dialog.show(); + dialogShowed = false; + } + + private void logout(final boolean deleteAccounts) { + showProgress(getResources().getString(R.string.progress_title_quit)); + Subscription logoutSubscription = AuthManager.logout() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(ResponseBody s) { + handleSuccessLogout(s, deleteAccounts); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorLogout(throwable); + } + }); + compositeSubscription.add(logoutSubscription); + } + + private void handleSuccessLogout(ResponseBody s, boolean deleteAccounts) { + if (deleteAccounts) XabberAccountManager.getInstance().deleteSyncedLocalAccounts(); + else AccountManager.getInstance().setAllAccountAutoLoginToXabber(false); + + XabberAccountManager.getInstance().removeAccount(); + hideProgress(); + Toast.makeText(this, R.string.quit_success, Toast.LENGTH_SHORT).show(); + Intent intent = ContactListActivity.createIntent(XabberAccountActivity.this); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } + + private void handleErrorLogout(Throwable throwable) { + String message = RetrofitErrorConverter.throwableToHttpError(throwable); + if (message != null) { + if (message.equals("Invalid token")) { + XabberAccountManager.getInstance().onInvalidToken(); + //showLoginFragment(); + } else { + Log.d(LOG_TAG, "Error while logout: " + message); + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + } + } else { + Log.d(LOG_TAG, "Error while logout: " + throwable.toString()); + Toast.makeText(this, R.string.logout_error, Toast.LENGTH_LONG).show(); + } + hideProgress(); + } + + /** RESET PASS */ + + private void onResetPassClick() { + String email = null; + XabberAccount account = XabberAccountManager.getInstance().getAccount(); + if (account == null) return; + + for (EmailDTO emailDTO : account.getEmails()) { + if (emailDTO.isVerified()) { + email = emailDTO.getEmail(); + break; + } + } + + if (email == null || email.isEmpty()) + Toast.makeText(this, R.string.password_reset_need_email, Toast.LENGTH_SHORT).show(); + else if (checkInternetOrShowError()) requestResetPass(email); + } + + private void requestResetPass(final String email) { + showProgress(""); + compositeSubscription.add(AuthManager.requestResetPassword(email) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(ResponseBody s) { + handleSuccessResetPass(email); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorResetPass(); + } + })); + } + + private void handleSuccessResetPass(String email) { + Toast.makeText(this, getString(R.string.password_reset_success, email), Toast.LENGTH_LONG).show(); + hideProgress(); + } + + private void handleErrorResetPass() { + Toast.makeText(this, R.string.password_reset_fail, Toast.LENGTH_SHORT).show(); + hideProgress(); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/XabberAccountInfoActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/XabberAccountInfoActivity.java deleted file mode 100644 index 40a0b7a452..0000000000 --- a/xabber/src/main/java/com/xabber/android/ui/activity/XabberAccountInfoActivity.java +++ /dev/null @@ -1,809 +0,0 @@ -package com.xabber.android.ui.activity; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.Fragment; -import android.app.FragmentTransaction; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.Toast; - -import com.xabber.android.BuildConfig; -import com.xabber.android.R; -import com.xabber.android.data.Application; -import com.xabber.android.data.SettingsManager; -import com.xabber.android.data.account.AccountManager; -import com.xabber.android.data.connection.NetworkManager; -import com.xabber.android.data.xaccount.AuthManager; -import com.xabber.android.data.xaccount.XMPPAccountSettings; -import com.xabber.android.data.xaccount.XabberAccount; -import com.xabber.android.data.xaccount.XabberAccountManager; -import com.xabber.android.ui.color.BarPainter; -import com.xabber.android.ui.fragment.XabberAccountCompleteRegsiterFrament; -import com.xabber.android.ui.fragment.XabberAccountConfirmPhoneFragment; -import com.xabber.android.ui.fragment.XabberAccountConfirmationFragment; -import com.xabber.android.ui.fragment.XabberAccountInfoFragment; -import com.xabber.android.ui.fragment.XabberAccountLastFragment; -import com.xabber.android.ui.fragment.XabberAccountLoginFragment; -import com.xabber.android.utils.RetrofitErrorConverter; - -import java.util.List; -import java.util.Locale; - -import okhttp3.ResponseBody; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Action1; -import rx.schedulers.Schedulers; - -/** - * Created by valery.miller on 19.07.17. - */ - -public class XabberAccountInfoActivity extends BaseLoginActivity implements Toolbar.OnMenuItemClickListener { - - private final static String LOG_TAG = XabberAccountInfoActivity.class.getSimpleName(); - private final static String EMAIL_CONFIRMATION_URI = "https://www.xabber.com/account/emails/confirmation/"; - - private final static String FRAGMENT_LOGIN = "fragment_login"; - private final static String FRAGMENT_INFO = "fragment_info"; - private final static String FRAGMENT_CONFIRM = "fragment_confirm"; - private final static String FRAGMENT_PHONE_CONFIRM = "fragment_phone_confirm"; - private final static String FRAGMENT_COMPLETE = "fragment_complete"; - private final static String FRAGMENT_LAST = "fragment_last"; - - public final static String CALL_FROM = "call_from"; - public final static String CALL_FROM_LOGIN = "call_from_login"; - private final static String CALL_FROM_SETTINGS = "call_from_settings"; - - private FragmentTransaction fTrans; - - private Toolbar toolbar; - private BarPainter barPainter; - private ProgressDialog progressDialog; - - private Fragment fragmentLogin; - private Fragment fragmentInfo; - private Fragment fragmentConfirmation; - private Fragment fragmentPhoneConfirmation; - private Fragment fragmentCompleteRegsiter; - private Fragment fragmentLastStep; - - private String callFrom = CALL_FROM_SETTINGS; - private boolean needShowSyncDialog = false; - - @NonNull - public static Intent createIntent(Context context) { - return new Intent(context, XabberAccountInfoActivity.class); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // handle call from - Bundle extras = getIntent().getExtras(); - if (extras != null) callFrom = extras.getString(CALL_FROM); - - setContentView(R.layout.activity_xabber_account_info); - - toolbar = (Toolbar) findViewById(R.id.toolbar_default); - toolbar.setNavigationIcon(R.drawable.ic_arrow_left_white_24dp); - toolbar.setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); - toolbar.inflateMenu(R.menu.toolbar_xabber_account_info); - toolbar.setOnMenuItemClickListener(this); - barPainter = new BarPainter(this, toolbar); - } - - @Override - protected void onResume() { - super.onResume(); - onPrepareOptionsMenu(toolbar.getMenu()); - - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null) { - handleCallFrom(account); - - if (XabberAccount.STATUS_NOT_CONFIRMED.equals(account.getAccountStatus())) { - showConfirmFragment(); - } - if (XabberAccount.STATUS_CONFIRMED.equals(account.getAccountStatus()) && BuildConfig.FLAVOR.equals("ru")) { - showPhoneConfirmFragment(); - } - if (XabberAccount.STATUS_CONFIRMED.equals(account.getAccountStatus()) && !account.isNeedToVerifyPhone()) { - showCompleteFragment(); - } - if (XabberAccount.STATUS_REGISTERED.equals(account.getAccountStatus())) { - showInfoFragment(); - needShowSyncDialog = false; - } - } else { - showLoginFragment(); - } - - handleIntent(getIntent()); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - compositeSubscription.clear(); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - if (menu == null) return true; - MenuItem menuItem = menu.findItem(R.id.action_cancel_register); - if (menuItem == null) return true; - - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null) { - menuItem.setVisible(!XabberAccount.STATUS_REGISTERED.equals(account.getAccountStatus())); - } else menuItem.setVisible(false); - return true; - } - - @Override - public boolean onMenuItemClick(MenuItem item) { - if (item.getItemId() == R.id.action_cancel_register) { - showCancelRegisterDialog(); - return true; - } - return false; - } - - private void showCancelRegisterDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.cancel_registration_progress) - .setMessage(R.string.cancel_registration_dialog_message) - .setPositiveButton(R.string.cancel_registration_dialog_resume, null) - .setNegativeButton(R.string.cancel_registration_dialog_cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - cancelRegistration(); - } - }); - Dialog dialog = builder.create(); - dialog.show(); - } - - private void cancelRegistration() { - showProgress(getString(R.string.cancel_registration_progress)); - Application.getInstance().runInBackground(new Runnable() { - @Override - public void run() { - XabberAccountManager.getInstance().deleteXabberAccountFromRealm(); - XabberAccountManager.getInstance().deleteSyncStatesFromRealm(); - Application.getInstance().runOnUiThread(new Runnable() { - @Override - public void run() { - XabberAccountManager.getInstance().removeAccount(); - showLoginFragment(); - onPrepareOptionsMenu(toolbar.getMenu()); - goToMainActivity(); - hideProgress(); - } - }); - } - }); - } - - private void handleCallFrom(XabberAccount account) { - - if (account != null && CALL_FROM_LOGIN.equals(callFrom)) - needShowSyncDialog = true; - - } - - @Override - protected void showProgress(String title) { - if (!isFinishing()) { - progressDialog = new ProgressDialog(this); - progressDialog.setTitle(title); - progressDialog.setMessage(getResources().getString(R.string.progress_message)); - progressDialog.show(); - } - } - - @Override - protected void hideProgress() { - if (progressDialog != null) { - progressDialog.dismiss(); - progressDialog = null; - } - } - - private void updateAccountInfo(XabberAccount account) { - if (account != null) { - XabberAccountInfoFragment fragment = (XabberAccountInfoFragment) getFragmentManager().findFragmentByTag(FRAGMENT_INFO); - if (fragment != null && fragment.isVisible()) - ((XabberAccountInfoFragment) fragmentInfo).updateData(account); - } - } - - private void updateLastSyncTime() { - XabberAccountInfoFragment fragment = (XabberAccountInfoFragment) getFragmentManager().findFragmentByTag(FRAGMENT_INFO); - if (fragment != null && fragment.isVisible()) - ((XabberAccountInfoFragment) fragmentInfo).updateLastSyncTime(); - } - - public void showLoginFragment() { - if (fragmentLogin == null) - fragmentLogin = new XabberAccountLoginFragment(); - - fTrans = getFragmentManager().beginTransaction(); - fTrans.replace(R.id.container, fragmentLogin, FRAGMENT_LOGIN); - fTrans.commit(); - - toolbar.setTitle(R.string.title_register_xabber_account); - barPainter.setBlue(this); - } - - public void showInfoFragment() { - if (fragmentInfo == null) { - fragmentInfo = new XabberAccountInfoFragment(); - Bundle bundle = new Bundle(); - bundle.putBoolean("SHOW_SYNC", needShowSyncDialog); - fragmentInfo.setArguments(bundle); - } - - fTrans = getFragmentManager().beginTransaction(); - fTrans.replace(R.id.container, fragmentInfo, FRAGMENT_INFO); - fTrans.commit(); - - toolbar.setTitle(R.string.title_xabber_account); - barPainter.setDefaultColor(); - } - - private void showConfirmFragment() { - if (fragmentConfirmation == null) - fragmentConfirmation = new XabberAccountConfirmationFragment(); - - fTrans = getFragmentManager().beginTransaction(); - fTrans.replace(R.id.container, fragmentConfirmation, FRAGMENT_CONFIRM); - fTrans.commit(); - - toolbar.setTitle(R.string.title_register_xabber_account); - barPainter.setBlue(this); - } - - private void showPhoneConfirmFragment() { - if (fragmentPhoneConfirmation == null) - fragmentPhoneConfirmation = new XabberAccountConfirmPhoneFragment(); - - fTrans = getFragmentManager().beginTransaction(); - fTrans.replace(R.id.container, fragmentPhoneConfirmation, FRAGMENT_PHONE_CONFIRM); - fTrans.commit(); - - toolbar.setTitle(R.string.title_register_xabber_account); - barPainter.setBlue(this); - } - - private void showCompleteFragment() { - if (fragmentCompleteRegsiter == null) - fragmentCompleteRegsiter = new XabberAccountCompleteRegsiterFrament(); - - fTrans = getFragmentManager().beginTransaction(); - fTrans.replace(R.id.container, fragmentCompleteRegsiter, FRAGMENT_COMPLETE); - fTrans.commit(); - - toolbar.setTitle(R.string.title_register_xabber_account); - barPainter.setBlue(this); - } - - public void showLastFragment() { - if (fragmentLastStep == null) - fragmentLastStep = new XabberAccountLastFragment(); - - fTrans = getFragmentManager().beginTransaction(); - fTrans.replace(R.id.container, fragmentLastStep, FRAGMENT_LAST); - fTrans.commit(); - - toolbar.setTitle(R.string.title_register_xabber_account); - barPainter.setBlue(this); - } - - public void onLoginClick() { - Intent intent = TutorialActivity.createIntent(XabberAccountInfoActivity.this); - startActivity(intent); - } - - public void onLogoutClick(boolean deleteAccounts) { - if (NetworkManager.isNetworkAvailable()) { - logout(deleteAccounts); - } else - Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); - } - - public void onSyncClick(boolean needGoToMainActivity) { - if (NetworkManager.isNetworkAvailable()) { - synchronize(needGoToMainActivity); - } else - Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); - } - - public void onSetPhoneClick(String phoneNumber) { - if (NetworkManager.isNetworkAvailable()) { - setPhoneNumber(phoneNumber); - } else - Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); - } - - public void onConfirmCodeClick(String code) { - if (NetworkManager.isNetworkAvailable()) { - confirmPhone(code); - } else - Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); - } - - public void onResendClick() { - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - String email; - if (account != null && account.getEmails() != null && account.getEmails().size() > 0) { - email = account.getEmails().get(0).getEmail(); - } else return; - - if (NetworkManager.isNetworkAvailable()) { - resendConfirmEmail(email); - } else - Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); - } - - public void onConfirmClick(String code) { - if (NetworkManager.isNetworkAvailable()) { - confirm(code); - } else - Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); - } - - public void onCompleteClick(String username, String pass, String pass2, String firstName, - String lastName, boolean createToken) { - if (NetworkManager.isNetworkAvailable()) { - completeRegister(username, pass, pass2, firstName, lastName, createToken); - } else - Toast.makeText(this, R.string.toast_no_internet, Toast.LENGTH_LONG).show(); - } - - public void onDeleteXabberOrgClick(String jid) { - showProgress(getString(R.string.progress_title_complete)); - Subscription deleteSubscription = AuthManager.deleteClientSettings(jid) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1>() { - @Override - public void call(List settings) { - handleSuccessDelete(settings); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorDelete(throwable); - } - }); - compositeSubscription.add(deleteSubscription); - } - - private void handleSuccessDelete(List settings) { - showInfoFragment(); - hideProgress(); - Toast.makeText(this, R.string.complete_success, Toast.LENGTH_SHORT).show(); - } - - private void handleErrorDelete(Throwable throwable) { - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - if (message.equals("Invalid token")) { - XabberAccountManager.getInstance().onInvalidToken(); - } else { - Log.d(LOG_TAG, "Error while deleting settings: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } - } else { - Log.d(LOG_TAG, "Error while deleting settings: " + throwable.toString()); - Toast.makeText(this, "Error while deleting settings: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } - showInfoFragment(); - hideProgress(); - } - - private void handleIntent(Intent intent) { - String appLinkAction = intent.getAction(); - Uri appLinkData = intent.getData(); - if (Intent.ACTION_VIEW.equals(appLinkAction) && appLinkData != null) { - String uri = appLinkData.toString(); - String key = uri.replace(EMAIL_CONFIRMATION_URI, ""); - key = key.replace("/", ""); - handlerEmailConfirmIntent(key); - } - } - - private void handlerEmailConfirmIntent(String key) { - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null) { - if (XabberAccount.STATUS_NOT_CONFIRMED.equals(account.getAccountStatus())) { - confirmWithKey(key); - } else { - Toast.makeText(this, R.string.toast_email_already_confirm, Toast.LENGTH_SHORT).show(); - } - } else - Toast.makeText(this, R.string.toast_not_authorized, Toast.LENGTH_SHORT).show(); - } - - private void synchronize(boolean needGoToMainActivity) { - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null && account.getToken() != null) { - showProgress(getResources().getString(R.string.progress_title_sync)); - getAccountWithUpdate(account.getToken(), needGoToMainActivity); - } else { - Toast.makeText(XabberAccountInfoActivity.this, R.string.sync_fail, Toast.LENGTH_SHORT).show(); - } - } - - private void goToMainActivity() { - Intent intent = ContactListActivity.createIntent(XabberAccountInfoActivity.this); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - finish(); - startActivity(intent); - } - - private void updateSettings(final boolean needGoToMainActivity) { - Subscription getSettingsSubscription = AuthManager.patchClientSettings(XabberAccountManager.getInstance().createSettingsList()) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1>() { - @Override - public void call(List s) { - Log.d(LOG_TAG, "XMPP accounts loading from net: successfully"); - hideProgress(); - updateLastSyncTime(); - Toast.makeText(XabberAccountInfoActivity.this, R.string.sync_success, Toast.LENGTH_SHORT).show(); - if (needGoToMainActivity) goToMainActivity(); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - Log.d(LOG_TAG, "XMPP accounts loading from net: error: " + throwable.toString()); - hideProgress(); - Toast.makeText(XabberAccountInfoActivity.this, R.string.sync_fail, Toast.LENGTH_SHORT).show(); - } - }); - compositeSubscription.add(getSettingsSubscription); - } - - private void getSettings() { - Subscription getSettingsSubscription = AuthManager.getClientSettings() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1>() { - @Override - public void call(List settings) { - Log.d(LOG_TAG, "XMPP accounts loading from net: successfully"); - XabberAccountManager.getInstance().setXmppAccountsForCreate(settings); - hideProgress(); - // update last synchronization time - SettingsManager.setLastSyncDate(XabberAccountManager.getCurrentTimeString()); - Toast.makeText(XabberAccountInfoActivity.this, R.string.sync_success, Toast.LENGTH_SHORT).show(); - goToMainActivity(); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - Log.d(LOG_TAG, "XMPP accounts loading from net: error: " + throwable.toString()); - hideProgress(); - } - }); - compositeSubscription.add(getSettingsSubscription); - } - - private void getAccountWithUpdate(String token, final boolean needGoToMainActivity) { - Subscription loadAccountsSubscription = AuthManager.getAccount(token) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { - @Override - public void call(XabberAccount s) { - Log.d(LOG_TAG, "Xabber account loading from net: successfully"); - updateAccountInfo(s); - - // if exist local accounts - if (AccountManager.getInstance().getAllAccountItems().size() > 0) - updateSettings(needGoToMainActivity); - else getSettings(); - - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - Log.d(LOG_TAG, "Xabber account loading from net: error: " + throwable.toString()); - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null && message.equals("Invalid token")) { - XabberAccountManager.getInstance().onInvalidToken(); - showLoginFragment(); - } - - hideProgress(); - Toast.makeText(XabberAccountInfoActivity.this, R.string.sync_fail, Toast.LENGTH_SHORT).show(); - } - }); - compositeSubscription.add(loadAccountsSubscription); - } - - private void logout(final boolean deleteAccounts) { - showProgress(getResources().getString(R.string.progress_title_quit)); - Subscription logoutSubscription = AuthManager.logout(deleteAccounts) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { - @Override - public void call(ResponseBody s) { - handleSuccessLogout(s, deleteAccounts); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorLogout(throwable); - } - }); - compositeSubscription.add(logoutSubscription); - } - - private void handleSuccessLogout(ResponseBody s, boolean deleteAccounts) { - if (deleteAccounts) XabberAccountManager.getInstance().deleteSyncedLocalAccounts(); - XabberAccountManager.getInstance().removeAccount(); - showLoginFragment(); - hideProgress(); - Toast.makeText(this, R.string.quit_success, Toast.LENGTH_SHORT).show(); - Intent intent = ContactListActivity.createIntent(XabberAccountInfoActivity.this); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - startActivity(intent); - } - - private void handleErrorLogout(Throwable throwable) { - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - if (message.equals("Invalid token")) { - XabberAccountManager.getInstance().onInvalidToken(); - showLoginFragment(); - } else { - Log.d(LOG_TAG, "Error while logout: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } - } else { - Log.d(LOG_TAG, "Error while logout: " + throwable.toString()); - Toast.makeText(this, "Error while logout: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } - hideProgress(); - } - - private void confirm(String code) { - showProgress(getResources().getString(R.string.progress_title_confirm)); - Subscription confirmSubscription = AuthManager.confirmEmail(code) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { - @Override - public void call(XabberAccount s) { - handleSuccessConfirm(s); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorConfirm(throwable); - } - }); - compositeSubscription.add(confirmSubscription); - } - - private void confirmWithKey(String key) { - showProgress(getResources().getString(R.string.progress_title_confirm)); - Subscription confirmWithKeySubscription = AuthManager.confirmEmailWithKey(key) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { - @Override - public void call(XabberAccount s) { - handleSuccessConfirm(s); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorConfirm(throwable); - } - }); - compositeSubscription.add(confirmWithKeySubscription); - } - - private void handleSuccessConfirm(XabberAccount response) { - if (BuildConfig.FLAVOR.equals("ru") && response.isNeedToVerifyPhone()) - showPhoneConfirmFragment(); - else showCompleteFragment(); - hideProgress(); - Toast.makeText(this, R.string.confirm_success, Toast.LENGTH_SHORT).show(); - } - - private void handleErrorConfirm(Throwable throwable) { - hideProgress(); - - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - Log.d(LOG_TAG, "Error while confirming email: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } else { - Log.d(LOG_TAG, "Error while confirming email: " + throwable.toString()); - Toast.makeText(this, "Error while confirming email: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } - } - - private void completeRegister(String username, String pass, String pass2, String firstName, String lastName, boolean createToken) { - showProgress(getResources().getString(R.string.progress_title_complete)); - Subscription completeSubscription = AuthManager.completeRegister(username, pass, pass2, - firstName, lastName, getString(R.string.xabber_xmpp_host), Locale.getDefault().getLanguage(), createToken) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { - @Override - public void call(XabberAccount s) { - handleSuccessComplete(s); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorComplete(throwable); - } - }); - compositeSubscription.add(completeSubscription); - } - - private void handleSuccessComplete(XabberAccount response) { - hideProgress(); - Toast.makeText(this, R.string.complete_success, Toast.LENGTH_SHORT).show(); - - if (AccountManager.getInstance().getAllAccountItems().size() > 0) { - needShowSyncDialog = true; - showLastFragment(); - } else getSettings(); - } - - private void handleErrorComplete(Throwable throwable) { - hideProgress(); - - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - Log.d(LOG_TAG, "Error while completing register: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } else { - Log.d(LOG_TAG, "Error while completing register: " + throwable.toString()); - Toast.makeText(this, "Error while completing register: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } - } - - private void confirmPhone(String code) { - showProgress(getResources().getString(R.string.progress_title_confirm_phone)); - Subscription subscription = AuthManager.confirmPhoneNumber(code) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { - @Override - public void call(ResponseBody s) { - handleSuccessConfirmPhone(s); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorConfirmPhone(throwable); - } - }); - compositeSubscription.add(subscription); - } - - private void handleSuccessConfirmPhone(ResponseBody response) { - showCompleteFragment(); - hideProgress(); - Toast.makeText(this, R.string.confirm_phone_success, Toast.LENGTH_SHORT).show(); - } - - private void handleErrorConfirmPhone(Throwable throwable) { - hideProgress(); - - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - Log.d(LOG_TAG, "Error while confirm phone number: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } else { - Log.d(LOG_TAG, "Error while confirm phone number: " + throwable.toString()); - Toast.makeText(this, "Error while confirm phone number: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } - } - - private void setPhoneNumber(String phoneNumber) { - showProgress(getResources().getString(R.string.progress_title_set_phone)); - Subscription subscription = AuthManager.setPhoneNumber(phoneNumber) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { - @Override - public void call(ResponseBody s) { - handleSuccessSetPhoneNumber(s); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorSetPhoneNumber(throwable); - } - }); - compositeSubscription.add(subscription); - } - - private void handleSuccessSetPhoneNumber(ResponseBody response) { - // enable code field and button - - hideProgress(); - Toast.makeText(this, R.string.set_phone_success, Toast.LENGTH_SHORT).show(); - } - - private void handleErrorSetPhoneNumber(Throwable throwable) { - hideProgress(); - - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - Log.d(LOG_TAG, "Error while send verification code: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } else { - Log.d(LOG_TAG, "Error while send verification code: " + throwable.toString()); - Toast.makeText(this, "Error while send verification code: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } - } - - private void resendConfirmEmail(String email) { - showProgress(getResources().getString(R.string.progress_title_resend)); - Subscription resendEmailSubscription = AuthManager.addEmail(email) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1() { - @Override - public void call(ResponseBody s) { - handleSuccessResendEmail(s); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorResendEmail(throwable); - } - }); - compositeSubscription.add(resendEmailSubscription); - } - - private void handleSuccessResendEmail(ResponseBody response) { - hideProgress(); - Toast.makeText(this, R.string.resend_success, Toast.LENGTH_SHORT).show(); - } - - private void handleErrorResendEmail(Throwable throwable) { - hideProgress(); - - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - Log.d(LOG_TAG, "Error while send verification email: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } else { - Log.d(LOG_TAG, "Error while send verification email: " + throwable.toString()); - Toast.makeText(this, "Error while send verification email: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } - } -} - diff --git a/xabber/src/main/java/com/xabber/android/ui/activity/XabberLoginActivity.java b/xabber/src/main/java/com/xabber/android/ui/activity/XabberLoginActivity.java index eba86a8a8a..411418f372 100644 --- a/xabber/src/main/java/com/xabber/android/ui/activity/XabberLoginActivity.java +++ b/xabber/src/main/java/com/xabber/android/ui/activity/XabberLoginActivity.java @@ -7,45 +7,86 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.widget.Toolbar; +import android.util.Log; import android.view.View; -import android.widget.ImageView; +import android.view.inputmethod.InputMethodManager; import android.widget.Toast; -import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.safetynet.SafetyNet; +import com.google.android.gms.safetynet.SafetyNetApi; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; import com.xabber.android.R; -import com.xabber.android.data.connection.NetworkManager; +import com.xabber.android.data.xaccount.AuthManager; import com.xabber.android.data.xaccount.HttpApiManager; +import com.xabber.android.data.xaccount.XAccountTokenDTO; +import com.xabber.android.data.xaccount.XabberAccount; +import com.xabber.android.data.xaccount.XabberAccountManager; +import com.xabber.android.presentation.mvp.signup.SignUpRepo; import com.xabber.android.ui.color.BarPainter; -import com.xabber.android.ui.fragment.XabberLoginFragment; +import com.xabber.android.ui.fragment.XAccountEmailLoginFragment; +import com.xabber.android.ui.fragment.XAccountLoginFragment; +import com.xabber.android.ui.fragment.XAccountSignUpFragment1; +import com.xabber.android.ui.fragment.XAccountSignUpFragment2; +import com.xabber.android.ui.fragment.XAccountSignUpFragment3; +import com.xabber.android.ui.fragment.XAccountSignUpFragment4; +import com.xabber.android.utils.RetrofitErrorConverter; + +import java.util.ArrayList; +import java.util.List; + +import rx.Single; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; /** * Created by valery.miller on 14.07.17. */ -public class XabberLoginActivity extends BaseLoginActivity implements View.OnClickListener, GoogleApiClient.OnConnectionFailedListener { +public class XabberLoginActivity extends BaseLoginActivity implements XAccountSignUpFragment1.Listener, + XAccountSignUpFragment2.Listener, XAccountSignUpFragment3.Listener, + XAccountSignUpFragment4.Listener, XAccountLoginFragment.EmailClickListener, + XAccountEmailLoginFragment.Listener, XAccountLoginFragment.ForgotPassClickListener { - private final static String TAG = XabberLoginActivity.class.getSimpleName(); + private final static String LOG_TAG = XabberLoginActivity.class.getSimpleName(); public final static String CURRENT_FRAGMENT = "current_fragment"; public final static String FRAGMENT_LOGIN = "fragment_login"; - public final static String FRAGMENT_SIGNUP = "fragment_signup"; + public final static String FRAGMENT_EMAIL_LOGIN = "fragment_email_login"; + public final static String FRAGMENT_SIGNUP_STEP1 = "fragment_signup_step1"; + public final static String FRAGMENT_SIGNUP_STEP2 = "fragment_signup_step2"; + public final static String FRAGMENT_SIGNUP_STEP3 = "fragment_signup_step3"; + public final static String FRAGMENT_SIGNUP_STEP4 = "fragment_signup_step4"; + + private static final String CAPTCHA_TOKEN = "RECAPTCHA"; + private static final String ERROR_NAME_NOT_AVAILABLE = "Username is not available."; - private Fragment fragmentLogin; private FragmentTransaction fTrans; + private Fragment fragmentLogin; + private Fragment fragmentEmailLogin; + private Fragment fragmentSignUpStep1; + private Fragment fragmentSignUpStep2; + private Fragment fragmentSignUpStep3; + private Fragment fragmentSignUpStep4; private String currentFragment = FRAGMENT_LOGIN; private ProgressDialog progressDialog; - - private ImageView ivFacebook; - private ImageView ivGoogle; - private ImageView ivTwitter; - private ImageView ivGithub; - private BarPainter barPainter; + private Toolbar toolbar; - public static Intent createIntent(Context context) { - return new Intent(context, XabberLoginActivity.class); + private List hosts = new ArrayList<>(); + + public static Intent createIntent(Context context, @Nullable String currentFragment) { + Intent intent = new Intent(context, XabberLoginActivity.class); + intent.putExtra(CURRENT_FRAGMENT, currentFragment); + return intent; } @Override @@ -61,72 +102,138 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_xabber_login); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_default); - toolbar.setTitle(R.string.title_login_xabber_account); - toolbar.setNavigationIcon(R.drawable.ic_arrow_left_white_24dp); + toolbar = (Toolbar) findViewById(R.id.toolbar_default); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + SignUpRepo.getInstance().clearRepo(); finish(); } }); barPainter = new BarPainter(this, toolbar); + setupToolbar(true); + } - ivFacebook = (ImageView) findViewById(R.id.ivFacebook); - ivGoogle = (ImageView) findViewById(R.id.ivGoogle); - ivTwitter = (ImageView) findViewById(R.id.ivTwitter); - ivGithub = (ImageView) findViewById(R.id.ivGithub); - - ivFacebook.setOnClickListener(this); - ivGoogle.setOnClickListener(this); - ivTwitter.setOnClickListener(this); - ivGithub.setOnClickListener(this); + private void setupToolbar(boolean signIn) { + if (signIn) { + toolbar.setTitle(R.string.title_login_xabber_account); + toolbar.setNavigationIcon(R.drawable.ic_arrow_left); + toolbar.setTitleTextColor(getResources().getColor(R.color.black_text)); + barPainter.setLiteGrey(); + } else { + toolbar.setTitle(R.string.title_register_xabber_account); + toolbar.setNavigationIcon(R.drawable.ic_arrow_left_white_24dp); + toolbar.setTitleTextColor(getResources().getColor(R.color.white)); + barPainter.setBlue(this); + } } public void showLoginFragment() { if (fragmentLogin == null) - fragmentLogin = new XabberLoginFragment(); + fragmentLogin = XAccountLoginFragment.newInstance(); fTrans = getFragmentManager().beginTransaction(); fTrans.replace(R.id.container, fragmentLogin); fTrans.commit(); currentFragment = FRAGMENT_LOGIN; + + setupToolbar(true); } - @Override - protected void onResume() { - super.onResume(); - showLoginFragment(); - barPainter.setBlue(this); + public void showEmailLoginFragment() { + if (fragmentEmailLogin == null) + fragmentEmailLogin = XAccountEmailLoginFragment.newInstance(); + + fTrans = getFragmentManager().beginTransaction(); + fTrans.replace(R.id.container, fragmentEmailLogin); + fTrans.commit(); + currentFragment = FRAGMENT_EMAIL_LOGIN; + + setupToolbar(true); } - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(CURRENT_FRAGMENT, currentFragment); + public void showSignUpStep1Fragment() { + if (fragmentSignUpStep1 == null) + fragmentSignUpStep1 = XAccountSignUpFragment1.newInstance(this); + + fTrans = getFragmentManager().beginTransaction(); + fTrans.replace(R.id.container, fragmentSignUpStep1, FRAGMENT_SIGNUP_STEP1); + fTrans.commit(); + currentFragment = FRAGMENT_SIGNUP_STEP1; + + setupToolbar(false); + } + + public void showSignUpStep2Fragment() { + if (fragmentSignUpStep2 == null) + fragmentSignUpStep2 = XAccountSignUpFragment2.newInstance(this); + + fTrans = getFragmentManager().beginTransaction(); + fTrans.replace(R.id.container, fragmentSignUpStep2, FRAGMENT_SIGNUP_STEP2); + fTrans.commit(); + currentFragment = FRAGMENT_SIGNUP_STEP2; + + setupToolbar(false); + } + + public void showSignUpStep3Fragment() { + if (fragmentSignUpStep3 == null) + fragmentSignUpStep3 = XAccountSignUpFragment3.newInstance(this); + + fTrans = getFragmentManager().beginTransaction(); + fTrans.replace(R.id.container, fragmentSignUpStep3, FRAGMENT_SIGNUP_STEP3); + fTrans.commit(); + currentFragment = FRAGMENT_SIGNUP_STEP3; + + setupToolbar(false); + hideKeyboard(); + } + + public void showSignUpStep4Fragment() { + if (fragmentSignUpStep4 == null) + fragmentSignUpStep4 = XAccountSignUpFragment4.newInstance(); + + fTrans = getFragmentManager().beginTransaction(); + fTrans.replace(R.id.container, fragmentSignUpStep4, FRAGMENT_SIGNUP_STEP4); + fTrans.commit(); + currentFragment = FRAGMENT_SIGNUP_STEP4; + + setupToolbar(false); } @Override - public void onClick(View v) { - if (NetworkManager.isNetworkAvailable()) { - switch (v.getId()) { - case R.id.ivFacebook: - loginFacebook(); + protected void onResume() { + super.onResume(); + if (currentFragment != null) { + switch (currentFragment) { + case FRAGMENT_SIGNUP_STEP1: + showSignUpStep1Fragment(); + break; + case FRAGMENT_SIGNUP_STEP2: + showSignUpStep2Fragment(); break; - case R.id.ivGoogle: - loginGoogle(); + case FRAGMENT_SIGNUP_STEP3: + showSignUpStep3Fragment(); break; - case R.id.ivGithub: - loginGithub(); + case FRAGMENT_SIGNUP_STEP4: + showSignUpStep4Fragment(); break; - case R.id.ivTwitter: - loginTwitter(); + case FRAGMENT_EMAIL_LOGIN: + showEmailLoginFragment(); break; + default: + showLoginFragment(); } - } else - Toast.makeText(this, "No internet connection", Toast.LENGTH_LONG).show(); + } else showLoginFragment(); } + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(CURRENT_FRAGMENT, currentFragment); + } + + @Override public void onForgotPassClick() { String url = HttpApiManager.XABBER_FORGOT_PASS_URL; Intent intent = new Intent(Intent.ACTION_VIEW); @@ -134,9 +241,18 @@ public void onForgotPassClick() { startActivity(intent); } + public void hideKeyboard() { + // Check if no view has focus + View view = getCurrentFocus(); + if (view != null) { + InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputManager != null) inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + @Override protected void showProgress(String title) { - if (!isFinishing()) { + if (!isFinishing() && !getString(R.string.progress_title_sync).equals(title)) { progressDialog = new ProgressDialog(this); progressDialog.setTitle(title); progressDialog.setMessage(getResources().getString(R.string.progress_message)); @@ -155,5 +271,294 @@ protected void hideProgress() { @Override public void onBackPressed() { super.onBackPressed(); + SignUpRepo.getInstance().clearRepo(); + } + + @Override + protected void onSocialAuthSuccess(String provider, String credentials) { + XabberAccount account = XabberAccountManager.getInstance().getAccount(); + if (account != null) bindSocial(provider, credentials); + else socialLogin(provider, credentials); + } + + @Override + public void onGetHosts() { + getHosts(); + } + + @Override + public void onStep1Completed(String username, String host) { + SignUpRepo signUpRepo = SignUpRepo.getInstance(); + signUpRepo.setUsername(username); + signUpRepo.setHost(host); + + if (signUpRepo.isCompleted()) onStep3Completed(); + else showSignUpStep2Fragment(); + } + + @Override + public void on2StepCompleted(String pass) { + SignUpRepo.getInstance().setPass(pass); + showSignUpStep3Fragment(); + } + + @Override + public void onStep3Completed() { + SignUpRepo signUpRepo = SignUpRepo.getInstance(); + + if (signUpRepo.getSocialProvider() != null + && signUpRepo.getSocialCredentials() != null) signUp(signUpRepo); + else getCaptchaToken(signUpRepo); + } + + @Override + public void onStep4Completed() { + goToMainActivity(); + } + + @Override + protected void onSynchronized() { } + + @Override + public void onEmailClick() { + showEmailLoginFragment(); + } + + @Override + public void onLoginClick(String email, String pass) { + emailLogin(email, pass); + } + + /** EMAIL LOGIN */ + + private void emailLogin(String email, String pass) { + showProgress(getString(R.string.progress_title_login)); + Subscription emailLoginSubscription = AuthManager.login(email, pass) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(XAccountTokenDTO xAccountTokenDTO) { + handleSuccessSocialLogin(xAccountTokenDTO); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorGetAccount(throwable); + } + }); + compositeSubscription.add(emailLoginSubscription); + } + + /** GET HOSTS */ + + private void getHosts() { + if (hosts != null && !hosts.isEmpty()) { + if (fragmentSignUpStep1 != null) ((XAccountSignUpFragment1)fragmentSignUpStep1).setupHosts(hosts); + } else { + if (fragmentSignUpStep1 != null) ((XAccountSignUpFragment1) fragmentSignUpStep1).showHostsProgress(true); + Subscription requestHosts = AuthManager.getHosts() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(AuthManager.HostResponse response) { + handleSuccessGetHosts(response); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorGetHosts(throwable); + } + }); + compositeSubscription.add(requestHosts); + } + } + + private void handleSuccessGetHosts(AuthManager.HostResponse response) { + List hosts = response.getHosts(); + if (hosts == null) return; + + this.hosts.clear(); + this.hosts.addAll(hosts); + + if (fragmentSignUpStep1 != null) { + ((XAccountSignUpFragment1) fragmentSignUpStep1).showHostsProgress(false); + ((XAccountSignUpFragment1) fragmentSignUpStep1).setupHosts(this.hosts); + } + } + + private void handleErrorGetHosts(Throwable throwable) { + if (fragmentSignUpStep1 != null) ((XAccountSignUpFragment1) fragmentSignUpStep1).showHostsProgress(false); + handleError(throwable, "Error while request hosts: ", LOG_TAG); + } + + /** SIGN UP */ + + private void signUp(SignUpRepo signUpRepo) { + String username = signUpRepo.getUsername(); + String host = signUpRepo.getHost(); + String pass = signUpRepo.getPass(); + String captchaToken = signUpRepo.getCaptchaToken(); + String credentials = signUpRepo.getSocialCredentials(); + String socialProvider = signUpRepo.getSocialProvider(); + + showProgress(getResources().getString(R.string.progress_title_signup)); + + Single signUpSingle; + if (credentials != null && socialProvider != null) + signUpSingle = AuthManager.signupv2(username, host, pass, socialProvider, credentials); + else signUpSingle = AuthManager.signupv2(username, host, pass, captchaToken); + + Subscription signUpSubscription = signUpSingle + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(XabberAccount account) { + handleSuccessSignUp(); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorSignUp(throwable); + } + }); + compositeSubscription.add(signUpSubscription); + } + + private void handleSuccessSignUp() { + SignUpRepo.getInstance().clearRepo(); + hideProgress(); + XabberAccountManager.getInstance().registerEndpoint(); + synchronize(false); + showSignUpStep4Fragment(); + } + + private void handleErrorSignUp(Throwable throwable) { + SignUpRepo.getInstance().setCaptchaToken(null); + hideProgress(); + String message = RetrofitErrorConverter.throwableToHttpError(throwable); + if (ERROR_NAME_NOT_AVAILABLE.equals(message)) { + SignUpRepo.getInstance().setLastErrorMessage(message); + showSignUpStep1Fragment(); + } + } + + /** SOCIAL LOGIN */ + + private void socialLogin(final String provider, final String credentials) { + showProgress(getString(R.string.progress_title_login)); + Subscription loginSocialSubscription = AuthManager.loginSocial(provider, credentials) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(XAccountTokenDTO s) { + handleSuccessSocialLogin(s); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorSocialLogin(throwable, credentials, provider); + } + }); + compositeSubscription.add(loginSocialSubscription); + } + + private void handleSuccessSocialLogin(@NonNull XAccountTokenDTO response) { + getAccount(response.getToken()); } + + private void handleErrorSocialLogin(Throwable throwable, String credentials, String provider) { + String message = RetrofitErrorConverter.throwableToHttpError(throwable); + if (message != null) { + if (message.contains("is not attached to any Xabber account")) { + // go to sign up + SignUpRepo.getInstance().setSocialCredentials(credentials); + SignUpRepo.getInstance().setSocialProvider(provider); + hideProgress(); + showSignUpStep1Fragment(); + + } else { + Log.d(LOG_TAG, "Error while social login request: " + message); + Toast.makeText(this, R.string.social_auth_fail, Toast.LENGTH_LONG).show(); + } + } else { + Log.d(LOG_TAG, "Error while social login request: " + throwable.toString()); + Toast.makeText(this, R.string.social_auth_fail, Toast.LENGTH_LONG).show(); + } + hideProgress(); + } + + /** GET ACCOUNT */ + + private void getAccount(String token) { + Subscription getAccountSubscription = AuthManager.getAccount(token) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1() { + @Override + public void call(XabberAccount xabberAccount) { + handleSuccessGetAccount(xabberAccount); + } + }, new Action1() { + @Override + public void call(Throwable throwable) { + handleErrorGetAccount(throwable); + } + }); + compositeSubscription.add(getAccountSubscription); + } + + private void handleSuccessGetAccount(@NonNull XabberAccount xabberAccount) { + XabberAccountManager.getInstance().registerEndpoint(); + synchronize(true); + } + + private void handleErrorGetAccount(Throwable throwable) { + hideProgress(); + handleError(throwable, "Error while login: ", LOG_TAG); + } + + /** CAPTCHA */ + + private void getCaptchaToken(final SignUpRepo signUpRepo) { + SafetyNet.getClient(this).verifyWithRecaptcha(getString(R.string.RECAPTCHA_KEY)) + .addOnSuccessListener(this, + new OnSuccessListener() { + @Override + public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) { + // Indicates communication with reCAPTCHA service was + // successful. + String userResponseToken = response.getTokenResult(); + if (!userResponseToken.isEmpty()) { + // Validate the user response token using the + // reCAPTCHA siteverify API. + Log.d(CAPTCHA_TOKEN, "Success: " + userResponseToken); + signUpRepo.setCaptchaToken(userResponseToken); + signUp(signUpRepo); + } + } + }) + .addOnFailureListener(this, + new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + if (e instanceof ApiException) { + // An error occurred when communicating with the + // reCAPTCHA service. Refer to the status code to + // handle the error appropriately. + ApiException apiException = (ApiException) e; + int statusCode = apiException.getStatusCode(); + Log.d(CAPTCHA_TOKEN, "Error: " + + CommonStatusCodes.getStatusCodeString(statusCode)); + } else { + // A different, unknown type of error occurred. + Log.d(CAPTCHA_TOKEN, "Error: " + e.getMessage()); + } + } + }); + } + } diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/AccountListPreferenceAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/AccountListPreferenceAdapter.java index ccb1a4b563..aea15cea73 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/AccountListPreferenceAdapter.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/AccountListPreferenceAdapter.java @@ -5,6 +5,8 @@ */ import android.app.Activity; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SwitchCompat; import android.view.ContextMenu; @@ -22,6 +24,7 @@ import com.xabber.android.data.extension.avatar.AvatarManager; import com.xabber.android.data.log.LogManager; import com.xabber.android.data.xaccount.XMPPAccountSettings; +import com.xabber.android.data.xaccount.XabberAccount; import com.xabber.android.data.xaccount.XabberAccountManager; import com.xabber.android.ui.color.ColorManager; @@ -80,10 +83,24 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { accountHolder.avatar.setImageDrawable( AvatarManager.getInstance().getAccountAvatar(accountItem.getAccount())); - accountHolder.avatar.setBorderColor(ColorManager.getInstance().getAccountPainter(). - getAccountMainColor(accountItem.getAccount())); + accountHolder.avatarBorder.setBorderColor(accountItem.isEnabled() ? ColorManager.getInstance().getAccountPainter(). + getAccountMainColor(accountItem.getAccount()) : activity.getResources().getColor(R.color.grey_400)); + + XabberAccount xabberAccount = XabberAccountManager.getInstance().getAccount(); + if (xabberAccount == null || !xabberAccount.getFullUsername() + .equals(AccountManager.getInstance().getVerboseName(accountItem.getAccount()))) + accountHolder.avatarBorder.setBorderColor(activity.getResources().getColor(R.color.transparent)); + + if (!accountItem.isEnabled()) { + ColorMatrix matrix = new ColorMatrix(); + matrix.setSaturation(0); + ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix); + accountHolder.avatar.setColorFilter(filter); + } else accountHolder.avatar.clearColorFilter(); accountHolder.name.setText(AccountManager.getInstance().getVerboseName(accountItem.getAccount())); + accountHolder.name.setTextColor(accountItem.isEnabled() ? ColorManager.getInstance().getAccountPainter(). + getAccountMainColor(accountItem.getAccount()) : activity.getResources().getColor(R.color.black_text)); accountHolder.status.setText(accountItem.getState().getStringId()); @@ -98,6 +115,7 @@ public int getItemCount() { private class AccountViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener { CircleImageView avatar; + CircleImageView avatarBorder; TextView name; TextView status; SwitchCompat enabledSwitch; @@ -106,6 +124,7 @@ private class AccountViewHolder extends RecyclerView.ViewHolder implements View. AccountViewHolder(View itemView) { super(itemView); avatar = (CircleImageView) itemView.findViewById(R.id.avatar); + avatarBorder = (CircleImageView) itemView.findViewById(R.id.avatarBorder); name = (TextView) itemView.findViewById(R.id.item_account_name); status = (TextView) itemView.findViewById(R.id.item_account_status); enabledSwitch = (SwitchCompat) itemView.findViewById(R.id.item_account_switch); diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/EmailAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/EmailAdapter.java new file mode 100644 index 0000000000..c96c193a9d --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/EmailAdapter.java @@ -0,0 +1,85 @@ +package com.xabber.android.ui.adapter; + +import android.content.res.Resources; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.Application; +import com.xabber.android.data.xaccount.EmailDTO; + +import java.util.ArrayList; +import java.util.List; + +public class EmailAdapter extends RecyclerView.Adapter { + + private List emails = new ArrayList(); + private Listener listener; + + public interface Listener { + void onEmailVerifyClick(String email); + void onEmailDeleteClick(int id); + } + + public EmailAdapter(Listener listener) { + this.listener = listener; + } + + public void setItems(List emails) { + this.emails.clear(); + this.emails.addAll(emails); + } + + @Override + public EmailViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_email, parent, false); + return new EmailViewHolder(view); + } + + @Override + public void onBindViewHolder(EmailViewHolder holder, final int position) { + final EmailDTO emailDTO = emails.get(position); + + Resources res = Application.getInstance().getResources(); + holder.tvEmail.setText(emailDTO.getEmail()); + holder.tvStatus.setText(emailDTO.isVerified() ? R.string.title_verified_email : R.string.title_unverified_email); + holder.tvStatus.setTextColor(emailDTO.isVerified() ? res.getColor(R.color.grey_500) : res.getColor(R.color.red_500)); + holder.tvAction.setVisibility(emailDTO.isVerified() ? View.GONE : View.VISIBLE); + holder.ivEmail.setImageResource(emailDTO.isVerified() ? R.drawable.ic_confirmed_email_circle : R.drawable.ic_email_circle); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (emailDTO.isVerified()) + listener.onEmailDeleteClick(emailDTO.getId()); + else listener.onEmailVerifyClick(emailDTO.getEmail()); + } + }); + } + + @Override + public int getItemCount() { + return emails.size(); + } + + class EmailViewHolder extends RecyclerView.ViewHolder { + + final TextView tvEmail; + final TextView tvStatus; + final TextView tvAction; + final ImageView ivEmail; + + public EmailViewHolder(View itemView) { + super(itemView); + this.tvEmail = itemView.findViewById(R.id.tvEmail); + this.tvStatus = itemView.findViewById(R.id.tvStatus); + this.tvAction = itemView.findViewById(R.id.tvAction); + this.ivEmail = itemView.findViewById(R.id.ivEmail); + } + } + +} diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/HostSpinnerAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/HostSpinnerAdapter.java new file mode 100644 index 0000000000..bfef0cdd3e --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/HostSpinnerAdapter.java @@ -0,0 +1,54 @@ +package com.xabber.android.ui.adapter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.Application; +import com.xabber.android.data.xaccount.AuthManager; + +import java.util.List; + +public class HostSpinnerAdapter extends ArrayAdapter { + + private List mData; + private LayoutInflater mInflater; + private int currentPosition; + + public HostSpinnerAdapter(@NonNull Context context, int resource, @NonNull List hosts, @NonNull List objects) { + super(context, resource, hosts); + + mData = objects; + mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + public void setCurrentPosition(int position) { + this.currentPosition = position; + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + return getCustomView(position, convertView, parent); + } + + public View getCustomView(int position, View convertView, ViewGroup parent) { + AuthManager.Host host = mData.get(position); + + View view = mInflater.inflate(R.layout.item_host, parent, false); + TextView tvHost = (TextView) view.findViewById(R.id.tvHost); + TextView tvStatus = (TextView) view.findViewById(R.id.tvStatus); + + tvHost.setText(host.getHost()); + tvStatus.setText(host.isFree() ? Application.getInstance().getResources().getString(R.string.free) : host.getPrice()); + + if (position == currentPosition) view.setBackgroundColor( + Application.getInstance().getResources().getColor(R.color.grey_200)); + + return view; + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/TutorialAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/TutorialAdapter.java index b68805fdfe..afa8b69cbf 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/TutorialAdapter.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/TutorialAdapter.java @@ -14,7 +14,7 @@ */ public class TutorialAdapter extends FragmentPagerAdapter { - private static int PAGE_NUMBERS = 4; + private static int PAGE_NUMBERS = 5; public TutorialAdapter(FragmentManager fm) { super(fm); @@ -24,13 +24,15 @@ public TutorialAdapter(FragmentManager fm) { public Fragment getItem(int position) { switch (position) { case 0: - return TutorialFragment.newInstance(R.string.tutorial_title_1, R.string.tutorial_description_1, R.drawable.art_tutorial_1); + return TutorialFragment.newInstance(R.string.tutorial_title_1, R.string.tutorial_description_1, R.drawable.art_welcome); case 1: - return TutorialFragment.newInstance(R.string.tutorial_title_2, R.string.tutorial_description_2, R.drawable.art_tutorial_2); + return TutorialFragment.newInstance(R.string.tutorial_title_2, R.string.tutorial_description_2, R.drawable.art_tutorial_1); case 2: - return TutorialFragment.newInstance(R.string.tutorial_title_3, R.string.tutorial_description_3, R.drawable.art_tutorial_3); + return TutorialFragment.newInstance(R.string.tutorial_title_6, R.string.tutorial_description_6, R.drawable.art_tutorial_3); case 3: - return TutorialFragment.newInstance(R.string.tutorial_title_4, R.string.tutorial_description_4, R.drawable.art_tutorial_4); + return TutorialFragment.newInstance(R.string.tutorial_title_8, R.string.tutorial_description_8, R.drawable.art_tutorial_4); + case 4: + return TutorialFragment.newInstance(R.string.tutorial_title_9, R.string.tutorial_description_9, R.drawable.art_tutorial_2); default: return null; } diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/XMPPAccountAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/XMPPAccountAdapter.java index 40badbf1d8..a02f54ba2d 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/XMPPAccountAdapter.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/XMPPAccountAdapter.java @@ -5,19 +5,19 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; +import android.widget.Switch; import android.widget.TextView; import com.xabber.android.R; -import com.xabber.android.data.account.AccountItem; -import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.extension.avatar.AvatarManager; import com.xabber.android.data.xaccount.XMPPAccountSettings; -import com.xabber.android.data.xaccount.XabberAccount; -import com.xabber.android.data.xaccount.XabberAccountManager; import com.xabber.android.ui.color.ColorManager; +import org.jxmpp.stringprep.XmppStringprepException; + import java.util.List; /** @@ -29,9 +29,15 @@ public class XMPPAccountAdapter extends RecyclerView.Adapter { private List items; private boolean isAllChecked; private Context context; + private Listener listener; + + public interface Listener { + void onChkClick(); + } - public XMPPAccountAdapter(Context context) { + public XMPPAccountAdapter(Context context, Listener listener) { this.context = context; + this.listener = listener; } public void setItems(List items) { @@ -62,74 +68,43 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { } }); - viewHolder.avatar.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (account.isSynchronization() || isAllChecked) { - if (account.getStatus() == XMPPAccountSettings.SyncStatus.localNewer) { - account.setStatus(XMPPAccountSettings.SyncStatus.remoteNewer); - account.setTimestamp(0); - - // change settings - XMPPAccountSettings set = XabberAccountManager.getInstance().getAccountSettingsForSync(account.getJid()); - if (set != null) { - account.setColor(set.getColor()); - } - } else if (account.getStatus() == XMPPAccountSettings.SyncStatus.remoteNewer) { - account.setStatus(XMPPAccountSettings.SyncStatus.localNewer); - account.setTimestamp((int) (System.currentTimeMillis() / 1000L)); - - // change settings - AccountItem item = AccountManager.getInstance().getAccount(XabberAccountManager.getInstance().getExistingAccount(account.getJid())); - if (item != null) { - account.setColor(ColorManager.getInstance().convertIndexToColorName(item.getColorIndex())); - } - } - notifyDataSetChanged(); - } - } - }); - // set colors int colorId = ColorManager.getInstance().convertColorNameToId(account.getColor()); - viewHolder.color.setColorFilter(colorId); - viewHolder.username.setTextColor(colorId); // set username if (account.getUsername() != null && !account.getUsername().isEmpty()) viewHolder.username.setText(account.getUsername()); else viewHolder.username.setText(account.getJid()); - // set jid - //viewHolder.jid.setText(account.getJid()); + // set avatar + try { + AccountJid accountJid = AccountJid.from(account.getJid() + "/resource"); + viewHolder.avatar.setImageDrawable(AvatarManager.getInstance().getAccountAvatarForSync(accountJid, colorId)); + } catch (XmppStringprepException e) { + e.printStackTrace(); + } if (account.isSynchronization() || isAllChecked) { if (account.getStatus() != null) { switch (account.getStatus()) { case local: viewHolder.jid.setText(R.string.sync_status_local); - viewHolder.avatar.setImageResource(R.drawable.ic_sync_upload); break; case remote: viewHolder.jid.setText(R.string.sync_status_remote); - viewHolder.avatar.setImageResource(R.drawable.ic_sync_download); break; case localNewer: viewHolder.jid.setText(R.string.sync_status_local); - viewHolder.avatar.setImageResource(R.drawable.ic_sync_upload); break; case remoteNewer: if (account.isDeleted()) { viewHolder.jid.setText(R.string.sync_status_deleted); - viewHolder.avatar.setImageResource(R.drawable.ic_delete_grey); } else { viewHolder.jid.setText(R.string.sync_status_remote); - viewHolder.avatar.setImageResource(R.drawable.ic_sync_download); } break; case localEqualsRemote: viewHolder.jid.setText(R.string.sync_status_ok); - viewHolder.avatar.setImageResource(R.drawable.ic_sync_done); break; default: break; @@ -137,8 +112,6 @@ public void onClick(View v) { } } else { viewHolder.jid.setText(R.string.sync_status_no); - viewHolder.avatar.setImageResource(R.drawable.ic_sync_disable); - viewHolder.username.setTextColor(context.getResources().getColor(R.color.grey_500)); } // set sync checkbox @@ -161,24 +134,23 @@ public int getItemCount() { private class XMPPAccountVH extends RecyclerView.ViewHolder { - ImageView color; ImageView avatar; TextView username; TextView jid; - CheckBox chkAccountSync; + Switch chkAccountSync; XMPPAccountVH(View itemView) { super(itemView); - color = (ImageView) itemView.findViewById(R.id.color); avatar = (ImageView) itemView.findViewById(R.id.avatar); username = (TextView) itemView.findViewById(R.id.tvAccountName); jid = (TextView) itemView.findViewById(R.id.tvAccountJid); - chkAccountSync = (CheckBox) itemView.findViewById(R.id.chkAccountSync); + chkAccountSync = (Switch) itemView.findViewById(R.id.chkAccountSync); chkAccountSync.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { notifyDataSetChanged(); + listener.onChkClick(); } }); } diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/XMPPAccountAuthAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/XMPPAccountAuthAdapter.java new file mode 100644 index 0000000000..22410b0c22 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/XMPPAccountAuthAdapter.java @@ -0,0 +1,105 @@ +package com.xabber.android.ui.adapter; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.account.AccountItem; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.extension.avatar.AvatarManager; +import com.xabber.android.ui.color.ColorManager; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by valery.miller on 20.07.17. + */ + +public class XMPPAccountAuthAdapter extends RecyclerView.Adapter { + + private List items = new ArrayList<>(); + private Listener listener; + + public XMPPAccountAuthAdapter(Listener listener) { + this.listener = listener; + } + + public interface Listener { + void onAccountClick(AccountJid accountJid); + } + + public void setItems(List items) { + this.items = items; + notifyDataSetChanged(); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new XMPPAccountVH(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_xmpp_account_choose, parent, false)); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + final AccountItem account = AccountManager.getInstance().getAccount(items.get(position).jid); + XMPPAccountVH viewHolder = (XMPPAccountVH) holder; + + // set color + viewHolder.jid.setTextColor(ColorManager.getInstance().getAccountPainter(). + getAccountMainColor(account.getAccount())); + + // set avatar + viewHolder.avatar.setImageDrawable( + AvatarManager.getInstance().getAccountAvatar(account.getAccount())); + + // set jid + final String accountJid = account.getAccount().getFullJid().asBareJid().toString(); + viewHolder.jid.setText(accountJid); + + // set action + viewHolder.action.setText(items.get(position).bind ? R.string.xaccount_exist : R.string.xaccount_not_exist); + + // set listener + viewHolder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onAccountClick(account.getAccount()); + } + }); + } + + @Override + public int getItemCount() { + return items.size(); + } + + private class XMPPAccountVH extends RecyclerView.ViewHolder { + + ImageView avatar; + TextView jid; + TextView action; + + XMPPAccountVH(View itemView) { + super(itemView); + avatar = (ImageView) itemView.findViewById(R.id.avatar); + jid = (TextView) itemView.findViewById(R.id.tvAccountJid); + action = (TextView) itemView.findViewById(R.id.tvAction); + } + } + + public static class AccountView { + AccountJid jid; + boolean bind; + + public AccountView(AccountJid jid, boolean bind) { + this.jid = jid; + this.bind = bind; + } + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/color/BarPainter.java b/xabber/src/main/java/com/xabber/android/ui/color/BarPainter.java index dfb0931a93..e6483addcc 100644 --- a/xabber/src/main/java/com/xabber/android/ui/color/BarPainter.java +++ b/xabber/src/main/java/com/xabber/android/ui/color/BarPainter.java @@ -6,6 +6,7 @@ import android.support.v7.widget.Toolbar; import com.xabber.android.R; +import com.xabber.android.data.Application; import com.xabber.android.data.entity.AccountJid; public class BarPainter { @@ -37,6 +38,10 @@ public void updateWithColorName(String targetColorName) { statusBarPainter.updateWithColor(accountPainter.getAccountDarkColorByColorName(targetColorName)); } + public void setLiteGrey() { + toolbar.setBackgroundColor(Application.getInstance().getResources().getColor(R.color.grey_200)); + } + public void setGrey() { toolbar.setBackgroundColor(accountPainter.getGreyMain()); statusBarPainter.updateWithColor(accountPainter.getGreyDark()); diff --git a/xabber/src/main/java/com/xabber/android/ui/dialog/AccountDeleteDialog.java b/xabber/src/main/java/com/xabber/android/ui/dialog/AccountDeleteDialog.java index 862f86dd00..dbd3185031 100644 --- a/xabber/src/main/java/com/xabber/android/ui/dialog/AccountDeleteDialog.java +++ b/xabber/src/main/java/com/xabber/android/ui/dialog/AccountDeleteDialog.java @@ -1,11 +1,10 @@ package com.xabber.android.ui.dialog; -import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; -import android.support.v4.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; +import android.support.v4.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.widget.CheckBox; @@ -14,7 +13,6 @@ import com.xabber.android.data.account.AccountManager; import com.xabber.android.data.entity.AccountJid; import com.xabber.android.data.xaccount.XabberAccountManager; -import com.xabber.android.ui.preferences.PreferenceEditor; public class AccountDeleteDialog extends DialogFragment implements DialogInterface.OnClickListener { @@ -60,16 +58,10 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { @Override public void onClick(DialogInterface dialog, int which) { - if (which != Dialog.BUTTON_POSITIVE) { - return; - } + if (which != Dialog.BUTTON_POSITIVE) return; AccountManager.getInstance().removeAccount(account); - - if (chbDeleteSettings != null && chbDeleteSettings.isChecked()) { - Activity activity = getActivity(); - if (activity instanceof PreferenceEditor) - ((PreferenceEditor)activity).onDeleteAccountSettings(jid); - } + if (chbDeleteSettings != null && chbDeleteSettings.isChecked()) + XabberAccountManager.getInstance().deleteAccountSettings(jid); } } diff --git a/xabber/src/main/java/com/xabber/android/ui/dialog/AddEmailDialogFragment.java b/xabber/src/main/java/com/xabber/android/ui/dialog/AddEmailDialogFragment.java new file mode 100644 index 0000000000..086b3bc065 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/dialog/AddEmailDialogFragment.java @@ -0,0 +1,72 @@ +package com.xabber.android.ui.dialog; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +import com.xabber.android.R; + +public class AddEmailDialogFragment extends DialogFragment { + + private Listener listener; + private EditText edtEmail; + + public interface Listener { + void onAddEmailClick(String email); + } + + public static AddEmailDialogFragment newInstance() { + AddEmailDialogFragment fragment = new AddEmailDialogFragment(); + return fragment; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setView(setupView()) + .setTitle(R.string.title_add_email) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }) + .setPositiveButton(R.string.action_connect, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (listener != null) listener.onAddEmailClick(edtEmail.getText().toString()); + } + }); + + return builder.create(); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof Listener) listener = (Listener) context; + else throw new RuntimeException(context.toString() + + " must implement AddEmailDialogFragment.Listener"); + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + } + + public View setupView() { + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.dialog_add_email, null); + + edtEmail = view.findViewById(R.id.edtEmail); + + return view; + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/dialog/ConfirmEmailDialogFragment.java b/xabber/src/main/java/com/xabber/android/ui/dialog/ConfirmEmailDialogFragment.java new file mode 100644 index 0000000000..84b86ddd13 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/dialog/ConfirmEmailDialogFragment.java @@ -0,0 +1,101 @@ +package com.xabber.android.ui.dialog; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.EditText; +import android.widget.TextView; + +import com.xabber.android.R; + +public class ConfirmEmailDialogFragment extends DialogFragment { + + private static final String KEY_EMAIL = "KEY_EMAIL"; + + private String email; + private Listener listener; + + private EditText edtCode; + + public interface Listener { + void onResendCodeClick(String email); + void onConfirmClick(String email, String code); + } + + public static ConfirmEmailDialogFragment newInstance(String email) { + ConfirmEmailDialogFragment fragment = new ConfirmEmailDialogFragment(); + fragment.email = email; + return fragment; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setView(setupView()) + .setTitle(R.string.title_email_confirm) + .setNeutralButton(R.string.button_resend_link, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (listener != null) listener.onResendCodeClick(email); + } + }) + .setPositiveButton(R.string.button_confirm, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (listener != null) listener.onConfirmClick(email, edtCode.getText().toString()); + } + }); + + return builder.create(); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof Listener) listener = (Listener) context; + else throw new RuntimeException(context.toString() + + " must implement ConfirmEmailDialogFragment.Listener"); + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(KEY_EMAIL, email); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + Window window = getDialog().getWindow(); + if (window != null) + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + + if (savedInstanceState != null) + email = savedInstanceState.getString(KEY_EMAIL); + } + + public View setupView() { + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.dialog_confirm_email, null); + + TextView tvDescription = view.findViewById(R.id.tvDescription); + tvDescription.setText(getString(R.string.xmpp_confirm_title, email)); + edtCode = view.findViewById(R.id.edtCode); + + return view; + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/dialog/EnterPassDialog.java b/xabber/src/main/java/com/xabber/android/ui/dialog/EnterPassDialog.java index 61619efe43..2b776fd7a8 100644 --- a/xabber/src/main/java/com/xabber/android/ui/dialog/EnterPassDialog.java +++ b/xabber/src/main/java/com/xabber/android/ui/dialog/EnterPassDialog.java @@ -92,7 +92,8 @@ public void onClick(DialogInterface dialog, int which) { private void createAccount(boolean enabled) { try { AccountJid accountJid = AccountManager.getInstance().addAccount(jid, - edtPass.getText().toString(), token, false, true, true, false, false, enabled); + edtPass.getText().toString(), token, false, true, + true, false, false, enabled, false); AccountManager.getInstance().setColor(accountJid, ColorManager.getInstance().convertColorNameToIndex(color)); AccountManager.getInstance().setOrder(accountJid, order); AccountManager.getInstance().setTimestamp(accountJid, timestamp); diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/AccountAddFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/AccountAddFragment.java index ec813a5dcd..3322b697b4 100644 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/AccountAddFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/AccountAddFragment.java @@ -18,10 +18,9 @@ import com.xabber.android.data.NetworkException; import com.xabber.android.data.account.AccountManager; import com.xabber.android.data.entity.AccountJid; -import com.xabber.android.data.xaccount.XabberAccount; import com.xabber.android.data.xaccount.XabberAccountManager; -import com.xabber.android.ui.activity.AccountAddActivity; import com.xabber.android.ui.activity.AccountActivity; +import com.xabber.android.ui.activity.AccountAddActivity; import com.xabber.android.ui.dialog.OrbotInstallerDialog; import com.xabber.android.ui.helper.OrbotHelper; @@ -29,7 +28,8 @@ public class AccountAddFragment extends Fragment implements View.OnClickListener private CheckBox storePasswordView; private CheckBox chkSync; - private CheckBox useOrbotView; + private CheckBox chkRequireTLS; + private CheckBox chkUseTOR; private CheckBox createAccountCheckBox; private LinearLayout passwordConfirmView; private EditText userView; @@ -51,7 +51,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa chkSync.setChecked(false); } - useOrbotView = (CheckBox) view.findViewById(R.id.use_orbot); + chkRequireTLS = view.findViewById(R.id.chkRequireTLS); + chkUseTOR = view.findViewById(R.id.chkUseTOR); createAccountCheckBox = (CheckBox) view.findViewById(R.id.register_account); createAccountCheckBox.setOnClickListener(this); @@ -82,7 +83,7 @@ public void onClick(View v) { } public void addAccount() { - if (useOrbotView.isChecked() && !OrbotHelper.isOrbotInstalled()) { + if (chkUseTOR.isChecked() && !OrbotHelper.isOrbotInstalled()) { OrbotInstallerDialog.newInstance().show(getFragmentManager(), OrbotInstallerDialog.class.getName()); return; } @@ -102,8 +103,9 @@ public void addAccount() { false, storePasswordView.isChecked(), chkSync.isChecked(), - useOrbotView.isChecked(), - createAccountCheckBox.isChecked(), true); + chkUseTOR.isChecked(), + createAccountCheckBox.isChecked(), true, + chkRequireTLS.isChecked()); } catch (NetworkException e) { Application.getInstance().onError(e); return; diff --git a/xabber/src/main/java/com/xabber/android/ui/dialog/AccountSyncDialogFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/AccountSyncFragment.java similarity index 53% rename from xabber/src/main/java/com/xabber/android/ui/dialog/AccountSyncDialogFragment.java rename to xabber/src/main/java/com/xabber/android/ui/fragment/AccountSyncFragment.java index 170725eb8a..cb6b2223e5 100644 --- a/xabber/src/main/java/com/xabber/android/ui/dialog/AccountSyncDialogFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/AccountSyncFragment.java @@ -1,24 +1,22 @@ -package com.xabber.android.ui.dialog; +package com.xabber.android.ui.fragment; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; +import android.app.Fragment; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.Switch; +import android.widget.TextView; import com.xabber.android.R; import com.xabber.android.data.SettingsManager; import com.xabber.android.data.account.AccountManager; -import com.xabber.android.data.entity.AccountJid; import com.xabber.android.data.xaccount.XMPPAccountSettings; import com.xabber.android.data.xaccount.XabberAccountManager; -import com.xabber.android.ui.activity.XabberAccountInfoActivity; import com.xabber.android.ui.adapter.XMPPAccountAdapter; import java.util.ArrayList; @@ -27,67 +25,29 @@ import java.util.List; import java.util.Map; - -/** - * Created by valery.miller on 02.08.17. - */ - -public class AccountSyncDialogFragment extends DialogFragment { +public class AccountSyncFragment extends Fragment implements XMPPAccountAdapter.Listener { private List xmppAccounts; private Switch switchSyncAll; private XMPPAccountAdapter adapter; - private boolean noCancel = false; + private TextView tvLastSyncDate; - private static final String NO_CANCEL = "NO_CANCEL"; - - public static AccountSyncDialogFragment newInstance(boolean noCancel) { - AccountSyncDialogFragment fragment = new AccountSyncDialogFragment(); - Bundle args = new Bundle(); - args.putBoolean(NO_CANCEL, noCancel); - fragment.setArguments(args); + public static AccountSyncFragment newInstance() { + AccountSyncFragment fragment = new AccountSyncFragment(); return fragment; } + @Nullable @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - Bundle args = getArguments(); - boolean noCancel = args.getBoolean(NO_CANCEL, false); - - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setView(setupView()) - .setTitle(R.string.title_sync); - - - if (!noCancel) { - builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - AccountSyncDialogFragment.this.getDialog().cancel(); - } - }).setPositiveButton(R.string.button_sync, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - onPositiveClick(false); - } - }); - } else { - builder.setPositiveButton(R.string.button_sync, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - onPositiveClick(true); - } - }); - } - this.noCancel = noCancel; - - return builder.create(); + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.dialog_account_sync, container, false); } - public View setupView() { - LayoutInflater inflater = getActivity().getLayoutInflater(); - View view = inflater.inflate(R.layout.dialog_account_sync, null); + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + tvLastSyncDate = (TextView) view.findViewById(R.id.tvLastSyncDate); switchSyncAll = (Switch) view.findViewById(R.id.switchSyncAll); switchSyncAll.setChecked(SettingsManager.isSyncAllAccounts()); @@ -96,13 +56,14 @@ public View setupView() { public void onCheckedChanged(CompoundButton compoundButton, boolean b) { if (adapter != null) adapter.setAllChecked(b); + saveSyncSettings(); } }); if (AccountManager.getInstance().haveNotAllowedSyncAccounts()) switchSyncAll.setEnabled(false); setXmppAccounts(XabberAccountManager.getInstance().getXmppAccountsForSync()); - adapter = new XMPPAccountAdapter(getActivity()); + adapter = new XMPPAccountAdapter(getActivity(), this); adapter.setItems(xmppAccounts); if (adapter != null && SettingsManager.isSyncAllAccounts()) @@ -111,11 +72,19 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean b) { RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); recyclerView.setAdapter(adapter); + } + + @Override + public void onResume() { + super.onResume(); + updateLastSyncTime(); + } - return view; + public void updateLastSyncTime() { + tvLastSyncDate.setText(getString(R.string.last_sync_date, SettingsManager.getLastSyncDate())); } - public void setXmppAccounts(List items) { + private void setXmppAccounts(List items) { this.xmppAccounts = new ArrayList<>(); for (XMPPAccountSettings account : items) { XMPPAccountSettings newAccount = new XMPPAccountSettings( @@ -134,13 +103,7 @@ public void setXmppAccounts(List items) { Collections.sort(xmppAccounts); } - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - if (noCancel) ((XabberAccountInfoActivity)getActivity()).onSyncClick(true); - } - - private void onPositiveClick(boolean needGoToMainActivity) { + private void saveSyncSettings() { // set accounts to sync map if (!switchSyncAll.isChecked()) { Map syncState = new HashMap<>(); @@ -155,17 +118,12 @@ private void onPositiveClick(boolean needGoToMainActivity) { XabberAccountManager.getInstance().setAccountSyncState(syncState); } - // update timestamp in accounts if timestamp was changed in dialog - for (XMPPAccountSettings account : xmppAccounts) { - AccountJid accountJid = XabberAccountManager.getInstance().getExistingAccount(account.getJid()); - if (accountJid != null) - AccountManager.getInstance().setTimestamp(accountJid, account.getTimestamp()); - } - // set sync all SettingsManager.setSyncAllAccounts(switchSyncAll.isChecked()); + } - // callback to sync-request - ((XabberAccountInfoActivity)getActivity()).onSyncClick(needGoToMainActivity); + @Override + public void onChkClick() { + saveSyncSettings(); } } diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/ChatFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/ChatFragment.java index ddecb45c72..aa972608a3 100644 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/ChatFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/ChatFragment.java @@ -8,6 +8,8 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.media.AudioAttributes; +import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; @@ -49,6 +51,7 @@ import com.xabber.android.data.SettingsManager; import com.xabber.android.data.account.AccountItem; import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.account.listeners.OnAccountChangedListener; import com.xabber.android.data.database.messagerealm.Attachment; import com.xabber.android.data.database.messagerealm.MessageItem; import com.xabber.android.data.database.messagerealm.SyncInfo; @@ -111,6 +114,7 @@ import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -130,7 +134,7 @@ public class ChatFragment extends Fragment implements PopupMenu.OnMenuItemClickL View.OnClickListener, Toolbar.OnMenuItemClickListener, ChatMessageAdapter.Message.MessageClickListener, HttpUploadListener, ChatMessageAdapter.Listener, AdapterView.OnItemClickListener, PopupWindow.OnDismissListener, - AttachDialog.Listener { + AttachDialog.Listener, OnAccountChangedListener { public static final String ARGUMENT_ACCOUNT = "ARGUMENT_ACCOUNT"; public static final String ARGUMENT_USER = "ARGUMENT_USER"; @@ -409,6 +413,8 @@ public void onResume() { showHideNotifyIfNeed(); showJoinButtonIfNeed(); + + Application.getInstance().addUIListener(OnAccountChangedListener.class, this); } @Override @@ -419,6 +425,8 @@ public void onPause() { saveInputState(); saveScrollState(); + + Application.getInstance().removeUIListener(OnAccountChangedListener.class, this); } @Override @@ -1446,6 +1454,11 @@ public boolean onMenuItemClick(MenuItem item) { popupMenu.show(); } + @Override + public void onAccountsChanged(Collection accounts) { + chatMessageAdapter.notifyDataSetChanged(); + } + private void onShareClick(Attachment attachment) { if (attachment == null) return; String path = attachment.getFilePath(); @@ -1551,7 +1564,18 @@ public void onImageClick(int messagePosition, int attachmentPosition) { public void playIncomingSound() { if (SettingsManager.eventsInChatSounds()) { - final MediaPlayer mp = MediaPlayer.create(getActivity(), SettingsManager.eventsSound()); + final MediaPlayer mp; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + AudioAttributes attr = new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) + .setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT).build(); + mp = MediaPlayer.create(getActivity(), SettingsManager.eventsSound(), + null, attr, AudioManager.AUDIO_SESSION_ID_GENERATE); + } else { + mp = MediaPlayer.create(getActivity(), SettingsManager.eventsSound()); + mp.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); + } + mp.start(); mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/ContactListDrawerFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/ContactListDrawerFragment.java index c3a6f7cd31..07dc9039e7 100644 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/ContactListDrawerFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/ContactListDrawerFragment.java @@ -2,12 +2,13 @@ import android.app.Activity; -import android.support.v4.app.Fragment; +import android.content.Context; import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -16,7 +17,6 @@ import android.widget.AdapterView; import android.widget.Button; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; @@ -46,17 +46,22 @@ import java.util.Collection; import java.util.List; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; + public class ContactListDrawerFragment extends Fragment implements View.OnClickListener, OnAccountChangedListener, AdapterView.OnItemClickListener, AccountListPreferenceAdapter.Listener { + private CompositeSubscription compositeSubscription = new CompositeSubscription(); ContactListDrawerListener listener; private ImageView drawerHeaderImage; private int[] headerImageResources; - private LinearLayout llAccountInfo; - private LinearLayout llNoAccount; private TextView tvAccountName; private TextView tvAccountEmail; + private ImageView ivSync; private TextView tvPatreonTitle; private ProgressBar pbPatreon; @@ -74,7 +79,10 @@ public static ContactListDrawerFragment newInstance() { @Override public void onAttach(Activity activity) { super.onAttach(activity); - listener = (ContactListDrawerListener) activity; + if (activity instanceof ContactListDrawerListener) + listener = (ContactListDrawerListener) activity; + else throw new RuntimeException(activity.toString() + + " must implement ContactListDrawerFragment.ContactListDrawerListener"); } @Override @@ -112,8 +120,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa view.findViewById(R.id.drawer_header_action_xabber_account).setOnClickListener(this); - llAccountInfo = (LinearLayout) view.findViewById(R.id.accountInfo); - llNoAccount = (LinearLayout) view.findViewById(R.id.noAccount); + ivSync = view.findViewById(R.id.ivSync); tvAccountName = (TextView) view.findViewById(R.id.tvAccountName); tvAccountEmail = (TextView) view.findViewById(R.id.tvAccountEmail); @@ -148,6 +155,7 @@ public void onResume() { getActivity().getWindow().setStatusBarColor(ColorManager.getInstance().getAccountPainter().getDefaultMainColor()); } update(); + subscribeForXabberAccount(); } @Override @@ -155,6 +163,7 @@ public void onPause() { super.onPause(); Application.getInstance().removeUIListener(OnAccountChangedListener.class, this); stopPatreonAnim(); + compositeSubscription.clear(); } @Override @@ -184,14 +193,12 @@ public void onAccountsChanged(Collection accounts) { } private void update() { - Glide.with(this) .fromResource() .load(headerImageResources[AccountPainter.getDefaultAccountColorLevel()]) .fitCenter() .into(drawerHeaderImage); - setupXabberAccountView(); setupPatreonView(); setupAccountList(); } @@ -205,33 +212,18 @@ public interface ContactListDrawerListener { void onAccountSelected(AccountJid account); } - private void setupXabberAccountView() { - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - + private void setupXabberAccountView(XabberAccount account) { if (account != null) { - llAccountInfo.setVisibility(View.VISIBLE); - llNoAccount.setVisibility(View.GONE); - String accountName = account.getFirstName() + " " + account.getLastName(); - if (accountName.trim().isEmpty()) - accountName = getActivity().getString(R.string.title_xabber_account); + if (accountName.trim().isEmpty()) accountName = getActivity().getString(R.string.title_xabber_account); + tvAccountName.setText(accountName); + tvAccountEmail.setText(account.getFullUsername()); + ivSync.setImageResource(R.drawable.ic_sync_done); - if (XabberAccount.STATUS_NOT_CONFIRMED.equals(account.getAccountStatus())) { - tvAccountName.setText(accountName); - tvAccountEmail.setText(R.string.title_email_confirm); - } - if (XabberAccount.STATUS_CONFIRMED.equals(account.getAccountStatus())) { - tvAccountName.setText(accountName); - tvAccountEmail.setText(R.string.title_complete_register); - } - if (XabberAccount.STATUS_REGISTERED.equals(account.getAccountStatus())) { - - tvAccountName.setText(accountName); - tvAccountEmail.setText(account.getUsername()); - } } else { - llAccountInfo.setVisibility(View.GONE); - llNoAccount.setVisibility(View.VISIBLE); + tvAccountName.setText(R.string.title_xabber_account); + tvAccountEmail.setText(R.string.not_login); + ivSync.setImageResource(R.drawable.ic_sync_disable); } } @@ -307,4 +299,16 @@ public void onDeleteAccount(AccountItem accountItem) { AccountDeleteDialog.newInstance(accountItem.getAccount()).show(getFragmentManager(), AccountDeleteDialog.class.getName()); } + + private void subscribeForXabberAccount() { + compositeSubscription.add(XabberAccountManager.getInstance().subscribeForAccount() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(new Action1() { + @Override + public void call(XabberAccount account) { + setupXabberAccountView(account); + } + }).subscribe()); + } } diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/ContactVcardViewerFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/ContactVcardViewerFragment.java index 14e909ed91..fc5866c056 100644 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/ContactVcardViewerFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/ContactVcardViewerFragment.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.app.Fragment; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; @@ -99,9 +100,12 @@ public static ContactVcardViewerFragment newInstance(AccountJid account) { @Override public void onAttach(Activity activity) { super.onAttach(activity); - - listener = (Listener) activity; - listener.registerVCardFragment(this); + if (activity instanceof Listener) { + listener = (Listener) activity; + listener.registerVCardFragment(this); + } + else throw new RuntimeException(activity.toString() + + " must implement ContactVcardViewerFragment.Listener"); } @Override diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/OccupantListFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/OccupantListFragment.java index 63b4425a74..9a536e605b 100644 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/OccupantListFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/OccupantListFragment.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.app.Fragment; +import android.content.Context; import android.os.Bundle; import android.support.annotation.Nullable; import android.view.LayoutInflater; @@ -145,7 +146,9 @@ public void onItemClick(AdapterView parent, View view, int position, long id) @Override public void onAttach(Activity activity) { super.onAttach(activity); - listener = (Listener) activity; + if (activity instanceof Listener) listener = (Listener) activity; + else throw new RuntimeException(activity.toString() + + " must implement OccupantListFragment.Listener"); } @Override diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/RecentChatFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/RecentChatFragment.java index 23f40baaf5..8a40bd7582 100644 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/RecentChatFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/RecentChatFragment.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.app.Fragment; +import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; @@ -79,9 +80,12 @@ public static RecentChatFragment newInstance() { @Override public void onAttach(Activity activity) { super.onAttach(activity); - - listener = (Listener) activity; - listener.registerRecentChatFragment(this); + if (activity instanceof Listener) { + listener = (Listener) activity; + listener.registerRecentChatFragment(this); + } + else throw new RuntimeException(activity.toString() + + " must implement RecentChatFragment.Listener"); } @Override @@ -114,10 +118,10 @@ public void onDetach() { @Override public boolean onMenuItemClick(MenuItem item) { - if (item.getItemId() == R.id.action_close_chats) { - MessageManager.closeActiveChats(); - updateChats(); - } +// if (item.getItemId() == R.id.action_close_chats) { +// MessageManager.closeActiveChats(); +// updateChats(); +// } return false; } diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountEmailLoginFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountEmailLoginFragment.java new file mode 100644 index 0000000000..2fbd2db88a --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountEmailLoginFragment.java @@ -0,0 +1,97 @@ +package com.xabber.android.ui.fragment; + +import android.app.Activity; +import android.app.Fragment; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; + +import com.xabber.android.R; + +public class XAccountEmailLoginFragment extends Fragment { + + private EditText edtEmail; + private EditText edtPass; + private Button btnLogin; + private Button btnForgotPass; + + private Listener listener; + private XAccountLoginFragment.ForgotPassClickListener forgotPassListener; + + public interface Listener { + void onLoginClick(String email, String pass); + } + + public static XAccountEmailLoginFragment newInstance() { + return new XAccountEmailLoginFragment(); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_xaccount_email_login, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + edtEmail = view.findViewById(R.id.edtEmail); + edtPass = view.findViewById(R.id.edtPass); + btnLogin = view.findViewById(R.id.btnLogin); + btnLogin.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String email = edtEmail.getText().toString().trim(); + String pass = edtPass.getText().toString().trim(); + if (verifyFields(email, pass)) listener.onLoginClick(email, pass); + } + }); + btnForgotPass = view.findViewById(R.id.btnForgotPass); + btnForgotPass.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + forgotPassListener.onForgotPassClick(); + } + }); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof Listener) listener = (Listener) activity; + else throw new RuntimeException(activity.toString() + + " must implement XAccountEmailLoginFragment.Listener"); + + if (activity instanceof XAccountLoginFragment.ForgotPassClickListener) + forgotPassListener = (XAccountLoginFragment.ForgotPassClickListener) activity; + else throw new RuntimeException(activity.toString() + + " must implement ForgotPassClickListener"); + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + forgotPassListener = null; + } + + private boolean verifyFields(String email, String pass) { + if (email.isEmpty()) { + edtEmail.setError(getString(R.string.empty_field)); + return false; + } + + if (pass.isEmpty()) { + edtPass.setError(getString(R.string.empty_field)); + return false; + } + + return true; + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountLinksFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountLinksFragment.java new file mode 100644 index 0000000000..c239e1be53 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountLinksFragment.java @@ -0,0 +1,290 @@ +package com.xabber.android.ui.fragment; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.xaccount.AuthManager; +import com.xabber.android.data.xaccount.EmailDTO; +import com.xabber.android.data.xaccount.SocialBindingDTO; +import com.xabber.android.data.xaccount.XabberAccount; +import com.xabber.android.data.xaccount.XabberAccountManager; +import com.xabber.android.ui.adapter.EmailAdapter; +import com.xabber.android.ui.dialog.AddEmailDialogFragment; +import com.xabber.android.ui.dialog.ConfirmEmailDialogFragment; +import com.xabber.android.ui.helper.OnSocialBindListener; + +import java.util.List; + +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; + +public class XAccountLinksFragment extends Fragment implements EmailAdapter.Listener { + + private ImageView ivGoogle; + private TextView tvNameGoogle; + private TextView tvStatusGoogle; + private TextView tvActionGoogle; + private LinearLayout itemGoogle; + private ImageView ivFacebook; + private TextView tvNameFacebook; + private TextView tvStatusFacebook; + private TextView tvActionFacebook; + private LinearLayout itemFacebook; + private ImageView ivTwitter; + private TextView tvNameTwitter; + private TextView tvStatusTwitter; + private TextView tvActionTwitter; + private LinearLayout itemTwitter; + + private RecyclerView rvEmails; + private EmailAdapter emailAdapter; + private View viewAddEmail; + + private CompositeSubscription compositeSubscription = new CompositeSubscription(); + private Listener listener; + private OnSocialBindListener bindListener; + + public interface Listener { + void onSocialUnbindClick(String provider); + void onDeleteEmailClick(int emailId); + } + + public static XAccountLinksFragment newInstance() { + XAccountLinksFragment fragment = new XAccountLinksFragment(); + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_xaccount_links, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + tvStatusGoogle = view.findViewById(R.id.tvStatusGoogle); + ivGoogle = view.findViewById(R.id.ivGoogle); + tvNameGoogle = view.findViewById(R.id.tvNameGoogle); + tvActionGoogle = view.findViewById(R.id.tvActionGoogle); + itemGoogle = view.findViewById(R.id.itemGoogle); + itemGoogle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (tvActionGoogle.getText().equals(getString(R.string.action_connect))) + bindListener.onBindClick(AuthManager.PROVIDER_GOOGLE); + else onSocialUnlinkClick(AuthManager.PROVIDER_GOOGLE); + } + }); + + tvStatusFacebook = view.findViewById(R.id.tvStatusFacebook); + ivFacebook = view.findViewById(R.id.ivFacebook); + tvNameFacebook = view.findViewById(R.id.tvNameFacebook); + tvActionFacebook = view.findViewById(R.id.tvActionFacebook); + itemFacebook = view.findViewById(R.id.itemFacebook); + itemFacebook.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (tvActionFacebook.getText().equals(getString(R.string.action_connect))) + bindListener.onBindClick(AuthManager.PROVIDER_FACEBOOK); + else onSocialUnlinkClick(AuthManager.PROVIDER_FACEBOOK); + } + }); + + tvStatusTwitter = view.findViewById(R.id.tvStatusTwitter); + ivTwitter = view.findViewById(R.id.ivTwitter); + tvNameTwitter = view.findViewById(R.id.tvNameTwitter); + tvActionTwitter = view.findViewById(R.id.tvActionTwitter); + itemTwitter = view.findViewById(R.id.itemTwitter); + itemTwitter.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (tvActionTwitter.getText().equals(getString(R.string.action_connect))) + bindListener.onBindClick(AuthManager.PROVIDER_TWITTER); + else onSocialUnlinkClick(AuthManager.PROVIDER_TWITTER); + } + }); + + rvEmails = view.findViewById(R.id.rvEmails); + rvEmails.setLayoutManager(new LinearLayoutManager(getActivity())); + emailAdapter = new EmailAdapter(this); + rvEmails.setAdapter(emailAdapter); + viewAddEmail = view.findViewById(R.id.viewAddEmail); + viewAddEmail.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AddEmailDialogFragment.newInstance() + .show(getFragmentManager(), AddEmailDialogFragment.class.getSimpleName()); + } + }); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof Listener) listener = (Listener) activity; + else throw new RuntimeException(activity.toString() + + " must implement XAccountLinksFragment.Listener"); + + if (activity instanceof OnSocialBindListener) bindListener = (OnSocialBindListener) activity; + else throw new RuntimeException(activity.toString() + + " must implement OnSocialBindListener"); + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + bindListener = null; + } + + @Override + public void onPause() { + super.onPause(); + compositeSubscription.clear(); + } + + @Override + public void onResume() { + super.onResume(); + subscribeForXabberAccount(); + } + + @Override + public void onEmailVerifyClick(String email) { + ConfirmEmailDialogFragment.newInstance(email) + .show(getFragmentManager(), ConfirmEmailDialogFragment.class.getSimpleName()); + } + + private void onSocialUnlinkClick(final String provider) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(getString(R.string.title_delete_social, AuthManager.getProviderName(provider))) + .setPositiveButton(R.string.action_disconnect, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + listener.onSocialUnbindClick(provider); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + builder.create().show(); + } + + @Override + public void onEmailDeleteClick(final int id) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(R.string.title_delete_email) + .setPositiveButton(R.string.action_disconnect, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + listener.onDeleteEmailClick(id); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + builder.create().show(); + } + + private void setupSocial(List socialBindings) { + clearSocial(); + for (SocialBindingDTO socialBinding : socialBindings) { + if ("google".equals(socialBinding.getProvider())) { + ivGoogle.setImageResource(R.drawable.ic_google_plus); + tvNameGoogle.setText(socialBinding.getFirstName() + " " + socialBinding.getLastName()); + tvNameGoogle.setVisibility(View.VISIBLE); + tvStatusGoogle.setText(getResources().getString(R.string.title_linked_account, + AuthManager.getProviderName(socialBinding.getProvider()))); + tvActionGoogle.setText(R.string.action_disconnect); + tvActionGoogle.setVisibility(View.GONE); + tvActionGoogle.setTextColor(getActivity().getResources().getColor(R.color.account_register_blue)); + } else if ("facebook".equals(socialBinding.getProvider())) { + ivFacebook.setImageResource(R.drawable.ic_facebook); + tvNameFacebook.setText(socialBinding.getFirstName() + " " + socialBinding.getLastName()); + tvNameFacebook.setVisibility(View.VISIBLE); + tvStatusFacebook.setText(getResources().getString(R.string.title_linked_account, + AuthManager.getProviderName(socialBinding.getProvider()))); + tvActionFacebook.setText(R.string.action_disconnect); + tvActionFacebook.setVisibility(View.GONE); + tvActionFacebook.setTextColor(getActivity().getResources().getColor(R.color.account_register_blue)); + } else if ("twitter".equals(socialBinding.getProvider())) { + ivTwitter.setImageResource(R.drawable.ic_twitter); + tvNameTwitter.setText(socialBinding.getFirstName() + " " + socialBinding.getLastName()); + tvNameTwitter.setVisibility(View.VISIBLE); + tvStatusTwitter.setText(getResources().getString(R.string.title_linked_account, + AuthManager.getProviderName(socialBinding.getProvider()))); + tvActionTwitter.setText(R.string.action_disconnect); + tvActionTwitter.setVisibility(View.GONE); + tvActionTwitter.setTextColor(getActivity().getResources().getColor(R.color.account_register_blue)); + } + } + } + + private void clearSocial() { + ivGoogle.setImageResource(R.drawable.ic_google_plus_disabled); + tvNameGoogle.setVisibility(View.GONE); + tvStatusGoogle.setText(R.string.title_not_linked_account); + tvActionGoogle.setText(R.string.action_connect); + tvActionGoogle.setVisibility(View.VISIBLE); + tvActionGoogle.setTextColor(getActivity().getResources().getColor(R.color.grey_500)); + + ivFacebook.setImageResource(R.drawable.ic_facebook_disabled); + tvNameFacebook.setVisibility(View.GONE); + tvStatusFacebook.setText(R.string.title_not_linked_account); + tvActionFacebook.setText(R.string.action_connect); + tvActionFacebook.setVisibility(View.VISIBLE); + tvActionFacebook.setTextColor(getActivity().getResources().getColor(R.color.grey_500)); + + ivTwitter.setImageResource(R.drawable.ic_twitter_disabled); + tvNameTwitter.setVisibility(View.GONE); + tvStatusTwitter.setText(R.string.title_not_linked_account); + tvActionTwitter.setText(R.string.action_connect); + tvActionTwitter.setVisibility(View.VISIBLE); + tvActionTwitter.setTextColor(getActivity().getResources().getColor(R.color.grey_500)); + } + + private void setupEmailList(List emails) { + emailAdapter.setItems(emails); + emailAdapter.notifyDataSetChanged(); + } + + private void subscribeForXabberAccount() { + compositeSubscription.add(XabberAccountManager.getInstance().subscribeForAccount() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(new Action1() { + @Override + public void call(XabberAccount account) { + if (account != null) { + setupSocial(account.getSocialBindings()); + setupEmailList(account.getEmails()); + } + } + }).subscribe()); + } + +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountLoginFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountLoginFragment.java new file mode 100644 index 0000000000..b341c5dbfd --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountLoginFragment.java @@ -0,0 +1,193 @@ +package com.xabber.android.ui.fragment; + +import android.app.Activity; +import android.app.Fragment; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.text.method.LinkMovementMethod; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.Application; +import com.xabber.android.data.NetworkException; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.xaccount.AuthManager; +import com.xabber.android.data.xaccount.XabberAccountManager; +import com.xabber.android.ui.activity.ContactListActivity; +import com.xabber.android.ui.dialog.OrbotInstallerDialog; +import com.xabber.android.ui.helper.OnSocialBindListener; +import com.xabber.android.ui.helper.OrbotHelper; + +public class XAccountLoginFragment extends Fragment implements View.OnClickListener { + + private CheckBox storePasswordView; + private CheckBox chkSync; + private CheckBox chkRequireTLS; + private CheckBox chkUseTOR; + private EditText edtUsername; + private EditText edtPassword; + private Button btnLogin; + private Button btnOptions; + private Button btnForgotPass; + private View optionsView; + private View socialView; + + private OnSocialBindListener listener; + private EmailClickListener emailListener; + private ForgotPassClickListener forgotPassListener; + + public interface EmailClickListener { + void onEmailClick(); + } + + public interface ForgotPassClickListener { + void onForgotPassClick(); + } + + public static XAccountLoginFragment newInstance() { + XAccountLoginFragment fragment = new XAccountLoginFragment(); + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_xaccount_login, container, false); + + storePasswordView = (CheckBox) view.findViewById(R.id.store_password); + chkSync = (CheckBox) view.findViewById(R.id.chkSync); + if (XabberAccountManager.getInstance().getAccount() == null) { + chkSync.setVisibility(View.GONE); + chkSync.setChecked(false); + } + + chkRequireTLS = view.findViewById(R.id.chkRequireTLS); + chkUseTOR = view.findViewById(R.id.chkUseTOR); + + optionsView = view.findViewById(R.id.optionsView); + socialView = view.findViewById(R.id.socialView); + edtUsername = (EditText) view.findViewById(R.id.edtUsername); + edtPassword = (EditText) view.findViewById(R.id.edtPass); + btnLogin = view.findViewById(R.id.btnLogin); + btnLogin.setOnClickListener(this); + btnOptions = view.findViewById(R.id.btnOptions); + btnOptions.setOnClickListener(this); + btnForgotPass = view.findViewById(R.id.btnForgotPass); + btnForgotPass.setOnClickListener(this); + + ((TextView) view.findViewById(R.id.account_help)) + .setMovementMethod(LinkMovementMethod.getInstance()); + + ImageView ivFacebook = view.findViewById(R.id.ivFacebook); + ImageView ivGoogle = view.findViewById(R.id.ivGoogle); + ImageView ivTwitter = view.findViewById(R.id.ivTwitter); + ImageView ivEmail = view.findViewById(R.id.ivEmail); + + ivFacebook.setOnClickListener(this); + ivGoogle.setOnClickListener(this); + ivTwitter.setOnClickListener(this); + ivEmail.setOnClickListener(this); + + return view; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof OnSocialBindListener) listener = (OnSocialBindListener) activity; + else throw new RuntimeException(activity.toString() + + " must implement OnSocialBindListener"); + + if (activity instanceof EmailClickListener) emailListener = (EmailClickListener) activity; + else throw new RuntimeException(activity.toString() + + " must implement EmailClickListener"); + + if (activity instanceof ForgotPassClickListener) + forgotPassListener = (ForgotPassClickListener) activity; + else throw new RuntimeException(activity.toString() + + " must implement ForgotPassClickListener"); + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + emailListener = null; + forgotPassListener = null; + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btnLogin: + addAccount(); + break; + case R.id.ivFacebook: + listener.onBindClick(AuthManager.PROVIDER_FACEBOOK); + break; + case R.id.ivGoogle: + listener.onBindClick(AuthManager.PROVIDER_GOOGLE); + break; + case R.id.ivTwitter: + listener.onBindClick(AuthManager.PROVIDER_TWITTER); + break; + case R.id.ivEmail: + emailListener.onEmailClick(); + break; + case R.id.btnOptions: + showOptions(); + break; + case R.id.btnForgotPass: + forgotPassListener.onForgotPassClick(); + break; + } + } + + private void addAccount() { + if (chkUseTOR.isChecked() && !OrbotHelper.isOrbotInstalled()) { + OrbotInstallerDialog.newInstance().show(getFragmentManager(), OrbotInstallerDialog.class.getName()); + return; + } + + AccountJid account; + try { + account = AccountManager.getInstance().addAccount( + edtUsername.getText().toString().trim(), + edtPassword.getText().toString(), + "", + false, + storePasswordView.isChecked(), + chkSync.isChecked(), + chkUseTOR.isChecked(), + false, true, + chkRequireTLS.isChecked()); + } catch (NetworkException e) { + Application.getInstance().onError(e); + return; + } + + startActivity(ContactListActivity.createIntent(getActivity())); + getActivity().finish(); + } + + private void showOptions() { + if (optionsView.getVisibility() == View.VISIBLE) { + optionsView.setVisibility(View.GONE); + socialView.setVisibility(View.VISIBLE); + btnOptions.setText(R.string.button_advanced_options); + } else { + optionsView.setVisibility(View.VISIBLE); + socialView.setVisibility(View.GONE); + btnOptions.setText(R.string.button_hide_options); + } + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment1.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment1.java new file mode 100644 index 0000000000..900fc76f2b --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment1.java @@ -0,0 +1,193 @@ +package com.xabber.android.ui.fragment; + +import android.app.Fragment; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebView; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.Spinner; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.xaccount.AuthManager; +import com.xabber.android.presentation.mvp.signup.SignUpRepo; +import com.xabber.android.ui.adapter.HostSpinnerAdapter; + +import java.util.ArrayList; +import java.util.List; + +public class XAccountSignUpFragment1 extends Fragment implements View.OnClickListener { + + private EditText edtUsername; + private Spinner spinnerDomain; + private View spinnerBorder; + private TextView tvSocialProvider; + private ProgressBar pbHosts; + private Button btnNext; + private WebView webViewDescription; + + private XAccountSignUpFragment1.Listener listener; + + private List hosts; + private HostSpinnerAdapter adapter; + + public interface Listener { + void onGetHosts(); + void onStep1Completed(String username, String host); + } + + public static XAccountSignUpFragment1 newInstance(XAccountSignUpFragment1.Listener listener) { + XAccountSignUpFragment1 fragment = new XAccountSignUpFragment1(); + fragment.listener = listener; + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_xaccount_signup_1, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + edtUsername = view.findViewById(R.id.edtUsername); + spinnerDomain = view.findViewById(R.id.spinnerDomain); + spinnerDomain.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + String htmlData = "" + + hosts.get(position).getDescription(); + webViewDescription.loadDataWithBaseURL("file:///android_asset/", + htmlData, "text/html", "UTF-8", null); + + if (adapter != null) adapter.setCurrentPosition(position); + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }); + spinnerBorder = view.findViewById(R.id.spinnerBorder); + + tvSocialProvider = view.findViewById(R.id.tvSocialProvider); + pbHosts = view.findViewById(R.id.pbHosts); + + btnNext = view.findViewById(R.id.btnNext); + btnNext.setOnClickListener(this); + + webViewDescription = view.findViewById(R.id.webViewDescription); + + if (listener != null) listener.onGetHosts(); + } + + @Override + public void onResume() { + super.onResume(); + setupSocial(); + + String username = SignUpRepo.getInstance().getUsername(); + if (username != null) edtUsername.setText(username); + + String errorMessage = SignUpRepo.getInstance().getLastErrorMessage(); + if (errorMessage != null) edtUsername.setError(errorMessage); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btnNext: + onNextClick(); + break; + } + } + + public void showHostsProgress(boolean visible) { + pbHosts.setVisibility(visible ? View.VISIBLE : View.GONE); + spinnerDomain.setVisibility(visible ? View.GONE : View.VISIBLE); + spinnerBorder.setVisibility(visible ? View.GONE : View.VISIBLE); + btnNext.setEnabled(!visible); + } + + private void setupSocial() { + String credentials = SignUpRepo.getInstance().getSocialCredentials(); + String provider = SignUpRepo.getInstance().getSocialProvider(); + if (credentials != null && provider != null) { + if (tvSocialProvider != null) { + tvSocialProvider.setVisibility(View.VISIBLE); + tvSocialProvider.setText(getString(R.string.signup_with_social, AuthManager.getProviderName(provider))); + + Drawable drawable; + switch (provider) { + case AuthManager.PROVIDER_TWITTER: + drawable = getResources().getDrawable(R.drawable.ic_twitter); + break; + case AuthManager.PROVIDER_FACEBOOK: + drawable = getResources().getDrawable(R.drawable.ic_facebook); + break; + default: + drawable = getResources().getDrawable(R.drawable.ic_google_plus); + } + tvSocialProvider.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); + } + } else if (tvSocialProvider != null) tvSocialProvider.setVisibility(View.GONE); + } + + private void onNextClick() { + String username = edtUsername.getText().toString().trim(); + + if (verifyFields(username) && spinnerDomain.getSelectedItem() != null && listener != null) { + listener.onStep1Completed(username, spinnerDomain.getSelectedItem().toString()); + } + } + + private boolean verifyFields(String username) { + + if (username.isEmpty()) { + edtUsername.setError(getString(R.string.empty_field)); + return false; + } + + // Username can contain only latin letters, numbers and dots + if (!username.matches("[a-z0-9.]+")) { + edtUsername.setError(getString(R.string.username_rules)); + return false; + } + + // Username must start with letter + if (!username.substring(0, 1).matches("[a-z]")) { + edtUsername.setError(getString(R.string.username_rules_first_symbol)); + return false; + } + + // Username cannot have two dots in a row + if (username.contains("..")) { + edtUsername.setError(getString(R.string.username_rules_dots)); + return false; + } + + return true; + } + + public void setupHosts(List hosts) { + if (spinnerDomain == null) return; + + this.hosts = hosts; + List strings = new ArrayList<>(); + for (AuthManager.Host host : hosts) { + strings.add(host.getHost()); + } + adapter = new HostSpinnerAdapter(getActivity(), + android.R.layout.simple_spinner_item, strings, this.hosts); + spinnerDomain.setAdapter(adapter); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment2.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment2.java new file mode 100644 index 0000000000..b7b8b3e052 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment2.java @@ -0,0 +1,88 @@ +package com.xabber.android.ui.fragment; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.widget.TextInputEditText; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.xabber.android.R; + +public class XAccountSignUpFragment2 extends Fragment implements View.OnClickListener { + + private Listener listener; + + private TextInputEditText edtPass; + private Button btnNext; + + public interface Listener { + void on2StepCompleted(String pass); + } + + public static XAccountSignUpFragment2 newInstance(Listener listener) { + XAccountSignUpFragment2 fragment = new XAccountSignUpFragment2(); + fragment.listener = listener; + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_xaccount_signup_2, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + edtPass = view.findViewById(R.id.edtPass); + edtPass.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) { + btnNext.setEnabled(s.length() >= 4); + } + + @Override + public void afterTextChanged(Editable s) { } + }); + + btnNext = view.findViewById(R.id.btnNext); + btnNext.setOnClickListener(this); + btnNext.setEnabled(false); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btnNext: + String pass = edtPass.getText().toString().trim(); + if (verifyFields(pass) && listener != null) listener.on2StepCompleted(pass); + break; + } + } + + private boolean verifyFields(String pass) { + + if (pass.isEmpty()) { + edtPass.setError(getString(R.string.empty_field)); + return false; + } + + if (pass.length() < 4) { + edtPass.setError(getString(R.string.pass_too_short)); + return false; + } + + return true; + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment3.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment3.java new file mode 100644 index 0000000000..a174c70366 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment3.java @@ -0,0 +1,63 @@ +package com.xabber.android.ui.fragment; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebView; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; + +import com.xabber.android.R; + +public class XAccountSignUpFragment3 extends Fragment { + + private Listener listener; + + private Button btnSignUp; + private CheckBox chkAccept; + + public interface Listener { + void onStep3Completed(); + } + + public static XAccountSignUpFragment3 newInstance(XAccountSignUpFragment3.Listener listener) { + XAccountSignUpFragment3 fragment = new XAccountSignUpFragment3(); + fragment.listener = listener; + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_xaccount_signup_3, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + btnSignUp = view.findViewById(R.id.btnSignUp); + btnSignUp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onStep3Completed(); + } + }); + + chkAccept = view.findViewById(R.id.chkAccept); + chkAccept.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + btnSignUp.setEnabled(isChecked); + } + }); + + WebView webView = view.findViewById(R.id.webView); + webView.loadUrl(getString(R.string.license_url)); + } + +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment4.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment4.java new file mode 100644 index 0000000000..81bcd7eb8e --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountSignUpFragment4.java @@ -0,0 +1,161 @@ +package com.xabber.android.ui.fragment; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.Context; +import android.graphics.PorterDuff; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.xaccount.XabberAccount; +import com.xabber.android.data.xaccount.XabberAccountManager; + +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; + +public class XAccountSignUpFragment4 extends Fragment { + + private Button btnStart; + private Listener listener; + private TextView tvDescription; + private Dialog skipDialog; + + private boolean haveLinks = false; + + public interface Listener { + void onStep4Completed(); + } + + private CompositeSubscription compositeSubscription = new CompositeSubscription(); + + public static XAccountSignUpFragment4 newInstance() { + XAccountSignUpFragment4 fragment = new XAccountSignUpFragment4(); + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_xaccount_signup_4, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + + tvDescription = view.findViewById(R.id.tvDescription); + tvDescription.setText(Html.fromHtml(getActivity().getString(R.string.account_secure_description))); + btnStart = view.findViewById(R.id.btnStart); + btnStart.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onStartClick(); + } + }); + + Fragment linksFragment = XAccountLinksFragment.newInstance(); + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + transaction.replace(R.id.childContainer, linksFragment).commit(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof Listener) listener = (Listener) activity; + else throw new RuntimeException(activity.toString() + + " must implement XAccountSignUpFragment4.Listener"); + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + } + + @Override + public void onResume() { + super.onResume(); + subscribeForXabberAccount(); + } + + @Override + public void onPause() { + super.onPause(); + compositeSubscription.clear(); + } + + private void subscribeForXabberAccount() { + compositeSubscription.add(XabberAccountManager.getInstance().subscribeForAccount() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(new Action1() { + @Override + public void call(XabberAccount account) { + if (account != null) { + if (account.getSocialBindings().size() > 0 || account.getEmails().size() > 0) + haveLinks = true; + else haveLinks = false; + setupStartButton(); + } + } + }).subscribe()); + } + + private void setupStartButton() { + btnStart.setText(haveLinks ? R.string.title_start_messaging : R.string.skip); + btnStart.getBackground().setColorFilter(ContextCompat.getColor(getActivity(), + haveLinks ? R.color.account_register_blue : R.color.grey_400), + PorterDuff.Mode.MULTIPLY); + } + + private void onStartClick() { + if (haveLinks) listener.onStep4Completed(); + else { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + skipDialog = builder.setTitle(R.string.warning) + .setMessage(R.string.account_secure_warning) + .setView(setupDialogView()).create(); + skipDialog.show(); + } + } + + private View setupDialogView() { + LayoutInflater inflater = getActivity().getLayoutInflater(); + View view = inflater.inflate(R.layout.skip_links_dialog, null); + + Button btnSkip = view.findViewById(R.id.btnSkip); + btnSkip.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onStep4Completed(); + } + }); + + Button btnCancel = view.findViewById(R.id.btnCancel); + btnCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + closeDialog(); + } + }); + + return view; + } + + private void closeDialog() { + if (skipDialog != null && skipDialog.isShowing()) + skipDialog.dismiss(); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountXMPPLoginFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountXMPPLoginFragment.java new file mode 100644 index 0000000000..e159ceb0be --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XAccountXMPPLoginFragment.java @@ -0,0 +1,171 @@ +package com.xabber.android.ui.fragment; + +import android.app.Activity; +import android.app.Fragment; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.extension.avatar.AvatarManager; +import com.xabber.android.data.extension.privatestorage.PrivateStorageManager; +import com.xabber.android.ui.adapter.XMPPAccountAuthAdapter; +import com.xabber.android.ui.color.ColorManager; + +import java.util.ArrayList; +import java.util.List; + +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; + +public class XAccountXMPPLoginFragment extends Fragment implements XMPPAccountAuthAdapter.Listener { + + private View progressView; + private TextView tvError; + private TextView tvTitle; + + private View loginProgressView; + private TextView tvAccountJidInLoginProgressView; + private TextView tvActionInLoginProgressView; + private ImageView ivAvatarInLoginProgressView; + + private XMPPAccountAuthAdapter adapter; + private RecyclerView recyclerView; + + private CompositeSubscription compositeSubscription = new CompositeSubscription(); + private Listener listener; + + public interface Listener { + void onAccountClick(String jid); + } + + public static XAccountXMPPLoginFragment newInstance() { + XAccountXMPPLoginFragment fragment = new XAccountXMPPLoginFragment(); + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_xaccount_xmpp_auth, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + progressView = view.findViewById(R.id.progressView); + tvTitle = view.findViewById(R.id.tvTitle); + tvError = view.findViewById(R.id.tvError); + + loginProgressView = view.findViewById(R.id.loginProgressView); + tvAccountJidInLoginProgressView = loginProgressView.findViewById(R.id.tvAccountJid); + tvActionInLoginProgressView = loginProgressView.findViewById(R.id.tvAction); + ivAvatarInLoginProgressView = loginProgressView.findViewById(R.id.avatar); + + recyclerView = view.findViewById(R.id.rlAccounts); + adapter = new XMPPAccountAuthAdapter(this); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + recyclerView.setAdapter(adapter); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof Listener) listener = (Listener) activity; + else throw new RuntimeException(activity.toString() + + " must implement XAccountXMPPLoginFragment.Listener"); + } + + @Override + public void onDetach() { + super.onDetach(); + listener = null; + } + + @Override + public void onPause() { + super.onPause(); + compositeSubscription.clear(); + } + + @Override + public void onResume() { + super.onResume(); + loadData(); + } + + @Override + public void onAccountClick(AccountJid accountJid) { + connectViaJid(accountJid); + } + + private void loadData() { + tvError.setVisibility(View.GONE); + recyclerView.setVisibility(View.GONE); + tvTitle.setVisibility(View.GONE); + + ArrayList accounts = new ArrayList<>(AccountManager.getInstance().getEnabledAccounts()); + if (accounts.size() < 1) tvError.setVisibility(View.VISIBLE); + else if (accounts.size() > 1) loadBindings(accounts); + else connectViaJid(accounts.get(0)); + } + + private void loadBindings(ArrayList accounts) { + showProgress(true); + compositeSubscription.add(PrivateStorageManager.getInstance().getAccountViewWithBindings(accounts) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1>() { + @Override + public void call(List accountViews) { + showProgress(false); + adapter.setItems(accountViews); + recyclerView.setVisibility(View.VISIBLE); + tvTitle.setVisibility(View.VISIBLE); + } + })); + } + + private void showProgress(boolean show) { + progressView.setVisibility(show ? View.VISIBLE : View.GONE); + } + + private void showLoginProgress(AccountJid account) { + + // set color + tvAccountJidInLoginProgressView.setTextColor(ColorManager.getInstance().getAccountPainter(). + getAccountMainColor(account)); + + // set avatar + ivAvatarInLoginProgressView.setImageDrawable( + AvatarManager.getInstance().getAccountAvatar(account)); + + // set jid + final String accountJid = account.getFullJid().asBareJid().toString(); + tvAccountJidInLoginProgressView.setText(accountJid); + + // set action + tvActionInLoginProgressView.setText(R.string.progress_title_connect); + + // show view + loginProgressView.setVisibility(View.VISIBLE); + } + + private void connectViaJid(AccountJid jid) { + recyclerView.setVisibility(View.GONE); + tvTitle.setVisibility(View.GONE); + showLoginProgress(jid); + listener.onAccountClick(jid.getFullJid().toString()); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountCompleteRegsiterFrament.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountCompleteRegsiterFrament.java deleted file mode 100644 index a3f9ea04a8..0000000000 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountCompleteRegsiterFrament.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.xabber.android.ui.fragment; - -import android.app.Fragment; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatCheckBox; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; - -import com.xabber.android.R; -import com.xabber.android.data.account.AccountManager; -import com.xabber.android.data.xaccount.XabberAccount; -import com.xabber.android.data.xaccount.XabberAccountManager; -import com.xabber.android.ui.activity.XabberAccountInfoActivity; - -/** - * Created by valery.miller on 27.07.17. - */ - -public class XabberAccountCompleteRegsiterFrament extends Fragment { - - private TextView tvAccountName; - private TextView tvSignType; - - private EditText edtUsername; - private EditText edtPass; - private EditText edtPass2; - private EditText edtFirstName; - private EditText edtLastName; - private Button btnRegister; - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_xabber_account_complete_register, container, false); - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - tvAccountName = (TextView) view.findViewById(R.id.tvAccountName); - tvSignType = (TextView) view.findViewById(R.id.tvSignType); - - edtUsername = (EditText) view.findViewById(R.id.edtUsername); - edtPass = (EditText) view.findViewById(R.id.edtPass); - edtPass2 = (EditText) view.findViewById(R.id.edtPass2); - edtFirstName = (EditText) view.findViewById(R.id.edtFirstName); - edtLastName = (EditText) view.findViewById(R.id.edtLastName); - - btnRegister = (Button) view.findViewById(R.id.btnRegister); - btnRegister.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - verifyFields(); - } - }); - } - - @Override - public void onResume() { - super.onResume(); - - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null) updateData(account); - else ((XabberAccountInfoActivity)getActivity()).showLoginFragment(); - } - - public void updateData(@NonNull XabberAccount account) { - if (account.getEmails().size() > 0) { - // if registered via email - tvAccountName.setText(account.getEmails().get(0).getEmail()); - tvSignType.setText(R.string.signed_up_email); - } else { - // if registered via social binding - String firstName = account.getFirstName(); - String lastName = account.getLastName(); - String name = ""; - if (firstName != null) { - name = name + firstName; - edtFirstName.setText(firstName); - } - if (lastName != null) { - name = name + " " + lastName; - edtLastName.setText(lastName); - } - if (!name.isEmpty()) tvAccountName.setText(name); - - if (account.getSocialBindings().size() > 0) { - switch (account.getSocialBindings().get(0).getProvider()) { - case "google": - tvSignType.setText(R.string.signed_up_google); - break; - case "facebook": - tvSignType.setText(R.string.signed_up_facebook); - break; - case "twitter": - tvSignType.setText(R.string.signed_up_twitter); - break; - case "github": - tvSignType.setText(R.string.signed_up_github); - break; - } - } - } - - } - - private void verifyFields() { - String username = edtUsername.getText().toString().trim(); - String pass = edtPass.getText().toString().trim(); - String pass2 = edtPass2.getText().toString().trim(); - String firstName = edtFirstName.getText().toString().trim(); - String lastName = edtLastName.getText().toString().trim(); - - if (username.isEmpty()) { - edtUsername.setError(getString(R.string.empty_field)); - return; - } - - // Username can contain only latin letters, numbers and dots - if (!username.matches("[a-z0-9.]+")) { - edtUsername.setError(getString(R.string.username_rules)); - return; - } - - // Username must start with letter - if (!username.substring(0, 1).matches("[a-z]")) { - edtUsername.setError(getString(R.string.username_rules_first_symbol)); - return; - } - - // Username cannot have two dots in a row - if (username.contains("..")) { - edtUsername.setError(getString(R.string.username_rules_dots)); - return; - } - - if (pass.isEmpty()) { - edtPass.setError(getString(R.string.empty_field)); - return; - } - - if (pass2.isEmpty()) { - edtPass2.setError(getString(R.string.empty_field)); - return; - } - - if (pass.length() < 4) { - edtPass.setError(getString(R.string.pass_too_short)); - return; - } - - if (!pass.equals(pass2)) { - edtPass2.setError(getString(R.string.passwords_not_match)); - return; - } - - ((XabberAccountInfoActivity)getActivity()).onCompleteClick(username, pass, pass2, firstName, lastName, true); - } - -} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountConfirmPhoneFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountConfirmPhoneFragment.java deleted file mode 100644 index 51476c9400..0000000000 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountConfirmPhoneFragment.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.xabber.android.ui.fragment; - -import android.app.Fragment; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; - -import com.xabber.android.R; -import com.xabber.android.ui.activity.XabberAccountInfoActivity; - -/** - * Created by valery.miller on 11.01.18. - */ - -public class XabberAccountConfirmPhoneFragment extends Fragment { - - private Button btnSetPhone; - private Button btnConfirm; - private EditText edtPhone; - private EditText edtCode; - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_xabber_account_phone_number_confirm, container, false); - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - btnSetPhone = (Button) view.findViewById(R.id.btnSetPhone); - btnSetPhone.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - checkPhoneNumber(); - } - }); - - btnConfirm = (Button) view.findViewById(R.id.btnConfirm); - btnConfirm.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - checkCode(); - } - }); - - edtPhone = (EditText) view.findViewById(R.id.edtPhone); - edtCode = (EditText) view.findViewById(R.id.edtCode); - } - - private void checkPhoneNumber() { - String phone = edtPhone.getText().toString().replaceAll(" ", ""); - - if (phone.isEmpty() || phone.length() < 12) { - edtPhone.setError(getString(R.string.empty_field)); - return; - } - - ((XabberAccountInfoActivity)getActivity()).onSetPhoneClick(phone); - } - - private void checkCode() { - String code = edtCode.getText().toString().replaceAll(" ", ""); - - if (code.isEmpty()) { - edtCode.setError(getString(R.string.empty_field)); - return; - } - - if (code.length() != 6) { - edtCode.setError(getString(R.string.code_length_wrong)); - return; - } - - ((XabberAccountInfoActivity)getActivity()).onConfirmCodeClick(code); - } -} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountConfirmationFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountConfirmationFragment.java deleted file mode 100644 index 02a6dd512b..0000000000 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountConfirmationFragment.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.xabber.android.ui.fragment; - -import android.app.Fragment; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import com.xabber.android.R; -import com.xabber.android.data.xaccount.XabberAccount; -import com.xabber.android.data.xaccount.XabberAccountManager; -import com.xabber.android.ui.activity.XabberAccountInfoActivity; - -/** - * Created by valery.miller on 27.07.17. - */ - -public class XabberAccountConfirmationFragment extends Fragment { - - private TextView tvSignType; - private TextView tvAccountName; - //private RelativeLayout rlLogout; - - private EditText edtCode; - private Button btnConfirm; - private Button btnResend; - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_xabber_account_confirmation, container, false); - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - tvSignType = (TextView) view.findViewById(R.id.tvSignType); - tvAccountName = (TextView) view.findViewById(R.id.tvAccountName); - -// rlLogout = (RelativeLayout) view.findViewById(R.id.rlLogout); -// rlLogout.setOnClickListener(new View.OnClickListener() { -// @Override -// public void onClick(View v) { -// ((XabberAccountInfoActivity)getActivity()).onLogoutClick(); -// } -// }); - - edtCode = (EditText) view.findViewById(R.id.edtCode); - btnConfirm = (Button) view.findViewById(R.id.btnConfirm); - btnConfirm.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - verifyFields(); - } - }); - btnResend = (Button) view.findViewById(R.id.btnResend); - btnResend.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((XabberAccountInfoActivity)getActivity()).onResendClick(); - } - }); - } - - @Override - public void onResume() { - super.onResume(); - - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null) updateData(account); - else ((XabberAccountInfoActivity)getActivity()).showLoginFragment(); - } - - private void verifyFields() { - String code = edtCode.getText().toString().trim(); - - if (code.isEmpty()) { - edtCode.setError(getString(R.string.empty_field)); - return; - } - - ((XabberAccountInfoActivity)getActivity()).onConfirmClick(code); - } - - public void updateData(@NonNull XabberAccount account) { - if (account.getEmails().size() > 0) - tvAccountName.setText(account.getEmails().get(0).getEmail()); - } - -} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountInfoFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountInfoFragment.java index a5351c28d4..9e07fa39f7 100644 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountInfoFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountInfoFragment.java @@ -1,30 +1,24 @@ package com.xabber.android.ui.fragment; -import android.app.AlertDialog; -import android.app.Dialog; import android.app.Fragment; -import android.content.DialogInterface; +import android.app.FragmentTransaction; import android.os.Bundle; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.RelativeLayout; +import android.widget.ImageView; +import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.xabber.android.BuildConfig; import com.xabber.android.R; -import com.xabber.android.data.SettingsManager; import com.xabber.android.data.xaccount.AuthManager; import com.xabber.android.data.xaccount.XMPPAccountSettings; import com.xabber.android.data.xaccount.XabberAccount; import com.xabber.android.data.xaccount.XabberAccountManager; -import com.xabber.android.ui.activity.XabberAccountInfoActivity; -import com.xabber.android.ui.dialog.AccountSyncDialogFragment; import com.xabber.android.utils.RetrofitErrorConverter; import java.util.List; @@ -47,79 +41,80 @@ public class XabberAccountInfoFragment extends Fragment { private TextView tvAccountUsername; private TextView tvLanguage; private TextView tvPhone; - private TextView tvLastSyncDate; - private RelativeLayout rlLogout; - private RelativeLayout rlSync; - private boolean dialogShowed; + + private TextView tvLinks; + private View viewShowLinks; + private View viewLinks; + private ImageView ivChevron; + + private ProgressBar progressBar; + private View progressView; + private Fragment fragmentSync; + private FragmentTransaction fTrans; private CompositeSubscription compositeSubscription = new CompositeSubscription(); + public static XabberAccountInfoFragment newInstance() { + XabberAccountInfoFragment fragment = new XabberAccountInfoFragment(); + return fragment; + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_xabber_account_info, container, false); + return inflater.inflate(R.layout.fragment_xaccount_info, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + progressBar = view.findViewById(R.id.toolbarProgress); tvPhone = (TextView) view.findViewById(R.id.tvPhoneNumber); tvAccountName = (TextView) view.findViewById(R.id.tvAccountName); tvAccountUsername = (TextView) view.findViewById(R.id.tvAccountUsername); tvLanguage = (TextView) view.findViewById(R.id.tvLanguage); - tvLastSyncDate = (TextView) view.findViewById(R.id.tvLastSyncDate); - rlLogout = (RelativeLayout) view.findViewById(R.id.rlLogout); - rlLogout.setOnClickListener(new View.OnClickListener() { + progressView = view.findViewById(R.id.progressView); + ivChevron = view.findViewById(R.id.ivChevron); + tvLinks = view.findViewById(R.id.tvLinks); + viewLinks = view.findViewById(R.id.viewLinks); + viewShowLinks = view.findViewById(R.id.viewShowLinks); + viewShowLinks.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (!dialogShowed) { - dialogShowed = true; - showLogoutDialog(); - } + viewLinks.setVisibility(viewLinks.getVisibility() == View.VISIBLE + ? View.GONE : View.VISIBLE ); + ivChevron.setImageResource(viewLinks.getVisibility() == View.VISIBLE + ? R.drawable.ic_chevron_up : R.drawable.ic_chevron_down); } }); - rlSync = (RelativeLayout) view.findViewById(R.id.rlSync); - rlSync.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (!dialogShowed) { - dialogShowed = true; - showSyncDialog(false); - } - } - }); - - if (getArguments().getBoolean("SHOW_SYNC", false)) - showSyncDialog(true); + Fragment linksFragment = XAccountLinksFragment.newInstance(); + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + transaction.replace(R.id.accountLinksFrame, linksFragment).commit(); } @Override public void onResume() { super.onResume(); - - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null) updateData(account); - else ((XabberAccountInfoActivity)getActivity()).showLoginFragment(); - updateLastSyncTime(); + subscribeForXabberAccount(); + getSettings(); } @Override - public void onDestroy() { - super.onDestroy(); + public void onPause() { + super.onPause(); compositeSubscription.clear(); } - public void updateData(@NonNull XabberAccount account) { - String accountName = account.getFirstName() + " " + account.getLastName(); - if (accountName.trim().isEmpty()) - accountName = getString(R.string.title_xabber_account); + public void updateData(XabberAccount account) { + if (account == null) return; + + String accountName = account.getFullUsername(); tvAccountName.setText(accountName); - if (account.getUsername() != null && !account.getUsername().isEmpty()) - tvAccountUsername.setText(account.getUsername()); + tvAccountUsername.setText("Free account"); if (account.getLanguage() != null && !account.getLanguage().equals("")) { tvLanguage.setText(account.getLanguage()); @@ -131,29 +126,53 @@ public void updateData(@NonNull XabberAccount account) { String phone = account.getPhone(); tvPhone.setText(phone != null ? phone : getString(R.string.no_phone)); } else tvPhone.setVisibility(View.GONE); + + // links + if (account.getSocialBindings().size() > 0 || account.getEmails().size() > 0) + tvLinks.setText(R.string.title_linked_accounts); + else tvLinks.setText(R.string.title_no_linked_accounts); } public void updateLastSyncTime() { - tvLastSyncDate.setText(getString(R.string.last_sync_date, SettingsManager.getLastSyncDate())); + if (fragmentSync != null && fragmentSync.isVisible()) + ((AccountSyncFragment) fragmentSync).updateLastSyncTime(); + } + + private void subscribeForXabberAccount() { + compositeSubscription.add(XabberAccountManager.getInstance().subscribeForAccount() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(new Action1() { + @Override + public void call(XabberAccount account) { + updateData(account); + } + }).subscribe()); + } + + public void showProgressInAccount(boolean show) { + progressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE); } - public void showSyncDialog(final boolean noCancel) { + /** GET SETTINGS */ + + public void getSettings() { + showProgressView(true); Subscription getSettingsSubscription = AuthManager.getClientSettings() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1>() { @Override public void call(List list) { + showProgressView(false); List items = XabberAccountManager.getInstance().createSyncList(list); if (items != null && items.size() > 0) { // save full list to list for sync XabberAccountManager.getInstance().setXmppAccountsForSync(items); - // show dialog - AccountSyncDialogFragment.newInstance(noCancel) - .show(getFragmentManager(), AccountSyncDialogFragment.class.getSimpleName()); - dialogShowed = false; - } else Toast.makeText(getActivity(), "Не удалось начать синхронизацию", Toast.LENGTH_SHORT).show(); + // show fragment + showSyncFragment(); + } else Toast.makeText(getActivity(), R.string.sync_fail, Toast.LENGTH_SHORT).show(); } }, new Action1() { @Override @@ -164,41 +183,33 @@ public void call(Throwable throwable) { compositeSubscription.add(getSettingsSubscription); } + private void showSyncFragment() { + fragmentSync = AccountSyncFragment.newInstance(); + fTrans = getFragmentManager().beginTransaction(); + fTrans.replace(R.id.childContainer, fragmentSync); + fTrans.commit(); + } + + private void showProgressView(boolean show) { + if (fragmentSync != null && fragmentSync.isVisible() && show) return; + progressView.setVisibility(show ? View.VISIBLE : View.GONE); + } + private void handleErrorGetSettings(Throwable throwable) { + showProgressView(false); String message = RetrofitErrorConverter.throwableToHttpError(throwable); if (message != null) { if (message.equals("Invalid token")) { XabberAccountManager.getInstance().onInvalidToken(); - ((XabberAccountInfoActivity)getActivity()).showLoginFragment(); - Toast.makeText(getActivity(), "Аккаунт был удален", Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity(), R.string.account_deleted, Toast.LENGTH_LONG).show(); + getActivity().finish(); } else { Log.d(LOG_TAG, "Error while synchronization: " + message); Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); } } else { Log.d(LOG_TAG, "Error while synchronization: " + throwable.toString()); - Toast.makeText(getActivity(), "Error while synchronization: " + throwable.toString(), Toast.LENGTH_LONG).show(); + Toast.makeText(getActivity(), R.string.sync_fail, Toast.LENGTH_LONG).show(); } } - - private void showLogoutDialog() { - LayoutInflater inflater = getActivity().getLayoutInflater(); - View view = inflater.inflate(R.layout.dialog_logout_xabber_account, null); - final CheckBox chbDeleteAccounts = (CheckBox) view.findViewById(R.id.chbDeleteAccounts); - - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setTitle(R.string.progress_title_quit) - .setMessage(R.string.logout_summary) - .setView(view) - .setPositiveButton(R.string.button_quit, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ((XabberAccountInfoActivity)getActivity()).onLogoutClick(chbDeleteAccounts.isChecked()); - } - }) - .setNegativeButton(R.string.cancel, null); - Dialog dialog = builder.create(); - dialog.show(); - dialogShowed = false; - } } diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountLastFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountLastFragment.java deleted file mode 100644 index d1ebe06c9a..0000000000 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountLastFragment.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.xabber.android.ui.fragment; - -import android.app.Fragment; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import com.xabber.android.R; -import com.xabber.android.data.xaccount.XMPPUser; -import com.xabber.android.data.xaccount.XabberAccount; -import com.xabber.android.data.xaccount.XabberAccountManager; -import com.xabber.android.ui.activity.XabberAccountInfoActivity; - -import rx.subscriptions.CompositeSubscription; - -/** - * Created by valery.miller on 20.09.17. - */ - -public class XabberAccountLastFragment extends Fragment { - - private static final String LOG_TAG = XabberAccountLastFragment.class.getSimpleName(); - - private TextView tvAccountName; - private TextView tvSignType; - - private Button btnYes; - private Button btnNo; - private TextView tvDescription; - - private String jid; - - private CompositeSubscription compositeSubscription = new CompositeSubscription(); - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_xabber_account_register_last, container, false); - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - tvAccountName = (TextView) view.findViewById(R.id.tvAccountName); - tvSignType = (TextView) view.findViewById(R.id.tvSignType); - - tvDescription = (TextView) view.findViewById(R.id.tvDescription); - btnYes = (Button) view.findViewById(R.id.btnYes); - btnYes.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ((XabberAccountInfoActivity)getActivity()).showInfoFragment(); - } - }); - - btnNo = (Button) view.findViewById(R.id.btnNo); - btnNo.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (jid != null && !jid.isEmpty()) - ((XabberAccountInfoActivity)getActivity()).onDeleteXabberOrgClick(jid); - else ((XabberAccountInfoActivity)getActivity()).showLastFragment(); - } - }); - } - - @Override - public void onResume() { - super.onResume(); - XabberAccount account = XabberAccountManager.getInstance().getAccount(); - if (account != null) { - XMPPUser user = account.getXmppUsers().get(0); - if (user != null) jid = user.getUsername() + "@" + user.getHost(); - tvDescription.setText(getString(R.string.complete_register_summary, jid)); - updateData(account); - } - } - - @Override - public void onDestroy() { - super.onDestroy(); - compositeSubscription.clear(); - } - - public void updateData(@NonNull XabberAccount account) { - if (account.getEmails().size() > 0) { - // if registered via email - tvAccountName.setText(account.getEmails().get(0).getEmail()); - tvSignType.setText(R.string.signed_up_email); - } else { - // if registered via social binding - String firstName = account.getFirstName(); - String lastName = account.getLastName(); - String name = ""; - if (firstName != null) { - name = name + firstName; - } - if (lastName != null) { - name = name + " " + lastName; - } - if (!name.isEmpty()) tvAccountName.setText(name); - - if (account.getSocialBindings().size() > 0) { - switch (account.getSocialBindings().get(0).getProvider()) { - case "google": - tvSignType.setText(R.string.signed_up_google); - break; - case "facebook": - tvSignType.setText(R.string.signed_up_facebook); - break; - case "twitter": - tvSignType.setText(R.string.signed_up_twitter); - break; - case "github": - tvSignType.setText(R.string.signed_up_github); - break; - } - } - } - - } -} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountLoginFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountLoginFragment.java deleted file mode 100644 index e108d78398..0000000000 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberAccountLoginFragment.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.xabber.android.ui.fragment; - -import android.app.Fragment; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatCheckBox; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.CompoundButton; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.Toast; - -import com.xabber.android.R; -import com.xabber.android.data.connection.NetworkManager; -import com.xabber.android.ui.activity.XabberAccountInfoActivity; - -/** - * Created by valery.miller on 27.07.17. - */ - -public class XabberAccountLoginFragment extends Fragment implements View.OnClickListener { - - private ImageView ivGoogle; - private ImageView ivFacebook; - private ImageView ivTwitter; - private ImageView ivGithub; - - private EditText edtEmail; - private AppCompatCheckBox checkBox; - private Button btnContinue; - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_xabber_account_login, container, false); - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - btnContinue = (Button) view.findViewById(R.id.btnContinue); - edtEmail = (EditText) view.findViewById(R.id.edtEmail); - - checkBox = (AppCompatCheckBox) view.findViewById(R.id.chbAgrees); - checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - btnContinue.setEnabled(isChecked); - } - }); - - ivFacebook = (ImageView) view.findViewById(R.id.ivFacebook); - ivGoogle = (ImageView) view.findViewById(R.id.ivGoogle); - ivTwitter = (ImageView) view.findViewById(R.id.ivTwitter); - ivGithub = (ImageView) view.findViewById(R.id.ivGithub); - - btnContinue.setOnClickListener(this); - ivFacebook.setOnClickListener(this); - ivGoogle.setOnClickListener(this); - ivTwitter.setOnClickListener(this); - ivGithub.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.btnContinue: - onContinueClick(); - break; - case R.id.ivFacebook: - ((XabberAccountInfoActivity)getActivity()).loginFacebook(); - break; - case R.id.ivGoogle: - ((XabberAccountInfoActivity)getActivity()).loginGoogle(); - break; - case R.id.ivGithub: - ((XabberAccountInfoActivity)getActivity()).loginGithub(); - break; - case R.id.ivTwitter: - ((XabberAccountInfoActivity)getActivity()).loginTwitter(); - break; - } - } - - private void onContinueClick() { - String email = edtEmail.getText().toString().trim(); - - if (email.isEmpty()) { - edtEmail.setError(getString(R.string.empty_field)); - return; - } - - if (NetworkManager.isNetworkAvailable()) { - ((XabberAccountInfoActivity)getActivity()).signup(email); - } else - Toast.makeText(getActivity(), R.string.toast_no_internet, Toast.LENGTH_LONG).show(); - } -} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberLoginFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/XabberLoginFragment.java deleted file mode 100644 index dd00641735..0000000000 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/XabberLoginFragment.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.xabber.android.ui.fragment; - -import android.app.Fragment; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.RelativeLayout; -import android.widget.Toast; - -import com.xabber.android.R; -import com.xabber.android.data.connection.NetworkManager; -import com.xabber.android.ui.activity.XabberAccountInfoActivity; -import com.xabber.android.ui.activity.XabberLoginActivity; - -/** - * Created by valery.miller on 25.07.17. - */ - -public class XabberLoginFragment extends Fragment implements View.OnClickListener { - - private EditText edtLogin; - private EditText edtPass; - private Button btnLogin; - private RelativeLayout rlForgotPass; - private RelativeLayout rlSignUp; - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.include_login_fields, container, false); - } - - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - edtLogin = (EditText) view.findViewById(R.id.edtLogin); - edtPass = (EditText) view.findViewById(R.id.edtPass); - btnLogin = (Button) view.findViewById(R.id.btnLogin); - rlForgotPass = (RelativeLayout) view.findViewById(R.id.rlForgotPass); - //rlSignUp = (RelativeLayout) view.findViewById(R.id.rlSignUp); - - btnLogin.setOnClickListener(this); - rlForgotPass.setOnClickListener(this); - //rlSignUp.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.btnLogin: - onLoginClick(); - break; - case R.id.rlForgotPass: - ((XabberLoginActivity)getActivity()).onForgotPassClick(); - break; -// case R.id.rlSignUp: -// Intent intent = XabberAccountInfoActivity.createIntent(getActivity()); -// intent.putExtra(XabberAccountInfoActivity.CALL_FROM, XabberAccountInfoActivity.CALL_FROM_LOGIN); -// startActivity(intent); -// break; - } - } - - private void onLoginClick() { - // hide keyboard - InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(edtPass.getWindowToken(), 0); - - String login = edtLogin.getText().toString().trim(); - String pass = edtPass.getText().toString().trim(); - - if (login.isEmpty()) { - edtLogin.setError("empty field"); - return; - } - - if (pass.isEmpty()) { - edtPass.setError("empty field"); - return; - } - - if (NetworkManager.isNetworkAvailable()) { - ((XabberLoginActivity)getActivity()).login(login, pass); - } else - Toast.makeText(getActivity(), "No internet connection", Toast.LENGTH_LONG).show(); - } -} diff --git a/xabber/src/main/java/com/xabber/android/ui/helper/OnSocialBindListener.java b/xabber/src/main/java/com/xabber/android/ui/helper/OnSocialBindListener.java new file mode 100644 index 0000000000..3d322fbce4 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/helper/OnSocialBindListener.java @@ -0,0 +1,5 @@ +package com.xabber.android.ui.helper; + +public interface OnSocialBindListener { + void onBindClick(String provider); +} diff --git a/xabber/src/main/java/com/xabber/android/ui/preferences/PreferenceEditor.java b/xabber/src/main/java/com/xabber/android/ui/preferences/PreferenceEditor.java index 8131d355c5..1b9d97e7a7 100644 --- a/xabber/src/main/java/com/xabber/android/ui/preferences/PreferenceEditor.java +++ b/xabber/src/main/java/com/xabber/android/ui/preferences/PreferenceEditor.java @@ -20,8 +20,6 @@ import android.content.pm.PackageManager; import android.os.Bundle; import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.widget.Toast; import com.xabber.android.R; import com.xabber.android.data.ActivityManager; @@ -29,9 +27,6 @@ import com.xabber.android.data.account.AccountItem; import com.xabber.android.data.entity.AccountJid; import com.xabber.android.data.log.LogManager; -import com.xabber.android.data.xaccount.AuthManager; -import com.xabber.android.data.xaccount.XMPPAccountSettings; -import com.xabber.android.data.xaccount.XabberAccountManager; import com.xabber.android.ui.activity.AccountActivity; import com.xabber.android.ui.activity.AccountAddActivity; import com.xabber.android.ui.activity.AccountListActivity; @@ -43,17 +38,10 @@ import com.xabber.android.ui.dialog.AccountDeleteDialog; import com.xabber.android.ui.helper.ToolbarHelper; import com.xabber.android.ui.widget.XMPPListPreference; -import com.xabber.android.utils.RetrofitErrorConverter; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; -import java.util.List; - -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Action1; -import rx.schedulers.Schedulers; import rx.subscriptions.CompositeSubscription; public class PreferenceEditor extends ManagedActivity @@ -164,48 +152,4 @@ public void onDeleteAccount(AccountItem accountItem) { AccountDeleteDialog.newInstance(accountItem.getAccount()).show(getSupportFragmentManager(), AccountDeleteDialog.class.getName()); } - - public void onDeleteAccountSettings(String jid) { - showProgress(getResources().getString(R.string.progress_title_delete_settings)); - - if (XabberAccountManager.getInstance().getAccountSyncState(jid) != null) { - - Subscription deleteSubscription = AuthManager.deleteClientSettings(jid) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Action1>() { - @Override - public void call(List settings) { - handleSuccessDelete(settings); - } - }, new Action1() { - @Override - public void call(Throwable throwable) { - handleErrorDelete(throwable); - } - }); - compositeSubscription.add(deleteSubscription); - } - } - - private void handleSuccessDelete(List settings) { - hideProgress(); - Toast.makeText(this, R.string.settings_delete_success, Toast.LENGTH_SHORT).show(); - } - - private void handleErrorDelete(Throwable throwable) { - String message = RetrofitErrorConverter.throwableToHttpError(throwable); - if (message != null) { - if (message.equals("Invalid token")) { - XabberAccountManager.getInstance().onInvalidToken(); - } else { - Log.d(LOG_TAG, "Error while deleting settings: " + message); - Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); - } - } else { - Log.d(LOG_TAG, "Error while deleting settings: " + throwable.toString()); - Toast.makeText(this, "Error while deleting settings: " + throwable.toString(), Toast.LENGTH_LONG).show(); - } - hideProgress(); - } } diff --git a/xabber/src/main/java/com/xabber/android/utils/HttpClientWithMTM.java b/xabber/src/main/java/com/xabber/android/utils/HttpClientWithMTM.java new file mode 100644 index 0000000000..80d03f9c0c --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/utils/HttpClientWithMTM.java @@ -0,0 +1,46 @@ +package com.xabber.android.utils; + +import com.xabber.android.data.connection.CertificateManager; +import com.xabber.android.data.entity.AccountJid; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + +import de.duenndns.ssl.MemorizingTrustManager; +import okhttp3.OkHttpClient; + +public class HttpClientWithMTM { + + public static OkHttpClient getClient(AccountJid accountJid) { + + // create ssl verification factory + SSLSocketFactory sslSocketFactory = null; + MemorizingTrustManager mtm = CertificateManager.getInstance().getNewFileUploadManager(accountJid); + + final SSLContext sslContext; + try { + sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, new X509TrustManager[]{mtm}, new java.security.SecureRandom()); + sslSocketFactory = sslContext.getSocketFactory(); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + return null; + } + + // build http client + final OkHttpClient client = new OkHttpClient().newBuilder() + .sslSocketFactory(sslSocketFactory) + .hostnameVerifier(mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier())) + .writeTimeout(5, TimeUnit.MINUTES) + .connectTimeout(5, TimeUnit.MINUTES) + .readTimeout(5, TimeUnit.MINUTES) + .build(); + + return client; + } + +} diff --git a/xabber/src/main/java/com/xabber/android/utils/RetrofitErrorConverter.java b/xabber/src/main/java/com/xabber/android/utils/RetrofitErrorConverter.java index d228ac9c8c..97a7db4cfa 100644 --- a/xabber/src/main/java/com/xabber/android/utils/RetrofitErrorConverter.java +++ b/xabber/src/main/java/com/xabber/android/utils/RetrofitErrorConverter.java @@ -42,6 +42,8 @@ public static String throwableToHttpError(Throwable throwable) { if (error != null) { if (error.getDetail() != null) errorMessage = error.getDetail(); + else if (error.getDetails() != null) + errorMessage = error.getDetails(); else if (error.getEmail() != null && error.getEmail().size() > 0) errorMessage = error.getEmail().get(0); else if (error.getCredentials() != null && error.getCredentials().size() > 0) @@ -60,15 +62,17 @@ else if (error.getPhone() != null && error.getPhone().size() > 0) class APIError { private String detail; + private String details; private ArrayList email; private ArrayList credentials; private ArrayList code; private ArrayList username; private ArrayList phone; - public APIError(String detail, ArrayList email, ArrayList credentials, + public APIError(String detail, String details, ArrayList email, ArrayList credentials, ArrayList code, ArrayList username, ArrayList phone) { this.detail = detail; + this.details = details; this.email = email; this.credentials = credentials; this.code = code; @@ -80,6 +84,10 @@ public String getDetail() { return detail; } + public String getDetails() { + return details; + } + public ArrayList getEmail() { return email; } diff --git a/xabber/src/main/res/drawable-hdpi/ic_account_box_outline_white_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_account_box_outline_white_24dp.png deleted file mode 100644 index 33eae95081..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_account_box_outline_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_account_multiple_white_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_account_multiple_white_24dp.png deleted file mode 100644 index a3546d56b8..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_account_multiple_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_account_remove_white_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_account_remove_white_24dp.png deleted file mode 100644 index 8fa2e62b16..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_account_remove_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_alert_white_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_alert_white_24dp.png deleted file mode 100644 index 5895a82d45..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_alert_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_attachment_grey600_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_attachment_grey600_24dp.png deleted file mode 100644 index 04b54445e0..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_attachment_grey600_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_avatar_2.png b/xabber/src/main/res/drawable-hdpi/ic_avatar_2.png deleted file mode 100644 index 2f1151c5c9..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_avatar_2.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_avatar_3.png b/xabber/src/main/res/drawable-hdpi/ic_avatar_3.png deleted file mode 100644 index 7e2bfccc98..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_avatar_3.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_avatar_4.png b/xabber/src/main/res/drawable-hdpi/ic_avatar_4.png deleted file mode 100644 index 532bc01e74..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_avatar_4.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_avatar_5.png b/xabber/src/main/res/drawable-hdpi/ic_avatar_5.png deleted file mode 100644 index d0c32dffc4..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_avatar_5.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_avatar_muc.png b/xabber/src/main/res/drawable-hdpi/ic_avatar_muc.png deleted file mode 100644 index f68590d2e4..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_avatar_muc.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_chat_white_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_chat_white_24dp.png deleted file mode 100644 index 53b527815a..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_chat_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_edit_white_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_edit_white_24dp.png deleted file mode 100644 index 1ca8fa1001..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_edit_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_help_circle_grey600_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_help_circle_grey600_24dp.png deleted file mode 100644 index 60db1bc9ad..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_help_circle_grey600_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_list_white_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_list_white_24dp.png deleted file mode 100644 index 436113d27b..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_search_white_24dp.png b/xabber/src/main/res/drawable-hdpi/ic_search_white_24dp.png deleted file mode 100644 index a2fc5b2e70..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_search_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_stat_play_circle_fill.png b/xabber/src/main/res/drawable-hdpi/ic_stat_play_circle_fill.png deleted file mode 100644 index a067505723..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_stat_play_circle_fill.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_status_available_18dp.png b/xabber/src/main/res/drawable-hdpi/ic_status_available_18dp.png deleted file mode 100644 index e49d570f9e..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_status_available_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_status_away_18dp.png b/xabber/src/main/res/drawable-hdpi/ic_status_away_18dp.png deleted file mode 100644 index f5773b652f..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_status_away_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_status_chat_18dp.png b/xabber/src/main/res/drawable-hdpi/ic_status_chat_18dp.png deleted file mode 100644 index cd17e6bab4..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_status_chat_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_status_connection_18dp.png b/xabber/src/main/res/drawable-hdpi/ic_status_connection_18dp.png deleted file mode 100644 index 3441b1d612..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_status_connection_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_status_dnd_18dp.png b/xabber/src/main/res/drawable-hdpi/ic_status_dnd_18dp.png deleted file mode 100644 index f0914eef58..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_status_dnd_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_status_unavailable_18dp.png b/xabber/src/main/res/drawable-hdpi/ic_status_unavailable_18dp.png deleted file mode 100644 index f70c4809c7..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_status_unavailable_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-hdpi/ic_status_xa_18dp.png b/xabber/src/main/res/drawable-hdpi/ic_status_xa_18dp.png deleted file mode 100644 index 023e369af6..0000000000 Binary files a/xabber/src/main/res/drawable-hdpi/ic_status_xa_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_account_box_outline_white_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_account_box_outline_white_24dp.png deleted file mode 100644 index a362b99959..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_account_box_outline_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_account_multiple_white_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_account_multiple_white_24dp.png deleted file mode 100644 index 6d8473bc8a..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_account_multiple_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_account_remove_white_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_account_remove_white_24dp.png deleted file mode 100644 index 35e94095f2..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_account_remove_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_alert_white_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_alert_white_24dp.png deleted file mode 100644 index f36c06f344..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_alert_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_attachment_grey600_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_attachment_grey600_24dp.png deleted file mode 100644 index 40ed600b18..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_attachment_grey600_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_avatar_2.png b/xabber/src/main/res/drawable-mdpi/ic_avatar_2.png deleted file mode 100644 index 3a867c6597..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_avatar_2.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_avatar_3.png b/xabber/src/main/res/drawable-mdpi/ic_avatar_3.png deleted file mode 100644 index 15a7775866..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_avatar_3.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_avatar_4.png b/xabber/src/main/res/drawable-mdpi/ic_avatar_4.png deleted file mode 100644 index 7c22a6bdab..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_avatar_4.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_avatar_5.png b/xabber/src/main/res/drawable-mdpi/ic_avatar_5.png deleted file mode 100644 index ba1d54fc68..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_avatar_5.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_avatar_muc.png b/xabber/src/main/res/drawable-mdpi/ic_avatar_muc.png deleted file mode 100644 index b5a7bfbb6d..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_avatar_muc.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_chat_white_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_chat_white_24dp.png deleted file mode 100644 index 6dffe16101..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_chat_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_edit_white_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_edit_white_24dp.png deleted file mode 100644 index 8c7ec3c17c..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_edit_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_help_circle_grey600_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_help_circle_grey600_24dp.png deleted file mode 100644 index b42e7a26c0..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_help_circle_grey600_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_list_white_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_list_white_24dp.png deleted file mode 100644 index 5e51ed4780..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_search_white_24dp.png b/xabber/src/main/res/drawable-mdpi/ic_search_white_24dp.png deleted file mode 100644 index dff1e3a8a4..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_search_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_stat_play_circle_fill.png b/xabber/src/main/res/drawable-mdpi/ic_stat_play_circle_fill.png deleted file mode 100644 index 8602f750e3..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_stat_play_circle_fill.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_status_available_18dp.png b/xabber/src/main/res/drawable-mdpi/ic_status_available_18dp.png deleted file mode 100644 index 891544550b..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_status_available_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_status_away_18dp.png b/xabber/src/main/res/drawable-mdpi/ic_status_away_18dp.png deleted file mode 100644 index 09f84ff1f1..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_status_away_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_status_chat_18dp.png b/xabber/src/main/res/drawable-mdpi/ic_status_chat_18dp.png deleted file mode 100644 index 6ef14ef42a..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_status_chat_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_status_connection_18dp.png b/xabber/src/main/res/drawable-mdpi/ic_status_connection_18dp.png deleted file mode 100644 index 806f3bd57e..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_status_connection_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_status_dnd_18dp.png b/xabber/src/main/res/drawable-mdpi/ic_status_dnd_18dp.png deleted file mode 100644 index 449b5c5b00..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_status_dnd_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_status_unavailable_18dp.png b/xabber/src/main/res/drawable-mdpi/ic_status_unavailable_18dp.png deleted file mode 100644 index 4c974b6bed..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_status_unavailable_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-mdpi/ic_status_xa_18dp.png b/xabber/src/main/res/drawable-mdpi/ic_status_xa_18dp.png deleted file mode 100644 index c8a5e04dbd..0000000000 Binary files a/xabber/src/main/res/drawable-mdpi/ic_status_xa_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_account_box_outline_white_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_account_box_outline_white_24dp.png deleted file mode 100644 index 75bf7d9c25..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_account_box_outline_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_account_multiple_white_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_account_multiple_white_24dp.png deleted file mode 100644 index 82e39c2956..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_account_multiple_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_account_remove_white_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_account_remove_white_24dp.png deleted file mode 100644 index b32b7fe810..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_account_remove_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_alert_white_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_alert_white_24dp.png deleted file mode 100644 index c690431c1b..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_alert_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_attachment_grey600_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_attachment_grey600_24dp.png deleted file mode 100644 index 764c82c3a7..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_attachment_grey600_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_avatar_2.png b/xabber/src/main/res/drawable-xhdpi/ic_avatar_2.png deleted file mode 100644 index a49745f294..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_avatar_2.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_avatar_3.png b/xabber/src/main/res/drawable-xhdpi/ic_avatar_3.png deleted file mode 100644 index cf3db22c2f..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_avatar_3.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_avatar_4.png b/xabber/src/main/res/drawable-xhdpi/ic_avatar_4.png deleted file mode 100644 index 9ac231b722..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_avatar_4.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_avatar_5.png b/xabber/src/main/res/drawable-xhdpi/ic_avatar_5.png deleted file mode 100644 index 06d30ea7c3..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_avatar_5.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_avatar_muc.png b/xabber/src/main/res/drawable-xhdpi/ic_avatar_muc.png deleted file mode 100644 index e06aedce78..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_avatar_muc.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_chat_white_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_chat_white_24dp.png deleted file mode 100644 index 23b1f69afc..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_chat_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_edit_white_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_edit_white_24dp.png deleted file mode 100644 index 7c6a745434..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_edit_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_help_circle_grey600_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_help_circle_grey600_24dp.png deleted file mode 100644 index 7abe2935aa..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_help_circle_grey600_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_list_white_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_list_white_24dp.png deleted file mode 100644 index abefc200a2..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_search_white_24dp.png b/xabber/src/main/res/drawable-xhdpi/ic_search_white_24dp.png deleted file mode 100644 index 043759acd4..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_search_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_stat_play_circle_fill.png b/xabber/src/main/res/drawable-xhdpi/ic_stat_play_circle_fill.png deleted file mode 100644 index 3cc201cea6..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_stat_play_circle_fill.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_status_available_18dp.png b/xabber/src/main/res/drawable-xhdpi/ic_status_available_18dp.png deleted file mode 100644 index 3d8b58cfe0..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_status_available_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_status_away_18dp.png b/xabber/src/main/res/drawable-xhdpi/ic_status_away_18dp.png deleted file mode 100644 index 7208de0663..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_status_away_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_status_chat_18dp.png b/xabber/src/main/res/drawable-xhdpi/ic_status_chat_18dp.png deleted file mode 100644 index 625aa8aeb6..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_status_chat_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_status_connection_18dp.png b/xabber/src/main/res/drawable-xhdpi/ic_status_connection_18dp.png deleted file mode 100644 index de9b7924e7..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_status_connection_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_status_dnd_18dp.png b/xabber/src/main/res/drawable-xhdpi/ic_status_dnd_18dp.png deleted file mode 100644 index 7c2e8216e4..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_status_dnd_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_status_unavailable_18dp.png b/xabber/src/main/res/drawable-xhdpi/ic_status_unavailable_18dp.png deleted file mode 100644 index 4bc80159c3..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_status_unavailable_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xhdpi/ic_status_xa_18dp.png b/xabber/src/main/res/drawable-xhdpi/ic_status_xa_18dp.png deleted file mode 100644 index de961b864a..0000000000 Binary files a/xabber/src/main/res/drawable-xhdpi/ic_status_xa_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_account_box_outline_white_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_account_box_outline_white_24dp.png deleted file mode 100644 index e371d2a02f..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_account_box_outline_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_account_multiple_white_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_account_multiple_white_24dp.png deleted file mode 100644 index e6bd3deadc..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_account_multiple_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_account_remove_white_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_account_remove_white_24dp.png deleted file mode 100644 index bdd14d5a46..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_account_remove_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_alert_white_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_alert_white_24dp.png deleted file mode 100644 index 65fc214f2b..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_alert_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_attachment_grey600_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_attachment_grey600_24dp.png deleted file mode 100644 index 6428fdd1f0..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_attachment_grey600_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_2.png b/xabber/src/main/res/drawable-xxhdpi/ic_avatar_2.png deleted file mode 100644 index 58a9128d05..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_2.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_3.png b/xabber/src/main/res/drawable-xxhdpi/ic_avatar_3.png deleted file mode 100644 index 4ac026663b..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_3.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_4.png b/xabber/src/main/res/drawable-xxhdpi/ic_avatar_4.png deleted file mode 100644 index d1ef0a1684..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_4.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_5.png b/xabber/src/main/res/drawable-xxhdpi/ic_avatar_5.png deleted file mode 100644 index 5ca2426090..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_5.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_muc.png b/xabber/src/main/res/drawable-xxhdpi/ic_avatar_muc.png deleted file mode 100644 index 5a936be92b..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_avatar_muc.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_chat_white_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_chat_white_24dp.png deleted file mode 100644 index 2ced3eb419..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_chat_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_edit_white_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_edit_white_24dp.png deleted file mode 100644 index 2beb2b4279..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_edit_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_help_circle_grey600_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_help_circle_grey600_24dp.png deleted file mode 100644 index a0bd78ae26..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_help_circle_grey600_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_list_white_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_list_white_24dp.png deleted file mode 100644 index 6b7e78f83f..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png deleted file mode 100644 index 0bbeab1501..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_stat_play_circle_fill.png b/xabber/src/main/res/drawable-xxhdpi/ic_stat_play_circle_fill.png deleted file mode 100644 index 549fdce137..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_stat_play_circle_fill.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_status_available_18dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_status_available_18dp.png deleted file mode 100644 index 9dc7da76f9..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_status_available_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_status_away_18dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_status_away_18dp.png deleted file mode 100644 index 22809e9a1b..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_status_away_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_status_chat_18dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_status_chat_18dp.png deleted file mode 100644 index 3f83767116..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_status_chat_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_status_connection_18dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_status_connection_18dp.png deleted file mode 100644 index bff0c53b46..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_status_connection_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_status_dnd_18dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_status_dnd_18dp.png deleted file mode 100644 index d02832690e..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_status_dnd_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_status_unavailable_18dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_status_unavailable_18dp.png deleted file mode 100644 index 27e184ba9d..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_status_unavailable_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable-xxhdpi/ic_status_xa_18dp.png b/xabber/src/main/res/drawable-xxhdpi/ic_status_xa_18dp.png deleted file mode 100644 index ca2328f1f5..0000000000 Binary files a/xabber/src/main/res/drawable-xxhdpi/ic_status_xa_18dp.png and /dev/null differ diff --git a/xabber/src/main/res/drawable/ic_add_email_circle.xml b/xabber/src/main/res/drawable/ic_add_email_circle.xml new file mode 100644 index 0000000000..275b4092f3 --- /dev/null +++ b/xabber/src/main/res/drawable/ic_add_email_circle.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_arrow_left.xml b/xabber/src/main/res/drawable/ic_arrow_left.xml new file mode 100644 index 0000000000..67ad5dcdc8 --- /dev/null +++ b/xabber/src/main/res/drawable/ic_arrow_left.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_cellphone.xml b/xabber/src/main/res/drawable/ic_cellphone.xml deleted file mode 100644 index b89b49f185..0000000000 --- a/xabber/src/main/res/drawable/ic_cellphone.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_chevron_up.xml b/xabber/src/main/res/drawable/ic_chevron_up.xml new file mode 100644 index 0000000000..f718a97485 --- /dev/null +++ b/xabber/src/main/res/drawable/ic_chevron_up.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_client_adium_10dp.xml b/xabber/src/main/res/drawable/ic_client_adium_10dp.xml deleted file mode 100644 index 929b53e298..0000000000 --- a/xabber/src/main/res/drawable/ic_client_adium_10dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_adium_18dp.xml b/xabber/src/main/res/drawable/ic_client_adium_18dp.xml deleted file mode 100644 index c795b2cdce..0000000000 --- a/xabber/src/main/res/drawable/ic_client_adium_18dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_conversations_10dp.xml b/xabber/src/main/res/drawable/ic_client_conversations_10dp.xml deleted file mode 100644 index c3e462ad89..0000000000 --- a/xabber/src/main/res/drawable/ic_client_conversations_10dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/xabber/src/main/res/drawable/ic_client_conversations_18dp.xml b/xabber/src/main/res/drawable/ic_client_conversations_18dp.xml deleted file mode 100644 index 9797f66a0c..0000000000 --- a/xabber/src/main/res/drawable/ic_client_conversations_18dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/xabber/src/main/res/drawable/ic_client_empathy_10dp.xml b/xabber/src/main/res/drawable/ic_client_empathy_10dp.xml deleted file mode 100644 index d8f2b8da4c..0000000000 --- a/xabber/src/main/res/drawable/ic_client_empathy_10dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - diff --git a/xabber/src/main/res/drawable/ic_client_empathy_18dp.xml b/xabber/src/main/res/drawable/ic_client_empathy_18dp.xml deleted file mode 100644 index 0c2c7a0518..0000000000 --- a/xabber/src/main/res/drawable/ic_client_empathy_18dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - diff --git a/xabber/src/main/res/drawable/ic_client_gajim_10dp.xml b/xabber/src/main/res/drawable/ic_client_gajim_10dp.xml deleted file mode 100644 index 8acef46571..0000000000 --- a/xabber/src/main/res/drawable/ic_client_gajim_10dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_gajim_18dp.xml b/xabber/src/main/res/drawable/ic_client_gajim_18dp.xml deleted file mode 100644 index bc9d4f78ca..0000000000 --- a/xabber/src/main/res/drawable/ic_client_gajim_18dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_gtalk_10dp.xml b/xabber/src/main/res/drawable/ic_client_gtalk_10dp.xml deleted file mode 100644 index 27b07da1ca..0000000000 --- a/xabber/src/main/res/drawable/ic_client_gtalk_10dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_gtalk_18dp.xml b/xabber/src/main/res/drawable/ic_client_gtalk_18dp.xml deleted file mode 100644 index 2b74001fd9..0000000000 --- a/xabber/src/main/res/drawable/ic_client_gtalk_18dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_ichat_10dp.xml b/xabber/src/main/res/drawable/ic_client_ichat_10dp.xml deleted file mode 100644 index 3a16ccf9f9..0000000000 --- a/xabber/src/main/res/drawable/ic_client_ichat_10dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_ichat_18dp.xml b/xabber/src/main/res/drawable/ic_client_ichat_18dp.xml deleted file mode 100644 index 1d1d4fc181..0000000000 --- a/xabber/src/main/res/drawable/ic_client_ichat_18dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_large.xml b/xabber/src/main/res/drawable/ic_client_large.xml deleted file mode 100644 index 6d7317e125..0000000000 --- a/xabber/src/main/res/drawable/ic_client_large.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_client_miranda_10dp.xml b/xabber/src/main/res/drawable/ic_client_miranda_10dp.xml deleted file mode 100644 index 2e3e544b08..0000000000 --- a/xabber/src/main/res/drawable/ic_client_miranda_10dp.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_miranda_18dp.xml b/xabber/src/main/res/drawable/ic_client_miranda_18dp.xml deleted file mode 100644 index 7b15d9591d..0000000000 --- a/xabber/src/main/res/drawable/ic_client_miranda_18dp.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_pidgin_10dp.xml b/xabber/src/main/res/drawable/ic_client_pidgin_10dp.xml deleted file mode 100644 index 9555fa6b07..0000000000 --- a/xabber/src/main/res/drawable/ic_client_pidgin_10dp.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_pidgin_18dp.xml b/xabber/src/main/res/drawable/ic_client_pidgin_18dp.xml deleted file mode 100644 index 4969a1cd12..0000000000 --- a/xabber/src/main/res/drawable/ic_client_pidgin_18dp.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_psi_10dp.xml b/xabber/src/main/res/drawable/ic_client_psi_10dp.xml deleted file mode 100644 index da4f54affa..0000000000 --- a/xabber/src/main/res/drawable/ic_client_psi_10dp.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/xabber/src/main/res/drawable/ic_client_psi_18dp.xml b/xabber/src/main/res/drawable/ic_client_psi_18dp.xml deleted file mode 100644 index 654e3e6f7c..0000000000 --- a/xabber/src/main/res/drawable/ic_client_psi_18dp.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/xabber/src/main/res/drawable/ic_client_qip_10dp.xml b/xabber/src/main/res/drawable/ic_client_qip_10dp.xml deleted file mode 100644 index 8932c21317..0000000000 --- a/xabber/src/main/res/drawable/ic_client_qip_10dp.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/xabber/src/main/res/drawable/ic_client_qip_18dp.xml b/xabber/src/main/res/drawable/ic_client_qip_18dp.xml deleted file mode 100644 index d7c069a459..0000000000 --- a/xabber/src/main/res/drawable/ic_client_qip_18dp.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/xabber/src/main/res/drawable/ic_client_small.xml b/xabber/src/main/res/drawable/ic_client_small.xml deleted file mode 100644 index 357fdf3f38..0000000000 --- a/xabber/src/main/res/drawable/ic_client_small.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_client_vip_10dp.xml b/xabber/src/main/res/drawable/ic_client_vip_10dp.xml deleted file mode 100644 index 9ebf597f92..0000000000 --- a/xabber/src/main/res/drawable/ic_client_vip_10dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/xabber/src/main/res/drawable/ic_client_vip_18dp.xml b/xabber/src/main/res/drawable/ic_client_vip_18dp.xml deleted file mode 100644 index 03d892627b..0000000000 --- a/xabber/src/main/res/drawable/ic_client_vip_18dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/xabber/src/main/res/drawable/ic_client_xabber_10dp.xml b/xabber/src/main/res/drawable/ic_client_xabber_10dp.xml deleted file mode 100644 index e9755a4591..0000000000 --- a/xabber/src/main/res/drawable/ic_client_xabber_10dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_client_xabber_18dp.xml b/xabber/src/main/res/drawable/ic_client_xabber_18dp.xml deleted file mode 100644 index fcf5fb19fc..0000000000 --- a/xabber/src/main/res/drawable/ic_client_xabber_18dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_cloud_sync_lightgrey.xml b/xabber/src/main/res/drawable/ic_cloud_sync_lightgrey.xml deleted file mode 100644 index 345ca237e1..0000000000 --- a/xabber/src/main/res/drawable/ic_cloud_sync_lightgrey.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_confirmed_email_circle.xml b/xabber/src/main/res/drawable/ic_confirmed_email_circle.xml new file mode 100644 index 0000000000..aed36af58f --- /dev/null +++ b/xabber/src/main/res/drawable/ic_confirmed_email_circle.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_email.xml b/xabber/src/main/res/drawable/ic_email.xml new file mode 100644 index 0000000000..bb3d177ce6 --- /dev/null +++ b/xabber/src/main/res/drawable/ic_email.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_email_add.xml b/xabber/src/main/res/drawable/ic_email_add.xml new file mode 100644 index 0000000000..344b815c00 --- /dev/null +++ b/xabber/src/main/res/drawable/ic_email_add.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_email_circle.xml b/xabber/src/main/res/drawable/ic_email_circle.xml new file mode 100644 index 0000000000..fda227304a --- /dev/null +++ b/xabber/src/main/res/drawable/ic_email_circle.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_email_confirmed.xml b/xabber/src/main/res/drawable/ic_email_confirmed.xml new file mode 100644 index 0000000000..64a893307a --- /dev/null +++ b/xabber/src/main/res/drawable/ic_email_confirmed.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_exit.xml b/xabber/src/main/res/drawable/ic_exit.xml deleted file mode 100644 index 5852cec8b4..0000000000 --- a/xabber/src/main/res/drawable/ic_exit.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_facebook.xml b/xabber/src/main/res/drawable/ic_facebook.xml index e1781fdf88..1827888c28 100644 --- a/xabber/src/main/res/drawable/ic_facebook.xml +++ b/xabber/src/main/res/drawable/ic_facebook.xml @@ -1,7 +1,7 @@ diff --git a/xabber/src/main/res/drawable/ic_facebook_disabled.xml b/xabber/src/main/res/drawable/ic_facebook_disabled.xml new file mode 100644 index 0000000000..8ed747fec6 --- /dev/null +++ b/xabber/src/main/res/drawable/ic_facebook_disabled.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_github_logo.xml b/xabber/src/main/res/drawable/ic_github_logo.xml deleted file mode 100644 index 9a848626a8..0000000000 --- a/xabber/src/main/res/drawable/ic_github_logo.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_google_plus.xml b/xabber/src/main/res/drawable/ic_google_plus.xml index 3dc8ee5e5f..137d79d439 100644 --- a/xabber/src/main/res/drawable/ic_google_plus.xml +++ b/xabber/src/main/res/drawable/ic_google_plus.xml @@ -1,7 +1,7 @@ diff --git a/xabber/src/main/res/drawable/ic_google_plus_disabled.xml b/xabber/src/main/res/drawable/ic_google_plus_disabled.xml new file mode 100644 index 0000000000..cfed3eb9b4 --- /dev/null +++ b/xabber/src/main/res/drawable/ic_google_plus_disabled.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_info_outline_white_24dp.xml b/xabber/src/main/res/drawable/ic_info_outline_white_24dp.xml deleted file mode 100644 index 9567ecd775..0000000000 --- a/xabber/src/main/res/drawable/ic_info_outline_white_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/xabber/src/main/res/drawable/ic_open_lock.xml b/xabber/src/main/res/drawable/ic_open_lock.xml deleted file mode 100644 index f5d0e0126f..0000000000 --- a/xabber/src/main/res/drawable/ic_open_lock.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_status_border.xml b/xabber/src/main/res/drawable/ic_status_border.xml deleted file mode 100644 index 73e1f1e349..0000000000 --- a/xabber/src/main/res/drawable/ic_status_border.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_status_thin_border.xml b/xabber/src/main/res/drawable/ic_status_thin_border.xml deleted file mode 100644 index 0d00dad5f8..0000000000 --- a/xabber/src/main/res/drawable/ic_status_thin_border.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_status_without_border.xml b/xabber/src/main/res/drawable/ic_status_without_border.xml deleted file mode 100644 index 8a829c615f..0000000000 --- a/xabber/src/main/res/drawable/ic_status_without_border.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_sync_grey.xml b/xabber/src/main/res/drawable/ic_sync_grey.xml deleted file mode 100644 index c929991321..0000000000 --- a/xabber/src/main/res/drawable/ic_sync_grey.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/ic_twitter.xml b/xabber/src/main/res/drawable/ic_twitter.xml index 6c2e56e601..ec631353be 100644 --- a/xabber/src/main/res/drawable/ic_twitter.xml +++ b/xabber/src/main/res/drawable/ic_twitter.xml @@ -1,7 +1,7 @@ diff --git a/xabber/src/main/res/drawable/ic_twitter_disabled.xml b/xabber/src/main/res/drawable/ic_twitter_disabled.xml new file mode 100644 index 0000000000..63e7147e4d --- /dev/null +++ b/xabber/src/main/res/drawable/ic_twitter_disabled.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/intro_background.webp b/xabber/src/main/res/drawable/intro_background.webp deleted file mode 100644 index 14488789bb..0000000000 Binary files a/xabber/src/main/res/drawable/intro_background.webp and /dev/null differ diff --git a/xabber/src/main/res/drawable/rounded_background.xml b/xabber/src/main/res/drawable/rounded_background.xml deleted file mode 100644 index 65a4682973..0000000000 --- a/xabber/src/main/res/drawable/rounded_background.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/xabber/src/main/res/drawable/xabber_logo_large.png b/xabber/src/main/res/drawable/xabber_logo_large.png deleted file mode 100644 index 766507ac65..0000000000 Binary files a/xabber/src/main/res/drawable/xabber_logo_large.png and /dev/null differ diff --git a/xabber/src/main/res/layout-land/activity_intro.xml b/xabber/src/main/res/layout-land/activity_intro.xml deleted file mode 100644 index 2fe60de1e1..0000000000 --- a/xabber/src/main/res/layout-land/activity_intro.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - -