package com.kickstarter.ui.intentmappers; import android.content.Intent; import android.net.Uri; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.kickstarter.libs.RefTag; import com.kickstarter.libs.rx.transformers.Transformers; import com.kickstarter.libs.utils.ObjectUtils; import com.kickstarter.models.Project; import com.kickstarter.services.ApiClientType; import com.kickstarter.services.apiresponses.PushNotificationEnvelope; import com.kickstarter.ui.IntentKey; import java.util.regex.Matcher; import java.util.regex.Pattern; import rx.Observable; public final class ProjectIntentMapper { private ProjectIntentMapper() {} // /projects/param-1/param-2* final static Pattern PROJECT_PATTERN = Pattern.compile("\\A\\/projects\\/([a-zA-Z0-9_-]+)(\\/([a-zA-Z0-9_-]+)).*"); /** * Returns an observable of projects retrieved from intent data. May hit the API if the intent only contains a project * param rather than a parceled project. */ public static @NonNull Observable<Project> project(final @NonNull Intent intent, final @NonNull ApiClientType client) { final Project intentProject = projectFromIntent(intent); final Observable<Project> projectFromParceledProject = intentProject == null ? Observable.empty() : Observable.just(intentProject) .flatMap(client::fetchProject) .startWith(intentProject) .retry(3); final Observable<Project> projectFromParceledParam = Observable.just(paramFromIntent(intent)) .filter(ObjectUtils::isNotNull) .flatMap(client::fetchProject) .retry(3); return projectFromParceledProject .mergeWith(projectFromParceledParam) .compose(Transformers.neverError()); } /** * Returns a {@link RefTag} observable. If there is no parceled RefTag, emit `null`. */ public static @NonNull Observable<RefTag> refTag(final @NonNull Intent intent) { return Observable.just(intent.getParcelableExtra(IntentKey.REF_TAG)); } /** * Returns an observable of push notification envelopes from the intent data. This will emit only when the project * is launched from a push notification. */ public static @NonNull Observable<PushNotificationEnvelope> pushNotificationEnvelope(final @NonNull Intent intent) { return Observable.just(intent.getParcelableExtra(IntentKey.PUSH_NOTIFICATION_ENVELOPE)) .ofType(PushNotificationEnvelope.class); } /** * Gets a parceled project from the intent data, may return `null`. */ private static @Nullable Project projectFromIntent(final @NonNull Intent intent) { return intent.getParcelableExtra(IntentKey.PROJECT); } /** * Gets a project param from the intent data, may return `null`. */ private static @Nullable String paramFromIntent(final @NonNull Intent intent) { if (intent.hasExtra(IntentKey.PROJECT_PARAM)) { return intent.getStringExtra(IntentKey.PROJECT_PARAM); } return paramFromUri(IntentMapper.uri(intent)); } /** * Extract the project param from a uri. e.g.: A uri like `ksr://www.kickstarter.com/projects/1186238668/skull-graphic-tee` * returns `skull-graphic-tee`. */ private static @Nullable String paramFromUri(final @Nullable Uri uri) { if (uri == null) { return null; } if (!uri.getScheme().equals("ksr")) { return null; } final Matcher matcher = PROJECT_PATTERN.matcher(uri.getPath()); if (matcher.matches() && matcher.group(3) != null) { return matcher.group(3); } return null; } }