package org.schabi.newpipe.local.subscription; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.text.util.Linkify; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.appcompat.app.ActionBar; import androidx.core.text.util.LinkifyCompat; import org.schabi.newpipe.BaseFragment; import org.schabi.newpipe.R; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService; import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard; import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ServiceHelper; import java.util.Collections; import java.util.List; import icepick.State; import static org.schabi.newpipe.extractor.subscription.SubscriptionExtractor.ContentSource.CHANNEL_URL; import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.CHANNEL_URL_MODE; import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.INPUT_STREAM_MODE; import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE; import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE; public class SubscriptionsImportFragment extends BaseFragment { @State int currentServiceId = Constants.NO_SERVICE_ID; private List supportedSources; private String relatedUrl; @StringRes private int instructionsString; /*////////////////////////////////////////////////////////////////////////// // Views //////////////////////////////////////////////////////////////////////////*/ private TextView infoTextView; private EditText inputText; private Button inputButton; private final ActivityResultLauncher requestImportFileLauncher = registerForActivityResult(new StartActivityForResult(), this::requestImportFileResult); public static SubscriptionsImportFragment getInstance(final int serviceId) { final SubscriptionsImportFragment instance = new SubscriptionsImportFragment(); instance.setInitialData(serviceId); return instance; } private void setInitialData(final int serviceId) { this.currentServiceId = serviceId; } /////////////////////////////////////////////////////////////////////////// // Fragment LifeCycle /////////////////////////////////////////////////////////////////////////// @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setupServiceVariables(); if (supportedSources.isEmpty() && currentServiceId != Constants.NO_SERVICE_ID) { ErrorUtil.showSnackbar(activity, new ErrorInfo(new String[]{}, UserAction.SUBSCRIPTION_IMPORT_EXPORT, NewPipe.getNameOfService(currentServiceId), "Service does not support importing subscriptions", R.string.general_error)); activity.finish(); } } @Override public void onResume() { super.onResume(); setTitle(getString(R.string.import_title)); } @Nullable @Override public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, final Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_import, container, false); } /*///////////////////////////////////////////////////////////////////////// // Fragment Views /////////////////////////////////////////////////////////////////////////*/ @Override protected void initViews(final View rootView, final Bundle savedInstanceState) { super.initViews(rootView, savedInstanceState); inputButton = rootView.findViewById(R.id.input_button); inputText = rootView.findViewById(R.id.input_text); infoTextView = rootView.findViewById(R.id.info_text_view); // TODO: Support services that can import from more than one source // (show the option to the user) if (supportedSources.contains(CHANNEL_URL)) { inputButton.setText(R.string.import_title); inputText.setVisibility(View.VISIBLE); inputText.setHint(ServiceHelper.getImportInstructionsHint(currentServiceId)); } else { inputButton.setText(R.string.import_file_title); } if (instructionsString != 0) { if (TextUtils.isEmpty(relatedUrl)) { setInfoText(getString(instructionsString)); } else { setInfoText(getString(instructionsString, relatedUrl)); } } else { setInfoText(""); } final ActionBar supportActionBar = activity.getSupportActionBar(); if (supportActionBar != null) { supportActionBar.setDisplayShowTitleEnabled(true); setTitle(getString(R.string.import_title)); } } @Override protected void initListeners() { super.initListeners(); inputButton.setOnClickListener(v -> onImportClicked()); } private void onImportClicked() { if (inputText.getVisibility() == View.VISIBLE) { final String value = inputText.getText().toString(); if (!value.isEmpty()) { onImportUrl(value); } } else { onImportFile(); } } public void onImportUrl(final String value) { ImportConfirmationDialog.show(this, new Intent(activity, SubscriptionsImportService.class) .putExtra(KEY_MODE, CHANNEL_URL_MODE) .putExtra(KEY_VALUE, value) .putExtra(Constants.KEY_SERVICE_ID, currentServiceId)); } public void onImportFile() { NoFileManagerSafeGuard.launchSafe( requestImportFileLauncher, // leave */* mime type to support all services // with different mime types and file extensions StoredFileHelper.getPicker(activity, "*/*"), TAG, getContext() ); } private void requestImportFileResult(final ActivityResult result) { if (result.getData() == null) { return; } if (result.getResultCode() == Activity.RESULT_OK && result.getData().getData() != null) { ImportConfirmationDialog.show(this, new Intent(activity, SubscriptionsImportService.class) .putExtra(KEY_MODE, INPUT_STREAM_MODE) .putExtra(KEY_VALUE, result.getData().getData()) .putExtra(Constants.KEY_SERVICE_ID, currentServiceId)); } } /////////////////////////////////////////////////////////////////////////// // Subscriptions /////////////////////////////////////////////////////////////////////////// private void setupServiceVariables() { if (currentServiceId != Constants.NO_SERVICE_ID) { try { final SubscriptionExtractor extractor = NewPipe.getService(currentServiceId) .getSubscriptionExtractor(); supportedSources = extractor.getSupportedSources(); relatedUrl = extractor.getRelatedUrl(); instructionsString = ServiceHelper.getImportInstructions(currentServiceId); return; } catch (final ExtractionException ignored) { } } supportedSources = Collections.emptyList(); relatedUrl = null; instructionsString = 0; } private void setInfoText(final String infoString) { infoTextView.setText(infoString); LinkifyCompat.addLinks(infoTextView, Linkify.WEB_URLS); } }