diff --git a/app/build.gradle b/app/build.gradle index b84ee539..a202d937 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -117,6 +117,7 @@ dependencies { compile "com.android.support:recyclerview-v7:$dependencyVersions.androidSupportLibrary" compile "com.android.support:cardview-v7:$dependencyVersions.androidSupportLibrary" compile "com.android.support:design:$dependencyVersions.androidSupportLibrary" + compile "com.android.support:customtabs:$dependencyVersions.androidSupportLibrary" // Dagger 2 apt "com.squareup:javapoet:$dependencyVersions.javaPoet" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ca94cc67..ba90b432 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,23 +13,24 @@ ~ 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. - --> - +--> + xmlns:tools="http://schemas.android.com/tools" + package="com.futurice.freesound"> - + @@ -37,12 +38,29 @@ - - + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/app/src/main/java/com/futurice/freesound/feature/home/HomeFragment.java b/app/src/main/java/com/futurice/freesound/feature/home/HomeFragment.java index d415aaf6..a5197ba4 100644 --- a/app/src/main/java/com/futurice/freesound/feature/home/HomeFragment.java +++ b/app/src/main/java/com/futurice/freesound/feature/home/HomeFragment.java @@ -26,52 +26,43 @@ import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import javax.inject.Inject; import butterknife.BindView; -import butterknife.Unbinder; import io.reactivex.disposables.CompositeDisposable; -import polanski.option.AtomicOption; import timber.log.Timber; -import static butterknife.ButterKnife.bind; import static com.futurice.freesound.common.utils.Preconditions.get; public final class HomeFragment extends BindingBaseFragment { - @Nullable @Inject HomeFragmentViewModel homeFragmentViewModel; - @Nullable @Inject Picasso picasso; - @Nullable @Inject SchedulerProvider schedulerProvider; - @Nullable @BindView(R.id.avatar_image) ImageView avatarImage; - @Nullable @BindView(R.id.username_textView) TextView userName; - @Nullable @BindView(R.id.about_textView) TextView about; - @NonNull - private final AtomicOption unbinder = new AtomicOption<>(); + @BindView(R.id.login_button) + Button login; @NonNull private final DataBinder dataBinder = new DataBinder() { @@ -118,19 +109,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, return inflater.inflate(R.layout.fragment_home, container, false); } - @Override - public void onViewCreated(final View view, @Nullable final Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - unbinder.setIfNone(bind(this, view)); - } - - @Override - public void onDestroyView() { - unbinder.getAndClear() - .ifSome(Unbinder::unbind); - super.onDestroyView(); - } - @Override public void inject() { component().inject(this); diff --git a/app/src/main/java/com/futurice/freesound/feature/login/LoginActivity.java b/app/src/main/java/com/futurice/freesound/feature/login/LoginActivity.java new file mode 100644 index 00000000..2cdfec1c --- /dev/null +++ b/app/src/main/java/com/futurice/freesound/feature/login/LoginActivity.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Futurice GmbH + * + * 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.futurice.freesound.feature.login; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +import javax.inject.Inject; + +import polanski.option.Option; +import polanski.option.function.Action0; + +public class LoginActivity extends AppCompatActivity { + + @Inject + OAuthLoginProvider oAuthLoginProvider; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + Uri uri = intent.getData(); + + Option.ofObj(uri.toString()) + .ifSome(__ -> handleAuthCallback(uri)) + .ifNone(cancelAuthRequest()); + + } + + private Action0 cancelAuthRequest() { + oAuthLoginProvider.cancel(); + } + + private void handleAuthCallback(final Uri uri) { + Option code = Option + .ofObj(uri.getQueryParameter(LoginConstants.CODE_AUTH_CALLBACK_QUERY_PARAMETER); + Option error = Option + .ofObj(uri.getQueryParameter(LoginConstants.ERROR_AUTH_CALLBACK_QUERY_PARAMETER); + oAuthLoginProvider.handleAuthorizationResponse(code, error); + } +} +} diff --git a/app/src/main/java/com/futurice/freesound/feature/login/LoginConstants.java b/app/src/main/java/com/futurice/freesound/feature/login/LoginConstants.java new file mode 100644 index 00000000..f5349cd2 --- /dev/null +++ b/app/src/main/java/com/futurice/freesound/feature/login/LoginConstants.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Futurice GmbH + * + * 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.futurice.freesound.feature.login; + +import com.futurice.freesound.common.InstantiationForbiddenError; + +final class LoginConstants { + + static final String CLIENT_ID_AUTH_REQUEST_QUERY_PARAMETER = "client_id"; + static final String RESPONSE_TYPE_AUTH_REQUEST_QUERY_PARAMETER = "response_type"; + + static final String CODE_AUTH_CALLBACK_QUERY_PARAMETER = "code"; + static final String ERROR_AUTH_CALLBACK_QUERY_PARAMETER = "error"; + + private LoginConstants() { + throw new InstantiationForbiddenError(); + } +} diff --git a/app/src/main/java/com/futurice/freesound/feature/login/LoginFragment.java b/app/src/main/java/com/futurice/freesound/feature/login/LoginFragment.java new file mode 100644 index 00000000..1e09dd37 --- /dev/null +++ b/app/src/main/java/com/futurice/freesound/feature/login/LoginFragment.java @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Futurice GmbH + * + * 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.futurice.freesound.feature.login; + +import com.futurice.freesound.core.BindingBaseFragment; +import com.futurice.freesound.viewmodel.DataBinder; +import com.futurice.freesound.viewmodel.ViewModel; + +import android.support.annotation.NonNull; + +/** + * Created by ptac on 19/02/17. + */ + +public class LoginFragment extends BindingBaseFragment<> { + + @NonNull + @Override + protected ViewModel viewModel() { + return null; + } + + @NonNull + @Override + protected DataBinder dataBinder() { + return null; + } + + @NonNull + @Override + protected Object createComponent() { + return null; + } + + @Override + public void inject() { + + } +} diff --git a/app/src/main/java/com/futurice/freesound/feature/login/OAuthLoginProvider.java b/app/src/main/java/com/futurice/freesound/feature/login/OAuthLoginProvider.java new file mode 100644 index 00000000..a8078333 --- /dev/null +++ b/app/src/main/java/com/futurice/freesound/feature/login/OAuthLoginProvider.java @@ -0,0 +1,81 @@ +/* + * Copyright 2017 Futurice GmbH + * + * 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.futurice.freesound.feature.login; + +import android.app.Activity; +import android.net.Uri; +import android.support.annotation.NonNull; +import android.support.customtabs.CustomTabsIntent; + +import io.reactivex.Completable; +import io.reactivex.Observable; +import polanski.option.Option; + +final class OAuthLoginProvider { + + @NonNull + Completable attemptAuthorize(Activity fromActivity) { + return Completable.fromAction(() -> openAuthorizationUrl(fromActivity); + } + + @NonNull + Completable handleAuthorizationResponse(@NonNull final Option code, + @NonNull final Option error) { + + if (code.isSome()) { + + } else if (error.isSome()) { + + } else { + cancel(); + } + // Either allow or denied. + // If allow then make request to API to get token. + // If deny show toast saying Login canceled? + // Need to show progress for login from the beginning (attemptAuthorize) so that it is smooth and continuous + // + + } + + Observable> + + void cancel() { + + } + + private void openAuthorizationUrl(Activity activity) { + Uri appAuthUrl = Uri.parse("https://www.freesound.org/apiv2/oauth2/authorize/") + .buildUpon() + .appendQueryParameter("client_id", "actualClientId") + .appendQueryParameter("response_type", "code") + .build(); + CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() + .enableUrlBarHiding() + .build(); + customTabsIntent.launchUrl(activity, appAuthUrl); + } + + // Ideally expose request status as + + // Data + // In Progress + // Failed + + // Have "SDK" that takes Activity as parameters + // Gives callbacks which are actually redirected launched Activity + // Make these callbacks actually reactive. +} diff --git a/app/src/main/java/com/futurice/freesound/feature/login/WebViewNavigationProvider.java b/app/src/main/java/com/futurice/freesound/feature/login/WebViewNavigationProvider.java new file mode 100644 index 00000000..8fbb8d73 --- /dev/null +++ b/app/src/main/java/com/futurice/freesound/feature/login/WebViewNavigationProvider.java @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Futurice GmbH + * + * 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.futurice.freesound.feature.login; + +/** + * Created by ptac on 14/02/17. + */ + +public class WebViewNavigationProvider { + + +} diff --git a/app/src/main/java/com/futurice/freesound/feature/search/SearchActivity.java b/app/src/main/java/com/futurice/freesound/feature/search/SearchActivity.java index 4c85519f..3ec9052a 100644 --- a/app/src/main/java/com/futurice/freesound/feature/search/SearchActivity.java +++ b/app/src/main/java/com/futurice/freesound/feature/search/SearchActivity.java @@ -146,27 +146,10 @@ public void onCreate(Bundle savedInstanceState) { } - @NonNull - private static Observable getTextChangeStream(@NonNull final SearchView view, - @NonNull final Scheduler uiScheduler) { - return Observable.create(e -> subscribeToSearchView(view, e)) - .subscribeOn(uiScheduler); - } - - private static void subscribeToSearchView(@NonNull final SearchView view, - @NonNull final ObservableEmitter emitter) { - view.setOnQueryTextListener(new OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(final String query) { - return false; - } - - @Override - public boolean onQueryTextChange(final String newText) { - emitter.onNext(get(newText)); - return true; - } - }); + @Override + public void onPause() { + dismissSnackbar(); + super.onPause(); } @NonNull @@ -203,12 +186,6 @@ private void addSearchFragment() { .commit(); } - @Override - public void onPause() { - dismissSnackbar(); - super.onPause(); - } - private void showSnackbar(@NonNull final CharSequence charSequence) { checkNotNull(charSequence); get(searchSnackbar).showNewSnackbar(get(coordinatorLayout), charSequence); @@ -217,4 +194,27 @@ private void showSnackbar(@NonNull final CharSequence charSequence) { private void dismissSnackbar() { get(searchSnackbar).dismissSnackbar(); } + + @NonNull + private static Observable getTextChangeStream(@NonNull final SearchView view, + @NonNull final Scheduler uiScheduler) { + return Observable.create(e -> subscribeToSearchView(view, e)) + .subscribeOn(uiScheduler); + } + + private static void subscribeToSearchView(@NonNull final SearchView view, + @NonNull final ObservableEmitter emitter) { + view.setOnQueryTextListener(new OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(final String query) { + return false; + } + + @Override + public boolean onQueryTextChange(final String newText) { + emitter.onNext(get(newText)); + return true; + } + }); + } } diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 01534058..a60acc92 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -45,4 +45,10 @@ android:layout_alignParentEnd="true" android:layout_toEndOf="@+id/avatar_image" tools:text="About"/> +