package org.tm.archive.proxy; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; import androidx.lifecycle.ViewModelProvider; import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.signal.core.util.logging.Log; import org.tm.archive.R; import org.tm.archive.preferences.EditProxyViewModel; import org.tm.archive.util.BottomSheetUtil; import org.signal.core.util.concurrent.LifecycleDisposable; import org.tm.archive.util.ThemeUtil; import org.tm.archive.util.WindowUtil; import org.tm.archive.util.views.CircularProgressMaterialButton; /** * A bottom sheet shown in response to a deep link. Allows a user to set a proxy. */ public final class ProxyBottomSheetFragment extends BottomSheetDialogFragment { private static final String TAG = Log.tag(ProxyBottomSheetFragment.class); private static final String ARG_PROXY_LINK = "proxy_link"; private TextView proxyText; private View cancelButton; private CircularProgressMaterialButton useProxyButton; private EditProxyViewModel viewModel; private LifecycleDisposable lifecycleDisposable; public static void showForProxy(@NonNull FragmentManager manager, @NonNull String proxyLink) { ProxyBottomSheetFragment fragment = new ProxyBottomSheetFragment(); Bundle args = new Bundle(); args.putString(ARG_PROXY_LINK, proxyLink); fragment.setArguments(args); fragment.show(manager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { setStyle(DialogFragment.STYLE_NORMAL, ThemeUtil.isDarkTheme(requireContext()) ? R.style.Theme_Signal_RoundedBottomSheet : R.style.Theme_Signal_RoundedBottomSheet_Light); super.onCreate(savedInstanceState); } @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.proxy_bottom_sheet, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { this.proxyText = view.findViewById(R.id.proxy_sheet_host); this.useProxyButton = view.findViewById(R.id.proxy_sheet_use_proxy); this.cancelButton = view.findViewById(R.id.proxy_sheet_cancel); lifecycleDisposable = new LifecycleDisposable(); lifecycleDisposable.bindTo(getViewLifecycleOwner()); String host = getArguments().getString(ARG_PROXY_LINK); proxyText.setText(host); initViewModel(); useProxyButton.setOnClickListener(v -> viewModel.onSaveClicked(host)); cancelButton.setOnClickListener(v -> dismiss()); } @Override public void onResume() { super.onResume(); WindowUtil.initializeScreenshotSecurity(requireContext(), requireDialog().getWindow()); } private void initViewModel() { this.viewModel = new ViewModelProvider(this).get(EditProxyViewModel.class); lifecycleDisposable.addAll( viewModel.getSaveState().subscribe(this::presentSaveState), viewModel.getEvents().subscribe(this::presentEvents) ); } private void presentSaveState(@NonNull EditProxyViewModel.SaveState state) { switch (state) { case IDLE: useProxyButton.cancelSpinning(); break; case IN_PROGRESS: useProxyButton.setSpinning(); break; } } private void presentEvents(@NonNull EditProxyViewModel.Event event) { if (isStateSaved()) { Log.w(TAG, "Got an event after state had been saved. Dropping. " + event.name()); return; } switch (event) { case PROXY_SUCCESS: Toast.makeText(requireContext(), R.string.ProxyBottomSheetFragment_successfully_connected_to_proxy, Toast.LENGTH_LONG).show(); dismiss(); break; case PROXY_FAILURE: new MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.preferences_failed_to_connect) .setMessage(R.string.preferences_couldnt_connect_to_the_proxy) .setPositiveButton(android.R.string.ok, (d, i) -> d.dismiss()) .show(); dismiss(); break; } } }