├── .gitignore ├── .travis.yml ├── LICENSE.md ├── README.md ├── app ├── .gitignore ├── app-config.gradle ├── build.gradle ├── google-services.json ├── keystore │ └── debug.keystore ├── proguard-rules │ ├── android-support-rules.pro │ ├── autovalue-rules.pro │ ├── okhttp3-rules.pro │ ├── okio-rules.pro │ ├── picasso-rules.pro │ ├── retrofit2-rules.pro │ └── rxjava2-rules.pro ├── quality │ ├── checkstyle.xml │ └── lint.xml └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── futurice │ │ └── freesound │ │ ├── helpers │ │ └── ParcelableExtensions.kt │ │ └── network │ │ └── api │ │ └── model │ │ └── SoundParcelTest.kt │ ├── debug │ └── java │ │ └── com │ │ └── futurice │ │ └── freesound │ │ ├── feature │ │ └── logging │ │ │ └── LoggingModule.java │ │ └── network │ │ └── api │ │ └── InstrumentationModule.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── futurice │ │ │ └── freesound │ │ │ ├── app │ │ │ ├── FreesoundApplication.java │ │ │ ├── FreesoundApplicationComponent.java │ │ │ └── FreesoundApplicationModule.java │ │ │ ├── arch │ │ │ ├── core │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseApplication.java │ │ │ │ └── BaseFragment.java │ │ │ ├── mvi │ │ │ │ ├── LoggingTransitionObserver.kt │ │ │ │ ├── Mvi.kt │ │ │ │ ├── Transitions.kt │ │ │ │ ├── view │ │ │ │ │ ├── Binder.kt │ │ │ │ │ ├── MviBaseFragment.kt │ │ │ │ │ └── MviView.kt │ │ │ │ └── viewmodel │ │ │ │ │ ├── BaseViewModel.kt │ │ │ │ │ ├── MviViewModel.kt │ │ │ │ │ ├── ReducerViewModel.kt │ │ │ │ │ ├── UglyViewModelProviderBridge.kt │ │ │ │ │ ├── ViewModelExtensions.kt │ │ │ │ │ └── ViewModels.kt │ │ │ └── mvvm │ │ │ │ ├── BaseLifecycleViewDataBinder.java │ │ │ │ ├── BaseViewModel.java │ │ │ │ ├── DataBinder.java │ │ │ │ ├── LifecycleDataBinder.java │ │ │ │ ├── SimpleDataBinder.java │ │ │ │ ├── SimpleViewModel.java │ │ │ │ ├── ViewModel.java │ │ │ │ ├── view │ │ │ │ ├── MvvmBaseActivity.java │ │ │ │ └── MvvmBaseFragment.java │ │ │ │ └── viewholder │ │ │ │ ├── AbstractBindingViewHolder.java │ │ │ │ └── BaseBindingViewHolder.java │ │ │ ├── common │ │ │ ├── InstantiationForbiddenError.java │ │ │ ├── Releasable.java │ │ │ ├── Text.java │ │ │ ├── functional │ │ │ │ ├── Functions.java │ │ │ │ ├── OptionFunctions.java │ │ │ │ └── StringFunctions.java │ │ │ ├── rx │ │ │ │ ├── DisposableExtensions.kt │ │ │ │ └── TimeScheduler.java │ │ │ └── utils │ │ │ │ ├── AndroidPreconditions.java │ │ │ │ ├── ExceptionHelper.java │ │ │ │ ├── Preconditions.java │ │ │ │ ├── StandardExtensions.kt │ │ │ │ └── TextUtils.java │ │ │ ├── feature │ │ │ ├── analytics │ │ │ │ ├── Analytics.kt │ │ │ │ ├── AnalyticsModule.kt │ │ │ │ └── FirebaseAnalytics.kt │ │ │ ├── audio │ │ │ │ ├── AudioModule.java │ │ │ │ ├── AudioPlayer.java │ │ │ │ ├── BaseAudioPlayerEventListener.java │ │ │ │ ├── DefaultObservableExoPlayer.java │ │ │ │ ├── ExoPlayerAudioPlayer.java │ │ │ │ ├── ExoPlayerProgressObservable.java │ │ │ │ ├── ExoPlayerState.kt │ │ │ │ ├── ExoPlayerStateObservable.java │ │ │ │ ├── Id.kt │ │ │ │ ├── MediaSourceFactory.java │ │ │ │ ├── ObservableExoPlayer.java │ │ │ │ ├── PlaybackSource.kt │ │ │ │ └── PlayerState.kt │ │ │ ├── common │ │ │ │ ├── DefaultNavigator.java │ │ │ │ ├── DisplayableItem.kt │ │ │ │ ├── Navigator.java │ │ │ │ ├── scheduling │ │ │ │ │ ├── DefaultSchedulerProvider.java │ │ │ │ │ ├── SchedulerProvider.java │ │ │ │ │ └── SchedulingModule.java │ │ │ │ ├── streams │ │ │ │ │ ├── Events.kt │ │ │ │ │ └── InteractorExtensions.kt │ │ │ │ ├── ui │ │ │ │ │ └── adapter │ │ │ │ │ │ ├── DiffUtilCallback.java │ │ │ │ │ │ ├── ItemComparator.java │ │ │ │ │ │ ├── RecyclerViewAdapter.java │ │ │ │ │ │ ├── ViewHolderBinder.java │ │ │ │ │ │ └── ViewHolderFactory.java │ │ │ │ └── waveform │ │ │ │ │ ├── BlackBackgroundWaveformExtractor.java │ │ │ │ │ ├── PlaybackWaveformView.java │ │ │ │ │ ├── WaveformExtractor.java │ │ │ │ │ ├── WaveformRender.java │ │ │ │ │ ├── WaveformView.java │ │ │ │ │ └── WaveformViewTarget.java │ │ │ ├── details │ │ │ │ └── DetailsActivity.kt │ │ │ ├── home │ │ │ │ ├── HomeActivity.kt │ │ │ │ ├── HomeActivityComponent.java │ │ │ │ ├── HomeActivityModule.java │ │ │ │ ├── HomeViewModel.kt │ │ │ │ └── user │ │ │ │ │ ├── HomeFragment.kt │ │ │ │ │ ├── HomeFragmentComponent.java │ │ │ │ │ ├── HomeFragmentModule.java │ │ │ │ │ ├── HomeFragmentViewModel.kt │ │ │ │ │ ├── HomeUserInteractor.kt │ │ │ │ │ ├── HomeUserUiReducer.kt │ │ │ │ │ └── RefreshInteractor.kt │ │ │ ├── images │ │ │ │ ├── ImagesModule.kt │ │ │ │ ├── PicassoTransformations.kt │ │ │ │ └── RoundEdgeTransformation.kt │ │ │ ├── search │ │ │ │ ├── DefaultSearchDataModel.java │ │ │ │ ├── SearchActivity.kt │ │ │ │ ├── SearchActivityComponent.java │ │ │ │ ├── SearchActivityModule.java │ │ │ │ ├── SearchActivityViewModel.kt │ │ │ │ ├── SearchConstants.java │ │ │ │ ├── SearchDataModel.java │ │ │ │ ├── SearchFragment.kt │ │ │ │ ├── SearchFragmentComponent.java │ │ │ │ ├── SearchFragmentModule.java │ │ │ │ ├── SearchFragmentViewModel.java │ │ │ │ ├── SearchQuery.java │ │ │ │ ├── SearchResultItemComparator.java │ │ │ │ ├── SearchSnackbar.java │ │ │ │ ├── SearchState.java │ │ │ │ ├── SoundItemViewHolder.java │ │ │ │ └── SoundItemViewModel.kt │ │ │ └── user │ │ │ │ ├── UserModule.java │ │ │ │ └── UserRepository.kt │ │ │ ├── inject │ │ │ ├── Injector.java │ │ │ ├── activity │ │ │ │ ├── ActivityScope.java │ │ │ │ ├── BaseActivityComponent.java │ │ │ │ ├── BaseActivityModule.java │ │ │ │ └── ForActivity.java │ │ │ ├── app │ │ │ │ ├── BaseApplicationComponent.java │ │ │ │ ├── BaseApplicationModule.java │ │ │ │ └── ForApplication.java │ │ │ └── fragment │ │ │ │ ├── BaseFragmentComponent.java │ │ │ │ ├── BaseFragmentModule.java │ │ │ │ └── FragmentScope.java │ │ │ ├── network │ │ │ └── api │ │ │ │ ├── ApiConfigModule.java │ │ │ │ ├── ApiConstants.java │ │ │ │ ├── ApiModule.java │ │ │ │ ├── ApiNetworkModule.java │ │ │ │ ├── DefaultFreeSoundApiService.java │ │ │ │ ├── FreeSoundApi.java │ │ │ │ ├── FreeSoundApiInterceptor.java │ │ │ │ ├── FreeSoundApiService.java │ │ │ │ └── model │ │ │ │ ├── AccessToken.kt │ │ │ │ ├── Avatar.kt │ │ │ │ ├── GeoLocation.kt │ │ │ │ ├── Requests.kt │ │ │ │ ├── Sound.kt │ │ │ │ ├── SoundFields.java │ │ │ │ ├── SoundSearchResult.kt │ │ │ │ ├── User.kt │ │ │ │ └── mapping │ │ │ │ ├── FreesoundDateAdapter.kt │ │ │ │ └── GeoLocationJsonAdapter.kt │ │ │ └── store │ │ │ ├── Cache.kt │ │ │ └── Store.kt │ └── res │ │ ├── drawable-hdpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── drawable │ │ ├── avatar_placeholder.xml │ │ └── ic_search_white_24px.xml │ │ ├── layout │ │ ├── activity_home.xml │ │ ├── activity_search.xml │ │ ├── fragment_home.xml │ │ ├── fragment_search.xml │ │ ├── view_playbackwaveform.xml │ │ └── view_sound_item.xml │ │ ├── menu │ │ └── home.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── release │ └── java │ │ └── com │ │ └── futurice │ │ └── freesound │ │ ├── feature │ │ └── logging │ │ │ ├── ErrorReporter.java │ │ │ ├── FirebaseErrorReporter.java │ │ │ ├── FirebaseReleaseTree.java │ │ │ └── LoggingModule.java │ │ └── network │ │ └── api │ │ └── InstrumentationModule.java │ ├── test │ ├── java │ │ └── com │ │ │ └── futurice │ │ │ └── freesound │ │ │ ├── common │ │ │ ├── functional │ │ │ │ ├── FunctionsTest.java │ │ │ │ ├── OptionFunctionsTest.java │ │ │ │ └── StringFunctionsTest.java │ │ │ └── utils │ │ │ │ ├── PreconditionsTest.java │ │ │ │ └── TextUtilsTest.java │ │ │ ├── feature │ │ │ ├── audio │ │ │ │ ├── DefaultObservableExoPlayerTest.java │ │ │ │ ├── ExoPlayerAudioPlayerTest.java │ │ │ │ ├── ExoPlayerProgressObservableTest.java │ │ │ │ └── ExoPlayerStateObservableTest.java │ │ │ ├── home │ │ │ │ └── HomeFragmentViewModelTest.kt │ │ │ └── search │ │ │ │ ├── DefaultSearchDataModelTest.java │ │ │ │ ├── SearchActivityViewModelTest.java │ │ │ │ ├── SearchFragmentViewModelTest.java │ │ │ │ └── SoundItemViewModelTest.kt │ │ │ ├── network │ │ │ └── api │ │ │ │ ├── DefaultFreeSoundApiServiceTest.kt │ │ │ │ ├── FreeSoundApiInterceptorTest.java │ │ │ │ └── model │ │ │ │ ├── RequestsTest.java │ │ │ │ └── mapping │ │ │ │ └── FreesoundDateAdapterTest.kt │ │ │ ├── store │ │ │ └── CacheTest.kt │ │ │ └── test │ │ │ ├── KotlinMock.kt │ │ │ ├── assertion │ │ │ ├── livedata │ │ │ │ ├── LiveDataAssertion.kt │ │ │ │ └── LiveDataAssertions.kt │ │ │ └── rx │ │ │ │ └── RxJava2OptionAssertions.java │ │ │ ├── data │ │ │ └── TestData.kt │ │ │ └── rx │ │ │ ├── TimeSkipScheduler.java │ │ │ └── TrampolineSchedulerProvider.java │ └── resources │ │ └── mockito-extensions │ │ └── org.mockito.plugins.MockMaker │ ├── testDebug │ └── java │ │ └── com │ │ └── futurice │ │ └── freesound │ │ └── feature │ │ ├── common │ │ └── ui │ │ │ └── adapter │ │ │ └── RecyclerViewAdapterTest.java │ │ └── logging │ │ └── LoggingModuleTest.java │ └── testRelease │ └── java │ └── com │ └── futurice │ └── freesound │ ├── feature │ └── logging │ │ ├── FirebaseReleaseTreeTest.java │ │ └── LoggingModuleTest.java │ └── network │ └── api │ └── InstrumentationModuleTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── ide └── android-studio │ ├── code-style │ └── freesound-code-style.xml │ └── copyright │ ├── Futurice_GmbH_Apache_2_0.xml │ └── profiles_settings.xml ├── screenshots └── screenshot1.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/android 2 | # and updated 3 | 4 | ### Android ### 5 | # Built application files 6 | *.apk 7 | *.ap_ 8 | 9 | # Files for the ART/Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | /local.properties 27 | 28 | # Proguard folder generated by Eclipse 29 | proguard/ 30 | 31 | # Log Files 32 | *.log 33 | 34 | # Android Studio Navigation editor temp files 35 | .navigation/ 36 | 37 | # Android Studio captures folder 38 | captures/ 39 | 40 | # Intellij 41 | *.iml 42 | .idea/workspace.xml 43 | .idea/libraries 44 | .idea 45 | 46 | # Keystore files 47 | *.jks 48 | 49 | ### Android Patch ### 50 | gen-external-apklibs 51 | 52 | # Mac autogenerated files 53 | .DS_Store 54 | 55 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | gradle.properties 3 | *.iml 4 | 5 | # Keep API keys out of repository 6 | freesound-api.properties -------------------------------------------------------------------------------- /app/app-config.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | ext { 18 | // Freesound API 19 | freesound_api_client_id = getFreesoundApiClientId() 20 | freesound_api_client_secret = getFreesoundApiClientSecret() 21 | freesound_api_url = "\"https://www.freesound.org/apiv2/\"" 22 | } 23 | 24 | String getFreesoundApiClientId() { 25 | return getProperty("freesound.api.clientId", "FREESOUND_API_CLIENT_ID") 26 | } 27 | 28 | String getFreesoundApiClientSecret() { 29 | return getProperty("freesound.api.clientSecret", "FREESOUND_API_CLIENT_SECRET") 30 | } 31 | 32 | String getProperty(String property, String envVariable) { 33 | String value = isCiBuild() ? fromEnv(envVariable) : fromFile(property); 34 | if (value == null || value.isEmpty()) { 35 | throw new IllegalStateException( 36 | "Could not find property: " + property + " value in property file or environment") 37 | } 38 | return "\"$value\"" 39 | } 40 | 41 | private boolean isCiBuild() { 42 | fromEnv("TRAVIS") == "true" 43 | } 44 | 45 | private static fromEnv(String property) { 46 | System.getenv(property) 47 | } 48 | 49 | private String fromFile(String property) { 50 | Properties apiProperties = loadFileProperties("$projectDir/freesound-api.properties") 51 | return apiProperties.getProperty(property) 52 | } 53 | 54 | Properties loadFileProperties(String fileLocation) { 55 | Properties properties = new Properties() 56 | try { 57 | properties.load(new FileInputStream(fileLocation)) 58 | } catch (FileNotFoundException fnf) { 59 | logger.log(LogLevel.ERROR, 60 | String.format("Missing Freesound API properties file: %s", fileLocation), 61 | fnf) 62 | throw fnf 63 | } 64 | return properties 65 | } 66 | -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "922134086853", 4 | "firebase_url": "https://freesound-3cb57.firebaseio.com", 5 | "project_id": "freesound-3cb57", 6 | "storage_bucket": "freesound-3cb57.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:922134086853:android:4de0d66623460057", 12 | "android_client_info": { 13 | "package_name": "com.futurice.freesound" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "922134086853-pddgj9u46rrrj6lm8lgdahf16hknqu10.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzaSyCOuH2Vs40j602-X_d9uIR9lgPLvnyBySg" 25 | } 26 | ], 27 | "services": { 28 | "analytics_service": { 29 | "status": 1 30 | }, 31 | "appinvite_service": { 32 | "status": 1, 33 | "other_platform_oauth_client": [] 34 | }, 35 | "ads_service": { 36 | "status": 2 37 | } 38 | } 39 | }, 40 | { 41 | "client_info": { 42 | "mobilesdk_app_id": "1:922134086853:android:b630009f5ca23311", 43 | "android_client_info": { 44 | "package_name": "com.futurice.freesound.debug" 45 | } 46 | }, 47 | "oauth_client": [ 48 | { 49 | "client_id": "922134086853-pddgj9u46rrrj6lm8lgdahf16hknqu10.apps.googleusercontent.com", 50 | "client_type": 3 51 | } 52 | ], 53 | "api_key": [ 54 | { 55 | "current_key": "AIzaSyCOuH2Vs40j602-X_d9uIR9lgPLvnyBySg" 56 | } 57 | ], 58 | "services": { 59 | "analytics_service": { 60 | "status": 1 61 | }, 62 | "appinvite_service": { 63 | "status": 1, 64 | "other_platform_oauth_client": [] 65 | }, 66 | "ads_service": { 67 | "status": 2 68 | } 69 | } 70 | } 71 | ], 72 | "configuration_version": "1" 73 | } 74 | -------------------------------------------------------------------------------- /app/keystore/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurice/freesound-android/2367d130a42d3acd2d863325a6dc694e2d551665/app/keystore/debug.keystore -------------------------------------------------------------------------------- /app/proguard-rules/android-support-rules.pro: -------------------------------------------------------------------------------- 1 | -dontwarn android.support.design.** 2 | -dontwarn android.support.v4.** 3 | -dontwarn android.support.v7.** 4 | 5 | -keep class android.support.design.** { *; } 6 | -keep class android.support.v4.** { *; } 7 | -keep class android.support.v7.** { *; } 8 | -keep interface android.support.v7.** { *; } 9 | 10 | -keep public class android.support.v7.widget.** { *; } 11 | -keep public class android.support.v7.internal.widget.** { *; } 12 | -keep public class android.support.v7.internal.view.menu.** { *; } 13 | 14 | -keep public class * extends android.support.v4.view.ActionProvider { 15 | public (android.content.Context); 16 | } 17 | -------------------------------------------------------------------------------- /app/proguard-rules/autovalue-rules.pro: -------------------------------------------------------------------------------- 1 | -dontwarn com.google.auto.** 2 | -dontwarn autovalue.shaded.com.** 3 | -dontwarn sun.misc.Unsafe 4 | -dontwarn javax.lang.model.element.Modifier 5 | -------------------------------------------------------------------------------- /app/proguard-rules/okhttp3-rules.pro: -------------------------------------------------------------------------------- 1 | # OkHttp3 rules from https://github.com/krschultz/android-proguard-snippets/blob/master/libraries/proguard-square-okhttp3.pro 2 | -keepattributes Signature 3 | -keepattributes *Annotation* 4 | -keep class okhttp3.** { *; } 5 | -keep interface okhttp3.** { *; } 6 | -dontwarn okhttp3.** 7 | -------------------------------------------------------------------------------- /app/proguard-rules/okio-rules.pro: -------------------------------------------------------------------------------- 1 | # Okio rules from https://github.com/krschultz/android-proguard-snippets/blob/master/libraries/proguard-square-okio.pro 2 | #-keep class sun.misc.Unsafe { *; } 3 | -dontwarn java.nio.file.* 4 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 5 | -dontwarn okio.** 6 | -------------------------------------------------------------------------------- /app/proguard-rules/picasso-rules.pro: -------------------------------------------------------------------------------- 1 | # Picasso rules from https://github.com/krschultz/android-proguard-snippets/blob/master/libraries/proguard-square-picasso.pro 2 | -dontwarn com.squareup.okhttp.** 3 | -------------------------------------------------------------------------------- /app/proguard-rules/retrofit2-rules.pro: -------------------------------------------------------------------------------- 1 | # Retrofit 2 rules from https://github.com/krschultz/android-proguard-snippets/blob/master/libraries/proguard-square-retrofit2.pro 2 | -dontwarn retrofit2.** 3 | -keep class retrofit2.** { *; } 4 | -keepattributes Signature 5 | -keepattributes Exceptions 6 | 7 | -keepclasseswithmembers class * { 8 | @retrofit2.http.* ; 9 | } 10 | 11 | # Keep the pojos and enums used by GSON 12 | -keep class com.futurice.freesound.network.api.model.** { *; } 13 | -------------------------------------------------------------------------------- /app/proguard-rules/rxjava2-rules.pro: -------------------------------------------------------------------------------- 1 | # Currently no rules for RxJava2. Will update when necessary and when RxJava2 is more stable. 2 | -------------------------------------------------------------------------------- /app/quality/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/quality/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/futurice/freesound/helpers/ParcelableExtensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.helpers 18 | 19 | import android.os.Bundle 20 | import android.os.Parcel 21 | import android.os.Parcelable 22 | 23 | inline fun R.testParcel(): R = 24 | marshallParcelable(this) 25 | .let { unmarshallParcelable(it) } 26 | 27 | inline fun marshallParcelable(parcelable: R): ByteArray = 28 | Bundle().apply { putParcelable(R::class.java.name, parcelable) } 29 | .let { marshall(it) } 30 | 31 | fun marshall(bundle: Bundle): ByteArray = 32 | Parcel.obtain().use { 33 | it.writeBundle(bundle) 34 | it.marshall() 35 | } 36 | 37 | inline fun unmarshallParcelable(bytes: ByteArray): R = unmarshall(bytes) 38 | .readBundle() 39 | .run { 40 | classLoader = R::class.java.classLoader 41 | getParcelable(R::class.java.name) 42 | } 43 | 44 | fun unmarshall(bytes: ByteArray): Parcel = 45 | Parcel.obtain().apply { 46 | unmarshall(bytes, 0, bytes.size) 47 | setDataPosition(0) 48 | } 49 | 50 | private fun Parcel.use(block: (Parcel) -> T): T = 51 | try { 52 | block(this) 53 | } finally { 54 | this.recycle() 55 | } 56 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/futurice/freesound/network/api/model/SoundParcelTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api.model 18 | 19 | import android.support.test.filters.SmallTest 20 | import android.support.test.runner.AndroidJUnit4 21 | import com.futurice.freesound.helpers.testParcel 22 | import org.assertj.core.api.Assertions.assertThat 23 | import org.junit.Test 24 | import org.junit.runner.RunWith 25 | import java.util.* 26 | 27 | @RunWith(AndroidJUnit4::class) 28 | @SmallTest 29 | class SoundParcelTest { 30 | 31 | @Test 32 | fun sound_is_parcelable() { 33 | val images = Image("medWav", "largeWav", 34 | "medSpec", "largeSpec") 35 | val preview = Preview("lowMp3", "highMp3", 36 | "lowOgg", "highOgg") 37 | 38 | val sound = Sound( 39 | id = 123L, 40 | url = "url", 41 | name = "name", 42 | tags = listOf("abc", "123"), 43 | description = "desc", 44 | geotag = GeoLocation(1.0, 2.0), 45 | username = "username", 46 | images = images, 47 | previews = preview, 48 | duration = 5.0F, 49 | created = Date(1000) 50 | ) 51 | 52 | sound.testParcel() 53 | .apply { 54 | assertThat(this).isEqualTo(sound) 55 | assertThat(this).isNotSameAs(sound) 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/debug/java/com/futurice/freesound/feature/logging/LoggingModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.logging; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import dagger.Module; 22 | import dagger.Provides; 23 | import timber.log.Timber; 24 | 25 | @Module 26 | public class LoggingModule { 27 | 28 | @Provides 29 | @Singleton 30 | static Timber.Tree provideLoggingTree() { 31 | return new Timber.DebugTree(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 23 | 31 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/app/FreesoundApplicationComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.app; 18 | 19 | import com.futurice.freesound.feature.analytics.Analytics; 20 | import com.futurice.freesound.feature.common.scheduling.SchedulerProvider; 21 | import com.futurice.freesound.feature.home.HomeActivityComponent; 22 | import com.futurice.freesound.feature.search.SearchActivityComponent; 23 | import com.futurice.freesound.feature.user.UserRepository; 24 | import com.futurice.freesound.inject.activity.BaseActivityModule; 25 | import com.futurice.freesound.inject.app.BaseApplicationComponent; 26 | import com.futurice.freesound.inject.app.ForApplication; 27 | import com.futurice.freesound.network.api.FreeSoundApiService; 28 | import com.squareup.picasso.Picasso; 29 | 30 | import android.content.Context; 31 | 32 | import javax.inject.Singleton; 33 | 34 | import dagger.Component; 35 | 36 | @Component(modules = FreesoundApplicationModule.class) 37 | @Singleton 38 | public interface FreesoundApplicationComponent extends BaseApplicationComponent { 39 | 40 | android.app.Application getApplication(); 41 | 42 | @ForApplication 43 | Context getApplicationContext(); 44 | 45 | FreeSoundApiService getFreeSoundApiService(); 46 | 47 | UserRepository getUserRepository(); 48 | 49 | Picasso getPicasso(); 50 | 51 | Analytics getAnalytics(); 52 | 53 | SchedulerProvider getSchedulerProvider(); 54 | 55 | void inject(final FreesoundApplication application); 56 | 57 | HomeActivityComponent plusHomeActivityComponent(BaseActivityModule baseActivityModule); 58 | 59 | SearchActivityComponent plusSearchActivityComponent(BaseActivityModule baseActivityModule); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/app/FreesoundApplicationModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.app; 18 | 19 | import com.futurice.freesound.feature.analytics.AnalyticsModule; 20 | import com.futurice.freesound.feature.common.scheduling.SchedulingModule; 21 | import com.futurice.freesound.feature.images.ImagesModule; 22 | import com.futurice.freesound.feature.logging.LoggingModule; 23 | import com.futurice.freesound.feature.user.UserModule; 24 | import com.futurice.freesound.inject.app.BaseApplicationModule; 25 | import com.futurice.freesound.network.api.ApiModule; 26 | 27 | import dagger.Module; 28 | 29 | @Module(includes = {BaseApplicationModule.class, 30 | ApiModule.class, 31 | ImagesModule.class, 32 | SchedulingModule.class, 33 | AnalyticsModule.class, 34 | LoggingModule.class, 35 | UserModule.class}) 36 | final class FreesoundApplicationModule { 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/core/BaseActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.core; 18 | 19 | import com.futurice.freesound.inject.Injector; 20 | 21 | import android.os.Bundle; 22 | import android.support.annotation.CallSuper; 23 | import android.support.annotation.NonNull; 24 | import android.support.annotation.Nullable; 25 | import android.support.v7.app.AppCompatActivity; 26 | 27 | /** 28 | * A base Activity which provides a dependency injection mechanism. 29 | * 30 | * @param The DI component class 31 | */ 32 | public abstract class BaseActivity extends AppCompatActivity implements Injector { 33 | 34 | private T component; 35 | 36 | @CallSuper 37 | @Override 38 | protected void onCreate(@Nullable final Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | inject(); 41 | } 42 | 43 | @NonNull 44 | @Override 45 | public T component() { 46 | if (component == null) { 47 | component = createComponent(); 48 | } 49 | return component; 50 | } 51 | 52 | @NonNull 53 | protected abstract T createComponent(); 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/core/BaseApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.core; 18 | 19 | import com.futurice.freesound.inject.Injector; 20 | 21 | import android.app.Application; 22 | import android.support.annotation.CallSuper; 23 | import android.support.annotation.NonNull; 24 | 25 | /** 26 | * A base Application which provides a dependency injection mechanism. 27 | * 28 | * @param The DI component class 29 | */ 30 | public abstract class BaseApplication extends Application implements Injector { 31 | 32 | private T component; 33 | 34 | @CallSuper 35 | @Override 36 | public void onCreate() { 37 | super.onCreate(); 38 | inject(); 39 | } 40 | 41 | @NonNull 42 | @Override 43 | public T component() { 44 | if (component == null) { 45 | component = createComponent(); 46 | } 47 | return component; 48 | } 49 | 50 | @NonNull 51 | protected abstract T createComponent(); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/core/BaseFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.core; 18 | 19 | import com.futurice.freesound.inject.Injector; 20 | 21 | import android.os.Bundle; 22 | import android.support.annotation.CallSuper; 23 | import android.support.annotation.NonNull; 24 | import android.support.annotation.Nullable; 25 | import android.support.v4.app.Fragment; 26 | 27 | /** 28 | * A base Fragment which provides a dependency injection mechanism. 29 | * 30 | * @param The DI component class 31 | */ 32 | public abstract class BaseFragment extends Fragment implements Injector { 33 | 34 | private T component; 35 | 36 | @CallSuper 37 | @Override 38 | public void onActivityCreated(@Nullable final Bundle savedInstanceState) { 39 | super.onActivityCreated(savedInstanceState); 40 | inject(); 41 | } 42 | 43 | @NonNull 44 | @Override 45 | public T component() { 46 | if (component == null) { 47 | component = createComponent(); 48 | } 49 | return component; 50 | } 51 | 52 | @NonNull 53 | protected abstract T createComponent(); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/LoggingTransitionObserver.kt: -------------------------------------------------------------------------------- 1 | package com.futurice.freesound.arch.mvi 2 | 3 | import timber.log.Timber 4 | 5 | class LoggingTransitionObserver : TransitionObserver { 6 | 7 | override fun onTransition(tag: String, transitionEvent: TransitionEvent) { 8 | when (transitionEvent) { 9 | is TransitionEvent.Event -> Timber.d("MVI|$tag| Event => $transitionEvent") 10 | is TransitionEvent.Action -> Timber.d("MVI|$tag| Action => $transitionEvent") 11 | is TransitionEvent.Result -> Timber.d("MVI|$tag| Result => $transitionEvent") 12 | is TransitionEvent.Reduce -> Timber.d("MVI|$tag| Reduce => $transitionEvent") 13 | is TransitionEvent.State -> Timber.d("MVI|$tag| State => $transitionEvent") 14 | is TransitionEvent.Error -> Timber.e(transitionEvent.throwable, "MVI|$tag| Fatal Error => $transitionEvent") 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/Mvi.kt: -------------------------------------------------------------------------------- 1 | package com.futurice.freesound.arch.mvi 2 | 3 | import io.reactivex.Flowable 4 | import io.reactivex.FlowableTransformer 5 | 6 | typealias Reducer = (S, R) -> S 7 | 8 | typealias Dispatcher = FlowableTransformer 9 | 10 | fun combine(vararg transformers: Dispatcher): Dispatcher { 11 | return Dispatcher { 12 | it.publish { actions: Flowable -> 13 | Flowable.merge(transformers.map { it2 -> actions.compose(it2) }) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/Transitions.kt: -------------------------------------------------------------------------------- 1 | package com.futurice.freesound.arch.mvi 2 | 3 | interface TransitionObserver { 4 | 5 | fun onTransition(tag: String, transitionEvent: TransitionEvent) 6 | } 7 | 8 | // FIXME This needs to represent the simple case and be expanded 9 | sealed class TransitionEvent { 10 | data class Event(val event: Any) : TransitionEvent() 11 | data class Action(val action: Any) : TransitionEvent() 12 | data class Result(val result: Any) : TransitionEvent() 13 | data class Reduce(val result: Any, val prevState: Any) : TransitionEvent() 14 | data class State(val state: Any) : TransitionEvent() 15 | data class Error(val throwable: Throwable) : TransitionEvent() 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/view/Binder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvi.view 18 | 19 | import android.arch.lifecycle.* 20 | import com.futurice.freesound.arch.mvi.viewmodel.MviViewModel 21 | 22 | /** 23 | * The MviView holds this instance. 24 | */ 25 | class Binder>(private val mviView: MviView, 26 | private val viewModel: VM, 27 | private val lifecycleOwner: LifecycleOwner) { 28 | 29 | init { 30 | lifecycleOwner.lifecycle.observeOnCreate { connect() } 31 | } 32 | 33 | private fun connect() { 34 | // Send UiEvents to the ViewModel 35 | mviView.uiEvents() 36 | .observe(lifecycleOwner, Observer { viewModel.uiEvents(it!!) }) 37 | 38 | // Send UiModels to the View 39 | viewModel.uiModels() 40 | .observe(lifecycleOwner, Observer { mviView.render(it!!) }) 41 | 42 | // Cancels asynchronous actions the view is handling 43 | lifecycleOwner.lifecycle.observeOnDestroy { mviView.cancel() } 44 | } 45 | 46 | private fun Lifecycle.observeOnDestroy(action: () -> Unit) { 47 | this.addObserver(object : LifecycleObserver { 48 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 49 | fun onDestroyed() = action() 50 | }) 51 | } 52 | 53 | private fun Lifecycle.observeOnCreate(action: () -> Unit) { 54 | this.addObserver(object : LifecycleObserver { 55 | @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) 56 | fun onCreate() = action() 57 | }) 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/view/MviBaseFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvi.view 18 | 19 | import com.futurice.freesound.arch.core.BaseFragment 20 | import com.futurice.freesound.arch.mvi.viewmodel.MviViewModel 21 | import javax.inject.Inject 22 | 23 | /** 24 | * A base Fragment which provides the binding mechanism hooks to a MviView Model. 25 | * 26 | * @param The DI component class. 27 | */ 28 | abstract class MviBaseFragment> : BaseFragment(), MviView { 29 | 30 | @Inject 31 | internal lateinit var binder: Binder 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/view/MviView.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvi.view 18 | 19 | import android.arch.lifecycle.LiveData 20 | 21 | interface MviView { 22 | fun uiEvents(): LiveData = EmptyLiveData() 23 | fun render(model: M) 24 | fun cancel() {} // nothing by default 25 | } 26 | 27 | private class EmptyLiveData : LiveData() 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/viewmodel/MviViewModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvi.viewmodel 18 | 19 | import android.arch.lifecycle.LiveData 20 | 21 | interface MviViewModel { 22 | 23 | fun uiEvents(uiEvent: E) 24 | 25 | fun uiModels(): LiveData 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/viewmodel/ReducerViewModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvi.viewmodel 18 | 19 | import com.futurice.freesound.arch.mvi.Dispatcher 20 | import com.futurice.freesound.arch.mvi.TransitionEvent 21 | import com.futurice.freesound.arch.mvi.TransitionObserver 22 | import com.futurice.freesound.feature.common.scheduling.SchedulerProvider 23 | import io.reactivex.Flowable 24 | 25 | /** 26 | * Provides the hooks to transform events->actions->results->states. 27 | * 28 | * This is a more involved version of the transformation process. 29 | */ 30 | abstract class ReducerViewModel(initialEvent: E, schedulerProvider: SchedulerProvider, 31 | transitionObserver: TransitionObserver, tag: String) 32 | : BaseViewModel(initialEvent, schedulerProvider, transitionObserver, tag) { 33 | 34 | override fun mapEventToStateStream(event: Flowable): Flowable { 35 | return event 36 | .startWith(initialEvent()) 37 | .doOnNext { onTransition(TransitionEvent.Event(it as Any)) } 38 | .map(::mapEvent) 39 | .doOnNext { onTransition(TransitionEvent.Action(it as Any)) } 40 | .compose(dispatch()) 41 | .doOnNext { onTransition(TransitionEvent.Result(it as Any)) } 42 | .compose { it.scan(initialUiState(), reduce()) } 43 | .doOnNext { onTransition(TransitionEvent.State(it as Any)) } 44 | } 45 | 46 | abstract fun initialEvent(): E 47 | 48 | abstract fun initialUiState(): S 49 | 50 | protected abstract fun mapEvent(event: E): A 51 | 52 | protected abstract fun dispatch(): Dispatcher 53 | 54 | protected abstract fun reduce(): (S, R) -> S 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/viewmodel/UglyViewModelProviderBridge.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvi.viewmodel 18 | 19 | import android.support.v4.app.Fragment 20 | 21 | // FIXME Not using this for now because it's too ugly in Java 22 | // Need this bridge for now because you can't call reified functions from Java. 23 | internal fun 24 | 25 | Fragment.createViewModel(provider: () -> BaseViewModel): BaseViewModel { 26 | return viewModelProvider(provider) 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/viewmodel/ViewModelExtensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvi.viewmodel; 18 | 19 | import io.reactivex.BackpressureStrategy 20 | import io.reactivex.Flowable 21 | import io.reactivex.Observable 22 | 23 | // For consumable values, we just take the latest if backpressure. 24 | fun Observable.asUiModelFlowable(): Flowable { 25 | return toFlowable(BackpressureStrategy.LATEST) 26 | } 27 | 28 | // For consumable values, we just take the latest if backpressure. 29 | fun Flowable.asUiModelFlowable(): Flowable { 30 | return onBackpressureLatest() 31 | } 32 | 33 | // Events from the UI are modelled as a buffering Observable. 34 | fun Observable.asUiEventFlowable(): Flowable { 35 | return toFlowable(BackpressureStrategy.BUFFER) 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvi/viewmodel/ViewModels.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvi.viewmodel 18 | 19 | import android.arch.lifecycle.ViewModel 20 | import android.arch.lifecycle.ViewModelProvider 21 | import android.arch.lifecycle.ViewModelProviders 22 | import android.support.v4.app.FragmentActivity 23 | 24 | // Fragment 25 | @Suppress("UNCHECKED_CAST") 26 | inline fun android.support.v4.app.Fragment.viewModelProvider( 27 | crossinline provider: () -> VM): VM { 28 | return ViewModelProviders.of(this, object : ViewModelProvider.Factory { 29 | override fun create(aClass: Class) = provider() as T1 30 | }).get(VM::class.java) 31 | } 32 | 33 | // Activity 34 | @Suppress("UNCHECKED_CAST") 35 | inline fun FragmentActivity.viewModelProvider( 36 | crossinline provider: () -> VM): VM { 37 | return ViewModelProviders.of(this, object : ViewModelProvider.Factory { 38 | override fun create(aClass: Class) = provider() as T1 39 | }).get(VM::class.java) 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvvm/BaseViewModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvvm; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | import io.reactivex.disposables.CompositeDisposable; 22 | 23 | public abstract class BaseViewModel implements ViewModel { 24 | 25 | private final CompositeDisposable dataDisposable = new CompositeDisposable(); 26 | 27 | @Override 28 | public final void bindToDataModel() { 29 | bind(dataDisposable); 30 | } 31 | 32 | @Override 33 | public final void unbindDataModel() { 34 | dataDisposable.clear(); 35 | unbind(); 36 | } 37 | 38 | protected abstract void bind(@NonNull final CompositeDisposable disposables); 39 | 40 | protected abstract void unbind(); 41 | 42 | @Override 43 | public final void dispose() { 44 | dataDisposable.dispose(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvvm/DataBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvvm; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | import io.reactivex.disposables.CompositeDisposable; 22 | 23 | /** 24 | * Provides the facility to bind/unbind to arbitrary data sources. 25 | */ 26 | public interface DataBinder { 27 | 28 | /** 29 | * Bind to the data source. 30 | * 31 | * @param disposables a {@link CompositeDisposable} to hold the bindings. 32 | */ 33 | void bind(@NonNull CompositeDisposable disposables); 34 | 35 | /** 36 | * Unbind from the data source. 37 | */ 38 | void unbind(); 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvvm/LifecycleDataBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvvm; 18 | 19 | interface LifecycleDataBinder extends DataBinder { 20 | 21 | void onCreate(); 22 | 23 | void onResume(); 24 | 25 | void onPause(); 26 | 27 | void onDestroyView(); 28 | 29 | void onDestroy(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvvm/SimpleDataBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvvm; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | import io.reactivex.disposables.CompositeDisposable; 22 | 23 | /** 24 | * Implements methods so that child classes don't need to declare empty implementations. 25 | */ 26 | public class SimpleDataBinder implements DataBinder { 27 | 28 | @Override 29 | public void bind(@NonNull final CompositeDisposable disposables) { 30 | // Override this when required. 31 | } 32 | 33 | @Override 34 | public void unbind() { 35 | // Override this when required. 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvvm/SimpleViewModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvvm; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | import io.reactivex.disposables.CompositeDisposable; 22 | 23 | /** 24 | * ViewModel that doesn't have a data connection. 25 | */ 26 | public class SimpleViewModel extends BaseViewModel { 27 | 28 | @Override 29 | protected void bind(@NonNull final CompositeDisposable disposables) { 30 | // Nothing - has no data source to bind to. 31 | } 32 | 33 | @Override 34 | protected void unbind() { 35 | // Nothing - has no data source to unbind from. 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvvm/ViewModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvvm; 18 | 19 | public interface ViewModel { 20 | 21 | /** 22 | * Bind the ViewModel to its data model (typically modelled Observable View data). 23 | */ 24 | void bindToDataModel(); 25 | 26 | /** 27 | * Unbind the ViewModel from its data model. 28 | */ 29 | void unbindDataModel(); 30 | 31 | /** 32 | * Permanently dispose of any resources held. 33 | * 34 | * The instance cannot be reused after this operation. 35 | */ 36 | void dispose(); 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/arch/mvvm/viewholder/AbstractBindingViewHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.arch.mvvm.viewholder; 18 | 19 | import com.futurice.freesound.arch.mvvm.ViewModel; 20 | 21 | import android.support.annotation.NonNull; 22 | import android.support.v7.widget.RecyclerView; 23 | import android.view.View; 24 | 25 | /** 26 | * A {@link android.support.v7.widget.RecyclerView.ViewHolder} which supports binding and unbinding 27 | * to a {@link ViewModel}. 28 | * 29 | * @param {@link ViewModel} type 30 | */ 31 | abstract class AbstractBindingViewHolder extends RecyclerView.ViewHolder { 32 | 33 | AbstractBindingViewHolder(final View itemView) { 34 | super(itemView); 35 | } 36 | 37 | public abstract void bind(@NonNull final T viewModel); 38 | 39 | public abstract void unbind(); 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/InstantiationForbiddenError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common; 18 | 19 | /** 20 | * An {@link Error} to be thrown to prevent unwanted instantiation of a class. 21 | */ 22 | public class InstantiationForbiddenError extends AssertionError { 23 | 24 | private static final String MESSAGE = "No instances allowed"; 25 | 26 | public InstantiationForbiddenError() { 27 | super(MESSAGE); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/Releasable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common; 18 | 19 | /** 20 | * An entity which has releasable resources. 21 | */ 22 | public interface Releasable { 23 | 24 | /** 25 | * Releases the resources. 26 | */ 27 | void release(); 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/Text.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common; 18 | 19 | /** 20 | * Simple text values available for reuse. 21 | */ 22 | public final class Text { 23 | 24 | public static final String EMPTY = ""; 25 | 26 | private Text() { 27 | throw new InstantiationForbiddenError(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/functional/StringFunctions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common.functional; 18 | 19 | import com.futurice.freesound.common.InstantiationForbiddenError; 20 | import com.futurice.freesound.common.utils.TextUtils; 21 | 22 | import android.support.annotation.NonNull; 23 | 24 | import io.reactivex.functions.Predicate; 25 | 26 | /** 27 | * Common String function implementations. 28 | */ 29 | public final class StringFunctions { 30 | 31 | /** 32 | * Returns a {@link Predicate} which evaluates if a String is null or empty. 33 | * 34 | * @return the {@link Predicate}. 35 | */ 36 | @NonNull 37 | public static Predicate isEmpty() { 38 | return TextUtils::isNullOrEmpty; 39 | } 40 | 41 | /** 42 | * Returns a {@link Predicate} which evaluates if a String is not null nor empty. 43 | * 44 | * @return the {@link Predicate}. 45 | */ 46 | @NonNull 47 | public static Predicate isNotEmpty() { 48 | return TextUtils::isNotEmpty; 49 | } 50 | 51 | private StringFunctions() { 52 | throw new InstantiationForbiddenError(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/rx/DisposableExtensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and limitations under the License. 12 | * 13 | */ 14 | 15 | package com.futurice.freesound.common.rx 16 | 17 | import io.reactivex.disposables.CompositeDisposable 18 | import io.reactivex.disposables.Disposable 19 | 20 | operator fun CompositeDisposable.plusAssign(element: T) { 21 | this.add(element) 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/rx/TimeScheduler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common.rx; 18 | 19 | import android.support.annotation.NonNull; 20 | import android.support.annotation.Nullable; 21 | 22 | import io.reactivex.Scheduler; 23 | import io.reactivex.functions.BiFunction; 24 | 25 | import static com.futurice.freesound.common.functional.Functions.apply; 26 | import static io.reactivex.schedulers.Schedulers.computation; 27 | 28 | /** 29 | * Scheduler used for time based operations. 30 | * 31 | * During normal application runtime, the computation scheduler should be used. 32 | * But during the tests, there is possibility to override it to be able to better 33 | * test time based actions. 34 | */ 35 | public final class TimeScheduler { 36 | 37 | @Nullable 38 | private static volatile BiFunction onTimeHandler = null; 39 | 40 | /** 41 | * Returns scheduler for time operations. 42 | * 43 | * @param tag Tag to be used in tests to mock the scheduler 44 | */ 45 | public static Scheduler time(@NonNull final String tag) { 46 | BiFunction f = onTimeHandler; 47 | if (f == null) { 48 | return computation(); 49 | } 50 | return apply(f, computation(), tag); 51 | } 52 | 53 | /** 54 | * Sets handler for time scheduler. 55 | * 56 | * @param handler Handler to be used 57 | */ 58 | public static void setTimeSchedulerHandler( 59 | @Nullable final BiFunction handler) { 60 | onTimeHandler = handler; 61 | } 62 | 63 | /** 64 | * Resets current scheduler handler. 65 | */ 66 | public static void reset() { 67 | onTimeHandler = null; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/utils/AndroidPreconditions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common.utils; 18 | 19 | import com.futurice.freesound.common.InstantiationForbiddenError; 20 | 21 | import android.os.Looper; 22 | 23 | import java.util.Objects; 24 | 25 | /** 26 | * Static class that provides helper methods to check Android related preconditions. 27 | */ 28 | public final class AndroidPreconditions { 29 | 30 | /** 31 | * Asserts that the current thread is a worker thread. 32 | */ 33 | public static void assertWorkerThread() { 34 | if (isMainThread()) { 35 | throw new IllegalStateException( 36 | "This task must be run on a worker thread and not on the Main thread."); 37 | } 38 | } 39 | 40 | /** 41 | * Asserts that the current thread is the Main Thread. 42 | */ 43 | public static void assertUiThread() { 44 | if (!isMainThread()) { 45 | throw new IllegalStateException( 46 | "This task must be run on the Main thread and not on a worker thread."); 47 | } 48 | } 49 | 50 | /** 51 | * Returns whether the current thread is the Android main thread 52 | * 53 | * @return true if the current thread is the main thread, otherwise; false. 54 | */ 55 | public static boolean isMainThread() { 56 | return Objects.equals(Looper.getMainLooper().getThread(), Thread.currentThread()); 57 | } 58 | 59 | private AndroidPreconditions() { 60 | throw new InstantiationForbiddenError(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/utils/ExceptionHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.futurice.freesound.common.utils; 17 | 18 | import com.futurice.freesound.common.InstantiationForbiddenError; 19 | 20 | import android.support.annotation.NonNull; 21 | 22 | /** 23 | * Utility class for exceptions. 24 | */ 25 | public final class ExceptionHelper { 26 | 27 | /** 28 | * If the provided Throwable is an Error this method 29 | * throws it, otherwise returns a RuntimeException wrapping the error 30 | * if that error is a checked exception. 31 | * 32 | * @param error the error to wrap or throw 33 | * @return the (wrapped) error 34 | */ 35 | @NonNull 36 | public static RuntimeException wrapOrThrow(@NonNull final Throwable error) { 37 | if (error instanceof Error) { 38 | throw (Error) error; 39 | } 40 | if (error instanceof RuntimeException) { 41 | return (RuntimeException) error; 42 | } 43 | return new RuntimeException(error); 44 | } 45 | 46 | private ExceptionHelper() { 47 | throw new InstantiationForbiddenError(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/utils/StandardExtensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and limitations under the License. 12 | * 13 | */ 14 | 15 | package com.futurice.freesound.common.utils 16 | 17 | inline fun T?.ifNull(block: () -> Unit) { 18 | if (this == null) block() 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/common/utils/TextUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common.utils; 18 | 19 | import com.futurice.freesound.common.InstantiationForbiddenError; 20 | 21 | import android.support.annotation.Nullable; 22 | 23 | /** 24 | * String utilities - matches those in the Android platform, but separated to allow for JVM unit 25 | * testing. 26 | */ 27 | public final class TextUtils { 28 | 29 | /** 30 | * Evaluates if the given sequence is either null or empty. 31 | * 32 | * @return true if the parameter is null or empty, false otherwise. 33 | */ 34 | public static boolean isNullOrEmpty(@Nullable final CharSequence chars) { 35 | return chars == null || chars.length() == 0; 36 | } 37 | 38 | /** 39 | * Evaluates if the given sequence is neither null nor empty. 40 | * 41 | * @return true if the parameter neither null nor empty, false otherwise. 42 | */ 43 | public static boolean isNotNullOrEmpty(@Nullable final CharSequence chars) { 44 | return !isNullOrEmpty(chars); 45 | } 46 | 47 | /** 48 | * Evaluates if the given sequence is neither null nor empty. 49 | * 50 | * @return true if the parameter has at least one char, false otherwise. 51 | */ 52 | public static boolean isNotEmpty(@Nullable final CharSequence chars) { 53 | return chars != null && chars.length() > 0; 54 | } 55 | 56 | private TextUtils() { 57 | throw new InstantiationForbiddenError(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/analytics/Analytics.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.analytics 18 | 19 | /** 20 | * Aggregates and sends events to analytics service. 21 | */ 22 | interface Analytics { 23 | 24 | /** 25 | * Sends event to analytics service. 26 | * 27 | * @param event Event name 28 | */ 29 | fun log(event: String) 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/analytics/AnalyticsModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.analytics 18 | 19 | import dagger.Module 20 | import dagger.Provides 21 | import javax.inject.Singleton 22 | 23 | @Module 24 | class AnalyticsModule { 25 | 26 | @Provides 27 | @Singleton 28 | internal fun provideAnalytics(firebaseAnalytics: FirebaseAnalytics): Analytics = 29 | firebaseAnalytics 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/analytics/FirebaseAnalytics.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.analytics 18 | 19 | import android.content.Context 20 | import android.os.Bundle 21 | import com.futurice.freesound.inject.app.ForApplication 22 | import javax.inject.Inject 23 | 24 | internal class FirebaseAnalytics @Inject 25 | constructor(@ForApplication context: Context) : Analytics { 26 | 27 | private val firebaseAnalytics: com.google.firebase.analytics.FirebaseAnalytics = 28 | com.google.firebase.analytics.FirebaseAnalytics.getInstance(context) 29 | 30 | override fun log(event: String) { 31 | val bundle = Bundle().apply { 32 | putString(SINGLE_TEST_EVENT, event) 33 | } 34 | firebaseAnalytics.logEvent(SINGLE_TEST_EVENT, bundle) 35 | } 36 | 37 | companion object { 38 | 39 | private const val SINGLE_TEST_EVENT = "SingleEvent" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/audio/AudioPlayer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.audio; 18 | 19 | import com.futurice.freesound.common.Releasable; 20 | 21 | import android.support.annotation.NonNull; 22 | 23 | import io.reactivex.Observable; 24 | 25 | /** 26 | * An AudioPlayer for URL based sources. 27 | */ 28 | public interface AudioPlayer extends Releasable { 29 | 30 | /** 31 | * Initialize the player. 32 | */ 33 | void init(); 34 | 35 | /** 36 | * Reports the initial player state and subsequent changes. 37 | * 38 | * @return A stream of the {@link PlayerState}. 39 | */ 40 | @NonNull 41 | Observable getPlayerStateOnceAndStream(); 42 | 43 | /** 44 | * Current playback time position with initial value. 45 | * 46 | * @return the Observable playback time position in milliseconds. 47 | */ 48 | @NonNull 49 | Observable getTimePositionMsOnceAndStream(); 50 | 51 | /** 52 | * Toggles the playback for the given URL. 53 | * 54 | * Starts playback if currently playing, otherwise will pause. 55 | * 56 | * @param playbackSource the audio source. 57 | */ 58 | void togglePlayback(@NonNull PlaybackSource playbackSource); 59 | 60 | /** 61 | * Stops the current playback and reset state. 62 | */ 63 | void stopPlayback(); 64 | 65 | /** 66 | * Dispose of the player, the instance cannot be reused. 67 | */ 68 | void release(); 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/audio/ExoPlayerState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.audio 18 | 19 | /** 20 | * See [com.google.android.exoplayer2.ExoPlayer] `STATE` for playbackState 21 | */ 22 | data class ExoPlayerState(val playWhenReady: Boolean, val playbackState: Int) 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/audio/Id.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.audio 18 | 19 | fun from(id: Long): Id = Id(id.toString()) 20 | 21 | data class Id(val id: String) 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/audio/MediaSourceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.audio; 18 | 19 | import com.google.android.exoplayer2.source.MediaSource; 20 | 21 | import android.support.annotation.NonNull; 22 | 23 | /** 24 | * Generates {@link MediaSource} from URIs. 25 | * 26 | * Can't be an AutoFactory because we can't annotate the ExoPlayer classes. 27 | */ 28 | interface MediaSourceFactory { 29 | 30 | /** 31 | * Creates a new instance of a {@link MediaSource}. 32 | * 33 | * @param uri The {@link MediaSource} source URI. 34 | * @return a new {@link MediaSource} instance. 35 | */ 36 | @NonNull 37 | MediaSource create(@NonNull String uri); 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/audio/ObservableExoPlayer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.audio; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | import java.util.concurrent.TimeUnit; 22 | 23 | import io.reactivex.Observable; 24 | 25 | /** 26 | * Represent the {@link com.google.android.exoplayer2.ExoPlayer} through Observables. 27 | */ 28 | interface ObservableExoPlayer { 29 | 30 | /** 31 | * ExoPlayer state {@link Observable} with initial value. 32 | * 33 | * @return the Observable {@link ExoPlayerState}. 34 | */ 35 | @NonNull 36 | Observable getExoPlayerStateOnceAndStream(); 37 | 38 | /** 39 | * ExoPlayer current playback time position with initial value. 40 | * 41 | * @return the Observable playback time position in milliseconds. 42 | */ 43 | @NonNull 44 | Observable getTimePositionMsOnceAndStream(long update, TimeUnit timeUnit); 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/audio/PlaybackSource.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.audio 18 | 19 | data class PlaybackSource(val id: Id, val url: String) 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/audio/PlayerState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.audio 18 | 19 | import polanski.option.Option 20 | 21 | enum class State { 22 | IDLE, 23 | BUFFERING, 24 | PLAYING, 25 | PAUSED, 26 | ENDED, 27 | ERROR 28 | } 29 | 30 | data class PlayerState(val state: State, val source: Option) 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/DefaultNavigator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common; 18 | 19 | import com.futurice.freesound.common.utils.AndroidPreconditions; 20 | import com.futurice.freesound.feature.search.SearchActivity; 21 | import com.futurice.freesound.network.api.model.Sound; 22 | 23 | import android.app.Activity; 24 | import android.support.annotation.NonNull; 25 | 26 | import static com.futurice.freesound.common.utils.Preconditions.get; 27 | 28 | public final class DefaultNavigator implements Navigator { 29 | 30 | @NonNull 31 | private final Activity activity; 32 | 33 | public DefaultNavigator(@NonNull final Activity activity) { 34 | this.activity = get(activity); 35 | } 36 | 37 | @Override 38 | public void openSearch() { 39 | AndroidPreconditions.assertUiThread(); 40 | 41 | SearchActivity.open(activity); 42 | } 43 | 44 | @Override 45 | public void openSoundDetails(@NonNull final Sound sound) { 46 | // TODO Via the DetailsActivity.open 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/DisplayableItem.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common 18 | 19 | /** 20 | * Wraps a model. Convenient for complex presentation layers such as 21 | * [android.support.v7.widget.RecyclerView] where different types of model are handled. 22 | */ 23 | data class DisplayableItem(val model: T, val type: Int) 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/Navigator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common; 18 | 19 | import com.futurice.freesound.network.api.model.Sound; 20 | 21 | import android.support.annotation.NonNull; 22 | 23 | public interface Navigator { 24 | 25 | void openSearch(); 26 | 27 | void openSoundDetails(@NonNull Sound sound); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/scheduling/SchedulerProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.scheduling; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | import io.reactivex.Scheduler; 22 | 23 | /** 24 | * Provides RxJava Schedulers. 25 | */ 26 | public interface SchedulerProvider { 27 | 28 | @NonNull 29 | Scheduler computation(); 30 | 31 | @NonNull 32 | Scheduler trampoline(); 33 | 34 | @NonNull 35 | Scheduler single(); 36 | 37 | @NonNull 38 | Scheduler newThread(); 39 | 40 | @NonNull 41 | Scheduler io(); 42 | 43 | @NonNull 44 | Scheduler time(@NonNull String tag); 45 | 46 | @NonNull 47 | Scheduler ui(); 48 | 49 | boolean isUiThread(); 50 | 51 | void assertUiThread(); 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/scheduling/SchedulingModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.scheduling; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import dagger.Module; 22 | import dagger.Provides; 23 | 24 | @Module 25 | public class SchedulingModule { 26 | 27 | @Provides 28 | @Singleton 29 | static SchedulerProvider provideSchedulerProvider() { 30 | return new DefaultSchedulerProvider(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/streams/Events.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.streams 18 | 19 | sealed class Fetch { 20 | class InProgress : Fetch() 21 | data class Success(val value: T) : Fetch() 22 | data class Failure(val error: Throwable) : Fetch() 23 | } 24 | 25 | sealed class Operation { 26 | object InProgress : Operation() 27 | object Complete : Operation() 28 | data class Failure(val error: Throwable) : Operation() 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/streams/InteractorExtensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.streams 18 | 19 | import io.reactivex.Observable 20 | import io.reactivex.Single 21 | 22 | fun Single.asOperation(): Observable { 23 | return toCompletable() 24 | .toObservable() 25 | .startWith(Operation.InProgress) 26 | .concatWith(Observable.just(Operation.Complete)) 27 | .onErrorResumeNext { t: Throwable -> Observable.just(Operation.Failure(t)) } 28 | } 29 | 30 | fun Observable.asFetch(): Observable> { 31 | return map { Fetch.Success(it) as Fetch } 32 | .startWith(Fetch.InProgress()) 33 | .onErrorResumeNext { t: Throwable -> Observable.just(Fetch.Failure(t)) } 34 | } 35 | 36 | fun Observable.asFetchStream(stream: Observable): Observable> { 37 | return asFetch().concatWith(stream.map { Fetch.Success(it) }) 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/ui/adapter/ItemComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.ui.adapter; 18 | 19 | import com.futurice.freesound.feature.common.DisplayableItem; 20 | 21 | public interface ItemComparator { 22 | 23 | /** 24 | * Decides whether two {@link DisplayableItem} represent the same Item. 25 | * For example, if your items have unique ids, this method should check their id equality. 26 | * 27 | * @return True if the two items represent the same object or false if they are different. 28 | */ 29 | boolean areItemsTheSame(final DisplayableItem item1, final DisplayableItem item2); 30 | 31 | /** 32 | * Checks whether the visual representation of two {@link DisplayableItem}s are the same. 33 | * 34 | * This method is called only if {@link #areItemsTheSame(DisplayableItem, DisplayableItem)} 35 | * returns {@code true} for these items. For instance, when the item is the same with different 36 | * state, like selected. 37 | * 38 | * @return True if the visual representation for the {@link DisplayableItem}s are the same or 39 | * false if they are different. 40 | */ 41 | boolean areContentsTheSame(final DisplayableItem item1, final DisplayableItem item2); 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/ui/adapter/ViewHolderBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.ui.adapter; 18 | 19 | import com.futurice.freesound.feature.common.DisplayableItem; 20 | 21 | import android.support.annotation.NonNull; 22 | import android.support.v7.widget.RecyclerView.ViewHolder; 23 | 24 | /** 25 | * Populates a {@link ViewHolder} with the model details. 26 | */ 27 | public interface ViewHolderBinder { 28 | 29 | /** 30 | * Populates the passed {@link ViewHolder} with the details of the passed 31 | * {@link DisplayableItem}. 32 | */ 33 | void bind(@NonNull final ViewHolder viewHolder, @NonNull final DisplayableItem item); 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/ui/adapter/ViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.ui.adapter; 18 | 19 | import android.content.Context; 20 | import android.support.annotation.NonNull; 21 | import android.support.v7.widget.RecyclerView.ViewHolder; 22 | import android.view.ViewGroup; 23 | 24 | /** 25 | * Instantiates a {@link ViewHolder} based on the type. 26 | */ 27 | public abstract class ViewHolderFactory { 28 | 29 | @NonNull 30 | protected final Context context; 31 | 32 | protected ViewHolderFactory(@NonNull final Context context) { 33 | this.context = context; 34 | } 35 | 36 | /** 37 | * Creates a {@link ViewHolder} 38 | * 39 | * @param parent The ViewGroup into which the new View will be added after it is bound to 40 | * an adapter position. 41 | * @return the newly created {@link ViewHolder} 42 | */ 43 | @NonNull 44 | public abstract ViewHolder createViewHolder(@NonNull final ViewGroup parent); 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/waveform/BlackBackgroundWaveformExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.waveform; 18 | 19 | import android.graphics.Bitmap; 20 | import android.graphics.Color; 21 | import android.support.annotation.NonNull; 22 | 23 | /** 24 | * Extracts the waveform from the background by evaluating that any non-waveform component is the 25 | * represented by the color black. 26 | */ 27 | public final class BlackBackgroundWaveformExtractor extends WaveformExtractor { 28 | 29 | @Override 30 | public boolean isWaveform(@NonNull final Bitmap bitmap, final int x, final int y) { 31 | return bitmap.getPixel(x, y) != Color.BLACK; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/waveform/WaveformExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.waveform; 18 | 19 | import android.graphics.Bitmap; 20 | import android.support.annotation.NonNull; 21 | 22 | import timber.log.Timber; 23 | 24 | abstract class WaveformExtractor { 25 | 26 | /** 27 | * Extracts the waveform amplitude array from the given bitmap. 28 | * 29 | * @param bitmap The source {@link Bitmap}. 30 | * @return the signed amplitude array. 31 | */ 32 | final float[] extract(@NonNull final Bitmap bitmap) { 33 | final long debugStartTime = System.currentTimeMillis(); 34 | 35 | final int width = bitmap.getWidth(); 36 | final float centreLine = bitmap.getHeight() / 2.0f; 37 | final float[] normalizedAmplitudes = new float[width]; 38 | 39 | for (int x = 0; x < width; x++) { 40 | for (int y = 0; y < centreLine; y++) { 41 | if (isWaveform(bitmap, x, y)) { 42 | normalizedAmplitudes[x] = (centreLine - y) / centreLine; 43 | break; // next sample in x. 44 | } 45 | } 46 | } 47 | Timber.d("Waveform extraction took: %d ms", System.currentTimeMillis() - debugStartTime); 48 | return normalizedAmplitudes; 49 | } 50 | 51 | protected abstract boolean isWaveform(@NonNull final Bitmap bitmap, 52 | final int x, 53 | final int y); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/waveform/WaveformRender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.waveform; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | /** 22 | * Renders a waveform, allows abstractions to the rendering for different views. 23 | */ 24 | public interface WaveformRender { 25 | 26 | /** 27 | * Renders the given waveform. 28 | * 29 | * @param waveform the waveform amplitude array, values in range [-1.0, 1.0]. 30 | */ 31 | void setWaveform(@NonNull float[] waveform); 32 | 33 | /** 34 | * Clear the waveform render. 35 | */ 36 | void clearWaveform(); 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/common/waveform/WaveformViewTarget.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.common.waveform; 18 | 19 | import com.squareup.picasso.Picasso; 20 | import com.squareup.picasso.Target; 21 | 22 | import android.graphics.Bitmap; 23 | import android.graphics.drawable.Drawable; 24 | import android.support.annotation.NonNull; 25 | 26 | import static com.futurice.freesound.common.utils.Preconditions.get; 27 | 28 | public class WaveformViewTarget implements Target { 29 | 30 | @NonNull 31 | private final WaveformRender waveformRender; 32 | 33 | @NonNull 34 | private final WaveformExtractor waveformExtractor; 35 | 36 | public WaveformViewTarget(@NonNull final WaveformRender waveformRender, 37 | @NonNull final WaveformExtractor waveformExtractor) { 38 | this.waveformRender = get(waveformRender); 39 | this.waveformExtractor = get(waveformExtractor); 40 | } 41 | 42 | @Override 43 | public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) { 44 | float[] waveform = waveformExtractor.extract(bitmap); 45 | waveformRender.setWaveform(waveform); 46 | } 47 | 48 | @Override 49 | public void onBitmapFailed(final Drawable errorDrawable) { 50 | 51 | } 52 | 53 | @Override 54 | public void onPrepareLoad(final Drawable placeHolderDrawable) { 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/details/DetailsActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.details 18 | 19 | import android.content.Context 20 | import android.content.Intent 21 | import android.support.v7.app.AppCompatActivity 22 | import com.futurice.freesound.inject.activity.ForActivity 23 | import com.futurice.freesound.network.api.model.Sound 24 | 25 | class DetailsActivity : AppCompatActivity() { 26 | companion object { 27 | 28 | private val SOUND_PARAM = "sound" 29 | 30 | fun open(@ForActivity context: Context, sound: Sound) { 31 | val intent = Intent(context, DetailsActivity::class.java).apply { 32 | putExtra(SOUND_PARAM, sound) 33 | } 34 | context.startActivity(intent) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/home/HomeActivityComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.home; 18 | 19 | import com.futurice.freesound.feature.common.Navigator; 20 | import com.futurice.freesound.feature.home.user.HomeFragmentComponent; 21 | import com.futurice.freesound.feature.home.user.HomeFragmentModule; 22 | import com.futurice.freesound.inject.activity.ActivityScope; 23 | import com.futurice.freesound.inject.activity.BaseActivityComponent; 24 | import com.futurice.freesound.inject.fragment.BaseFragmentModule; 25 | 26 | import dagger.Subcomponent; 27 | 28 | @ActivityScope 29 | @Subcomponent(modules = HomeActivityModule.class) 30 | public interface HomeActivityComponent extends BaseActivityComponent { 31 | 32 | Navigator getNavigator(); 33 | 34 | void inject(final HomeActivity activity); 35 | 36 | HomeFragmentComponent plus(HomeFragmentModule homeFragmentModule, 37 | BaseFragmentModule baseFragmentModule); 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/home/HomeActivityModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.home; 18 | 19 | import com.futurice.freesound.common.InstantiationForbiddenError; 20 | import com.futurice.freesound.feature.common.Navigator; 21 | import com.futurice.freesound.feature.common.scheduling.SchedulerProvider; 22 | import com.futurice.freesound.inject.activity.ActivityScope; 23 | import com.futurice.freesound.inject.activity.BaseActivityModule; 24 | 25 | import dagger.Module; 26 | import dagger.Provides; 27 | 28 | @Module(includes = BaseActivityModule.class) 29 | class HomeActivityModule { 30 | 31 | @Provides 32 | @ActivityScope 33 | static HomeViewModel provideHomeViewModel(Navigator navigator, 34 | SchedulerProvider schedulerProvider) { 35 | return new HomeViewModel(navigator, schedulerProvider); 36 | } 37 | 38 | private HomeActivityModule() { 39 | throw new InstantiationForbiddenError(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/home/HomeViewModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.home 18 | 19 | import com.futurice.freesound.common.rx.plusAssign 20 | import com.futurice.freesound.feature.common.Navigator 21 | import com.futurice.freesound.feature.common.scheduling.SchedulerProvider 22 | import com.futurice.freesound.arch.mvvm.SimpleViewModel 23 | import io.reactivex.disposables.CompositeDisposable 24 | import io.reactivex.subjects.PublishSubject 25 | import polanski.option.Unit 26 | import timber.log.Timber 27 | 28 | internal class HomeViewModel(val navigator: Navigator, 29 | val schedulerProvider: SchedulerProvider) : SimpleViewModel() { 30 | 31 | private val openSearchStream = PublishSubject.create() 32 | 33 | fun openSearch() { 34 | openSearchStream.onNext(Unit.DEFAULT) 35 | } 36 | 37 | override fun bind(disposables: CompositeDisposable) { 38 | disposables += 39 | openSearchStream.observeOn(schedulerProvider.ui()) 40 | .subscribe({ navigator.openSearch() }, 41 | { Timber.e(it, "Error opening search") }) 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/home/user/HomeFragmentComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.home.user; 18 | 19 | import com.futurice.freesound.inject.fragment.BaseFragmentComponent; 20 | import com.futurice.freesound.inject.fragment.FragmentScope; 21 | 22 | import dagger.Subcomponent; 23 | 24 | @FragmentScope 25 | @Subcomponent(modules = HomeFragmentModule.class) 26 | public interface HomeFragmentComponent extends BaseFragmentComponent { 27 | 28 | void inject(final HomeFragment homeFragment); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/home/user/HomeUserInteractor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.home.user 18 | 19 | import android.support.annotation.VisibleForTesting 20 | import com.futurice.freesound.feature.common.streams.Fetch 21 | import com.futurice.freesound.feature.common.streams.asFetchStream 22 | import com.futurice.freesound.feature.user.UserRepository 23 | import com.futurice.freesound.network.api.model.User 24 | import io.reactivex.Observable 25 | 26 | class HomeUserInteractor(private val userRepository: UserRepository) { 27 | 28 | companion object { 29 | @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) 30 | val HOME_USERNAME = "SpiceProgram" 31 | } 32 | 33 | /** 34 | * Emits the any current cached home user, triggers a fetch from the API and then streams 35 | * further updates. 36 | */ 37 | fun homeUserStream(): Observable> { 38 | return userRepository.user(HOME_USERNAME) 39 | .toObservable() 40 | .asFetchStream(userRepository.awaitUserStream(HOME_USERNAME)) 41 | .distinctUntilChanged() 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/home/user/HomeUserUiReducer.kt: -------------------------------------------------------------------------------- 1 | package com.futurice.freesound.feature.home.user 2 | 3 | import com.futurice.freesound.feature.common.streams.Fetch 4 | import com.futurice.freesound.feature.common.streams.Operation 5 | import com.futurice.freesound.arch.mvi.Reducer 6 | import com.futurice.freesound.network.api.model.User 7 | import timber.log.Timber 8 | 9 | val reducer: Reducer = 10 | { current: HomeUiModel, result: HomeUiResult -> current.reduceModel(result) } 11 | 12 | private fun HomeUiModel.reduceModel(result: HomeUiResult): HomeUiModel = 13 | when (result) { 14 | is HomeUiResult.NoChange -> this 15 | is HomeUiResult.UserUpdated -> reduce(result.userFetch) 16 | is HomeUiResult.Refreshed -> reduce(result.refresh) 17 | HomeUiResult.ErrorCleared -> copy(errorMsg = null) 18 | }.also { Timber.d("Result: $result was reduced to: $it") } 19 | 20 | private fun HomeUiModel.reduce(refresh: Operation): HomeUiModel = 21 | when (refresh) { 22 | Operation.InProgress -> copy(isRefreshing = true, errorMsg = null) 23 | Operation.Complete -> copy(isRefreshing = false, errorMsg = null) 24 | is Operation.Failure -> copy(isRefreshing = false, errorMsg = toFetchFailureMsg(refresh.error)) 25 | }.also { Timber.d("Operation: $refresh was reduced to: $it") } 26 | 27 | private fun HomeUiModel.reduce(fetch: Fetch): HomeUiModel = 28 | when (fetch) { 29 | is Fetch.InProgress -> copy(isLoading = user == null, errorMsg = null) 30 | is Fetch.Success -> copy(user = toUserUiModel(fetch.value), isLoading = false) 31 | is Fetch.Failure -> copy(errorMsg = toFetchFailureMsg(fetch.error), isLoading = false) 32 | }.also { Timber.d("Fetch: $fetch was reduced to: $it") } 33 | 34 | 35 | // TODO This could return an @ResId instead of a string. Issues with config changes e.g. language? 36 | private fun toFetchFailureMsg(throwable: Throwable) = throwable.localizedMessage 37 | 38 | private fun toUserUiModel(user: User) = 39 | UserUiModel(user.username, about = user.about, avatarUrl = user.avatar.large) 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/home/user/RefreshInteractor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.home.user 18 | 19 | import android.support.annotation.VisibleForTesting 20 | import com.futurice.freesound.feature.common.streams.Operation 21 | import com.futurice.freesound.feature.common.streams.asOperation 22 | import com.futurice.freesound.feature.user.UserRepository 23 | import io.reactivex.Observable 24 | 25 | class RefreshInteractor(private val userRepository: UserRepository) { 26 | 27 | companion object { 28 | @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) 29 | val HOME_USERNAME = "SpiceProgram" 30 | } 31 | 32 | /** 33 | * Refreshes the contents of the home user 34 | */ 35 | fun refresh(): Observable { 36 | // Ignore the returned value, let homeUserStream emit the change. 37 | return refreshUser().asOperation() 38 | } 39 | 40 | private fun refreshUser() = userRepository.refreshUser(HOME_USERNAME) 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/images/ImagesModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.images 18 | 19 | import android.content.Context 20 | import com.futurice.freesound.BuildConfig 21 | import com.futurice.freesound.inject.app.ForApplication 22 | import com.squareup.picasso.Picasso 23 | import dagger.Module 24 | import dagger.Provides 25 | import javax.inject.Singleton 26 | 27 | @Module 28 | class ImagesModule { 29 | 30 | @Provides 31 | @Singleton 32 | internal fun providePicasso(@ForApplication context: Context) = 33 | Picasso.Builder(context) 34 | .loggingEnabled(BuildConfig.DEBUG) 35 | .build() 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/images/PicassoTransformations.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | @file:JvmName("PicassoTransformations") 17 | 18 | package com.futurice.freesound.feature.images 19 | 20 | import com.squareup.picasso.Transformation 21 | 22 | fun circularTransformation(): Transformation = RoundEdgeTransformation 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/images/RoundEdgeTransformation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.images 18 | 19 | import android.graphics.* 20 | import com.squareup.picasso.Transformation 21 | 22 | object RoundEdgeTransformation : Transformation { 23 | 24 | override fun transform(source: Bitmap): Bitmap { 25 | 26 | val roundEdgeBitmap = Bitmap 27 | .createBitmap(source.width, source.height, Bitmap.Config.ARGB_8888) 28 | 29 | val paint = Paint().apply { 30 | isAntiAlias = true 31 | shader = BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) 32 | } 33 | 34 | Canvas(roundEdgeBitmap).apply { 35 | drawCircle(source.width / 2f, source.height / 2f, 36 | source.shortestAxis() / 2f, paint) 37 | } 38 | 39 | if (roundEdgeBitmap != source) { 40 | source.recycle() 41 | } 42 | return roundEdgeBitmap 43 | } 44 | 45 | override fun key(): String = "roundEdge" 46 | 47 | private fun Bitmap.shortestAxis(): Float { 48 | return Math.min(width, height).toFloat() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/search/SearchActivityComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.search; 18 | 19 | import com.futurice.freesound.feature.audio.AudioPlayer; 20 | import com.futurice.freesound.feature.common.Navigator; 21 | import com.futurice.freesound.inject.activity.ActivityScope; 22 | import com.futurice.freesound.inject.activity.BaseActivityComponent; 23 | import com.futurice.freesound.inject.fragment.BaseFragmentModule; 24 | 25 | import dagger.Subcomponent; 26 | 27 | @ActivityScope 28 | @Subcomponent(modules = SearchActivityModule.class) 29 | public interface SearchActivityComponent extends BaseActivityComponent { 30 | 31 | SearchDataModel getSearchDataModel(); 32 | 33 | Navigator getNavigator(); 34 | 35 | AudioPlayer getAudioPlayer(); 36 | 37 | void inject(final SearchActivity activity); 38 | 39 | SearchFragmentComponent plusSearchFragmentComponent(BaseFragmentModule baseFragmentModule); 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/search/SearchConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.search; 18 | 19 | import com.futurice.freesound.common.InstantiationForbiddenError; 20 | 21 | final class SearchConstants { 22 | 23 | static final class SearchResultListItems { 24 | 25 | static final int SOUND = 0; 26 | static final int AD = 1; 27 | 28 | SearchResultListItems() { 29 | throw new InstantiationForbiddenError(); 30 | } 31 | } 32 | 33 | SearchConstants() { 34 | throw new InstantiationForbiddenError(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/search/SearchDataModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.search; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | import io.reactivex.Completable; 22 | import io.reactivex.Observable; 23 | 24 | public interface SearchDataModel { 25 | 26 | @NonNull 27 | Completable querySearch(@NonNull String query, @NonNull final Completable preliminaryTask); 28 | 29 | @NonNull 30 | Observable getSearchStateOnceAndStream(); 31 | 32 | @NonNull 33 | Completable clear(); 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/search/SearchFragmentComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.search; 18 | 19 | import com.futurice.freesound.inject.fragment.BaseFragmentComponent; 20 | import com.futurice.freesound.inject.fragment.FragmentScope; 21 | 22 | import dagger.Subcomponent; 23 | 24 | @FragmentScope 25 | @Subcomponent(modules = SearchFragmentModule.class) 26 | public interface SearchFragmentComponent extends BaseFragmentComponent { 27 | 28 | void inject(final SearchFragment searchFragment); 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/search/SearchQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.search; 18 | 19 | import com.google.auto.value.AutoValue; 20 | 21 | import android.support.annotation.NonNull; 22 | 23 | import polanski.option.Option; 24 | 25 | @AutoValue 26 | abstract class SearchQuery { 27 | 28 | @NonNull 29 | abstract Option query(); 30 | 31 | abstract boolean clearEnabled(); 32 | 33 | @NonNull 34 | static SearchQuery create(@NonNull final Option query, 35 | final boolean clearEnabled) { 36 | return new AutoValue_SearchQuery(query, clearEnabled); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/search/SearchResultItemComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.search; 18 | 19 | import com.futurice.freesound.feature.common.DisplayableItem; 20 | import com.futurice.freesound.feature.common.ui.adapter.ItemComparator; 21 | 22 | final class SearchResultItemComparator implements ItemComparator { 23 | 24 | @Override 25 | public boolean areItemsTheSame(final DisplayableItem item1, final DisplayableItem item2) { 26 | return item1.equals(item2); 27 | } 28 | 29 | @Override 30 | public boolean areContentsTheSame(final DisplayableItem item1, final DisplayableItem item2) { 31 | // There is no state in any of the items shown in this list. 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/search/SearchSnackbar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.search; 18 | 19 | import com.futurice.freesound.R; 20 | 21 | import android.support.annotation.NonNull; 22 | import android.support.design.widget.Snackbar; 23 | import android.support.v4.content.ContextCompat; 24 | import android.view.View; 25 | 26 | import polanski.option.Option; 27 | 28 | import static com.futurice.freesound.common.utils.Preconditions.checkNotNull; 29 | 30 | /** 31 | * A helper class, which can display and dismiss a SnackBar 32 | */ 33 | class SearchSnackbar { 34 | 35 | private Snackbar snackbar; 36 | 37 | /** 38 | * Shows a snackbar indefinitely in the first parent view found above the provided view. 39 | * Dismisses a previous SnackBar if one was shown before. 40 | * 41 | * @param view The view supposed to show the SnackBar. If not a CoordinatorLayout, 42 | * SnackBar will find the first parent view which is suitable to hold a 43 | * SnackBar 44 | * @param charSequence The message to be displayed in the SnackBar 45 | */ 46 | void showNewSnackbar(@NonNull View view, @NonNull final CharSequence charSequence) { 47 | checkNotNull(view); 48 | checkNotNull(charSequence); 49 | dismissSnackbar(); 50 | 51 | snackbar = Snackbar.make(view, charSequence, Snackbar.LENGTH_INDEFINITE); 52 | snackbar.setAction(android.R.string.ok, __ -> dismissSnackbar()); 53 | snackbar.setActionTextColor(ContextCompat.getColor(view.getContext(), 54 | R.color.colorContrastAccent)); 55 | snackbar.show(); 56 | } 57 | 58 | /** 59 | * Dismisses a previously shown SnackBar if it exists 60 | */ 61 | void dismissSnackbar() { 62 | Option.ofObj(snackbar) 63 | .ifSome(Snackbar::dismiss); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/search/SearchState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.search; 18 | 19 | import com.google.auto.value.AutoValue; 20 | 21 | import com.futurice.freesound.network.api.model.Sound; 22 | 23 | import android.support.annotation.NonNull; 24 | 25 | import java.util.List; 26 | 27 | import polanski.option.Option; 28 | 29 | @AutoValue 30 | abstract class SearchState { 31 | 32 | @NonNull 33 | abstract Option> results(); 34 | 35 | @NonNull 36 | abstract Option error(); 37 | 38 | abstract boolean isInProgress(); 39 | 40 | @NonNull 41 | static SearchState create(Option> results, Option error, 42 | boolean isInProgress) { 43 | return new AutoValue_SearchState(results, error, isInProgress); 44 | } 45 | 46 | @NonNull 47 | static SearchState cleared() { 48 | return new AutoValue_SearchState(Option.none(), Option.none(), false); 49 | } 50 | 51 | @NonNull 52 | static SearchState error(@NonNull Throwable throwable) { 53 | return new AutoValue_SearchState(Option.none(), Option.ofObj(throwable), false); 54 | } 55 | 56 | @NonNull 57 | static SearchState success(@NonNull List results) { 58 | return new AutoValue_SearchState(Option.ofObj(results), Option.none(), false); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/user/UserModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.user; 18 | 19 | import com.futurice.freesound.network.api.FreeSoundApiService; 20 | import com.futurice.freesound.network.api.model.User; 21 | import com.futurice.freesound.store.Cache; 22 | import com.futurice.freesound.store.Store; 23 | 24 | import javax.inject.Named; 25 | import javax.inject.Singleton; 26 | 27 | import dagger.Module; 28 | import dagger.Provides; 29 | 30 | @Module 31 | public class UserModule { 32 | 33 | private static final String USER_STORE = "userstore"; 34 | 35 | @Provides 36 | @Singleton 37 | UserRepository provideUserRepository(FreeSoundApiService freesoundApiService, 38 | @Named(USER_STORE) Store userStore) { 39 | return new UserRepository(freesoundApiService, userStore); 40 | } 41 | 42 | @Provides 43 | @Named("userstore") 44 | Store provideUserCacheStore() { 45 | return new Cache<>(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/feature/user/UserRepository.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.user 18 | 19 | import com.futurice.freesound.network.api.FreeSoundApiService 20 | import com.futurice.freesound.network.api.model.User 21 | import com.futurice.freesound.store.Store 22 | import io.reactivex.Observable 23 | import io.reactivex.Single 24 | 25 | /* 26 | * refresh: Active, Single: Always fetches, stores and emits once. Can error. 27 | * get: Active, Single: Returns cache if it exists, otherwise it fetches, stores and emits once. Can error. 28 | * await: Passive, Single TODO 29 | * awaitStream Passive, Observable, Stream. Doesn't fetch. Just Observes. Never errors. 30 | * 31 | * WONTDO getStream: Active, Observable: Returns cache if it exists, fetches, stores and emits value and future values. 32 | * Question: Should we just return the fetched value or always use the value in the store? 33 | * By emitting the fetched value, we are assuming that the store does not alter that. 34 | */ 35 | class UserRepository(private val freeSoundApi: FreeSoundApiService, 36 | private val userStore: Store) { 37 | 38 | // refresh. 39 | fun refreshUser(username: String): Single { 40 | return freeSoundApi.getUser(username) 41 | .flatMap { user -> userStore.put(username, user).toSingle { user } } // emits fetched/stored. 42 | } 43 | 44 | // get 45 | fun user(username: String): Single { 46 | return userStore.get(username) 47 | .switchIfEmpty(refreshUser(username)) // emits fetched/stored 48 | } 49 | 50 | // awaitUserStream 51 | fun awaitUserStream(username: String): Observable { 52 | return userStore.getStream(username) 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/Injector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | public interface Injector { 22 | 23 | @NonNull 24 | T component(); 25 | 26 | void inject(); 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/activity/ActivityScope.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.activity; 18 | 19 | import java.lang.annotation.Retention; 20 | 21 | import javax.inject.Scope; 22 | 23 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 24 | 25 | @Scope 26 | @Retention(RUNTIME) 27 | public @interface ActivityScope { 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/activity/BaseActivityComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.activity; 18 | 19 | import com.futurice.freesound.app.FreesoundApplicationComponent; 20 | 21 | import android.content.Context; 22 | 23 | import dagger.Component; 24 | 25 | @ActivityScope 26 | @Component(dependencies = FreesoundApplicationComponent.class, modules = BaseActivityModule.class) 27 | public interface BaseActivityComponent { 28 | 29 | android.app.Activity getActivity(); 30 | 31 | @ForActivity 32 | Context getActivityContext(); 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/activity/BaseActivityModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.activity; 18 | 19 | import com.futurice.freesound.feature.common.DefaultNavigator; 20 | import com.futurice.freesound.feature.common.Navigator; 21 | 22 | import android.content.Context; 23 | import android.support.annotation.NonNull; 24 | 25 | import dagger.Module; 26 | import dagger.Provides; 27 | 28 | @Module 29 | public class BaseActivityModule { 30 | 31 | private final android.app.Activity activity; 32 | 33 | public BaseActivityModule(@NonNull final android.app.Activity activity) { 34 | this.activity = activity; 35 | } 36 | 37 | @Provides 38 | @ActivityScope 39 | @ForActivity 40 | Context provideActivityContext() { 41 | return activity; 42 | } 43 | 44 | @Provides 45 | @ActivityScope 46 | android.app.Activity provideActivity() { 47 | return activity; 48 | } 49 | 50 | @Provides 51 | @ActivityScope 52 | static Navigator provideNavigator(android.app.Activity activity) { 53 | return new DefaultNavigator(activity); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/activity/ForActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.activity; 18 | 19 | import java.lang.annotation.Retention; 20 | 21 | import javax.inject.Qualifier; 22 | 23 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 24 | 25 | @Qualifier 26 | @Retention(RUNTIME) 27 | public @interface ForActivity { 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/app/BaseApplicationComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.app; 18 | 19 | import android.content.Context; 20 | 21 | import javax.inject.Singleton; 22 | 23 | import dagger.Component; 24 | 25 | @Component(modules = BaseApplicationModule.class) 26 | @Singleton 27 | public interface BaseApplicationComponent { 28 | 29 | android.app.Application getApplication(); 30 | 31 | @ForApplication 32 | Context getApplicationContext(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/app/BaseApplicationModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.app; 18 | 19 | import android.content.Context; 20 | 21 | import javax.inject.Singleton; 22 | 23 | import dagger.Module; 24 | import dagger.Provides; 25 | 26 | @Module 27 | public class BaseApplicationModule { 28 | 29 | private final android.app.Application application; 30 | 31 | public BaseApplicationModule(android.app.Application application) { 32 | this.application = application; 33 | } 34 | 35 | @Provides 36 | @Singleton 37 | @ForApplication 38 | public Context provideApplicationContext() { 39 | return application.getApplicationContext(); 40 | } 41 | 42 | @Provides 43 | @Singleton 44 | public android.app.Application provideApplication() { 45 | return application; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/app/ForApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.app; 18 | 19 | import java.lang.annotation.Retention; 20 | 21 | import javax.inject.Qualifier; 22 | 23 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 24 | 25 | @Qualifier 26 | @Retention(RUNTIME) 27 | public @interface ForApplication { 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/fragment/BaseFragmentComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.fragment; 18 | 19 | import com.futurice.freesound.inject.activity.BaseActivityModule; 20 | 21 | import dagger.Component; 22 | 23 | @FragmentScope 24 | @Component(dependencies = BaseActivityModule.class, modules = BaseFragmentModule.class) 25 | public interface BaseFragmentComponent { 26 | 27 | @FragmentScope 28 | android.support.v4.app.Fragment getFragment(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/fragment/BaseFragmentModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.fragment; 18 | 19 | import android.support.annotation.NonNull; 20 | import android.support.v4.app.Fragment; 21 | 22 | import dagger.Module; 23 | import dagger.Provides; 24 | 25 | @Module 26 | public class BaseFragmentModule { 27 | 28 | private final Fragment fragment; 29 | 30 | public BaseFragmentModule(@NonNull final android.support.v4.app.Fragment fragment) { 31 | this.fragment = fragment; 32 | } 33 | 34 | @Provides 35 | @FragmentScope 36 | Fragment provideFragment() { 37 | return fragment; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/inject/fragment/FragmentScope.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.inject.fragment; 18 | 19 | import java.lang.annotation.Retention; 20 | 21 | import javax.inject.Scope; 22 | 23 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 24 | 25 | @Scope 26 | @Retention(RUNTIME) 27 | public @interface FragmentScope { 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/ApiConfigModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api; 18 | 19 | import com.futurice.freesound.BuildConfig; 20 | 21 | import javax.inject.Named; 22 | import javax.inject.Singleton; 23 | 24 | import dagger.Module; 25 | import dagger.Provides; 26 | 27 | @Module 28 | public class ApiConfigModule { 29 | 30 | static final String API_URL_CONFIG = "ApiConfigModule.API_URL_CONFIG"; 31 | static final String API_CLIENT_SECRET_CONFIG = "ApiConfigModule.API_CLIENT_ID_SECRET_CONFIG"; 32 | static final String API_CLIENT_ID_CONFIG = "ApiConfigModule.API_CLIENT_ID_CONFIG"; 33 | 34 | @Provides 35 | @Singleton 36 | @Named(API_URL_CONFIG) 37 | static String provideApiModuleUrlConfig() { 38 | return BuildConfig.FREESOUND_API_URL; 39 | } 40 | 41 | @Provides 42 | @Singleton 43 | @Named(API_CLIENT_SECRET_CONFIG) 44 | static String provideApiModuleApiClientSecretConfig() { 45 | return BuildConfig.FREESOUND_API_CLIENT_SECRET; 46 | } 47 | 48 | @Provides 49 | @Singleton 50 | @Named(API_CLIENT_ID_CONFIG) 51 | static String provideApiModuleApiClientIdConfig() { 52 | return BuildConfig.FREESOUND_API_CLIENT_ID; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/ApiConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api; 18 | 19 | import com.futurice.freesound.common.InstantiationForbiddenError; 20 | 21 | /** 22 | * Constants used in the Freesound API. 23 | */ 24 | final class ApiConstants { 25 | 26 | // Authentication 27 | static final String TOKEN_QUERY_PARAM = "token"; 28 | static final String AUTHORIZATION_CODE_GRANT_TYPE_VALUE = "authorization_code"; 29 | 30 | // The pattern used is a compromise because the Freesound API data pattern inconsistent. 31 | // Some Sound objects have up to 6 decimal places for the seconds value, whereas others 32 | // don't have any. 33 | // 34 | // This pattern might not be sufficient for fields that require high accuracy because it 35 | // truncates sub-second values. 36 | static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss"; 37 | 38 | private ApiConstants() { 39 | throw new InstantiationForbiddenError(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/ApiModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import dagger.Binds; 22 | import dagger.Module; 23 | 24 | @Module(includes = ApiNetworkModule.class) 25 | public abstract class ApiModule { 26 | 27 | @Binds 28 | @Singleton 29 | abstract FreeSoundApiService provideFreeSoundApiService( 30 | DefaultFreeSoundApiService defaultFreeSoundApiService); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/FreeSoundApiService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api; 18 | 19 | import com.futurice.freesound.network.api.model.AccessToken; 20 | import com.futurice.freesound.network.api.model.SoundSearchResult; 21 | import com.futurice.freesound.network.api.model.User; 22 | 23 | import android.support.annotation.NonNull; 24 | 25 | import io.reactivex.Single; 26 | 27 | /** 28 | * The application access interface for interactions with the Freesound API. 29 | */ 30 | public interface FreeSoundApiService { 31 | 32 | @NonNull 33 | Single getUser(@NonNull final String user); 34 | 35 | @NonNull 36 | Single getAccessToken(@NonNull String code); 37 | 38 | @NonNull 39 | Single search(@NonNull String query); 40 | 41 | @NonNull 42 | Single sounds(@NonNull String username); 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/AccessToken.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api.model 18 | 19 | import com.squareup.moshi.Json 20 | 21 | data class AccessToken( 22 | @Json(name = "access_token") val accessToken: String, 23 | val scope: String, 24 | @Json(name = "expires_in") val expiresIn: Long, 25 | @Json(name = "refresh_token") val refreshToken: String) 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/Avatar.kt: -------------------------------------------------------------------------------- 1 | package com.futurice.freesound.network.api.model 2 | 3 | data class Avatar( 4 | val small: String, 5 | val medium: String, 6 | val large: String) 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/GeoLocation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api.model 18 | 19 | import android.annotation.SuppressLint 20 | import android.os.Parcelable 21 | import kotlinx.android.parcel.Parcelize 22 | 23 | @SuppressLint("ParcelCreator") 24 | @Parcelize 25 | data class GeoLocation( 26 | val latitude: Double, 27 | val longitude: Double) : Parcelable -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/Requests.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api.model 18 | 19 | 20 | fun Iterable.asCommaSeparated(): String { 21 | return joinToString(",") 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/SoundFields.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api.model; 18 | 19 | public enum SoundFields { 20 | BASE(Sound_JontyFielder.INSTANCE.getFields()); 21 | 22 | private final Iterable fields; 23 | 24 | SoundFields(Iterable fields) { 25 | this.fields = fields; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return RequestsKt.asCommaSeparated(fields); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/SoundSearchResult.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api.model 18 | 19 | data class SoundSearchResult ( 20 | val count: Int, 21 | val next: String?, 22 | val results: List, 23 | val previous: String? 24 | ) 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/User.kt: -------------------------------------------------------------------------------- 1 | package com.futurice.freesound.network.api.model 2 | 3 | data class User( 4 | val username: String, 5 | val about: String, 6 | val avatar: Avatar) 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/mapping/FreesoundDateAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api.model.mapping 18 | 19 | import com.squareup.moshi.FromJson 20 | import com.squareup.moshi.JsonDataException 21 | import com.squareup.moshi.ToJson 22 | import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter 23 | import java.util.* 24 | 25 | /** 26 | * Required as the Freesound API uses RFC-3339, *except* that it omits the "Z" suffix! 27 | * This adds that suffix to make it RFC-3339 compliant and then delegates to the actual 28 | * Rfc3339DateJsonAdapter. 29 | */ 30 | class FreesoundDateAdapter(private val delegate: Rfc3339DateJsonAdapter) { 31 | 32 | @FromJson 33 | fun fromJson(json: String): Date { 34 | val parsableDate = if (json.endsWith("Z")) json else json.plus("Z") 35 | return delegate.fromJson("\"$parsableDate\"") 36 | ?: throw JsonDataException("Unable to deserialize Date from: $json") 37 | } 38 | 39 | @ToJson 40 | fun toJson(date: Date): String { 41 | return delegate.toJson(date) 42 | .removePrefix("\"") 43 | .removeSuffix("Z\"") 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/network/api/model/mapping/GeoLocationJsonAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.futurice.freesound.network.api.model.mapping 17 | 18 | import com.futurice.freesound.network.api.model.GeoLocation 19 | import com.squareup.moshi.FromJson 20 | import com.squareup.moshi.JsonDataException 21 | 22 | class GeoLocationJsonAdapter { 23 | 24 | @FromJson fun fromJson(json: String): GeoLocation = 25 | json.trim() 26 | .split(' ') 27 | .mapNotNull { it.toDoubleOrNull() } 28 | .takeIf { it.size == 2 } 29 | ?.let { GeoLocation(latitude = it[0], longitude = it[1]) } 30 | ?: throw JsonDataException("Unable to deserialize latitude/long values from: $json") 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/futurice/freesound/store/Store.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.store 18 | 19 | import io.reactivex.Completable 20 | import io.reactivex.Maybe 21 | import io.reactivex.Observable 22 | 23 | interface Store { 24 | 25 | fun put(key: K, value: V): Completable 26 | 27 | fun get(key: K): Maybe 28 | 29 | fun getStream(key: K): Observable 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurice/freesound-android/2367d130a42d3acd2d863325a6dc694e2d551665/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurice/freesound-android/2367d130a42d3acd2d863325a6dc694e2d551665/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurice/freesound-android/2367d130a42d3acd2d863325a6dc694e2d551665/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurice/freesound-android/2367d130a42d3acd2d863325a6dc694e2d551665/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/avatar_placeholder.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 23 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search_white_24px.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 26 | 27 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_playbackwaveform.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 30 | 31 | 38 | 39 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/res/menu/home.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 21 | 22 | 24 | 25 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 48dp 21 | 22 | 23 | 32dp 24 | 16dp 25 | 8dp 26 | 4dp 27 | 2dp 28 | 29 | 30 | 31 | 112sp 32 | 56sp 33 | 45sp 34 | 34sp 35 | 24sp 36 | 20sp 37 | 16sp 38 | 14sp 39 | 14sp 40 | 12sp 41 | 20sp 42 | 14sp 43 | 44 | 16dp 45 | 16dp 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | Freesound 21 | 22 | 23 | About 24 | Search 25 | 26 | 27 | No results found 28 | There was an error searching 29 | 30 | 31 | Sound item image 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 35 | 36 | 40 | 41 | 45 | 46 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/release/java/com/futurice/freesound/feature/logging/ErrorReporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.logging; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | /** 22 | * Exception reporting mechanism. 23 | * 24 | * Implementations should simply delegate to the Exception reporting mechanism of choice. 25 | */ 26 | interface ErrorReporter { 27 | 28 | /** 29 | * Report the {@link Throwable} 30 | * 31 | * @param throwable the {@link Throwable} instance that occurred. 32 | */ 33 | void report(@NonNull Throwable throwable); 34 | } 35 | -------------------------------------------------------------------------------- /app/src/release/java/com/futurice/freesound/feature/logging/FirebaseErrorReporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.logging; 18 | 19 | import com.google.firebase.crash.FirebaseCrash; 20 | 21 | import android.support.annotation.NonNull; 22 | 23 | import static com.futurice.freesound.common.utils.Preconditions.get; 24 | 25 | /** 26 | * A {@Link ErrorReporter} that reports exceptions via Firebase. 27 | */ 28 | class FirebaseErrorReporter implements ErrorReporter { 29 | 30 | @Override 31 | public void report(@NonNull final Throwable throwable) { 32 | FirebaseCrash.report(get(throwable)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/release/java/com/futurice/freesound/feature/logging/FirebaseReleaseTree.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.logging; 18 | 19 | import android.support.annotation.NonNull; 20 | import android.support.annotation.Nullable; 21 | 22 | import polanski.option.Option; 23 | import timber.log.Timber; 24 | 25 | import static com.futurice.freesound.common.utils.Preconditions.get; 26 | 27 | /** 28 | * Timber logging {@link timber.log.Timber.Tree} to be used in release builds. 29 | * 30 | * Only errors are reported. 31 | */ 32 | class FirebaseReleaseTree extends Timber.Tree { 33 | 34 | @NonNull 35 | private final FirebaseErrorReporter firebaseErrorReporter; 36 | 37 | FirebaseReleaseTree(@NonNull final FirebaseErrorReporter firebaseErrorReporter) { 38 | this.firebaseErrorReporter = get(firebaseErrorReporter); 39 | } 40 | 41 | @Override 42 | protected void log(final int priority, 43 | @Nullable final String tag, 44 | @Nullable final String message, 45 | @Nullable final Throwable throwable) { 46 | Option.ofObj(throwable) 47 | .ifSome(firebaseErrorReporter::report); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/release/java/com/futurice/freesound/feature/logging/LoggingModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.logging; 18 | 19 | import javax.inject.Singleton; 20 | 21 | import dagger.Module; 22 | import dagger.Provides; 23 | import timber.log.Timber; 24 | 25 | @Module 26 | public class LoggingModule { 27 | 28 | @Provides 29 | @Singleton 30 | static Timber.Tree provideLoggingTree(FirebaseErrorReporter firebaseErrorReporter) { 31 | return new FirebaseReleaseTree(firebaseErrorReporter); 32 | } 33 | 34 | @Provides 35 | @Singleton 36 | static FirebaseErrorReporter provideFirebaseErrorReporter() { 37 | return new FirebaseErrorReporter(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/release/java/com/futurice/freesound/network/api/InstrumentationModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api; 18 | 19 | import java.util.Collections; 20 | import java.util.List; 21 | 22 | import javax.inject.Singleton; 23 | 24 | import dagger.Module; 25 | import dagger.Provides; 26 | import okhttp3.Interceptor; 27 | 28 | @Module 29 | public final class InstrumentationModule { 30 | 31 | @Provides 32 | @Singleton 33 | @ApiNetworkModule.NetworkInterceptors 34 | static List provideNetworkInterceptors() { 35 | return Collections.emptyList(); 36 | } 37 | 38 | @Provides 39 | @Singleton 40 | @ApiNetworkModule.AppInterceptors 41 | static List provideAppInterceptors() { 42 | return Collections.emptyList(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/test/java/com/futurice/freesound/common/functional/StringFunctionsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common.functional; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | public class StringFunctionsTest { 24 | 25 | @Test 26 | public void isEmpty_returnsTrue_whenCalled_withEmptyString() throws Exception { 27 | assertThat(StringFunctions.isEmpty().test("")).isTrue(); 28 | } 29 | 30 | @Test 31 | public void isEmpty_returnsTrue_whenCalled_withNull() throws Exception { 32 | assertThat(StringFunctions.isEmpty().test(null)).isTrue(); 33 | } 34 | 35 | @Test 36 | public void isEmpty_returnsFalse_whenCalled_withString() throws Exception { 37 | assertThat(StringFunctions.isEmpty().test("dummy")).isFalse(); 38 | } 39 | 40 | @Test 41 | public void isNotEmpty_returnsFalse_whenCalled_withEmptyString() throws Exception { 42 | assertThat(StringFunctions.isNotEmpty().test("")).isFalse(); 43 | } 44 | 45 | @Test 46 | public void isNotEmpty_returnsFalse_whenCalled_withNull() throws Exception { 47 | assertThat(StringFunctions.isNotEmpty().test(null)).isFalse(); 48 | } 49 | 50 | @Test 51 | public void isNotEmpty_returnsTrue_whenCalled_withString() throws Exception { 52 | assertThat(StringFunctions.isNotEmpty().test("dummy")).isTrue(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/test/java/com/futurice/freesound/common/utils/PreconditionsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common.utils; 18 | 19 | import org.junit.Rule; 20 | import org.junit.Test; 21 | import org.junit.rules.ExpectedException; 22 | 23 | import static org.assertj.core.api.Assertions.assertThat; 24 | 25 | public class PreconditionsTest { 26 | 27 | @Rule 28 | public ExpectedException thrown = ExpectedException.none(); 29 | 30 | @Test 31 | public void checkNotNull_doesNotThrowException_whenNonNull() { 32 | 33 | Preconditions.checkNotNull(new Object()); 34 | } 35 | 36 | @Test 37 | public void checkNotNull_throwsNullPointerException_whenNull() { 38 | thrown.expect(NullPointerException.class); 39 | 40 | Preconditions.checkNotNull(null); 41 | } 42 | 43 | @Test 44 | public void checkNotNullWithMessage_doesNotThrowException_whenNonNull() { 45 | Preconditions.checkNotNull(new Object(), "Unused message"); 46 | } 47 | 48 | @Test 49 | public void checkNotNullWithMessage_throwsNullPointerExceptionWithMessage_whenNull() { 50 | final String message = "message"; 51 | thrown.expect(NullPointerException.class); 52 | thrown.expectMessage(message); 53 | 54 | Preconditions.checkNotNull(null, message); 55 | } 56 | 57 | @Test 58 | public void get_returnsParameter_whenNonNull() { 59 | Object obj = new Object(); 60 | 61 | assertThat(Preconditions.get(obj)).isEqualTo(obj); 62 | } 63 | 64 | @Test 65 | public void get_throwsNullPointerException_whenNull() { 66 | thrown.expect(NullPointerException.class); 67 | 68 | Preconditions.get(null); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /app/src/test/java/com/futurice/freesound/common/utils/TextUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.common.utils; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | public class TextUtilsTest { 24 | 25 | @Test 26 | public void isNotNullOrEmpty_returnFalse_whenEmptyString() { 27 | assertThat(TextUtils.isNotNullOrEmpty("")).isFalse(); 28 | } 29 | 30 | @Test 31 | public void isNotNullOrEmpty_returnFalse_whenNull() { 32 | assertThat(TextUtils.isNotNullOrEmpty(null)).isFalse(); 33 | } 34 | 35 | @Test 36 | public void isNotNullOrEmpty_returnTrue_whenString() { 37 | assertThat(TextUtils.isNotNullOrEmpty("dummy")).isTrue(); 38 | } 39 | 40 | @Test 41 | public void isNullOrEmpty_returnTrue_whenEmptyString() { 42 | assertThat(TextUtils.isNullOrEmpty("")).isTrue(); 43 | } 44 | 45 | @Test 46 | public void isNullOrEmpty_returnTrue_whenNull() { 47 | assertThat(TextUtils.isNullOrEmpty(null)).isTrue(); 48 | } 49 | 50 | @Test 51 | public void isNullOrEmpty_returnFalse_whenString() { 52 | assertThat(TextUtils.isNullOrEmpty("dummy")).isFalse(); 53 | } 54 | 55 | @Test 56 | public void isNotEmpty_returnFalse_whenNull() { 57 | assertThat(TextUtils.isNotEmpty(null)).isFalse(); 58 | } 59 | 60 | @Test 61 | public void isNotEmpty_returnTrue_whenNonEmptyString() { 62 | assertThat(TextUtils.isNotEmpty("dummy")).isTrue(); 63 | } 64 | 65 | @Test 66 | public void isNotEmpty_returnFalse_whenEmptyString() { 67 | assertThat(TextUtils.isNotEmpty("")).isFalse(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /app/src/test/java/com/futurice/freesound/network/api/model/RequestsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api.model; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | import java.util.Collections; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | public class RequestsTest { 27 | 28 | @Test 29 | public void asCommaSeparated_isEmpty_whenEmptyIterable() { 30 | assertThat(RequestsKt.asCommaSeparated(Collections.emptyList())).isEmpty(); 31 | } 32 | 33 | @Test 34 | public void asCommaSeparated_containsOnlyValue_whenSingleItem() { 35 | String value = "value"; 36 | 37 | assertThat(RequestsKt.asCommaSeparated(Collections.singletonList(value))) 38 | .isEqualTo(value); 39 | } 40 | 41 | @Test 42 | public void asCommaSeparated_containCommasBetweenItems() { 43 | String value1 = "value1"; 44 | String value2 = "value2"; 45 | String[] values = {value1, value2}; 46 | 47 | assertThat(RequestsKt.asCommaSeparated(Arrays.asList(values))) 48 | .isEqualTo(value1 + "," + value2); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/src/test/java/com/futurice/freesound/test/KotlinMock.kt: -------------------------------------------------------------------------------- 1 | package com.futurice.freesound.test 2 | 3 | import org.mockito.Mockito 4 | 5 | inline fun mock(): T = Mockito.mock(T::class.java) 6 | 7 | inline fun any(): T = Mockito.any(T::class.java) 8 | 9 | -------------------------------------------------------------------------------- /app/src/test/java/com/futurice/freesound/test/assertion/livedata/LiveDataAssertions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.test.assertion.livedata 18 | 19 | import android.arch.lifecycle.LiveData 20 | 21 | fun LiveData.test(): TestObserver { 22 | return TestObserver() 23 | .apply { 24 | observeForever(this) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/test/java/com/futurice/freesound/test/assertion/rx/RxJava2OptionAssertions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.test.assertion.rx; 18 | 19 | import com.futurice.freesound.common.InstantiationForbiddenError; 20 | 21 | import android.support.annotation.NonNull; 22 | 23 | import io.reactivex.functions.Function; 24 | import io.reactivex.functions.Predicate; 25 | import polanski.option.Option; 26 | 27 | /** 28 | * Helpers for testing {@link Option} values using RxJava2's {@link io.reactivex.Observable#test()} 29 | */ 30 | public final class RxJava2OptionAssertions { 31 | 32 | @NonNull 33 | public static Predicate> isNone() { 34 | return Option::isNone; 35 | } 36 | 37 | @NonNull 38 | public static Predicate isNone(@NonNull final Function> selector) { 39 | return v -> selector.apply(v).isNone(); 40 | } 41 | 42 | @NonNull 43 | public static Predicate> isSome() { 44 | return Option::isSome; 45 | } 46 | 47 | @NonNull 48 | public static Predicate isSome(@NonNull final Function> selector) { 49 | return v -> selector.apply(v).isSome(); 50 | } 51 | 52 | @NonNull 53 | public static Predicate> hasOptionValue(@NonNull final T expected) { 54 | return t -> t.filter(actual -> actual.equals(expected)).isSome(); 55 | } 56 | 57 | private RxJava2OptionAssertions() { 58 | throw new InstantiationForbiddenError(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/test/java/com/futurice/freesound/test/rx/TimeSkipScheduler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.test.rx; 18 | 19 | import android.support.annotation.NonNull; 20 | 21 | import java.util.concurrent.TimeUnit; 22 | 23 | import io.reactivex.Scheduler; 24 | import io.reactivex.disposables.Disposable; 25 | import io.reactivex.disposables.Disposables; 26 | 27 | /** 28 | * Scheduler that executes immediately even the time based actions. 29 | * 30 | * When this scheduler is used in tests with an operator where we specify time, 31 | * it will ignore the time values and schedule the action immediately. 32 | * 33 | * The reason behind it is to run tests as quickly as possible and not use 34 | * {@link io.reactivex.schedulers.TestScheduler} every time. 35 | */ 36 | public final class TimeSkipScheduler extends Scheduler { 37 | 38 | @NonNull 39 | private static final TimeSkipScheduler INSTANCE = new TimeSkipScheduler(); 40 | 41 | private TimeSkipScheduler() { 42 | } 43 | 44 | /** 45 | * Returns the instance of time skip scheduler. 46 | */ 47 | @NonNull 48 | public static TimeSkipScheduler instance() { 49 | return INSTANCE; 50 | } 51 | 52 | @Override 53 | public Worker createWorker() { 54 | return new InnerTimeSkipScheduler(); 55 | } 56 | 57 | private static class InnerTimeSkipScheduler extends Worker { 58 | 59 | @Override 60 | public Disposable schedule(final Runnable run, final long delay, final TimeUnit unit) { 61 | run.run(); 62 | 63 | return Disposables.empty(); 64 | } 65 | 66 | @Override 67 | public void dispose() { 68 | // Empty on purpose 69 | } 70 | 71 | @Override 72 | public boolean isDisposed() { 73 | return false; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline 2 | -------------------------------------------------------------------------------- /app/src/testDebug/java/com/futurice/freesound/feature/logging/LoggingModuleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.logging; 18 | 19 | import org.junit.Test; 20 | 21 | import timber.log.Timber; 22 | 23 | import static org.assertj.core.api.Assertions.assertThat; 24 | 25 | public class LoggingModuleTest { 26 | 27 | @Test 28 | public void provideLoggingTree_isDebugTree_inDebugVariant() { 29 | assertThat(LoggingModule.provideLoggingTree()) 30 | .isInstanceOf(Timber.DebugTree.class); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/testRelease/java/com/futurice/freesound/feature/logging/FirebaseReleaseTreeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.logging; 18 | 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | import org.mockito.Mock; 22 | import org.mockito.MockitoAnnotations; 23 | 24 | import static org.mockito.ArgumentMatchers.eq; 25 | import static org.mockito.Mockito.verify; 26 | import static org.mockito.Mockito.verifyZeroInteractions; 27 | 28 | public class FirebaseReleaseTreeTest { 29 | 30 | @Mock 31 | private FirebaseErrorReporter firebaseErrorReporter; 32 | 33 | private FirebaseReleaseTree firebaseReleaseTree; 34 | 35 | @Before 36 | public void setUp() { 37 | MockitoAnnotations.initMocks(this); 38 | this.firebaseReleaseTree = new FirebaseReleaseTree(firebaseErrorReporter); 39 | } 40 | 41 | @Test 42 | public void log_doesNothing_whenThrowableIsNull() { 43 | firebaseReleaseTree.log(1, "dummyTag", "dummyMsg", null); 44 | 45 | verifyZeroInteractions(firebaseErrorReporter); 46 | } 47 | 48 | @Test 49 | public void log_reportsThrowableToFirebase_whenThrowableIsNonNull() { 50 | Throwable expected = new Throwable(); 51 | int dummyPriority = 1; 52 | firebaseReleaseTree.log(dummyPriority, "dummyTag", "dummyMsg", expected); 53 | 54 | verify(firebaseErrorReporter).report(eq(expected)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/testRelease/java/com/futurice/freesound/feature/logging/LoggingModuleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.feature.logging; 18 | 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | import org.mockito.Mock; 22 | import org.mockito.MockitoAnnotations; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | public class LoggingModuleTest { 27 | 28 | @Mock 29 | private FirebaseErrorReporter mFirebaseErrorReporter; 30 | 31 | @Before 32 | public void setUp() throws Exception { 33 | MockitoAnnotations.initMocks(this); 34 | } 35 | 36 | @Test 37 | public void provideLoggingTree_isFirebaseReleaseTree_inReleaseVariant() { 38 | assertThat(LoggingModule.provideLoggingTree(mFirebaseErrorReporter)) 39 | .isInstanceOf(FirebaseReleaseTree.class); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/testRelease/java/com/futurice/freesound/network/api/InstrumentationModuleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.futurice.freesound.network.api; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | public class InstrumentationModuleTest { 24 | 25 | @Test 26 | public void provideNetworkInterceptors_isEmpty_inReleaseVariant() { 27 | assertThat(InstrumentationModule.provideNetworkInterceptors()).isEmpty(); 28 | } 29 | 30 | @Test 31 | public void provideAppInterceptors_isEmpty_inReleaseVariant() { 32 | assertThat(InstrumentationModule.provideAppInterceptors()).isEmpty(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 18 | 19 | buildscript { 20 | ext.kotlin_version = '1.3.11' 21 | repositories { 22 | jcenter() 23 | google() 24 | maven { 25 | url "https://plugins.gradle.org/m2/" 26 | } 27 | } 28 | dependencies { 29 | classpath 'com.android.tools.build:gradle:3.4.1' 30 | classpath 'com.google.gms:google-services:4.2.0' 31 | classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.1" 32 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 33 | } 34 | } 35 | 36 | allprojects { 37 | repositories { 38 | jcenter() 39 | google() 40 | maven { url "https://jitpack.io" } 41 | } 42 | 43 | gradle.projectsEvaluated { 44 | tasks.withType(JavaCompile) { 45 | options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" 46 | } 47 | } 48 | } 49 | 50 | apply plugin: "org.sonarqube" 51 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 Futurice GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # Project-wide Gradle settings. 18 | 19 | # IDE (e.g. Android Studio) users: 20 | # Settings specified in this file will override any Gradle settings 21 | # configured through the IDE. 22 | 23 | # For more details on how to configure your build environment visit 24 | # http://www.gradle.org/docs/current/userguide/build_environment.html 25 | 26 | # Specifies the JVM arguments used for the daemon process. 27 | # The setting is particularly useful for tweaking memory settings. 28 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 29 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 30 | 31 | # When configured, Gradle will run in incubating parallel mode. 32 | # This option should only be used with decoupled projects. More details, visit 33 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 34 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurice/freesound-android/2367d130a42d3acd2d863325a6dc694e2d551665/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon May 27 11:59:12 CEST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /ide/android-studio/copyright/Futurice_GmbH_Apache_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /ide/android-studio/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /screenshots/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futurice/freesound-android/2367d130a42d3acd2d863325a6dc694e2d551665/screenshots/screenshot1.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Futurice GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | include ':app' 18 | --------------------------------------------------------------------------------