From 2199dfc088b8731fa5158ffc5bfe4b5fdb799803 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Mon, 6 Nov 2017 20:01:53 +0100 Subject: [PATCH] Do bunch of work on settings Signed-off-by: Mario Danic --- app/build.gradle | 47 +-- app/src/main/AndroidManifest.xml | 2 + .../talk/adapters/items/RoomItem.java | 2 +- .../talk/adapters/items/UserItem.java | 2 +- .../AccountVerificationController.java | 14 +- .../talk/controllers/SettingsController.java | 271 ++++++++++++++++++ .../controllers/WebViewLoginController.java | 19 +- .../talk/dagger/modules/RestModule.java | 26 +- .../AccountRemovalJob.java} | 42 ++- .../talk/jobs/creator/MagicJobCreator.java | 3 + .../talk/persistence/entities/User.java | 2 + .../com/nextcloud/talk/utils/PushUtils.java | 5 +- .../talk/utils/database/user/UserUtils.java | 29 +- .../utils/preferences/AppPreferences.java | 85 +++++- .../preferences/MagicUserInputModule.java | 81 ++++++ .../preferences/json/ProxyTypeAdapter.java | 61 ---- .../main/res/layout/controller_settings.xml | 183 +++++++++++- app/src/main/res/values/arrays.xml | 29 ++ app/src/main/res/values/dimens.xml | 1 + app/src/main/res/values/setup.xml | 7 +- app/src/main/res/values/strings.xml | 25 ++ 21 files changed, 788 insertions(+), 148 deletions(-) rename app/src/main/java/com/nextcloud/talk/{utils/preferences/json/ProxyPrefs.java => jobs/AccountRemovalJob.java} (53%) create mode 100644 app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java delete mode 100644 app/src/main/java/com/nextcloud/talk/utils/preferences/json/ProxyTypeAdapter.java create mode 100644 app/src/main/res/values/arrays.xml diff --git a/app/build.gradle b/app/build.gradle index 11ed649b7..81bb84981 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,6 @@ versioning { //preRelease "rc1" } -// For maven repository version = versioning.name android { @@ -16,10 +15,9 @@ android { buildToolsVersion '26.0.2' defaultConfig { applicationId "com.nextcloud.talk" + versionName version minSdkVersion 21 targetSdkVersion 26 - versionCode 1 - versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" // Enabling multidex support. @@ -58,14 +56,22 @@ ext { googleLibraryVersion = '11.4.2' } + +configurations.all { + resolutionStrategy { + force "com.android.support:cardview-v7:${supportLibraryVersion}" + force "com.android.support:preference-v7:${supportLibraryVersion}" + } +} + dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "com.android.support:appcompat-v7:${supportLibraryVersion}" implementation "com.android.support:design:${supportLibraryVersion}" implementation 'com.android.support:multidex:1.0.2' - compile 'io.reactivex.rxjava2:rxandroid:2.0.1' - compile "io.reactivex.rxjava2:rxjava:2.1.4" + implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' + implementation "io.reactivex.rxjava2:rxjava:2.1.4" implementation 'com.bluelinelabs:conductor:2.1.4' implementation 'com.bluelinelabs:conductor-support:2.1.4' @@ -78,7 +84,7 @@ dependencies { annotationProcessor 'com.bluelinelabs:logansquare-compiler:1.3.7' implementation 'com.squareup.retrofit2:retrofit:2.3.0' - compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' implementation 'com.github.aurae.retrofit2:converter-logansquare:1.4.1' implementation 'com.google.dagger:dagger:2.8' @@ -88,37 +94,36 @@ dependencies { implementation 'org.greenrobot:eventbus:3.0.0' - compile 'io.requery:requery:1.4.0' - compile 'io.requery:requery-android:1.4.0' - compile 'net.zetetic:android-database-sqlcipher:3.5.7' - annotationProcessor 'io.requery:requery-processor:1.4.0' + implementation 'io.requery:requery:1.4.1' + implementation 'io.requery:requery-android:1.4.1' + implementation 'net.zetetic:android-database-sqlcipher:3.5.7' + annotationProcessor 'io.requery:requery-processor:1.4.1' compile 'org.parceler:parceler-api:1.1.9' annotationProcessor 'org.parceler:parceler:1.1.9' - compile 'net.orange-box.storebox:storebox-lib:1.4.0' + implementation 'net.orange-box.storebox:storebox-lib:1.4.0' compileOnly "org.projectlombok:lombok:1.16.18" annotationProcessor "org.projectlombok:lombok:1.16.18" - compile 'com.jakewharton:butterknife:8.8.1' + implementation 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' - compile "javax.transaction:transaction-api:1.1-rev-1" + implementation "javax.transaction:transaction-api:1.1-rev-1" - compile 'com.github.HITGIF:TextFieldBoxes:1.3.4' + implementation 'com.github.HITGIF:TextFieldBoxes:1.3.4' - compile 'eu.davidea:flexible-adapter:5.0.0-rc2' + implementation 'eu.davidea:flexible-adapter:5.0.0-rc2' - compile 'cn.carbs.android:AvatarImageView:1.0.4' - - compile 'com.github.bumptech.glide:glide:4.2.0' - annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0' - compile 'com.github.bumptech.glide:okhttp3-integration:4.2.0@aar' + implementation 'cn.carbs.android:AvatarImageView:1.0.4' + implementation 'com.github.bumptech.glide:glide:4.3.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.3.0' + implementation 'com.github.bumptech.glide:okhttp3-integration:4.3.0@aar' implementation 'org.webrtc:google-webrtc:1.0.+' implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}" @@ -130,6 +135,8 @@ dependencies { implementation "com.google.firebase:firebase-core:${googleLibraryVersion}" implementation 'com.yarolegovich:lovely-dialog:1.0.7' + implementation 'com.yarolegovich:lovelyinput:1.0.2' + implementation 'com.yarolegovich:mp:1.0.8' testImplementation 'junit:junit:4.12' androidTestImplementation ('com.android.support.test.espresso:espresso-core:3.0.1', { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 155732353..8fbf79ee1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ @@ -17,6 +18,7 @@ if (!TextUtils.isEmpty(room.getName())) { GlideUrl glideUrl = new GlideUrl(ApiHelper.getUrlForAvatarWithName(userEntity.getBaseUrl(), room.getName()), new LazyHeaders.Builder() - .setHeader("Accept", "*/*") + .setHeader("Accept", "image/*") .setHeader("User-Agent", ApiHelper.getUserAgent()) .build()); diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java index 2b6223f8a..1eb3ca72f 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java @@ -101,7 +101,7 @@ public class UserItem extends AbstractFlexibleItem GlideUrl glideUrl = new GlideUrl(ApiHelper.getUrlForAvatarWithName(userEntity.getBaseUrl(), user.getUserId()), new LazyHeaders.Builder() - .setHeader("Accept", "*/*") + .setHeader("Accept", "image/*") .setHeader("User-Agent", ApiHelper.getUserAgent()) .build()); diff --git a/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java b/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java index b3d16c94e..a9d3e998f 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java @@ -134,7 +134,7 @@ public class AccountVerificationController extends BaseController { if (!TextUtils.isEmpty(displayName)) { dbQueryDisposable = userUtils.createOrUpdateUser(username, token, - baseUrl, displayName, null) + baseUrl, displayName, null, true) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(userEntity -> { @@ -146,10 +146,14 @@ public class AccountVerificationController extends BaseController { new JobRequest.Builder(PushRegistrationJob.TAG). setUpdateCurrent(true).startNow().build().schedule(); - getRouter().setRoot(RouterTransaction.with(new - BottomNavigationController(R.menu.menu_navigation)) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); + if (userUtils.getUsers().size() == 1) { + getRouter().setRoot(RouterTransaction.with(new + BottomNavigationController(R.menu.menu_navigation)) + .pushChangeHandler(new HorizontalChangeHandler()) + .popChangeHandler(new HorizontalChangeHandler())); + } else { + getRouter().popToRoot(); + } }, throwable -> { progressText.setText(progressText.getText().toString() + diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java index 318f5f3e8..005c5071e 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java @@ -20,24 +20,295 @@ package com.nextcloud.talk.controllers; +import android.content.Intent; +import android.net.Uri; import android.support.annotation.NonNull; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; +import com.bluelinelabs.conductor.RouterTransaction; +import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.load.model.LazyHeaders; +import com.nextcloud.talk.BuildConfig; import com.nextcloud.talk.R; +import com.nextcloud.talk.api.helpers.api.ApiHelper; import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.controllers.base.BaseController; +import com.nextcloud.talk.persistence.entities.UserEntity; +import com.nextcloud.talk.utils.ColorUtils; +import com.nextcloud.talk.utils.database.user.UserUtils; +import com.nextcloud.talk.utils.glide.GlideApp; +import com.nextcloud.talk.utils.preferences.AppPreferences; +import com.nextcloud.talk.utils.preferences.MagicUserInputModule; +import com.yarolegovich.mp.MaterialChoicePreference; +import com.yarolegovich.mp.MaterialEditTextPreference; +import com.yarolegovich.mp.MaterialPreferenceScreen; +import com.yarolegovich.mp.MaterialStandardPreference; + +import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.inject.Inject; import autodagger.AutoInjector; +import butterknife.BindView; +import cn.carbs.android.avatarimageview.library.AvatarImageView; @AutoInjector(NextcloudTalkApplication.class) public class SettingsController extends BaseController { public static final String TAG = "SettingsController"; + @BindView(R.id.settings_screen) + MaterialPreferenceScreen settingsScreen; + + @BindView(R.id.settings_proxy_choice) + MaterialChoicePreference proxyChoice; + + @BindView(R.id.settings_proxy_port_edit) + MaterialEditTextPreference proxyPortEditText; + + @BindView(R.id.settings_licence) + MaterialStandardPreference licenceButton; + + @BindView(R.id.settings_privacy) + MaterialStandardPreference privacyButton; + + @BindView(R.id.settings_source_code) + MaterialStandardPreference sourceCodeButton; + + @BindView(R.id.settings_version) + MaterialStandardPreference versionInfo; + + @BindView(R.id.avatar_image) + AvatarImageView avatarImageView; + + @BindView(R.id.avatar_image_invisible) + AvatarImageView avatarImageViewInvisible; + + @BindView(R.id.display_name_text) + TextView displayName; + + @BindView(R.id.settings_remove_account) + MaterialStandardPreference removeAccountButton; + + @BindView(R.id.settings_switch) + MaterialStandardPreference switchAccountButton; + + @BindView(R.id.settings_reauthorize) + MaterialStandardPreference reauthorizeButton; + + @BindView(R.id.settings_add_account) + MaterialStandardPreference addAccountButton; + + @Inject + AppPreferences appPreferences; + + @Inject + UserUtils userUtils; + + private OnPreferenceValueChangedListener proxyTypeChangeListener; + private OnPreferenceValueChangedListener proxyCredentialsChangeListener; + @Override protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) { return inflater.inflate(R.layout.controller_settings, container, false); } + + @Override + protected void onViewBound(@NonNull View view) { + super.onViewBound(view); + NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this); + } + + @Override + protected void onAttach(@NonNull View view) { + super.onAttach(view); + + if ("No proxy".equals(appPreferences.getProxyType()) || appPreferences.getProxyType() == null) { + hideProxySettings(); + } else { + showProxySettings(); + } + + if (appPreferences.getProxyCredentials()) { + showProxyCredentials(); + } else { + hideProxyCredentials(); + } + + appPreferences.registerProxyTypeListener(proxyTypeChangeListener = new ProxyTypeChangeListener()); + appPreferences.registerProxyCredentialsListener(proxyCredentialsChangeListener = new + ProxyCredentialsChangeListener()); + + List listWithIntFields = new ArrayList<>(); + listWithIntFields.add("proxy_port"); + + settingsScreen.setUserInputModule(new MagicUserInputModule(getActivity(), listWithIntFields)); + settingsScreen.setVisibilityController(R.id.settings_proxy_use_credentials, + Arrays.asList(R.id.settings_proxy_username_edit, R.id.settings_proxy_password_edit), + true); + + if (!TextUtils.isEmpty(getResources().getString(R.string.nc_gpl3_url))) { + licenceButton.setOnClickListener(view1 -> { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getResources(). + getString(R.string.nc_gpl3_url))); + startActivity(browserIntent); + }); + } else { + licenceButton.setVisibility(View.GONE); + } + + if (!TextUtils.isEmpty(getResources().getString(R.string.nc_privacy_url))) { + privacyButton.setOnClickListener(view12 -> { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getResources(). + getString(R.string.nc_privacy_url))); + startActivity(browserIntent); + }); + } else { + privacyButton.setVisibility(View.GONE); + } + + if (!TextUtils.isEmpty(getResources().getString(R.string.nc_source_code_url))) { + sourceCodeButton.setOnClickListener(view13 -> { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getResources(). + getString(R.string.nc_source_code_url))); + startActivity(browserIntent); + }); + } else { + sourceCodeButton.setVisibility(View.GONE); + } + + versionInfo.setSummary("v" + BuildConfig.VERSION_NAME); + + UserEntity userEntity = userUtils.getCurrentUser(); + if (userEntity != null) { + // Awful hack + avatarImageViewInvisible.setTextAndColorSeed(String.valueOf(userEntity.getDisplayName(). + toUpperCase().charAt(0)), ColorUtils.colorSeed); + + GlideUrl glideUrl = new GlideUrl(ApiHelper.getUrlForAvatarWithName(userEntity.getBaseUrl(), + userEntity.getUsername()), new LazyHeaders.Builder() + .setHeader("Accept", "image/*") + .setHeader("User-Agent", ApiHelper.getUserAgent()) + .build()); + + GlideApp.with(NextcloudTalkApplication.getSharedApplication().getApplicationContext()) + .load(glideUrl) + .circleCrop() + .centerInside() + .into(avatarImageView) + .onLoadFailed(avatarImageViewInvisible.getDrawable()); + + displayName.setText(userEntity.getDisplayName()); + } + + if (userUtils.getUsers().size() <= 1) { + switchAccountButton.setVisibility(View.GONE); + } + + + reauthorizeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + getParentController().getRouter().pushController(RouterTransaction.with( + new WebViewLoginController(userEntity.getBaseUrl(), + true)).pushChangeHandler(new VerticalChangeHandler()) + .popChangeHandler(new VerticalChangeHandler())); + } + }); + + addAccountButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + getParentController().getRouter().pushController(RouterTransaction.with(new + ServerSelectionController()).pushChangeHandler(new VerticalChangeHandler()) + .popChangeHandler(new VerticalChangeHandler())); + } + }); + } + + @Override + public void onDestroy() { + appPreferences.unregisterProxyTypeListener(proxyTypeChangeListener); + appPreferences.unregisterProxyCredentialsListener(proxyCredentialsChangeListener); + super.onDestroy(); + } + + + private void hideProxySettings() { + appPreferences.removeProxyHost(); + appPreferences.removeProxyPort(); + appPreferences.removeProxyCredentials(); + appPreferences.removeProxyUsername(); + appPreferences.removeProxyPassword(); + settingsScreen.findViewById(R.id.settings_proxy_host_edit).setVisibility(View.GONE); + settingsScreen.findViewById(R.id.settings_proxy_port_edit).setVisibility(View.GONE); + settingsScreen.findViewById(R.id.settings_proxy_use_credentials).setVisibility(View.GONE); + settingsScreen.findViewById(R.id.settings_proxy_username_edit).setVisibility(View.GONE); + settingsScreen.findViewById(R.id.settings_proxy_password_edit).setVisibility(View.GONE); + } + + private void showProxySettings() { + settingsScreen.findViewById(R.id.settings_proxy_host_edit).setVisibility(View.VISIBLE); + settingsScreen.findViewById(R.id.settings_proxy_port_edit).setVisibility(View.VISIBLE); + settingsScreen.findViewById(R.id.settings_proxy_use_credentials).setVisibility(View.VISIBLE); + } + + private void showProxyCredentials() { + settingsScreen.findViewById(R.id.settings_proxy_username_edit).setVisibility(View.VISIBLE); + settingsScreen.findViewById(R.id.settings_proxy_password_edit).setVisibility(View.VISIBLE); + } + + private void hideProxyCredentials() { + appPreferences.removeProxyUsername(); + appPreferences.removeProxyPassword(); + settingsScreen.findViewById(R.id.settings_proxy_username_edit).setVisibility(View.GONE); + settingsScreen.findViewById(R.id.settings_proxy_password_edit).setVisibility(View.GONE); + } + + private class ProxyCredentialsChangeListener implements OnPreferenceValueChangedListener { + + @Override + public void onChanged(Boolean newValue) { + if (newValue) { + showProxyCredentials(); + } else { + hideProxyCredentials(); + } + } + } + + private class ProxyTypeChangeListener implements OnPreferenceValueChangedListener { + + @Override + public void onChanged(String newValue) { + if ("No proxy".equals(newValue)) { + hideProxySettings(); + } else { + switch (newValue) { + case "HTTP": + proxyPortEditText.setValue("3128"); + break; + case "DIRECT": + proxyPortEditText.setValue("8080"); + break; + case "SOCKS": + proxyPortEditText.setValue("1080"); + break; + default: + break; + } + + showProxySettings(); + } + } + } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java b/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java index 82ad3ebce..f9d300ffc 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java @@ -29,6 +29,8 @@ import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.webkit.CookieManager; +import android.webkit.CookieSyncManager; import android.webkit.SslErrorHandler; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -132,6 +134,10 @@ public class WebViewLoginController extends BaseController { webView.getSettings().setSavePassword(false); webView.clearCache(true); webView.clearFormData(); + webView.clearHistory(); + + CookieSyncManager.createInstance(getActivity()); + CookieManager.getInstance().removeAllCookies(null); Map headers = new HashMap<>(); headers.put("OCS-APIRequest", "true"); @@ -219,7 +225,7 @@ public class WebViewLoginController extends BaseController { // We use the URL user entered because one provided by the server is NOT reliable userQueryDisposable = userUtils.createOrUpdateUser(loginData.getUsername(), loginData.getToken(), - baseUrl, displayName, pushConfiguration). + baseUrl, displayName, pushConfiguration, true). subscribe(userEntity -> { if (!isPasswordUpdate) { BundleBuilder bundleBuilder = new BundleBuilder(new Bundle()); @@ -230,9 +236,14 @@ public class WebViewLoginController extends BaseController { (bundleBuilder.build())).pushChangeHandler(new HorizontalChangeHandler()) .popChangeHandler(new HorizontalChangeHandler())); } else { - getRouter().setRoot(RouterTransaction.with(new BottomNavigationController(R.menu.menu_navigation)) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); + if (getRouter().hasRootController()) { + getRouter().popToRoot(); + } else { + getRouter().setRoot(RouterTransaction.with( + new BottomNavigationController(R.menu.menu_navigation) + ).pushChangeHandler(new HorizontalChangeHandler()) + .popChangeHandler(new HorizontalChangeHandler())); + } } }, throwable -> dispose(), this::dispose); diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java b/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java index 665cbcb28..505575317 100644 --- a/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java +++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java @@ -30,7 +30,6 @@ import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.api.helpers.api.ApiHelper; import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.utils.preferences.AppPreferences; -import com.nextcloud.talk.utils.preferences.json.ProxyPrefs; import com.nextcloud.talk.utils.ssl.MagicTrustManager; import com.nextcloud.talk.utils.ssl.SSLSocketFactoryCompat; @@ -71,14 +70,16 @@ public class RestModule { @Provides @Singleton Proxy provideProxy(AppPreferences appPreferences) { - ProxyPrefs proxyPrefs = appPreferences.getProxyServer(); - if (!TextUtils.isEmpty(proxyPrefs.getProxyHost())) { - if (Proxy.Type.SOCKS.equals(Proxy.Type.valueOf(proxyPrefs.getProxyType()))) { - return (new Proxy(Proxy.Type.valueOf(proxyPrefs.getProxyType()), - InetSocketAddress.createUnresolved(proxyPrefs.getProxyHost(), proxyPrefs.getProxyPort()))); + if (!TextUtils.isEmpty(appPreferences.getProxyType()) && !"No proxy".equals(appPreferences.getProxyType()) + && !TextUtils.isEmpty(appPreferences.getProxyHost())) { + if (Proxy.Type.SOCKS.equals(Proxy.Type.valueOf(appPreferences.getProxyType()))) { + return (new Proxy(Proxy.Type.valueOf(appPreferences.getProxyType()), + InetSocketAddress.createUnresolved(appPreferences.getProxyHost(), Integer.parseInt( + appPreferences.getProxyPort())))); } else { - return (new Proxy(Proxy.Type.valueOf(proxyPrefs.getProxyType()), - new InetSocketAddress(proxyPrefs.getProxyHost(), proxyPrefs.getProxyPort()))); + return (new Proxy(Proxy.Type.valueOf(appPreferences.getProxyType()), + new InetSocketAddress(appPreferences.getProxyHost(), + Integer.parseInt(appPreferences.getProxyPort())))); } } else { return Proxy.NO_PROXY; @@ -138,11 +139,12 @@ public class RestModule { if (!Proxy.NO_PROXY.equals(proxy)) { httpClient.proxy(proxy); - if (!TextUtils.isEmpty(appPreferences.getProxyServer().getUsername()) && - !TextUtils.isEmpty(appPreferences.getProxyServer().getPassword())) { + if (appPreferences.getProxyCredentials() && + !TextUtils.isEmpty(appPreferences.getProxyUsername()) && + !TextUtils.isEmpty(appPreferences.getProxyPassword())) { httpClient.proxyAuthenticator(new ProxyAuthenticator(Credentials.basic( - appPreferences.getProxyServer().getUsername(), - appPreferences.getProxyServer().getPassword()))); + appPreferences.getProxyUsername(), + appPreferences.getProxyPassword()))); } } diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/json/ProxyPrefs.java b/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalJob.java similarity index 53% rename from app/src/main/java/com/nextcloud/talk/utils/preferences/json/ProxyPrefs.java rename to app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalJob.java index 4829c3de0..b6349802b 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/json/ProxyPrefs.java +++ b/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalJob.java @@ -18,32 +18,30 @@ * along with this program. If not, see . */ -package com.nextcloud.talk.utils.preferences.json; - -import com.bluelinelabs.logansquare.annotation.JsonField; -import com.bluelinelabs.logansquare.annotation.JsonObject; - -import org.parceler.Parcel; - -import lombok.Data; +package com.nextcloud.talk.jobs; -@Data -@Parcel -@JsonObject -public class ProxyPrefs { - @JsonField(name = "proxy_host") - String proxyHost; +import android.support.annotation.NonNull; - @JsonField(name = "proxy_port") - int proxyPort; +import com.evernote.android.job.Job; +import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.utils.database.user.UserUtils; - @JsonField(name = "proxy_type") - String proxyType; +import javax.inject.Inject; - @JsonField(name = "username") - String username; +import autodagger.AutoInjector; - @JsonField(name = "password") - String password; +@AutoInjector(NextcloudTalkApplication.class) +public class AccountRemovalJob extends Job { + public static final String TAG = "AccountRemovalJob"; + + @Inject + UserUtils userUtils; + + @NonNull + @Override + protected Result onRunJob(Params params) { + NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this); + return Result.SUCCESS; + } } diff --git a/app/src/main/java/com/nextcloud/talk/jobs/creator/MagicJobCreator.java b/app/src/main/java/com/nextcloud/talk/jobs/creator/MagicJobCreator.java index 4bf0473f6..60e228e3e 100644 --- a/app/src/main/java/com/nextcloud/talk/jobs/creator/MagicJobCreator.java +++ b/app/src/main/java/com/nextcloud/talk/jobs/creator/MagicJobCreator.java @@ -25,6 +25,7 @@ import android.support.annotation.Nullable; import com.evernote.android.job.Job; import com.evernote.android.job.JobCreator; +import com.nextcloud.talk.jobs.AccountRemovalJob; import com.nextcloud.talk.jobs.PushRegistrationJob; public class MagicJobCreator implements JobCreator { @@ -36,6 +37,8 @@ public class MagicJobCreator implements JobCreator { switch (tag) { case PushRegistrationJob.TAG: return new PushRegistrationJob(); + case AccountRemovalJob.TAG: + return new AccountRemovalJob(); default: return null; } diff --git a/app/src/main/java/com/nextcloud/talk/persistence/entities/User.java b/app/src/main/java/com/nextcloud/talk/persistence/entities/User.java index 4e39e6c16..8eefbb193 100644 --- a/app/src/main/java/com/nextcloud/talk/persistence/entities/User.java +++ b/app/src/main/java/com/nextcloud/talk/persistence/entities/User.java @@ -44,4 +44,6 @@ public interface User extends Parcelable, Persistable, Serializable { String getDisplayName(); String getPushConfigurationState(); + + boolean getCurrent(); } diff --git a/app/src/main/java/com/nextcloud/talk/utils/PushUtils.java b/app/src/main/java/com/nextcloud/talk/utils/PushUtils.java index cd5bb2115..04ac5972a 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/PushUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/PushUtils.java @@ -231,7 +231,8 @@ public class PushUtils { if (userUtils.anyUserExists()) { String providerValue; PushConfigurationState accountPushData = null; - for (UserEntity userEntity : userUtils.getUsers()) { + for (Object userEntityObject : userUtils.getUsers()) { + UserEntity userEntity = (UserEntity) userEntityObject; providerValue = userEntity.getPushConfigurationState(); if (!TextUtils.isEmpty(providerValue)) { try { @@ -296,7 +297,7 @@ public class PushUtils { userUtils.createOrUpdateUser(userEntity.getUsername(), userEntity.getToken(), userEntity.getBaseUrl(), userEntity.getDisplayName(), - LoganSquare.serialize(pushConfigurationState)) + LoganSquare.serialize(pushConfigurationState), null) .subscribe(new Consumer() { @Override public void accept(UserEntity userEntity) throws Exception { diff --git a/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java b/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java index 435a6205c..835baabbd 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java @@ -49,7 +49,7 @@ public class UserUtils { return (dataStore.count(User.class).limit(1).get().value() > 0); } - public List getUsers() { + public List getUsers() { Result findUsersQueryResult = dataStore.select(User.class).get(); return findUsersQueryResult.toList(); @@ -57,7 +57,8 @@ public class UserUtils { // temporary method while we only support 1 user public UserEntity getCurrentUser() { - Result findUserQueryResult = dataStore.select(User.class).limit(1).get(); + Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.CURRENT.eq(true)) + .limit(1).get(); return (UserEntity) findUserQueryResult.firstOrNull(); } @@ -74,9 +75,21 @@ public class UserUtils { } + private void disableAllUsersWithoutId(long userId) { + Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.ID.notEqual(userId)) + .and(UserEntity.CURRENT.eq(true)).get(); + + for (Object object : findUserQueryResult) { + UserEntity userEntity = (UserEntity) object; + userEntity.setCurrent(false); + dataStore.update(userEntity).blockingGet(); + } + } + public Observable createOrUpdateUser(String username, String token, String serverUrl, @Nullable String displayName, - @Nullable String pushConfigurationState) { + @Nullable String pushConfigurationState, + @Nullable Boolean currentUser) { Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.USERNAME.eq(username). and(UserEntity.BASE_URL.eq(serverUrl.toLowerCase()))).limit(1).get(); @@ -96,6 +109,8 @@ public class UserUtils { user.setPushConfigurationState(pushConfigurationState); } + user.setCurrent(true); + } else { if (!token.equals(user.getToken())) { user.setToken(token); @@ -108,6 +123,14 @@ public class UserUtils { if (pushConfigurationState != null && !pushConfigurationState.equals(user.getPushConfigurationState())) { user.setPushConfigurationState(pushConfigurationState); } + + if (currentUser != null) { + user.setCurrent(currentUser); + + if (currentUser) { + disableAllUsersWithoutId(user.getId()); + } + } } return dataStore.upsert(user) diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java index 114adc9b7..63d4ca720 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java @@ -20,30 +20,93 @@ package com.nextcloud.talk.utils.preferences; -import com.nextcloud.talk.utils.preferences.json.ProxyPrefs; -import com.nextcloud.talk.utils.preferences.json.ProxyTypeAdapter; - import net.orange_box.storebox.annotations.method.ClearMethod; import net.orange_box.storebox.annotations.method.KeyByString; +import net.orange_box.storebox.annotations.method.RegisterChangeListenerMethod; import net.orange_box.storebox.annotations.method.RemoveMethod; -import net.orange_box.storebox.annotations.method.TypeAdapter; +import net.orange_box.storebox.annotations.method.UnregisterChangeListenerMethod; import net.orange_box.storebox.annotations.option.SaveOption; import net.orange_box.storebox.enums.SaveMode; +import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener; @SaveOption(SaveMode.APPLY) public interface AppPreferences { - @KeyByString("proxy_server") - @TypeAdapter(ProxyTypeAdapter.class) - ProxyPrefs getProxyServer(); + @KeyByString("proxy_type") + @RegisterChangeListenerMethod + void registerProxyTypeListener(OnPreferenceValueChangedListener listener); - @KeyByString("proxy_server") - @TypeAdapter(ProxyTypeAdapter.class) - void setProxyServer(ProxyPrefs proxyPrefsServer); + @KeyByString("proxy_type") + @UnregisterChangeListenerMethod + void unregisterProxyTypeListener(OnPreferenceValueChangedListener listener); + + @KeyByString("proxy_type") + String getProxyType(); + + @KeyByString("proxy_type") + void setProxyType(String proxyType); @KeyByString("proxy_server") @RemoveMethod - void removeProxyServer(); + void removeProxyType(); + + @KeyByString("proxy_host") + String getProxyHost(); + + @KeyByString("proxy_host") + void setProxyHost(String proxyHost); + + @KeyByString("proxy_host") + @RemoveMethod + void removeProxyHost(); + + @KeyByString("proxy_port") + String getProxyPort(); + + @KeyByString("proxy_port") + void setProxyPort(String proxyPort); + + @KeyByString("proxy_port") + @RemoveMethod + void removeProxyPort(); + + @KeyByString("proxy_credentials") + @RegisterChangeListenerMethod + void registerProxyCredentialsListener(OnPreferenceValueChangedListener listener); + + @KeyByString("proxy_credentials") + @UnregisterChangeListenerMethod + void unregisterProxyCredentialsListener(OnPreferenceValueChangedListener listener); + + @KeyByString("proxy_credentials") + boolean getProxyCredentials(); + + @KeyByString("proxy_credentials") + void setProxyNeedsCredentials(boolean proxyNeedsCredentials); + + @KeyByString("proxy_credentials") + @RemoveMethod + void removeProxyCredentials(); + + @KeyByString("proxy_username") + String getProxyUsername(); + + @KeyByString("proxy_username") + void setProxyUsername(String proxyUsername); + + @KeyByString("proxy_username") + @RemoveMethod + void removeProxyUsername(); + + @KeyByString("proxy_password") + String getProxyPassword(); + + @KeyByString("proxy_password") + void setProxyPassword(String proxyPassword); + + @KeyByString("proxy_password") + @RemoveMethod + void removeProxyPassword(); @KeyByString("push_token") String getPushToken(); diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java new file mode 100644 index 000000000..b1b89f22b --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java @@ -0,0 +1,81 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.utils.preferences; + +import android.app.Dialog; +import android.content.Context; +import android.support.v7.app.AlertDialog; +import android.text.InputType; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +import com.nextcloud.talk.R; +import com.yarolegovich.mp.io.StandardUserInputModule; + +import java.util.ArrayList; +import java.util.List; + +public class MagicUserInputModule extends StandardUserInputModule { + + private List keysWithIntegerInput = new ArrayList<>(); + + public MagicUserInputModule(Context context) { + super(context); + } + + public MagicUserInputModule(Context context, List keysWithIntegerInput) { + super(context); + this.keysWithIntegerInput = keysWithIntegerInput; + } + + @Override + public void showEditTextInput( + String key, + CharSequence title, + CharSequence defaultValue, + final Listener listener) { + final View view = LayoutInflater.from(context).inflate(R.layout.dialog_edittext, null); + final EditText inputField = (EditText) view.findViewById(R.id.mp_text_input); + + if (defaultValue != null) { + inputField.setText(defaultValue); + inputField.setSelection(defaultValue.length()); + } + + if (keysWithIntegerInput.contains(key)) { + inputField.setInputType(InputType.TYPE_CLASS_NUMBER); + } + + final Dialog dialog = new AlertDialog.Builder(context) + .setTitle(title) + .setView(view) + .show(); + view.findViewById(R.id.mp_btn_confirm).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onInput(inputField.getText().toString()); + dialog.dismiss(); + } + }); + } + +} diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/json/ProxyTypeAdapter.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/json/ProxyTypeAdapter.java deleted file mode 100644 index f1e263b2a..000000000 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/json/ProxyTypeAdapter.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * Copyright (C) 2017 Mario Danic - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.nextcloud.talk.utils.preferences.json; - -import android.support.annotation.Nullable; -import android.util.Log; - -import com.bluelinelabs.logansquare.LoganSquare; - -import net.orange_box.storebox.adapters.base.BaseStringTypeAdapter; - -import java.io.IOException; - -public class ProxyTypeAdapter extends BaseStringTypeAdapter { - - private static final String TAG = "ProxyTypeAdapter"; - - @Nullable - @Override - public String adaptForPreferences(@Nullable ProxyPrefs value) { - if (value != null) { - try { - return LoganSquare.serialize(value); - } catch (IOException e) { - Log.d(TAG, "Failed to serialize proxy from preferences"); - } - } - return ""; - } - - @Nullable - @Override - public ProxyPrefs adaptFromPreferences(@Nullable String value) { - if (value != null) { - try { - return LoganSquare.parse(value, ProxyPrefs.class); - } catch (IOException e) { - Log.d(TAG, "Failed to parse proxy from preferences"); - } - } - return new ProxyPrefs(); - } -} diff --git a/app/src/main/res/layout/controller_settings.xml b/app/src/main/res/layout/controller_settings.xml index afe912e1f..896eb5958 100644 --- a/app/src/main/res/layout/controller_settings.xml +++ b/app/src/main/res/layout/controller_settings.xml @@ -19,8 +19,183 @@ ~ along with this program. If not, see . --> - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml new file mode 100644 index 000000000..d5abe5d16 --- /dev/null +++ b/app/src/main/res/values/arrays.xml @@ -0,0 +1,29 @@ + + + + + + No proxy + HTTP + DIRECT + SOCKS + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index b1c4af522..2cfeae4e3 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -15,6 +15,7 @@ 8dp 8dp 40dp + 80dp 20dp diff --git a/app/src/main/res/values/setup.xml b/app/src/main/res/values/setup.xml index dc1a2ce3d..91574306e 100644 --- a/app/src/main/res/values/setup.xml +++ b/app/src/main/res/values/setup.xml @@ -8,7 +8,10 @@ Nextcloud @color/per70white - https://push-notifications.nextcloud.com - \ No newline at end of file + + https://nextcloud.com/privacy/ + https://www.gnu.org/licenses/gpl-3.0.en.html + https://github.com/nextcloud/talk-android + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 12d25c569..437c7e798 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,4 +31,29 @@ Details Your SSL setup prevented us from connecting + + Proxy + proxy_type + Proxy type + proxy_host + Proxy host + proxy_port + Proxy port + proxy_username + proxy_password + Use credentials + proxy_credentials + Switch between accounts + Reauthorize + Remove account + Add a new account + + No proxy + Username + Password + About + Privacy + Get source code + License + GNU General Public License, Version 3