mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 20:55:10 +00:00
Convert MainActivity to Kotlin.
This commit is contained in:
committed by
Cody Henthorne
parent
e22c403b10
commit
bf83914357
@@ -1,305 +0,0 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import org.signal.core.util.BundleExtensions;
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable;
|
||||
import org.signal.donations.StripeApi;
|
||||
import org.thoughtcrime.securesms.calls.YouAreAlreadyInACallSnackbar;
|
||||
import org.thoughtcrime.securesms.components.ConnectivityWarningBottomSheet;
|
||||
import org.thoughtcrime.securesms.components.DebugLogsPromptDialogFragment;
|
||||
import org.thoughtcrime.securesms.components.DeviceSpecificNotificationBottomSheet;
|
||||
import org.thoughtcrime.securesms.components.PromptBatterySaverDialogFragment;
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity;
|
||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaController;
|
||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaControllerOwner;
|
||||
import org.thoughtcrime.securesms.conversationlist.RelinkDevicesReminderBottomSheetFragment;
|
||||
import org.thoughtcrime.securesms.conversationlist.RestoreCompleteBottomSheetDialog;
|
||||
import org.thoughtcrime.securesms.devicetransfer.olddevice.OldDeviceExitActivity;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.net.DeviceTransferBlockingInterceptor;
|
||||
import org.thoughtcrime.securesms.notifications.VitalsViewModel;
|
||||
import org.thoughtcrime.securesms.stories.Stories;
|
||||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTab;
|
||||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabRepository;
|
||||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel;
|
||||
import org.thoughtcrime.securesms.util.AppStartup;
|
||||
import org.thoughtcrime.securesms.util.CachedInflater;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.SplashScreenUtil;
|
||||
import org.thoughtcrime.securesms.util.WindowUtil;
|
||||
|
||||
public class MainActivity extends PassphraseRequiredActivity implements VoiceNoteMediaControllerOwner {
|
||||
|
||||
private static final String KEY_STARTING_TAB = "STARTING_TAB";
|
||||
public static final int RESULT_CONFIG_CHANGED = Activity.RESULT_FIRST_USER + 901;
|
||||
|
||||
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
|
||||
private final MainNavigator navigator = new MainNavigator(this);
|
||||
|
||||
private VoiceNoteMediaController mediaController;
|
||||
private ConversationListTabsViewModel conversationListTabsViewModel;
|
||||
private VitalsViewModel vitalsViewModel;
|
||||
|
||||
private final LifecycleDisposable lifecycleDisposable = new LifecycleDisposable();
|
||||
|
||||
private boolean onFirstRender = false;
|
||||
|
||||
public static @NonNull Intent clearTop(@NonNull Context context) {
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK |
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static @NonNull Intent clearTopAndOpenTab(@NonNull Context context, @NonNull ConversationListTab startingTab) {
|
||||
Intent intent = clearTop(context);
|
||||
intent.putExtra(KEY_STARTING_TAB, startingTab);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState, boolean ready) {
|
||||
AppStartup.getInstance().onCriticalRenderEventStart();
|
||||
super.onCreate(savedInstanceState, ready);
|
||||
|
||||
setContentView(R.layout.main_activity);
|
||||
final View content = findViewById(android.R.id.content);
|
||||
content.getViewTreeObserver().addOnPreDrawListener(
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
// Use pre draw listener to delay drawing frames till conversation list is ready
|
||||
if (onFirstRender) {
|
||||
content.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
lifecycleDisposable.bindTo(this);
|
||||
|
||||
mediaController = new VoiceNoteMediaController(this, true);
|
||||
|
||||
|
||||
ConversationListTab startingTab = null;
|
||||
if (getIntent().getExtras() != null) {
|
||||
startingTab = BundleExtensions.getSerializableCompat(getIntent().getExtras(), KEY_STARTING_TAB, ConversationListTab.class);
|
||||
}
|
||||
|
||||
ConversationListTabRepository repository = new ConversationListTabRepository();
|
||||
ConversationListTabsViewModel.Factory factory = new ConversationListTabsViewModel.Factory(startingTab, repository);
|
||||
|
||||
handleDeeplinkIntent(getIntent());
|
||||
|
||||
CachedInflater.from(this).clear();
|
||||
|
||||
conversationListTabsViewModel = new ViewModelProvider(this, factory).get(ConversationListTabsViewModel.class);
|
||||
updateTabVisibility();
|
||||
|
||||
vitalsViewModel = new ViewModelProvider(this).get(VitalsViewModel.class);
|
||||
|
||||
lifecycleDisposable.add(
|
||||
vitalsViewModel
|
||||
.getVitalsState()
|
||||
.subscribe(this::presentVitalsState)
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void presentVitalsState(VitalsViewModel.State state) {
|
||||
switch (state) {
|
||||
case NONE:
|
||||
break;
|
||||
case PROMPT_SPECIFIC_BATTERY_SAVER_DIALOG:
|
||||
DeviceSpecificNotificationBottomSheet.show(getSupportFragmentManager());
|
||||
break;
|
||||
case PROMPT_GENERAL_BATTERY_SAVER_DIALOG:
|
||||
PromptBatterySaverDialogFragment.show(getSupportFragmentManager());
|
||||
break;
|
||||
case PROMPT_CONNECTIVITY_WARNING:
|
||||
ConnectivityWarningBottomSheet.show(getSupportFragmentManager());
|
||||
break;
|
||||
case PROMPT_DEBUGLOGS_FOR_NOTIFICATIONS:
|
||||
DebugLogsPromptDialogFragment.show(this, DebugLogsPromptDialogFragment.Purpose.NOTIFICATIONS);
|
||||
break;
|
||||
case PROMPT_DEBUGLOGS_FOR_CRASH:
|
||||
DebugLogsPromptDialogFragment.show(this, DebugLogsPromptDialogFragment.Purpose.CRASH);
|
||||
break;
|
||||
case PROMPT_DEBUGLOGS_FOR_CONNECTIVITY_WARNING:
|
||||
DebugLogsPromptDialogFragment.show(this, DebugLogsPromptDialogFragment.Purpose.CONNECTIVITY_WARNING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
return super.getIntent().setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK |
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
handleDeeplinkIntent(intent);
|
||||
|
||||
if (intent.getExtras() != null) {
|
||||
ConversationListTab startingTab = BundleExtensions.getSerializableCompat(intent.getExtras(), KEY_STARTING_TAB, ConversationListTab.class);
|
||||
if (startingTab != null) {
|
||||
switch (startingTab) {
|
||||
case CHATS -> conversationListTabsViewModel.onChatsSelected();
|
||||
case CALLS -> conversationListTabsViewModel.onCallsSelected();
|
||||
case STORIES -> {
|
||||
if (Stories.isFeatureEnabled()) {
|
||||
conversationListTabsViewModel.onStoriesSelected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreCreate() {
|
||||
super.onPreCreate();
|
||||
dynamicTheme.onCreate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
dynamicTheme.onResume(this);
|
||||
|
||||
if (SignalStore.misc().getShouldShowLinkedDevicesReminder()) {
|
||||
SignalStore.misc().setShouldShowLinkedDevicesReminder(false);
|
||||
RelinkDevicesReminderBottomSheetFragment.show(getSupportFragmentManager());
|
||||
}
|
||||
|
||||
if (SignalStore.registration().isRestoringOnNewDevice()) {
|
||||
SignalStore.registration().setRestoringOnNewDevice(false);
|
||||
RestoreCompleteBottomSheetDialog.show(getSupportFragmentManager());
|
||||
} else if (SignalStore.misc().isOldDeviceTransferLocked()) {
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.OldDeviceTransferLockedDialog__complete_registration_on_your_new_device)
|
||||
.setMessage(R.string.OldDeviceTransferLockedDialog__your_signal_account_has_been_transferred_to_your_new_device)
|
||||
.setPositiveButton(R.string.OldDeviceTransferLockedDialog__done, (d, w) -> OldDeviceExitActivity.exit(this))
|
||||
.setNegativeButton(R.string.OldDeviceTransferLockedDialog__cancel_and_activate_this_device, (d, w) -> {
|
||||
SignalStore.misc().setOldDeviceTransferLocked(false);
|
||||
DeviceTransferBlockingInterceptor.getInstance().unblockNetwork();
|
||||
})
|
||||
.setCancelable(false)
|
||||
.show();
|
||||
}
|
||||
|
||||
updateTabVisibility();
|
||||
|
||||
vitalsViewModel.checkSlowNotificationHeuristics();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
SplashScreenUtil.setSplashScreenThemeIfNecessary(this, SignalStore.settings().getTheme());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (!navigator.onBackPressed()) {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == MainNavigator.REQUEST_CONFIG_CHANGES && resultCode == RESULT_CONFIG_CHANGED) {
|
||||
recreate();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTabVisibility() {
|
||||
findViewById(R.id.conversation_list_tabs).setVisibility(View.VISIBLE);
|
||||
WindowUtil.setNavigationBarColor(this, ContextCompat.getColor(this, R.color.signal_colorSurface2));
|
||||
}
|
||||
|
||||
public @NonNull MainNavigator getNavigator() {
|
||||
return navigator;
|
||||
}
|
||||
|
||||
private void handleDeeplinkIntent(Intent intent) {
|
||||
handleGroupLinkInIntent(intent);
|
||||
handleProxyInIntent(intent);
|
||||
handleSignalMeIntent(intent);
|
||||
handleCallLinkInIntent(intent);
|
||||
handleDonateReturnIntent(intent);
|
||||
}
|
||||
|
||||
private void handleGroupLinkInIntent(Intent intent) {
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
CommunicationActions.handlePotentialGroupLinkUrl(this, data.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleProxyInIntent(Intent intent) {
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
CommunicationActions.handlePotentialProxyLinkUrl(this, data.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSignalMeIntent(Intent intent) {
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
CommunicationActions.handlePotentialSignalMeUrl(this, data.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCallLinkInIntent(Intent intent) {
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
CommunicationActions.handlePotentialCallLinkUrl(this, data.toString(), () -> {
|
||||
YouAreAlreadyInACallSnackbar.show(findViewById(android.R.id.content));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDonateReturnIntent(Intent intent) {
|
||||
Uri data = intent.getData();
|
||||
if (data != null && data.toString().startsWith(StripeApi.RETURN_URL_IDEAL)) {
|
||||
startActivity(AppSettingsActivity.manageSubscriptions(this));
|
||||
}
|
||||
}
|
||||
|
||||
public void onFirstRender() {
|
||||
onFirstRender = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull VoiceNoteMediaController getVoiceNoteMediaController() {
|
||||
return mediaController;
|
||||
}
|
||||
}
|
||||
257
app/src/main/java/org/thoughtcrime/securesms/MainActivity.kt
Normal file
257
app/src/main/java/org/thoughtcrime/securesms/MainActivity.kt
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewTreeObserver
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.getSerializableCompat
|
||||
import org.signal.donations.StripeApi
|
||||
import org.thoughtcrime.securesms.calls.YouAreAlreadyInACallSnackbar.show
|
||||
import org.thoughtcrime.securesms.components.ConnectivityWarningBottomSheet
|
||||
import org.thoughtcrime.securesms.components.DebugLogsPromptDialogFragment
|
||||
import org.thoughtcrime.securesms.components.DeviceSpecificNotificationBottomSheet
|
||||
import org.thoughtcrime.securesms.components.PromptBatterySaverDialogFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity.Companion.manageSubscriptions
|
||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaController
|
||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaControllerOwner
|
||||
import org.thoughtcrime.securesms.conversationlist.RelinkDevicesReminderBottomSheetFragment
|
||||
import org.thoughtcrime.securesms.conversationlist.RestoreCompleteBottomSheetDialog
|
||||
import org.thoughtcrime.securesms.devicetransfer.olddevice.OldDeviceExitActivity
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.net.DeviceTransferBlockingInterceptor
|
||||
import org.thoughtcrime.securesms.notifications.VitalsViewModel
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTab
|
||||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabRepository
|
||||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel
|
||||
import org.thoughtcrime.securesms.util.AppStartup
|
||||
import org.thoughtcrime.securesms.util.CachedInflater
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme
|
||||
import org.thoughtcrime.securesms.util.SplashScreenUtil
|
||||
import org.thoughtcrime.securesms.util.WindowUtil
|
||||
import org.thoughtcrime.securesms.util.viewModel
|
||||
|
||||
class MainActivity : PassphraseRequiredActivity(), VoiceNoteMediaControllerOwner, MainNavigator.NavigatorProvider {
|
||||
|
||||
companion object {
|
||||
private const val KEY_STARTING_TAB = "STARTING_TAB"
|
||||
const val RESULT_CONFIG_CHANGED = Activity.RESULT_FIRST_USER + 901
|
||||
|
||||
@JvmStatic
|
||||
fun clearTop(context: Context): Intent {
|
||||
return Intent(context, MainActivity::class.java)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun clearTopAndOpenTab(context: Context, startingTab: ConversationListTab): Intent {
|
||||
return clearTop(context).putExtra(KEY_STARTING_TAB, startingTab)
|
||||
}
|
||||
}
|
||||
|
||||
private val dynamicTheme = DynamicNoActionBarTheme()
|
||||
private val navigator = MainNavigator(this)
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
private lateinit var mediaController: VoiceNoteMediaController
|
||||
|
||||
override val voiceNoteMediaController: VoiceNoteMediaController
|
||||
get() = mediaController
|
||||
|
||||
private val conversationListTabsViewModel: ConversationListTabsViewModel by viewModel {
|
||||
val startingTab = intent.extras?.getSerializableCompat(KEY_STARTING_TAB, ConversationListTab::class.java)
|
||||
ConversationListTabsViewModel(startingTab ?: ConversationListTab.CHATS, ConversationListTabRepository())
|
||||
}
|
||||
|
||||
private val vitalsViewModel: VitalsViewModel by viewModel {
|
||||
VitalsViewModel(application)
|
||||
}
|
||||
|
||||
private var onFirstRender = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
||||
AppStartup.getInstance().onCriticalRenderEventStart()
|
||||
super.onCreate(savedInstanceState, ready)
|
||||
|
||||
setContentView(R.layout.main_activity)
|
||||
|
||||
val content: View = findViewById(android.R.id.content)
|
||||
content.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
|
||||
override fun onPreDraw(): Boolean {
|
||||
// Use pre draw listener to delay drawing frames till conversation list is ready
|
||||
return if (onFirstRender) {
|
||||
content.viewTreeObserver.removeOnPreDrawListener(this)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
lifecycleDisposable.bindTo(this)
|
||||
|
||||
mediaController = VoiceNoteMediaController(this, true)
|
||||
conversationListTabsViewModel
|
||||
|
||||
handleDeepLinkIntent(intent)
|
||||
CachedInflater.from(this).clear()
|
||||
updateNavigationBarColor()
|
||||
|
||||
lifecycleDisposable += vitalsViewModel.vitalsState.subscribe(this::presentVitalsState)
|
||||
}
|
||||
|
||||
override fun getIntent(): Intent {
|
||||
return super.getIntent().setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
handleDeepLinkIntent(intent)
|
||||
|
||||
val extras = intent.extras ?: return
|
||||
val startingTab = extras.getSerializableCompat(KEY_STARTING_TAB, ConversationListTab::class.java)
|
||||
|
||||
when (startingTab) {
|
||||
ConversationListTab.CHATS -> conversationListTabsViewModel.onChatsSelected()
|
||||
ConversationListTab.CALLS -> conversationListTabsViewModel.onCallsSelected()
|
||||
ConversationListTab.STORIES -> {
|
||||
if (Stories.isFeatureEnabled()) {
|
||||
conversationListTabsViewModel.onStoriesSelected()
|
||||
}
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreCreate() {
|
||||
super.onPreCreate()
|
||||
dynamicTheme.onCreate(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
dynamicTheme.onResume(this)
|
||||
|
||||
if (SignalStore.misc.shouldShowLinkedDevicesReminder) {
|
||||
SignalStore.misc.shouldShowLinkedDevicesReminder = false
|
||||
RelinkDevicesReminderBottomSheetFragment.show(supportFragmentManager)
|
||||
}
|
||||
|
||||
if (SignalStore.registration.restoringOnNewDevice) {
|
||||
SignalStore.registration.restoringOnNewDevice = false
|
||||
RestoreCompleteBottomSheetDialog.show(supportFragmentManager)
|
||||
} else if (SignalStore.misc.isOldDeviceTransferLocked) {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.OldDeviceTransferLockedDialog__complete_registration_on_your_new_device)
|
||||
.setMessage(R.string.OldDeviceTransferLockedDialog__your_signal_account_has_been_transferred_to_your_new_device)
|
||||
.setPositiveButton(R.string.OldDeviceTransferLockedDialog__done) { _, _ -> OldDeviceExitActivity.exit(this) }
|
||||
.setNegativeButton(R.string.OldDeviceTransferLockedDialog__cancel_and_activate_this_device) { _, _ ->
|
||||
SignalStore.misc.isOldDeviceTransferLocked = false
|
||||
DeviceTransferBlockingInterceptor.getInstance().unblockNetwork()
|
||||
}
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
updateNavigationBarColor()
|
||||
|
||||
vitalsViewModel.checkSlowNotificationHeuristics()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
SplashScreenUtil.setSplashScreenThemeIfNecessary(this, SignalStore.settings.theme)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (!navigator.onBackPressed()) {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == MainNavigator.REQUEST_CONFIG_CHANGES && resultCode == RESULT_CONFIG_CHANGED) {
|
||||
recreate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFirstRender() {
|
||||
onFirstRender = true
|
||||
}
|
||||
|
||||
override fun getNavigator(): MainNavigator {
|
||||
return navigator
|
||||
}
|
||||
|
||||
private fun handleDeepLinkIntent(intent: Intent) {
|
||||
handleGroupLinkInIntent(intent)
|
||||
handleProxyInIntent(intent)
|
||||
handleSignalMeIntent(intent)
|
||||
handleCallLinkInIntent(intent)
|
||||
handleDonateReturnIntent(intent)
|
||||
}
|
||||
|
||||
private fun updateNavigationBarColor() {
|
||||
WindowUtil.setNavigationBarColor(this, ContextCompat.getColor(this, R.color.signal_colorSurface2))
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun presentVitalsState(state: VitalsViewModel.State) {
|
||||
when (state) {
|
||||
VitalsViewModel.State.NONE -> Unit
|
||||
VitalsViewModel.State.PROMPT_SPECIFIC_BATTERY_SAVER_DIALOG -> DeviceSpecificNotificationBottomSheet.show(supportFragmentManager)
|
||||
VitalsViewModel.State.PROMPT_GENERAL_BATTERY_SAVER_DIALOG -> PromptBatterySaverDialogFragment.show(supportFragmentManager)
|
||||
VitalsViewModel.State.PROMPT_DEBUGLOGS_FOR_NOTIFICATIONS -> DebugLogsPromptDialogFragment.show(this, DebugLogsPromptDialogFragment.Purpose.NOTIFICATIONS)
|
||||
VitalsViewModel.State.PROMPT_DEBUGLOGS_FOR_CRASH -> DebugLogsPromptDialogFragment.show(this, DebugLogsPromptDialogFragment.Purpose.CRASH)
|
||||
VitalsViewModel.State.PROMPT_CONNECTIVITY_WARNING -> ConnectivityWarningBottomSheet.show(supportFragmentManager)
|
||||
VitalsViewModel.State.PROMPT_DEBUGLOGS_FOR_CONNECTIVITY_WARNING -> DebugLogsPromptDialogFragment.show(this, DebugLogsPromptDialogFragment.Purpose.CONNECTIVITY_WARNING)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleGroupLinkInIntent(intent: Intent) {
|
||||
intent.data?.let { data ->
|
||||
CommunicationActions.handlePotentialGroupLinkUrl(this, data.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleProxyInIntent(intent: Intent) {
|
||||
intent.data?.let { data ->
|
||||
CommunicationActions.handlePotentialProxyLinkUrl(this, data.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSignalMeIntent(intent: Intent) {
|
||||
intent.data?.let { data ->
|
||||
CommunicationActions.handlePotentialSignalMeUrl(this, data.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCallLinkInIntent(intent: Intent) {
|
||||
intent.data?.let { data ->
|
||||
CommunicationActions.handlePotentialCallLinkUrl(this, data.toString()) {
|
||||
show(findViewById(android.R.id.content))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDonateReturnIntent(intent: Intent) {
|
||||
intent.data?.let { data ->
|
||||
if (data.toString().startsWith(StripeApi.RETURN_URL_IDEAL)) {
|
||||
startActivity(manageSubscriptions(this))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
@@ -19,10 +20,10 @@ public class MainNavigator {
|
||||
|
||||
public static final int REQUEST_CONFIG_CHANGES = 901;
|
||||
|
||||
private final MainActivity activity;
|
||||
private final AppCompatActivity activity;
|
||||
private final LifecycleDisposable lifecycleDisposable;
|
||||
|
||||
public MainNavigator(@NonNull MainActivity activity) {
|
||||
public MainNavigator(@NonNull AppCompatActivity activity) {
|
||||
this.activity = activity;
|
||||
this.lifecycleDisposable = new LifecycleDisposable();
|
||||
|
||||
@@ -34,7 +35,7 @@ public class MainNavigator {
|
||||
throw new IllegalArgumentException("Activity must be an instance of MainActivity!");
|
||||
}
|
||||
|
||||
return ((MainActivity) activity).getNavigator();
|
||||
return ((NavigatorProvider) activity).getNavigator();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,4 +89,9 @@ public class MainNavigator {
|
||||
*/
|
||||
boolean onBackPressed();
|
||||
}
|
||||
|
||||
public interface NavigatorProvider {
|
||||
@NonNull MainNavigator getNavigator();
|
||||
void onFirstRender();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.signal.core.util.DimensionUnit
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.concurrent.addTo
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.MainActivity
|
||||
import org.thoughtcrime.securesms.MainNavigator
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.calls.YouAreAlreadyInACallSnackbar
|
||||
import org.thoughtcrime.securesms.calls.links.details.CallLinkDetailsActivity
|
||||
@@ -134,7 +134,7 @@ class CallLogFragment : Fragment(R.layout.call_log_fragment), CallLogAdapter.Cal
|
||||
callLogAdapter.setPagingController(viewModel.controller)
|
||||
callLogAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
||||
(requireActivity() as? MainActivity)?.onFirstRender()
|
||||
(requireActivity() as? MainNavigator.NavigatorProvider)?.onFirstRender()
|
||||
callLogAdapter.unregisterAdapterDataObserver(this)
|
||||
}
|
||||
})
|
||||
@@ -328,8 +328,7 @@ class CallLogFragment : Fragment(R.layout.call_log_fragment), CallLogAdapter.Cal
|
||||
}
|
||||
}
|
||||
|
||||
filterViewOffsetChangeListener = AppBarLayout.OnOffsetChangedListener {
|
||||
layout: AppBarLayout, verticalOffset: Int ->
|
||||
filterViewOffsetChangeListener = AppBarLayout.OnOffsetChangedListener { layout: AppBarLayout, verticalOffset: Int ->
|
||||
val progress = 1 - verticalOffset.toFloat() / -layout.height
|
||||
binding.pullView.onUserDrag(progress)
|
||||
}
|
||||
@@ -485,6 +484,7 @@ class CallLogFragment : Fragment(R.layout.call_log_fragment), CallLogAdapter.Cal
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
CallLogDeletionResult.Success -> {
|
||||
Snackbar
|
||||
.make(
|
||||
@@ -494,6 +494,7 @@ class CallLogFragment : Fragment(R.layout.call_log_fragment), CallLogAdapter.Cal
|
||||
)
|
||||
.show()
|
||||
}
|
||||
|
||||
is CallLogDeletionResult.UnknownFailure -> {
|
||||
Log.w(TAG, "Deletion failed.", it.reason)
|
||||
Toast.makeText(requireContext(), R.string.CallLogFragment__deletion_failed, Toast.LENGTH_SHORT).show()
|
||||
|
||||
@@ -53,6 +53,7 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
|
||||
StartLocation.BACKUPS -> AppSettingsFragmentDirections.actionDirectToBackupsPreferenceFragment()
|
||||
StartLocation.HELP -> AppSettingsFragmentDirections.actionDirectToHelpFragment()
|
||||
.setStartCategoryIndex(intent.getIntExtra(HelpFragment.START_CATEGORY_INDEX, 0))
|
||||
|
||||
StartLocation.PROXY -> AppSettingsFragmentDirections.actionDirectToEditProxyFragment()
|
||||
StartLocation.NOTIFICATIONS -> AppSettingsFragmentDirections.actionDirectToNotificationsSettingsFragment()
|
||||
StartLocation.CHANGE_NUMBER -> AppSettingsFragmentDirections.actionDirectToChangeNumberFragment()
|
||||
@@ -64,6 +65,7 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
|
||||
StartLocation.NOTIFICATION_PROFILE_DETAILS -> AppSettingsFragmentDirections.actionDirectToNotificationProfileDetails(
|
||||
EditNotificationProfileScheduleFragmentArgs.fromBundle(intent.getBundleExtra(START_ARGUMENTS)!!).profileId
|
||||
)
|
||||
|
||||
StartLocation.PRIVACY -> AppSettingsFragmentDirections.actionDirectToPrivacy()
|
||||
StartLocation.LINKED_DEVICES -> AppSettingsFragmentDirections.actionDirectToDevices()
|
||||
StartLocation.USERNAME_LINK -> AppSettingsFragmentDirections.actionDirectToUsernameLinkSettings()
|
||||
@@ -74,6 +76,7 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
|
||||
CreateFoldersFragmentArgs.fromBundle(intent.getBundleExtra(START_ARGUMENTS)!!).folderId,
|
||||
CreateFoldersFragmentArgs.fromBundle(intent.getBundleExtra(START_ARGUMENTS)!!).threadIds
|
||||
)
|
||||
|
||||
StartLocation.BACKUPS_SETTINGS -> AppSettingsFragmentDirections.actionDirectToBackupsSettingsFragment()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1066,6 +1066,7 @@ class ConversationFragment :
|
||||
AvatarDownloadStateCache.DownloadState.FINISHED -> {
|
||||
viewModel.updateThreadHeader()
|
||||
}
|
||||
|
||||
AvatarDownloadStateCache.DownloadState.FAILED -> {
|
||||
Snackbar.make(requireView(), R.string.ConversationFragment_photo_failed, Snackbar.LENGTH_LONG).show()
|
||||
presentConversationTitle(recipient)
|
||||
@@ -2255,6 +2256,7 @@ class ConversationFragment :
|
||||
Log.d(TAG, "report spam complete")
|
||||
toast(R.string.ConversationFragment_reported_as_spam_and_blocked)
|
||||
}
|
||||
|
||||
is Result.Failure -> {
|
||||
Log.d(TAG, "report spam failed ${result.failure}")
|
||||
toast(GroupErrors.getUserDisplayMessage(result.failure))
|
||||
@@ -3724,7 +3726,10 @@ class ConversationFragment :
|
||||
MediaUtil.isVideoType(it.contentType) -> VideoSlide(requireContext(), it.uri, it.size, it.isVideoGif, it.width, it.height, it.caption.orNull(), it.transformProperties.orNull())
|
||||
MediaUtil.isGif(it.contentType) -> GifSlide(requireContext(), it.uri, it.size, it.width, it.height, it.isBorderless, it.caption.orNull())
|
||||
MediaUtil.isImageType(it.contentType) -> ImageSlide(requireContext(), it.uri, it.contentType, it.size, it.width, it.height, it.isBorderless, it.caption.orNull(), null, it.transformProperties.orNull())
|
||||
MediaUtil.isDocumentType(it.contentType) -> { DocumentSlide(requireContext(), it.uri, it.contentType, it.size, it.fileName.orNull()) }
|
||||
MediaUtil.isDocumentType(it.contentType) -> {
|
||||
DocumentSlide(requireContext(), it.uri, it.contentType, it.size, it.fileName.orNull())
|
||||
}
|
||||
|
||||
else -> {
|
||||
Log.w(TAG, "Asked to send an unexpected mimeType: '${it.contentType}'. Skipping.")
|
||||
null
|
||||
@@ -4142,7 +4147,13 @@ class ConversationFragment :
|
||||
.request(Manifest.permission.RECORD_AUDIO)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getString(R.string.ConversationActivity_allow_access_microphone), getString(R.string.ConversationActivity_to_send_voice_messages_allow_signal_access_to_your_microphone), R.drawable.ic_mic_24)
|
||||
.withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_requires_the_microphone_permission_in_order_to_send_audio_messages), null, R.string.ConversationActivity_allow_access_microphone, R.string.ConversationActivity_signal_to_send_audio_messages, this@ConversationFragment.parentFragmentManager)
|
||||
.withPermanentDenialDialog(
|
||||
getString(R.string.ConversationActivity_signal_requires_the_microphone_permission_in_order_to_send_audio_messages),
|
||||
null,
|
||||
R.string.ConversationActivity_allow_access_microphone,
|
||||
R.string.ConversationActivity_signal_to_send_audio_messages,
|
||||
this@ConversationFragment.parentFragmentManager
|
||||
)
|
||||
.onAnyDenied { Toast.makeText(this@ConversationFragment.requireContext(), R.string.ConversationActivity_signal_needs_microphone_access_voice_message, Toast.LENGTH_LONG).show() }
|
||||
.execute()
|
||||
}
|
||||
|
||||
@@ -970,8 +970,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
||||
startupStopwatch.split("data-set");
|
||||
SignalLocalMetrics.ColdStart.onConversationListDataLoaded();
|
||||
defaultAdapter.unregisterAdapterDataObserver(this);
|
||||
if (requireActivity() instanceof MainActivity) {
|
||||
((MainActivity) requireActivity()).onFirstRender();
|
||||
if (requireActivity() instanceof MainNavigator.NavigatorProvider) {
|
||||
((MainNavigator.NavigatorProvider) requireActivity()).onFirstRender();
|
||||
}
|
||||
list.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
||||
@Override
|
||||
|
||||
@@ -10,8 +10,8 @@ import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
|
||||
import org.signal.core.util.SetUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.MainActivity;
|
||||
import org.thoughtcrime.securesms.NewConversationActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.conversationlist.model.ConversationFilter;
|
||||
@@ -19,10 +19,10 @@ import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadTable;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.MainActivity;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationIds;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.signal.core.util.SetUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
Reference in New Issue
Block a user