diff --git a/app/build.gradle b/app/build.gradle index d058ea692..392bbbfd9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -160,7 +160,7 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' - implementation 'androidx.biometric:biometric:1.0.0-alpha04' + implementation 'androidx.biometric:biometric:1.0.0-beta01' implementation "androidx.lifecycle:lifecycle-extensions:2.0.0" implementation 'androidx.multidex:multidex:2.0.1' @@ -212,7 +212,7 @@ dependencies { implementation 'me.zhanghai.android.effortlesspermissions:library:1.1.0' implementation 'org.apache.commons:commons-lang3:3.9' implementation 'com.github.wooplr:Spotlight:1.3' - implementation('com.github.mario:chatkit:a7c4f3c9ea', { + implementation('com.github.mario:chatkit:a183142049', { exclude group: 'com.facebook.fresco' }) diff --git a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.java b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.java deleted file mode 100644 index 737cd566a..000000000 --- a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * Copyright (C) 2017-2018 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.activities; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; -import android.view.WindowManager; -import android.webkit.SslErrorHandler; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import autodagger.AutoInjector; -import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.events.CertificateEvent; -import com.nextcloud.talk.utils.SecurityUtils; -import com.nextcloud.talk.utils.preferences.AppPreferences; -import com.nextcloud.talk.utils.ssl.MagicTrustManager; -import com.yarolegovich.lovelydialog.LovelyStandardDialog; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - -import javax.inject.Inject; -import java.security.cert.CertificateParsingException; -import java.security.cert.X509Certificate; -import java.text.DateFormat; -import java.util.List; - -@AutoInjector(NextcloudTalkApplication.class) -public class BaseActivity extends AppCompatActivity { - private static final String TAG = "BaseActivity"; - - @Inject - EventBus eventBus; - - @Inject - AppPreferences appPreferences; - - @Inject - Context context; - - @Override - protected void onCreate(Bundle savedInstanceState) { - NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); - super.onCreate(savedInstanceState); - } - - @Override - public void onResume() { - super.onResume(); - if (appPreferences.getIsScreenSecured()) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); - } else { - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE); - } - - if (appPreferences.getIsScreenLocked()) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - SecurityUtils.createKey(appPreferences.getScreenLockTimeout()); - } - } - } - - public void showCertificateDialog(X509Certificate cert, MagicTrustManager magicTrustManager, - @Nullable SslErrorHandler sslErrorHandler) { - DateFormat formatter = DateFormat.getDateInstance(DateFormat.LONG); - String validFrom = formatter.format(cert.getNotBefore()); - String validUntil = formatter.format(cert.getNotAfter()); - - String issuedBy = cert.getIssuerDN().toString(); - String issuedFor; - - try { - if (cert.getSubjectAlternativeNames() != null) { - StringBuilder stringBuilder = new StringBuilder(); - for (Object o : cert.getSubjectAlternativeNames()) { - List list = (List) o; - int type = (Integer) list.get(0); - if (type == 2) { - String name = (String) list.get(1); - stringBuilder.append("[").append(type).append("]").append(name).append(" "); - } - } - issuedFor = stringBuilder.toString(); - } else { - issuedFor = cert.getSubjectDN().getName(); - } - - @SuppressLint("StringFormatMatches") String dialogText = String.format(getResources() - .getString(R.string.nc_certificate_dialog_text), - issuedBy, issuedFor, validFrom, validUntil); - - new LovelyStandardDialog(this) - .setTopColorRes(R.color.nc_darkRed) - .setNegativeButtonColorRes(R.color.nc_darkRed) - .setPositiveButtonColorRes(R.color.colorPrimaryDark) - .setIcon(R.drawable.ic_security_white_24dp) - .setTitle(R.string.nc_certificate_dialog_title) - .setMessage(dialogText) - .setPositiveButton(R.string.nc_yes, v -> { - magicTrustManager.addCertInTrustStore(cert); - if (sslErrorHandler != null) { - sslErrorHandler.proceed(); - } - }) - .setNegativeButton(R.string.nc_no, view1 -> { - if (sslErrorHandler != null) { - sslErrorHandler.cancel(); - } - }) - .show(); - - } catch (CertificateParsingException e) { - Log.d(TAG, "Failed to parse the certificate"); - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onMessageEvent(CertificateEvent event) { - showCertificateDialog(event.getX509Certificate(), event.getMagicTrustManager(), event.getSslErrorHandler()); - } - - @Override - public void onStart() { - super.onStart(); - eventBus.register(this); - } - - @Override - public void onStop() { - super.onStop(); - eventBus.unregister(this); - } -} diff --git a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt new file mode 100644 index 000000000..006adc33d --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt @@ -0,0 +1,148 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2018 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.activities + +import android.annotation.SuppressLint +import android.content.Context +import android.os.Build +import android.os.Bundle +import android.util.Log +import android.view.WindowManager +import android.webkit.SslErrorHandler +import androidx.appcompat.app.AppCompatActivity +import autodagger.AutoInjector +import com.nextcloud.talk.R +import com.nextcloud.talk.application.NextcloudTalkApplication +import com.nextcloud.talk.events.CertificateEvent +import com.nextcloud.talk.utils.SecurityUtils +import com.nextcloud.talk.utils.preferences.AppPreferences +import com.nextcloud.talk.utils.ssl.MagicTrustManager +import com.yarolegovich.lovelydialog.LovelyStandardDialog +import org.greenrobot.eventbus.EventBus +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode +import java.security.cert.CertificateParsingException +import java.security.cert.X509Certificate +import java.text.DateFormat +import javax.inject.Inject + +@AutoInjector(NextcloudTalkApplication::class) +open class BaseActivity : AppCompatActivity() { + + @Inject + lateinit var eventBus: EventBus + + @Inject + lateinit var appPreferences: AppPreferences + + @Inject + lateinit var context: Context + + override fun onCreate(savedInstanceState: Bundle?) { + NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) + super.onCreate(savedInstanceState) + } + + public override fun onResume() { + super.onResume() + if (appPreferences.isScreenSecured) { + window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) + } + + if (appPreferences.isScreenLocked) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + SecurityUtils.createKey(appPreferences.screenLockTimeout) + } + } + } + + fun showCertificateDialog(cert: X509Certificate, magicTrustManager: MagicTrustManager, + sslErrorHandler: SslErrorHandler?) { + val formatter = DateFormat.getDateInstance(DateFormat.LONG) + val validFrom = formatter.format(cert.notBefore) + val validUntil = formatter.format(cert.notAfter) + + val issuedBy = cert.issuerDN.toString() + val issuedFor: String + + try { + if (cert.subjectAlternativeNames != null) { + val stringBuilder = StringBuilder() + for (o in cert.subjectAlternativeNames) { + val list = o as List<*> + val type = list[0] as Int + if (type == 2) { + val name = list[1] as String + stringBuilder.append("[").append(type).append("]").append(name).append(" ") + } + } + issuedFor = stringBuilder.toString() + } else { + issuedFor = cert.subjectDN.name + } + + @SuppressLint("StringFormatMatches") val dialogText = String.format(resources + .getString(R.string.nc_certificate_dialog_text), + issuedBy, issuedFor, validFrom, validUntil) + + LovelyStandardDialog(this) + .setTopColorRes(R.color.nc_darkRed) + .setNegativeButtonColorRes(R.color.nc_darkRed) + .setPositiveButtonColorRes(R.color.colorPrimaryDark) + .setIcon(R.drawable.ic_security_white_24dp) + .setTitle(R.string.nc_certificate_dialog_title) + .setMessage(dialogText) + .setPositiveButton(R.string.nc_yes) { v -> + magicTrustManager.addCertInTrustStore(cert) + sslErrorHandler?.proceed() + } + .setNegativeButton(R.string.nc_no) { view1 -> + sslErrorHandler?.cancel() + } + .show() + + } catch (e: CertificateParsingException) { + Log.d(TAG, "Failed to parse the certificate") + } + + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onMessageEvent(event: CertificateEvent) { + showCertificateDialog(event.x509Certificate, event.magicTrustManager, event.sslErrorHandler) + } + + public override fun onStart() { + super.onStart() + eventBus.register(this) + } + + public override fun onStop() { + super.onStop() + eventBus.unregister(this) + } + + companion object { + private val TAG = "BaseActivity" + } +} diff --git a/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.java deleted file mode 100644 index b0e9cbddf..000000000 --- a/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * Copyright (C) 2017-2018 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.activities; - -import android.content.res.Configuration; -import android.os.Bundle; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import autodagger.AutoInjector; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.bluelinelabs.conductor.Conductor; -import com.bluelinelabs.conductor.Router; -import com.bluelinelabs.conductor.RouterTransaction; -import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler; -import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.controllers.CallController; -import com.nextcloud.talk.controllers.CallNotificationController; -import com.nextcloud.talk.events.ConfigurationChangeEvent; -import com.nextcloud.talk.utils.bundle.BundleKeys; -import org.greenrobot.eventbus.EventBus; - -import javax.inject.Inject; - -@AutoInjector(NextcloudTalkApplication.class) -public class MagicCallActivity extends BaseActivity { - private static final String TAG = "MagicCallActivity"; - - @Inject - EventBus eventBus; - - @BindView(R.id.controller_container) - ViewGroup container; - - private Router router; - - private static int getSystemUiVisibility() { - int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; - flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; - return flags; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); - - requestWindowFeature(Window.FEATURE_NO_TITLE); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | - WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | - WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | - WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - getWindow().getDecorView().setSystemUiVisibility(getSystemUiVisibility()); - - setContentView(R.layout.activity_magic_call); - - ButterKnife.bind(this); - router = Conductor.attachRouter(this, container, savedInstanceState); - router.setPopsLastView(false); - - if (!router.hasRootController()) { - if (getIntent().getBooleanExtra(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL(), false)) { - router.setRoot(RouterTransaction.with(new CallNotificationController(getIntent().getExtras())) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); - } else { - router.setRoot(RouterTransaction.with(new CallController(getIntent().getExtras())) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); - } - } - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - eventBus.post(new ConfigurationChangeEvent()); - } -} diff --git a/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.kt new file mode 100644 index 000000000..0a864f24b --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.kt @@ -0,0 +1,96 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2018 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.activities + +import android.content.res.Configuration +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import android.view.Window +import android.view.WindowManager +import autodagger.AutoInjector +import butterknife.BindView +import butterknife.ButterKnife +import com.bluelinelabs.conductor.Conductor +import com.bluelinelabs.conductor.Router +import com.bluelinelabs.conductor.RouterTransaction +import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler +import com.nextcloud.talk.R +import com.nextcloud.talk.application.NextcloudTalkApplication +import com.nextcloud.talk.controllers.CallController +import com.nextcloud.talk.controllers.CallNotificationController +import com.nextcloud.talk.events.ConfigurationChangeEvent +import com.nextcloud.talk.utils.bundle.BundleKeys + +@AutoInjector(NextcloudTalkApplication::class) +class MagicCallActivity : BaseActivity() { + + @BindView(R.id.controller_container) + lateinit var container: ViewGroup + + private var router: Router? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) + + requestWindowFeature(Window.FEATURE_NO_TITLE) + window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN or + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) + window.decorView.systemUiVisibility = systemUiVisibility + + setContentView(R.layout.activity_magic_call) + + ButterKnife.bind(this) + router = Conductor.attachRouter(this, container, savedInstanceState) + router!!.setPopsLastView(false) + + if (!router!!.hasRootController()) { + if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) { + router!!.setRoot(RouterTransaction.with(CallNotificationController(intent.extras)) + .pushChangeHandler(HorizontalChangeHandler()) + .popChangeHandler(HorizontalChangeHandler())) + } else { + router!!.setRoot(RouterTransaction.with(CallController(intent.extras)) + .pushChangeHandler(HorizontalChangeHandler()) + .popChangeHandler(HorizontalChangeHandler())) + } + } + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + eventBus.post(ConfigurationChangeEvent()) + } + + companion object { + private val TAG = "MagicCallActivity" + + private val systemUiVisibility: Int + get() { + var flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN + flags = flags or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + return flags + } + } +} diff --git a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.java b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.java deleted file mode 100644 index 1e3f831c0..000000000 --- a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * - * Nextcloud Talk application - * - * @author Mario Danic - * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com) - * - * 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.activities; - -import android.app.KeyguardManager; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.os.Bundle; -import android.view.ViewGroup; -import androidx.annotation.RequiresApi; -import androidx.appcompat.widget.Toolbar; -import autodagger.AutoInjector; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.bluelinelabs.conductor.Conductor; -import com.bluelinelabs.conductor.Router; -import com.bluelinelabs.conductor.RouterTransaction; -import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler; -import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler; -import com.google.android.material.appbar.MaterialToolbar; -import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.controllers.CallNotificationController; -import com.nextcloud.talk.controllers.ConversationsListController; -import com.nextcloud.talk.controllers.LockedController; -import com.nextcloud.talk.controllers.ServerSelectionController; -import com.nextcloud.talk.controllers.base.providers.ActionBarProvider; -import com.nextcloud.talk.utils.ConductorRemapping; -import com.nextcloud.talk.utils.SecurityUtils; -import com.nextcloud.talk.utils.bundle.BundleKeys; -import com.nextcloud.talk.utils.database.user.UserUtils; -import io.requery.Persistable; -import io.requery.android.sqlcipher.SqlCipherDatabaseSource; -import io.requery.reactivex.ReactiveEntityStore; - -import javax.inject.Inject; - -@AutoInjector(NextcloudTalkApplication.class) -public final class MainActivity extends BaseActivity implements ActionBarProvider { - private static final String TAG = "MainActivity"; - - @BindView(R.id.toolbar) - MaterialToolbar toolbar; - @BindView(R.id.controller_container) - ViewGroup container; - - @Inject - UserUtils userUtils; - @Inject - ReactiveEntityStore dataStore; - @Inject - SqlCipherDatabaseSource sqlCipherDatabaseSource; - - private Router router; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.activity_main); - - NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); - ButterKnife.bind(this); - - setSupportActionBar(toolbar); - - router = Conductor.attachRouter(this, container, savedInstanceState); - - boolean hasDb = true; - - try { - sqlCipherDatabaseSource.getWritableDatabase(); - } catch (Exception exception) { - hasDb = false; - } - - if (getIntent().hasExtra(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) { - if (!router.hasRootController()) { - router.setRoot(RouterTransaction.with(new ConversationsListController()) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); - } - onNewIntent(getIntent()); - } else if (!router.hasRootController()) { - if (hasDb) { - if (userUtils.anyUserExists()) { - router.setRoot(RouterTransaction.with(new ConversationsListController()) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); - } else { - router.setRoot(RouterTransaction.with(new ServerSelectionController()) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); - } - } else { - router.setRoot(RouterTransaction.with(new ServerSelectionController()) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); - - } - } - } - - @Override - public void onStart() { - super.onStart(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - checkIfWeAreSecure(); - } - } - - - @RequiresApi(api = Build.VERSION_CODES.M) - public void checkIfWeAreSecure() { - KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); - if (keyguardManager != null && keyguardManager.isKeyguardSecure() && appPreferences.getIsScreenLocked()) { - if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.getScreenLockTimeout())) { - if (router != null && router.getControllerWithTag(LockedController.TAG) == null) { - router.pushController(RouterTransaction.with(new LockedController()) - .pushChangeHandler(new VerticalChangeHandler()) - .popChangeHandler(new VerticalChangeHandler()) - .tag(LockedController.TAG)); - } - } - } - } - - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - - if (intent.hasExtra(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) { - if (intent.getBooleanExtra(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL(), false)) { - router.pushController(RouterTransaction.with(new CallNotificationController(intent.getExtras())) - .pushChangeHandler(new HorizontalChangeHandler()) - .popChangeHandler(new HorizontalChangeHandler())); - } else { - ConductorRemapping.INSTANCE.remapChatController(router, intent.getLongExtra(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1), - intent.getStringExtra(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN()), intent.getExtras(), false); - ; - } - } - } - - @Override - public void onBackPressed() { - if (router.getControllerWithTag(LockedController.TAG) != null) { - return; - } - - if (!router.handleBack()) { - super.onBackPressed(); - } - } -} diff --git a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt new file mode 100644 index 000000000..00a7f618d --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt @@ -0,0 +1,171 @@ +/* + * + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com) + * + * 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.activities + +import android.app.KeyguardManager +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.Bundle +import android.view.ViewGroup +import androidx.annotation.RequiresApi +import autodagger.AutoInjector +import butterknife.BindView +import butterknife.ButterKnife +import com.bluelinelabs.conductor.Conductor +import com.bluelinelabs.conductor.Router +import com.bluelinelabs.conductor.RouterTransaction +import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler +import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler +import com.google.android.material.appbar.MaterialToolbar +import com.nextcloud.talk.R +import com.nextcloud.talk.application.NextcloudTalkApplication +import com.nextcloud.talk.controllers.CallNotificationController +import com.nextcloud.talk.controllers.ConversationsListController +import com.nextcloud.talk.controllers.LockedController +import com.nextcloud.talk.controllers.ServerSelectionController +import com.nextcloud.talk.controllers.base.providers.ActionBarProvider +import com.nextcloud.talk.utils.ConductorRemapping +import com.nextcloud.talk.utils.SecurityUtils +import com.nextcloud.talk.utils.bundle.BundleKeys +import com.nextcloud.talk.utils.database.user.UserUtils +import io.requery.Persistable +import io.requery.android.sqlcipher.SqlCipherDatabaseSource +import io.requery.reactivex.ReactiveEntityStore +import javax.inject.Inject + +@AutoInjector(NextcloudTalkApplication::class) +class MainActivity : BaseActivity(), ActionBarProvider { + + @BindView(R.id.toolbar) + lateinit var toolbar: MaterialToolbar + @BindView(R.id.controller_container) + lateinit var container: ViewGroup + + @Inject + lateinit var userUtils: UserUtils + @Inject + lateinit var dataStore: ReactiveEntityStore + @Inject + lateinit var sqlCipherDatabaseSource: SqlCipherDatabaseSource + + private var router: Router? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContentView(R.layout.activity_main) + + NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) + ButterKnife.bind(this) + + setSupportActionBar(toolbar) + + router = Conductor.attachRouter(this, container, savedInstanceState) + + var hasDb = true + + try { + sqlCipherDatabaseSource.writableDatabase + } catch (exception: Exception) { + hasDb = false + } + + if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) { + if (!router!!.hasRootController()) { + router!!.setRoot(RouterTransaction.with(ConversationsListController()) + .pushChangeHandler(HorizontalChangeHandler()) + .popChangeHandler(HorizontalChangeHandler())) + } + onNewIntent(intent) + } else if (!router!!.hasRootController()) { + if (hasDb) { + if (userUtils.anyUserExists()) { + router!!.setRoot(RouterTransaction.with(ConversationsListController()) + .pushChangeHandler(HorizontalChangeHandler()) + .popChangeHandler(HorizontalChangeHandler())) + } else { + router!!.setRoot(RouterTransaction.with(ServerSelectionController()) + .pushChangeHandler(HorizontalChangeHandler()) + .popChangeHandler(HorizontalChangeHandler())) + } + } else { + router!!.setRoot(RouterTransaction.with(ServerSelectionController()) + .pushChangeHandler(HorizontalChangeHandler()) + .popChangeHandler(HorizontalChangeHandler())) + + } + } + } + + override fun onStart() { + super.onStart() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + checkIfWeAreSecure() + } + } + + + @RequiresApi(api = Build.VERSION_CODES.M) + fun checkIfWeAreSecure() { + val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager + if (keyguardManager.isKeyguardSecure && appPreferences.isScreenLocked) { + if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)) { + if (router != null && router!!.getControllerWithTag(LockedController.TAG) == null) { + router!!.pushController(RouterTransaction.with(LockedController()) + .pushChangeHandler(VerticalChangeHandler()) + .popChangeHandler(VerticalChangeHandler()) + .tag(LockedController.TAG)) + } + } + } + } + + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + + if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) { + if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) { + router!!.pushController(RouterTransaction.with(CallNotificationController(intent.extras)) + .pushChangeHandler(HorizontalChangeHandler()) + .popChangeHandler(HorizontalChangeHandler())) + } else { + ConductorRemapping.remapChatController(router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1), + intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.extras!!, false) + } + } + } + + override fun onBackPressed() { + if (router!!.getControllerWithTag(LockedController.TAG) != null) { + return + } + + if (!router!!.handleBack()) { + super.onBackPressed() + } + } + + companion object { + private val TAG = "MainActivity" + } +} diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallController.java b/app/src/main/java/com/nextcloud/talk/controllers/CallController.java index 89e96636f..28a34350e 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/CallController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/CallController.java @@ -1118,9 +1118,9 @@ public class CallController extends BaseController { } if (!conversationUser.hasSpreedFeatureCapability("no-ping") && !TextUtils.isEmpty(roomId)) { - NotificationUtils.cancelExistingNotificationsForRoom(getApplicationContext(), conversationUser, roomId); + NotificationUtils.INSTANCE.cancelExistingNotificationsForRoom(getApplicationContext(), conversationUser, roomId); } else if (!TextUtils.isEmpty(roomToken)) { - NotificationUtils.cancelExistingNotificationsForRoom(getApplicationContext(), conversationUser, roomToken); + NotificationUtils.INSTANCE.cancelExistingNotificationsForRoom(getApplicationContext(), conversationUser, roomToken); } if (!hasExternalSignalingServer) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java index ebc30713e..423532251 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java @@ -701,9 +701,9 @@ public class ChatController extends BaseController implements MessagesListAdapte private void cancelNotificationsForCurrentConversation() { if (!conversationUser.hasSpreedFeatureCapability("no-ping") && !TextUtils.isEmpty(roomId)) { - NotificationUtils.cancelExistingNotificationsForRoom(getApplicationContext(), conversationUser, roomId); + NotificationUtils.INSTANCE.cancelExistingNotificationsForRoom(getApplicationContext(), conversationUser, roomId); } else if (!TextUtils.isEmpty(roomToken)) { - NotificationUtils.cancelExistingNotificationsForRoom(getApplicationContext(), conversationUser, roomToken); + NotificationUtils.INSTANCE.cancelExistingNotificationsForRoom(getApplicationContext(), conversationUser, roomToken); } } @@ -1160,7 +1160,6 @@ public class ChatController extends BaseController implements MessagesListAdapte unreadChatMessage.setTimestamp(chatMessageList.get(0).getTimestamp()); unreadChatMessage.setMessage(context.getString(R.string.nc_new_messages)); adapter.addToStart(unreadChatMessage, false); - layoutManager.scrollToPosition(chatMessageList.size() - 1); } for (int i = 0; i < chatMessageList.size(); i++) { @@ -1200,6 +1199,10 @@ public class ChatController extends BaseController implements MessagesListAdapte } + if (shouldAddNewMessagesNotice && adapter != null) { + layoutManager.scrollToPositionWithOffset(adapter.getMessagePositionByIdInReverse("-1"), messagesListView.getHeight() / 2); + } + String xChatLastGivenHeader; if (response.headers().size() > 0 && !TextUtils.isEmpty((xChatLastGivenHeader = response.headers().get ("X-Chat-Last-Given")))) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/ButterKnifeController.java b/app/src/main/java/com/nextcloud/talk/controllers/base/ButterKnifeController.java deleted file mode 100644 index 54ee017f8..000000000 --- a/app/src/main/java/com/nextcloud/talk/controllers/base/ButterKnifeController.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Nextcloud Talk application - * - * @author BlueLine Labs, Inc. - * Copyright (C) 2016 BlueLine Labs, Inc. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.nextcloud.talk.controllers.base; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import androidx.annotation.NonNull; -import butterknife.ButterKnife; -import butterknife.Unbinder; -import com.bluelinelabs.conductor.Controller; - -public abstract class ButterKnifeController extends Controller { - - private Unbinder unbinder; - - public ButterKnifeController() { - } - - public ButterKnifeController(Bundle args) { - super(args); - } - - protected abstract View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container); - - @NonNull - @Override - protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) { - View view = inflateView(inflater, container); - unbinder = ButterKnife.bind(this, view); - onViewBound(view); - return view; - } - - protected void onViewBound(@NonNull View view) { - } - - @Override - protected void onDestroyView(@NonNull View view) { - super.onDestroyView(view); - unbinder.unbind(); - unbinder = null; - } - -} diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/ButterKnifeController.kt b/app/src/main/java/com/nextcloud/talk/controllers/base/ButterKnifeController.kt new file mode 100644 index 000000000..630219e24 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/controllers/base/ButterKnifeController.kt @@ -0,0 +1,57 @@ +/** + * Nextcloud Talk application + * + * @author BlueLine Labs, Inc. + * Copyright (C) 2016 BlueLine Labs, Inc. + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.nextcloud.talk.controllers.base + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import butterknife.ButterKnife +import butterknife.Unbinder +import com.bluelinelabs.conductor.Controller + +abstract class ButterKnifeController : Controller { + + private var unbinder: Unbinder? = null + + constructor() {} + + constructor(args: Bundle) : super(args) {} + + protected abstract fun inflateView(inflater: LayoutInflater, container: ViewGroup): View + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View { + val view = inflateView(inflater, container) + unbinder = ButterKnife.bind(this, view) + onViewBound(view) + return view + } + + protected open fun onViewBound(view: View) {} + + override fun onDestroyView(view: View) { + super.onDestroyView(view) + unbinder!!.unbind() + unbinder = null + } + +} diff --git a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java index b929e905c..626d4b59e 100644 --- a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java +++ b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java @@ -343,21 +343,21 @@ public class NotificationWorker extends Worker { groupName);*/ if (decryptedPushMessage.getType().equals("chat") || decryptedPushMessage.getType().equals("room")) { - NotificationUtils.createNotificationChannel(context, - NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES_V3, context.getResources() + NotificationUtils.INSTANCE.createNotificationChannel(context, + NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_MESSAGES_V3(), context.getResources() .getString(R.string.nc_notification_channel_messages), context.getResources() .getString(R.string.nc_notification_channel_messages), true, NotificationManager.IMPORTANCE_HIGH); - notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES_V3); + notificationBuilder.setChannelId(NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_MESSAGES_V3()); } else { - NotificationUtils.createNotificationChannel(context, - NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V3, context.getResources() + NotificationUtils.INSTANCE.createNotificationChannel(context, + NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_CALLS_V3(), context.getResources() .getString(R.string.nc_notification_channel_calls), context.getResources() .getString(R.string.nc_notification_channel_calls_description), true, NotificationManager.IMPORTANCE_HIGH); - notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V3); + notificationBuilder.setChannelId(NotificationUtils.INSTANCE.getNOTIFICATION_CHANNEL_CALLS_V3()); } } else { @@ -380,7 +380,7 @@ public class NotificationWorker extends Worker { crc32.update(stringForCrc.getBytes()); StatusBarNotification activeStatusBarNotification = - NotificationUtils.findNotificationForRoom(context, + NotificationUtils.INSTANCE.findNotificationForRoom(context, signatureVerification.getUserEntity(), decryptedPushMessage.getId()); int notificationId; @@ -562,9 +562,9 @@ public class NotificationWorker extends Worker { decryptedPushMessage.setTimestamp(System.currentTimeMillis()); if (decryptedPushMessage.isDelete()) { - NotificationUtils.cancelExistingNotificationWithId(context, signatureVerification.getUserEntity(), decryptedPushMessage.getNotificationId()); + NotificationUtils.INSTANCE.cancelExistingNotificationWithId(context, signatureVerification.getUserEntity(), decryptedPushMessage.getNotificationId()); } else if (decryptedPushMessage.isDeleteAll()) { - NotificationUtils.cancelAllNotificationsForAccount(context, signatureVerification.getUserEntity()); + NotificationUtils.INSTANCE.cancelAllNotificationsForAccount(context, signatureVerification.getUserEntity()); } else { credentials = ApiUtils.getCredentials(signatureVerification.getUserEntity().getUsername(), signatureVerification.getUserEntity().getToken()); diff --git a/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.java b/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.java deleted file mode 100644 index 28fba9729..000000000 --- a/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * Copyright (C) 2017-2018 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.receivers; - -import android.app.NotificationChannelGroup; -import android.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.os.Build; -import android.util.Log; -import autodagger.AutoInjector; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.utils.NotificationUtils; -import com.nextcloud.talk.utils.database.user.UserUtils; -import com.nextcloud.talk.utils.preferences.AppPreferences; - -import javax.inject.Inject; - -@AutoInjector(NextcloudTalkApplication.class) -public class PackageReplacedReceiver extends BroadcastReceiver { - private static final String TAG = "PackageReplacedReceiver"; - - @Inject - UserUtils userUtils; - - @Inject - AppPreferences appPreferences; - - @Override - public void onReceive(Context context, Intent intent) { - NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); - - if (intent != null && intent.getAction() != null && - intent.getAction().equals("android.intent.action.MY_PACKAGE_REPLACED")) { - try { - PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); - if (packageInfo.versionCode > 43 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context - .NOTIFICATION_SERVICE); - - if (notificationManager != null) { - if (!appPreferences.getIsNotificationChannelUpgradedToV2()) { - for (NotificationChannelGroup notificationChannelGroup : notificationManager - .getNotificationChannelGroups()) { - notificationManager.deleteNotificationChannelGroup(notificationChannelGroup.getId()); - } - - notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_CALLS); - notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES); - - appPreferences.setNotificationChannelIsUpgradedToV2(true); - } - - if ((!appPreferences.getIsNotificationChannelUpgradedToV3()) && packageInfo.versionCode > 51) { - notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES_V2); - notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V2); - appPreferences.setNotificationChannelIsUpgradedToV3(true); - } - } - - } - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Failed to fetch package info"); - } - } - } -} diff --git a/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.kt b/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.kt new file mode 100644 index 000000000..c0c77303e --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.kt @@ -0,0 +1,91 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2018 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.receivers + +import android.app.NotificationChannelGroup +import android.app.NotificationManager +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import android.os.Build +import android.util.Log +import autodagger.AutoInjector +import com.nextcloud.talk.application.NextcloudTalkApplication +import com.nextcloud.talk.utils.NotificationUtils +import com.nextcloud.talk.utils.database.user.UserUtils +import com.nextcloud.talk.utils.preferences.AppPreferences + +import javax.inject.Inject + +@AutoInjector(NextcloudTalkApplication::class) +class PackageReplacedReceiver : BroadcastReceiver() { + + @Inject + lateinit var userUtils: UserUtils + + @Inject + lateinit var appPreferences: AppPreferences + + override fun onReceive(context: Context, intent: Intent?) { + NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) + + if (intent != null && intent.action != null && + intent.action == "android.intent.action.MY_PACKAGE_REPLACED") { + try { + val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0) + if (packageInfo.versionCode > 43 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val notificationManager = context.getSystemService(Context + .NOTIFICATION_SERVICE) as NotificationManager + + if (notificationManager != null) { + if (!appPreferences!!.isNotificationChannelUpgradedToV2) { + for (notificationChannelGroup in notificationManager + .notificationChannelGroups) { + notificationManager.deleteNotificationChannelGroup(notificationChannelGroup.id) + } + + notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_CALLS) + notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES) + + appPreferences!!.setNotificationChannelIsUpgradedToV2(true) + } + + if (!appPreferences!!.isNotificationChannelUpgradedToV3 && packageInfo.versionCode > 51) { + notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES_V2) + notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V2) + appPreferences!!.setNotificationChannelIsUpgradedToV3(true) + } + } + + } + } catch (e: PackageManager.NameNotFoundException) { + Log.e(TAG, "Failed to fetch package info") + } + + } + } + + companion object { + private val TAG = "PackageReplacedReceiver" + } +} diff --git a/app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.java b/app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.java deleted file mode 100644 index 9f679fd3d..000000000 --- a/app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.java +++ /dev/null @@ -1,185 +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; - -import android.annotation.TargetApi; -import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationChannelGroup; -import android.app.NotificationManager; -import android.content.Context; -import android.os.Build; -import android.service.notification.StatusBarNotification; -import android.text.TextUtils; - -import com.nextcloud.talk.R; -import com.nextcloud.talk.models.database.UserEntity; -import com.nextcloud.talk.utils.bundle.BundleKeys; - -import java.util.zip.CRC32; - -public class NotificationUtils { - public static final String NOTIFICATION_CHANNEL_CALLS = "NOTIFICATION_CHANNEL_CALLS"; - public static final String NOTIFICATION_CHANNEL_MESSAGES = "NOTIFICATION_CHANNEL_MESSAGES"; - public static final String NOTIFICATION_CHANNEL_CALLS_V2 = "NOTIFICATION_CHANNEL_CALLS_V2"; - public static final String NOTIFICATION_CHANNEL_MESSAGES_V2 = "NOTIFICATION_CHANNEL_MESSAGES_V2"; - public static final String NOTIFICATION_CHANNEL_MESSAGES_V3 = "NOTIFICATION_CHANNEL_MESSAGES_V3"; - public static final String NOTIFICATION_CHANNEL_CALLS_V3 = "NOTIFICATION_CHANNEL_CALLS_V3"; - - @TargetApi(Build.VERSION_CODES.O) - public static void createNotificationChannel(Context context, - String channelId, String channelName, - String channelDescription, boolean enableLights, - int importance) { - - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O - && notificationManager.getNotificationChannel(channelId) == null) { - - NotificationChannel channel = new NotificationChannel(channelId, channelName, - importance); - - channel.setDescription(channelDescription); - channel.enableLights(enableLights); - channel.setLightColor(R.color.colorPrimary); - channel.setSound(null, null); - - notificationManager.createNotificationChannel(channel); - } - } - - @TargetApi(Build.VERSION_CODES.O) - public static void createNotificationChannelGroup(Context context, - String groupId, CharSequence groupName) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - - NotificationChannelGroup notificationChannelGroup = new NotificationChannelGroup(groupId, groupName); - if (!notificationManager.getNotificationChannelGroups().contains(notificationChannelGroup)) { - notificationManager.createNotificationChannelGroup(notificationChannelGroup); - } - } - } - - public static void cancelAllNotificationsForAccount(Context context, UserEntity conversationUser) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M && conversationUser.getId() != -1 && - context != null) { - - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - - if (notificationManager != null) { - StatusBarNotification[] statusBarNotifications = notificationManager.getActiveNotifications(); - Notification notification; - for (StatusBarNotification statusBarNotification : statusBarNotifications) { - notification = statusBarNotification.getNotification(); - - if (notification != null && !notification.extras.isEmpty()) { - if (conversationUser.getId() == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID())) { - notificationManager.cancel(statusBarNotification.getId()); - } - } - } - } - } - - } - - public static void cancelExistingNotificationWithId(Context context, UserEntity conversationUser, long notificationId) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M && conversationUser.getId() != -1 && - context != null) { - - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - - if (notificationManager != null) { - StatusBarNotification[] statusBarNotifications = notificationManager.getActiveNotifications(); - Notification notification; - for (StatusBarNotification statusBarNotification : statusBarNotifications) { - notification = statusBarNotification.getNotification(); - - if (notification != null && !notification.extras.isEmpty()) { - if (conversationUser.getId() == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()) && - notificationId == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_NOTIFICATION_ID())) { - notificationManager.cancel(statusBarNotification.getId()); - } - } - } - } - } - } - - public static StatusBarNotification findNotificationForRoom(Context context, - UserEntity conversationUser, - String roomTokenOrId) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M && conversationUser.getId() != -1 && - context != null) { - - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - - if (notificationManager != null) { - StatusBarNotification[] statusBarNotifications = notificationManager.getActiveNotifications(); - Notification notification; - for (StatusBarNotification statusBarNotification : statusBarNotifications) { - notification = statusBarNotification.getNotification(); - - if (notification != null && !notification.extras.isEmpty()) { - if (conversationUser.getId() == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()) && - roomTokenOrId.equals(statusBarNotification.getNotification().extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN()))) { - return statusBarNotification; - } - } - } - } - } - - return null; - } - - public static void cancelExistingNotificationsForRoom(Context context, UserEntity conversationUser, - String roomTokenOrId) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M && conversationUser.getId() != -1 && - context != null) { - - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - - if (notificationManager != null) { - StatusBarNotification[] statusBarNotifications = notificationManager.getActiveNotifications(); - Notification notification; - for (StatusBarNotification statusBarNotification : statusBarNotifications) { - notification = statusBarNotification.getNotification(); - - if (notification != null && !notification.extras.isEmpty()) { - if (conversationUser.getId() == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()) && - roomTokenOrId.equals(statusBarNotification.getNotification().extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN()))) { - notificationManager.cancel(statusBarNotification.getId()); - } - } - } - } - } - } -} diff --git a/app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.kt new file mode 100644 index 000000000..876919ee8 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.kt @@ -0,0 +1,162 @@ +/* + * 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 + +import android.annotation.TargetApi +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationChannelGroup +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import android.service.notification.StatusBarNotification +import com.nextcloud.talk.R +import com.nextcloud.talk.models.database.UserEntity +import com.nextcloud.talk.utils.bundle.BundleKeys + +object NotificationUtils { + val NOTIFICATION_CHANNEL_CALLS = "NOTIFICATION_CHANNEL_CALLS" + val NOTIFICATION_CHANNEL_MESSAGES = "NOTIFICATION_CHANNEL_MESSAGES" + val NOTIFICATION_CHANNEL_CALLS_V2 = "NOTIFICATION_CHANNEL_CALLS_V2" + val NOTIFICATION_CHANNEL_MESSAGES_V2 = "NOTIFICATION_CHANNEL_MESSAGES_V2" + val NOTIFICATION_CHANNEL_MESSAGES_V3 = "NOTIFICATION_CHANNEL_MESSAGES_V3" + val NOTIFICATION_CHANNEL_CALLS_V3 = "NOTIFICATION_CHANNEL_CALLS_V3" + + @TargetApi(Build.VERSION_CODES.O) + fun createNotificationChannel(context: Context, + channelId: String, channelName: String, + channelDescription: String, enableLights: Boolean, + importance: Int) { + + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O && notificationManager.getNotificationChannel(channelId) == null) { + + val channel = NotificationChannel(channelId, channelName, + importance) + + channel.description = channelDescription + channel.enableLights(enableLights) + channel.lightColor = R.color.colorPrimary + channel.setSound(null, null) + + notificationManager.createNotificationChannel(channel) + } + } + + @TargetApi(Build.VERSION_CODES.O) + fun createNotificationChannelGroup(context: Context, + groupId: String, groupName: CharSequence) { + if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + val notificationChannelGroup = NotificationChannelGroup(groupId, groupName) + if (!notificationManager.notificationChannelGroups.contains(notificationChannelGroup)) { + notificationManager.createNotificationChannelGroup(notificationChannelGroup) + } + } + } + + fun cancelAllNotificationsForAccount(context: Context?, conversationUser: UserEntity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L && context != null) { + + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + val statusBarNotifications = notificationManager.activeNotifications + var notification: Notification? + for (statusBarNotification in statusBarNotifications) { + notification = statusBarNotification.notification + + if (notification != null && !notification.extras.isEmpty) { + if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID)) { + notificationManager.cancel(statusBarNotification.id) + } + } + } + } + + } + + fun cancelExistingNotificationWithId(context: Context?, conversationUser: UserEntity, notificationId: Long) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L && + context != null) { + + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + val statusBarNotifications = notificationManager.activeNotifications + var notification: Notification? + for (statusBarNotification in statusBarNotifications) { + notification = statusBarNotification.notification + + if (notification != null && !notification.extras.isEmpty) { + if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) && notificationId == notification.extras.getLong(BundleKeys.KEY_NOTIFICATION_ID)) { + notificationManager.cancel(statusBarNotification.id) + } + } + } + } + } + + fun findNotificationForRoom(context: Context?, + conversationUser: UserEntity, + roomTokenOrId: String): StatusBarNotification? { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L && + context != null) { + + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + val statusBarNotifications = notificationManager.activeNotifications + var notification: Notification? + for (statusBarNotification in statusBarNotifications) { + notification = statusBarNotification.notification + + if (notification != null && !notification.extras.isEmpty) { + if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) && roomTokenOrId == statusBarNotification.notification.extras.getString(BundleKeys.KEY_ROOM_TOKEN)) { + return statusBarNotification + } + } + } + } + + return null + } + + fun cancelExistingNotificationsForRoom(context: Context?, conversationUser: UserEntity, + roomTokenOrId: String) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L && + context != null) { + + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + val statusBarNotifications = notificationManager.activeNotifications + var notification: Notification? + for (statusBarNotification in statusBarNotifications) { + notification = statusBarNotification.notification + + if (notification != null && !notification.extras.isEmpty) { + if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) && roomTokenOrId == statusBarNotification.notification.extras.getString(BundleKeys.KEY_ROOM_TOKEN)) { + notificationManager.cancel(statusBarNotification.id) + } + } + } + } + } +}