diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 07a213cec..ea273849e 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -10,14 +10,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: set up JDK - uses: actions/setup-java@v1 - with: - java-version: 17 - - name: Decode google-services.json - env: - FIREBASE_CONFIG: ${{ secrets.FIREBASE_CONFIG }} - run: echo $FIREBASE_CONFIG > android/google-services.json - - name: Build with Gradle - run: ./gradlew android:bundleDebug + - uses: actions/checkout@v2 + - name: set up JDK + uses: actions/setup-java@v1 + with: + java-version: 17 + - name: Decode google-services.json + env: + FIREBASE_CONFIG: ${{ secrets.FIREBASE_CONFIG }} + run: echo $FIREBASE_CONFIG > app/google-services.json + - name: Build with Gradle + run: ./gradlew app:bundleDebug diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index 9f889a3bf..000000000 --- a/android/build.gradle +++ /dev/null @@ -1,149 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'com.google.gms.google-services' -apply plugin: 'com.google.firebase.crashlytics' - -buildscript { - repositories { - mavenCentral() - google() - } - - dependencies { - classpath 'com.android.tools.build:gradle:8.2.2' - classpath 'com.google.gms:google-services:4.4.2' - classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.2' - } -} - -allprojects { - repositories { - mavenCentral() - google() - } -} - -android { - flavorDimensions "tier" - - defaultConfig { - compileSdk 34 - applicationId "bbct.android.common" - minSdk 21 - targetSdk 34 - versionCode 25 - versionName "1.1.1" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - javaCompileOptions { - annotationProcessorOptions { - arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] - } - } - multiDexEnabled true - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - signingConfigs { - release - } - buildTypes { - release { - signingConfig signingConfigs.release - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - debug { - ext.enableCrashlytics = false - debuggable true - } - } - productFlavors { - lite { - dimension "tier" - applicationId "bbct.android" - } - premium { - dimension "tier" - applicationId "bbct.android.premium" - } - } - packagingOptions { - resources { - excludes += ['LICENSE.txt'] - } - } - - useLibrary 'android.test.runner' - useLibrary 'android.test.base' - useLibrary 'android.test.mock' - namespace 'bbct.android.common' -} - -Properties props = new Properties() -def propFile = new File('bbct.properties') -if (propFile.canRead()) { - props.load(new FileInputStream(propFile)) - - if (props != null) { - if (props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') - && props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) { - android.signingConfigs.release.storeFile = file(props['STORE_FILE']) - android.signingConfigs.release.storePassword = props['STORE_PASSWORD'] - android.signingConfigs.release.keyAlias = props['KEY_ALIAS'] - android.signingConfigs.release.keyPassword = props['KEY_PASSWORD'] - } else { - println 'bbct.properties found but SIGNING entries are missing' - android.buildTypes.release.signingConfig = null - } - } -} else { - println 'bbct.properties not found' -} - -ext { - annotationVersion = '1.1.0' - appcompatVersion = '1.7.0' - archCompVersion = '1.1.1' - butterknifeVersion = '10.0.0' - espressoVersion = '3.6.1' - fastlaneVersion = '2.1.1' - firebaseAnalyticsVersion = '22.0.2' - firebaseCrashlyticsVersion = '19.0.3' - fragmentVersion = '1.8.2' - googleServiceAdsVersion = '23.2.0' - junitVersion = '4.13.1' - lifecycleVersion = '2.8.4' - materialVersion = '1.12.0' - roomVersion = '2.6.1' - testLibVersion = '1.6.1' - uiautomatorVersion = '2.3.0' -} - -dependencies { - implementation "androidx.appcompat:appcompat:${appcompatVersion}" - implementation "com.google.android.material:material:${materialVersion}" - implementation "androidx.room:room-runtime:${roomVersion}" - implementation "com.google.firebase:firebase-analytics:${firebaseAnalyticsVersion}" - implementation "com.google.firebase:firebase-crashlytics:${firebaseCrashlyticsVersion}" - implementation "com.jakewharton:butterknife:${butterknifeVersion}" - - liteImplementation "com.google.android.gms:play-services-ads:${googleServiceAdsVersion}" - - annotationProcessor "com.jakewharton:butterknife-compiler:${butterknifeVersion}" - annotationProcessor "androidx.room:room-compiler:${roomVersion}" - - testImplementation "junit:junit:${junitVersion}" - testImplementation "androidx.room:room-testing:${roomVersion}" - - androidTestImplementation "androidx.annotation:annotation:${annotationVersion}" - androidTestImplementation 'androidx.test.ext:junit:1.2.1' - androidTestImplementation "androidx.test:runner:${testLibVersion}" - androidTestImplementation "androidx.test:rules:${testLibVersion}" - androidTestImplementation "androidx.fragment:fragment-testing:${fragmentVersion}" - androidTestImplementation "androidx.test.uiautomator:uiautomator:${uiautomatorVersion}" - androidTestImplementation "androidx.test.espresso:espresso-core:${espressoVersion}" - androidTestImplementation "androidx.test.espresso:espresso-contrib:${espressoVersion}" - androidTestImplementation "androidx.test.espresso:espresso-intents:${espressoVersion}" - androidTestImplementation "tools.fastlane:screengrab:2.1.1" -} diff --git a/android/proguard-rules.pro b/android/proguard-rules.pro deleted file mode 100644 index 06c2cb71a..000000000 --- a/android/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /usr/local/bin/android-sdk-linux/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/AboutTest.java b/android/src/androidTest/java/bbct/android/common/fragment/AboutTest.java deleted file mode 100644 index b5fa787a9..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/AboutTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Activity; - -import androidx.fragment.app.Fragment; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.test.rule.SupportFragmentTestRule; - -// TODO: Add tests for the layout of {@link About} -public class AboutTest { - @Rule - public SupportFragmentTestRule fragmentTestRule = new SupportFragmentTestRule(new About()); - - private Activity activity; - private Fragment aboutFragment; - - @Before - public void setUp() { - this.activity = fragmentTestRule.getActivity(); - this.aboutFragment = fragmentTestRule.getFragment(); - } - - @Test - public void testPreConditions() { - Assert.assertNotNull(this.activity); - Assert.assertNotNull(this.aboutFragment); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsAddCardsTest.java b/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsAddCardsTest.java deleted file mode 100644 index 2c1b547d3..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsAddCardsTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Instrumentation; - -import androidx.test.platform.app.InstrumentationRegistry; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.InputStream; -import java.util.List; - -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.BBCTTestUtil; -import bbct.android.common.test.BaseballCardCsvFileReader; -import bbct.android.common.test.DatabaseUtil; -import bbct.android.common.test.rule.SupportFragmentTestRule; - -public class BaseballCardDetailsAddCardsTest { - @Rule - public SupportFragmentTestRule fragmentTestRule = - new SupportFragmentTestRule(new BaseballCardDetails()); - - private static final String CARD_DATA = "three_cards.csv"; - - private List allCards = null; - private BaseballCard card = null; - private DatabaseUtil dbUtil; - - @Before - public void setUp() throws Exception { - Instrumentation inst = InstrumentationRegistry.getInstrumentation(); - dbUtil = new DatabaseUtil(inst.getTargetContext()); - - InputStream in = inst.getContext().getAssets().open(CARD_DATA); - BaseballCardCsvFileReader cardInput = new BaseballCardCsvFileReader(in, - true); - this.allCards = cardInput.getAllBaseballCards(); - this.card = this.allCards.get(0); - cardInput.close(); - } - - @After - public void tearDown() { - dbUtil.clearDatabase(); - } - - @Test - public void testAddCard() { - BBCTTestUtil.addCard(card); - // BBCTTestUtil.waitForToast(fragmentTestRule.getActivity(), BBCTTestUtil.ADD_MESSAGE); - Assert.assertTrue("Missing card: " + card, dbUtil.containsBaseballCard(card)); - } - - @Test - public void testAddCardAlphanumericCardNumber() { - card.number = "123Abc"; - BBCTTestUtil.addCard(card); - // BBCTTestUtil.waitForToast(fragmentTestRule.getActivity(), BBCTTestUtil.ADD_MESSAGE); - Assert.assertTrue("Missing card: " + card, dbUtil.containsBaseballCard(card)); - } - - @Test - public void testAddMultipleCards() { - for (BaseballCard nextCard : this.allCards) { - BBCTTestUtil.addCard(nextCard); - // BBCTTestUtil.waitForToast(this.solo, BBCTTestUtil.ADD_MESSAGE); - } - - for (BaseballCard nextCard : this.allCards) { - Assert.assertTrue("Missing card: " + nextCard, dbUtil.containsBaseballCard(nextCard)); - } - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsEditCardTest.java b/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsEditCardTest.java deleted file mode 100644 index c12959784..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsEditCardTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Instrumentation; -import android.test.ActivityInstrumentationTestCase2; -import android.util.Log; - -import junit.framework.Test; -import junit.framework.TestSuite; - -import org.junit.Assert; - -import java.io.InputStream; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import bbct.android.common.R; -import bbct.android.common.activity.FragmentTestActivity; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.BBCTTestUtil; -import bbct.android.common.test.BaseballCardCsvFileReader; -import bbct.android.common.test.DatabaseUtil; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.matcher.ViewMatchers.withId; - -public class BaseballCardDetailsEditCardTest extends - ActivityInstrumentationTestCase2 { - private static final String TEST_NAME = "testEditCard"; - private static final String CARD_DATA = "cards.csv"; - private static final String TAG = BaseballCardDetailsEditCardTest.class.getName(); - - private final Set inputMask; - private BaseballCard oldCard = null; - private BaseballCard newCard = null; - private DatabaseUtil dbUtil = null; - - public static Test suite() { - Log.d(TAG, "suite()"); - - TestSuite suite = new TestSuite(); - Set editTexts = EnumSet.allOf(BBCTTestUtil.EditTexts.class); - - for (BBCTTestUtil.EditTexts editText : editTexts) { - Set mask = new HashSet<>(); - mask.add(editText); - Log.d(TAG, "mask: " + mask); - suite.addTest(new BaseballCardDetailsEditCardTest(mask)); - } - - return suite; - } - - public BaseballCardDetailsEditCardTest(Set inputMask) { - super(FragmentTestActivity.class); - - this.setName(TEST_NAME); - this.inputMask = inputMask; - } - - @Override - public void setUp() throws Exception { - Log.d(TAG, "setUp()"); - Log.d(TAG, "inputMask=" + this.inputMask); - - super.setUp(); - - Instrumentation inst = this.getInstrumentation(); - InputStream in = inst.getContext().getAssets() - .open(CARD_DATA); - BaseballCardCsvFileReader cardInput = new BaseballCardCsvFileReader(in, - true); - List allCards = cardInput.getAllBaseballCards(); - this.oldCard = allCards.get(0); // Alex Fernandez - this.newCard = allCards.get(4); // Dave Hollins - cardInput.close(); - - this.newCard.value = this.newCard.value + 50; - this.newCard.quantity = this.newCard.quantity + 1; - - this.dbUtil = new DatabaseUtil(inst.getTargetContext()); - long cardId = this.dbUtil.insertBaseballCard(this.oldCard); - - Log.d(TAG, "cardId=" + cardId); - - if (cardId == -1) { - Log.e(TAG, this.oldCard.toString()); - } - - inst.setInTouchMode(true); - FragmentTestActivity activity = this.getActivity(); - BaseballCardDetails fragment = BaseballCardDetails.getInstance(cardId); - activity.replaceFragment(fragment); - } - - @Override - public void tearDown() throws Exception { - this.dbUtil.clearDatabase(); - - super.tearDown(); - - Log.d(TAG, "tearDown()"); - } - - public void testEditCard() { - Log.d(TAG, "testEditCard()"); - - Assert.assertTrue(this.dbUtil.containsBaseballCard(this.oldCard)); - - BBCTTestUtil.assertAllEditTextContents(this.oldCard); - BBCTTestUtil.sendKeysToCardDetails(this.newCard, this.inputMask); - - BaseballCard expected = this.getExpectedCard(); - - Log.d("DEBUG", "Checking cards for inputMask " + this.inputMask); - BBCTTestUtil.assertAllEditTextContents(expected); - Log.d("DEBUG", "Success!"); - - onView(withId(R.id.save_button)).perform(click()); - Assert.assertTrue(this.dbUtil.containsBaseballCard(expected)); - } - - private BaseballCard getExpectedCard() { - boolean autographed = this.inputMask.contains(BBCTTestUtil.EditTexts.AUTOGRAPHED) - ? this.newCard.autographed : this.oldCard.autographed; - String condition = this.inputMask.contains(BBCTTestUtil.EditTexts.CONDITION) - ? this.newCard.condition : this.oldCard.condition; - String brand = this.inputMask.contains(BBCTTestUtil.EditTexts.BRAND) - ? this.newCard.brand : this.oldCard.brand; - int year = this.inputMask.contains(BBCTTestUtil.EditTexts.YEAR) - ? this.newCard.year : this.oldCard.year; - String number = this.inputMask.contains(BBCTTestUtil.EditTexts.NUMBER) - ? this.newCard.number : this.oldCard.number; - int value = this.inputMask.contains(BBCTTestUtil.EditTexts.VALUE) - ? this.newCard.value : this.oldCard.value; - int quantity = this.inputMask.contains(BBCTTestUtil.EditTexts.COUNT) - ? this.newCard.quantity : this.oldCard.quantity; - String name = this.inputMask.contains(BBCTTestUtil.EditTexts.PLAYER_NAME) - ? this.newCard.playerName : this.oldCard.playerName; - String team = this.inputMask.contains(BBCTTestUtil.EditTexts.TEAM) - ? this.newCard.team : this.oldCard.team; - String position = this.inputMask.contains(BBCTTestUtil.EditTexts.PLAYER_POSITION) - ? this.newCard.position : this.oldCard.position; - return new BaseballCard( - autographed, - condition, - brand, - year, - number, - value, - quantity, - name, - team, - position - ); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsPartialInputTest.java b/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsPartialInputTest.java deleted file mode 100644 index a395ff557..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsPartialInputTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru { - private static final String CARD_DATA = "cards.csv"; - private static final String TEST_NAME = "testPartialInput"; - private static final String TAG = BaseballCardDetailsPartialInputTest.class.getName(); - - private BaseballCard card = null; - private final Set inputFieldsMask; - - public static Test suite() { - TestSuite suite = new TestSuite(); - Set editTexts = - EnumSet.range(BBCTTestUtil.EditTexts.BRAND, BBCTTestUtil.EditTexts.TEAM); - - for (BBCTTestUtil.EditTexts editText : editTexts) { - Set mask = new HashSet<>(); - mask.add(editText); - Log.d(TAG, "mask: " + mask); - suite.addTest(new BaseballCardDetailsPartialInputTest(mask)); - } - - return suite; - } - - public BaseballCardDetailsPartialInputTest(Set inputFieldsFlags) { - super(FragmentTestActivity.class); - - this.setName(TEST_NAME); - this.inputFieldsMask = inputFieldsFlags; - } - - @Override - public void setUp() throws IOException { - Instrumentation inst = this.getInstrumentation(); - InputStream in = inst.getContext().getAssets().open(CARD_DATA); - BaseballCardCsvFileReader cardInput = new BaseballCardCsvFileReader(in, true); - this.card = cardInput.getNextBaseballCard(); - cardInput.close(); - - inst.setInTouchMode(true); - FragmentTestActivity activity = this.getActivity(); - activity.replaceFragment(new BaseballCardDetails()); - } - - public void testPartialInput() { - Log.d(TAG, "testPartialInput()"); - Log.d(TAG, "inputFieldsMask=" + this.inputFieldsMask); - - BBCTTestUtil.sendKeysToCardDetails(this.card, this.inputFieldsMask); - onView(withId(R.id.save_button)).perform(click()); - - int focusId = -1; - - if (!this.inputFieldsMask.contains(BBCTTestUtil.EditTexts.TEAM)) { - onView(withId(R.id.team_text)) - .check(matches(hasErrorText(R.string.team_input_error))); - focusId = R.id.team_text; - } - if (!this.inputFieldsMask.contains(BBCTTestUtil.EditTexts.PLAYER_NAME)) { - onView(withId(R.id.player_name_text)) - .check(matches(hasErrorText(R.string.player_name_input_error))); - focusId = R.id.player_name_text; - } - if (!this.inputFieldsMask.contains(BBCTTestUtil.EditTexts.COUNT)) { - onView(withId(R.id.count_text)) - .check(matches(hasErrorText(R.string.count_input_error))); - focusId = R.id.count_text; - } - if (!this.inputFieldsMask.contains(BBCTTestUtil.EditTexts.VALUE)) { - onView(withId(R.id.value_text)) - .check(matches(hasErrorText(R.string.value_input_error))); - focusId = R.id.value_text; - } - if (!this.inputFieldsMask.contains(BBCTTestUtil.EditTexts.NUMBER)) { - onView(withId(R.id.number_text)) - .check(matches(hasErrorText(R.string.number_input_error))); - focusId = R.id.number_text; - } - if (!this.inputFieldsMask.contains(BBCTTestUtil.EditTexts.YEAR)) { - onView(withId(R.id.year_text)) - .check(matches(hasErrorText(R.string.year_input_error))); - focusId = R.id.year_text; - } - if (!this.inputFieldsMask.contains(BBCTTestUtil.EditTexts.BRAND)) { - onView(withId(R.id.brand_text)) - .check(matches(hasErrorText(R.string.brand_input_error))); - focusId = R.id.brand_text; - } - - if (focusId != -1) { - onView(withId(focusId)).check(matches(hasFocus())); - } - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsTest.java b/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsTest.java deleted file mode 100644 index 4fa6e0c64..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Activity; -import android.app.Instrumentation; -import android.graphics.Rect; -import android.os.RemoteException; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; - -import androidx.test.espresso.Espresso; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.uiautomator.UiDevice; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.InputStream; - -import bbct.android.common.R; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.BBCTTestUtil; -import bbct.android.common.test.BaseballCardCsvFileReader; -import bbct.android.common.test.rule.SupportFragmentTestRule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.scrollTo; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.hasFocus; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; - -public class BaseballCardDetailsTest { - - private static final int SLEEP_TIME_TO_REFRESH = 200; - private static final int KEYPAD_HEIGHT = 100; - private static final String CARD_DATA = "cards.csv"; - private static final String TAG = BaseballCardDetailsTest.class.getName(); - - @Rule - public SupportFragmentTestRule fragmentTestRule - = new SupportFragmentTestRule(new BaseballCardDetails()); - - private UiDevice device; - private Activity activity; - private BaseballCard card; - - @Before - public void setUp() throws Exception { - Instrumentation inst = InstrumentationRegistry.getInstrumentation(); - this.device = UiDevice.getInstance(inst); - - InputStream in = inst.getContext().getAssets().open(CARD_DATA); - BaseballCardCsvFileReader cardInput = new BaseballCardCsvFileReader(in, - true); - this.card = cardInput.getNextBaseballCard(); - cardInput.close(); - - this.activity = fragmentTestRule.getActivity(); - } - - @After - public void tearDown() throws RemoteException { - device.setOrientationNatural(); - } - - @Test - public void testPreConditions() { - Assert.assertNotNull(this.activity); - onView(withId(R.id.brand_text)).check(matches(isDisplayed())); - onView(withId(R.id.year_text)).check(matches(isDisplayed())); - onView(withId(R.id.number_text)).check(matches(isDisplayed())); - onView(withId(R.id.value_text)).check(matches(isDisplayed())); - onView(withId(R.id.count_text)).check(matches(isDisplayed())); - onView(withId(R.id.player_name_text)).check(matches(isDisplayed())); - onView(withId(R.id.team_text)).check(matches(isDisplayed())); - onView(withId(R.id.player_position_text)).check(matches(isDisplayed())); - onView(withId(R.id.scroll_card_details)).check(matches(isDisplayed())); - } - - @Test - public void testStateDestroy() throws RemoteException { - BBCTTestUtil.sendKeysToCardDetails(this.card); - device.setOrientationLeft(); - BBCTTestUtil.assertAllEditTextContents(this.card); - } - - @Test - public void testNextButtonOnClick() { - onView(withId(R.id.brand_text)).check(matches(hasFocus())); - device.pressEnter(); - onView(withId(R.id.year_text)).perform(click()).check(matches(hasFocus())); - device.pressEnter(); - onView(withId(R.id.number_text)).check(matches(hasFocus())); - device.pressEnter(); - onView(withId(R.id.value_text)).check(matches(hasFocus())); - device.pressEnter(); - onView(withId(R.id.count_text)).check(matches(hasFocus())); - device.pressEnter(); - onView(withId(R.id.player_name_text)).check(matches(hasFocus())); - device.pressEnter(); - onView(withId(R.id.team_text)).check(matches(hasFocus())); - - ViewGroup content = activity.findViewById(android.R.id.content); - View rootView = content.getChildAt(0); - Rect r = new Rect(); - // r will be populated with the coordinates of the view area still - // visible. - rootView.getWindowVisibleDisplayFrame(r); - - int heightdiffBefore = rootView.getRootView().getHeight() - - (r.bottom - r.top); - boolean condnBefore = heightdiffBefore > KEYPAD_HEIGHT; - - device.pressEnter(); - // Wait for the keyboard to disappear and view to be refreshed - try { - Thread.sleep(SLEEP_TIME_TO_REFRESH); - } catch (InterruptedException e) { - Log.e(TAG, "Click Done button in soft Keyboard"); - } - rootView.getWindowVisibleDisplayFrame(r); - int heightdiffAfter = rootView.getRootView().getHeight() - - (r.bottom - r.top); - boolean condnAfter = heightdiffAfter < KEYPAD_HEIGHT; - Assert.assertTrue(condnBefore && condnAfter); - } - - @Test - public void testCardDetailsScroll() { - Espresso.closeSoftKeyboard(); - onView(withId(R.id.player_position_text)) - .perform(scrollTo()) - .check(matches(isDisplayed())); - } - -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsWithDataTest.java b/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsWithDataTest.java deleted file mode 100644 index f5710b325..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardDetailsWithDataTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2014 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.os.RemoteException; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.uiautomator.UiDevice; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.rule.DataTestRule; -import bbct.android.common.test.rule.SupportFragmentTestRule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.RootMatchers.isPlatformPopup; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; - -public class BaseballCardDetailsWithDataTest { - @Rule - public DataTestRule dataTestRule = new DataTestRule(); - @Rule - public SupportFragmentTestRule fragmentTestRule - = new SupportFragmentTestRule(new BaseballCardDetails()); - - private BaseballCard mCard; - private UiDevice device; - - @Before - public void setUp() { - mCard = dataTestRule.getCard(0); - device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); - } - - @After - public void tearDown() throws RemoteException { - device.setOrientationNatural(); - } - - @Test - public void testBrandAutoCompletePopup() { - this.testAutoCompletePopup(R.id.brand_text, mCard.brand); - } - - @Test - public void testPlayerNameAutoCompletePopup() { - this.testAutoCompletePopup(R.id.player_name_text, mCard.playerName); - } - - @Test - public void testTeamAutoCompletePopup() { - this.testAutoCompletePopup(R.id.team_text, mCard.team); - } - - private void testAutoCompletePopup(int textViewId, String text) { - onView(withId(textViewId)).perform(typeText(text.substring(0, 2))); - onView(withText(text)) - .inRoot(isPlatformPopup()) - .perform(click()); - } - - @Test - public void testBrandAutoCompleteDestroy() throws RemoteException { - testAutoCompleteDestroy(R.id.brand_text, mCard.brand); - } - - @Test - public void testPlayerNameAutoCompleteDestroy() throws RemoteException { - testAutoCompleteDestroy(R.id.player_name_text, mCard.playerName); - } - - @Test - public void testTeamAutoCompleteDestroy() throws RemoteException { - testAutoCompleteDestroy(R.id.team_text, mCard.team); - } - - private void testAutoCompleteDestroy(int id, String text) throws RemoteException { - onView(withId(id)).perform(typeText(text)); - device.setOrientationLeft(); - onView(withId(id)).check(matches(withText(text))); - } - - @Test - public void testBrandAutoCompleteSelect() { - testAutoCompleteSelect(R.id.brand_text, mCard.brand); - } - - @Test - public void testPlayerNameAutoCompleteSelect() { - testAutoCompleteSelect(R.id.player_name_text, mCard.playerName); - } - - @Test - public void testTeamAutoCompleteSelect() { - testAutoCompleteSelect(R.id.team_text, mCard.team); - } - - private void testAutoCompleteSelect(int textViewId, String text) { - onView(withId(textViewId)).perform(typeText(text.substring(0, 2))); - onView(withText(text)) - .inRoot(isPlatformPopup()) - .perform(click()); - onView(withId(textViewId)).check(matches(withText(text))); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListSelectionTest.java b/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListSelectionTest.java deleted file mode 100644 index 3c6abe4c7..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListSelectionTest.java +++ /dev/null @@ -1,146 +0,0 @@ -package bbct.android.common.fragment; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.longClick; -import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isChecked; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static org.hamcrest.Matchers.instanceOf; -import static bbct.android.common.test.matcher.Matchers.atPosition; -import static bbct.android.common.test.matcher.Matchers.first; - -import android.app.Instrumentation; - -import androidx.test.ext.junit.rules.ActivityScenarioRule; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.uiautomator.UiDevice; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.util.List; - -import bbct.android.common.R; -import bbct.android.common.activity.MainActivity; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.BBCTTestUtil; -import bbct.android.common.test.DatabaseUtil; -import bbct.android.common.test.rule.DataTestRule; -import bbct.android.common.view.BaseballCardView; - -abstract public class BaseballCardListSelectionTest { - @Rule - public DataTestRule dataTestRule = new DataTestRule(); - @Rule - public ActivityScenarioRule activityScenarioRule; - - private UiDevice device; - private Instrumentation inst; - private DatabaseUtil dbUtil; - private List allCards; - - public BaseballCardListSelectionTest(Class activityClass) { - activityScenarioRule = new ActivityScenarioRule<>(activityClass); - } - - @Before - public void setUp() { - inst = InstrumentationRegistry.getInstrumentation(); - device = UiDevice.getInstance(inst); - allCards = dataTestRule.getAllCards(); - dbUtil = new DatabaseUtil(inst.getTargetContext()); - } - - @After - public void tearDown() throws Throwable{ - device.setOrientationNatural(); - } - - @Test - public void testPreConditions() { - BBCTTestUtil.assertDatabaseCreated(inst.getTargetContext()); - Assert.assertTrue(dbUtil.containsAllBaseballCards(this.allCards)); - BBCTTestUtil.assertListContainsItems(this.allCards); - } - - @Test - public void testSelectAll() { - onView(first(withId(R.id.checkmark))) - .perform(click()); - onView(withId(R.id.select_all_menu)) - .perform(click()); - this.assertAllCheckboxesChecked(); - } - - @Test - public void testSelectionAfterSaveInstanceState() throws Throwable { - int index = 1; - onView(atPosition(index, withId(R.id.checkmark))) - .perform(click()); - onView(withId(R.id.delete_menu)) - .check(matches(isDisplayed())); - device.setOrientationLeft(); - onView(atPosition(index, withId(R.id.checkmark))) - .check(matches(isChecked())); - } - - @Test - public void testOnClickCheckboxStartActionMode() { - int index = 4; - onView(atPosition(index, withId(R.id.checkmark))) - .perform(click()); - onView(withId(R.id.delete_menu)) - .check(matches(isDisplayed())); - onView(withId(R.id.select_all_menu)) - .check(matches(isDisplayed())); - } - - @Test - public void testOnClickCheckboxStopActionMode() { - int index = 4; - onView(atPosition(index, withId(R.id.checkmark))) - .perform(click()); - onView(withId(R.id.delete_menu)) - .check(matches(isDisplayed())); - onView(atPosition(index, withId(R.id.checkmark))) - .perform(click()); - onView(withId(R.id.delete_menu)) - .check(doesNotExist()); - onView(withId(R.id.select_all_menu)) - .check(doesNotExist()); - assertNoCheckboxesChecked(); - } - - @Test - public void testOnItemLongClickStartActionMode() { - int index = 4; - onView(atPosition(index, instanceOf(BaseballCardView.class))) - .perform(longClick()); - onView(withId(R.id.delete_menu)) - .check(matches(isDisplayed())); - onView(withId(R.id.select_all_menu)) - .check(matches(isDisplayed())); - } - - private void assertAllCheckboxesChecked() { - for (int i = 0; i < allCards.size(); i++) { - onView(atPosition(i, instanceOf(BaseballCardView.class))) - .check(matches(isChecked())); - } - } - - private void assertNoCheckboxesChecked() { - for (int i = 0; i < allCards.size(); i++) { - onView(atPosition(i, instanceOf(BaseballCardView.class))) - .check(matches(isNotChecked())); - } - } - -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListWithDataTest.java b/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListWithDataTest.java deleted file mode 100644 index fb9f83132..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListWithDataTest.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Activity; -import android.app.Instrumentation; -import android.os.RemoteException; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.ActivityTestRule; -import androidx.test.uiautomator.UiDevice; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import bbct.android.common.R; -import bbct.android.common.activity.MainActivity; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.BBCTTestUtil; -import bbct.android.common.test.DatabaseUtil; -import bbct.android.common.test.rule.DataTestRule; -import bbct.android.common.view.BaseballCardView; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static bbct.android.common.test.matcher.BaseballCardMatchers.withYear; -import static bbct.android.common.test.matcher.Matchers.atPosition; -import static bbct.android.common.test.matcher.Matchers.first; -import static bbct.android.common.test.matcher.RecyclerViewMatcher.contains; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; - -abstract public class BaseballCardListWithDataTest { - @Rule - public DataTestRule dataTestRule = new DataTestRule(); - @Rule - public ActivityTestRule activityTestRule; - - private static final String TAG = BaseballCardListWithDataTest.class.getName(); - - private UiDevice device; - private List expectedCards; - private Instrumentation inst; - private Activity activity; - private List allCards; - private BaseballCard newCard = null; - private DatabaseUtil dbUtil; - - public BaseballCardListWithDataTest(Class activityClass) { - activityTestRule = new ActivityTestRule<>(activityClass); - } - - @Before - public void setUp() { - inst = InstrumentationRegistry.getInstrumentation(); - device = UiDevice.getInstance(inst); - activity = activityTestRule.getActivity(); - allCards = dataTestRule.getAllCards(); - newCard = new BaseballCard(true, "Mint", "Code Guru Apps", 1993, - "1", 50000, 1, "Code Guru", "Code Guru Devs", "Catcher"); - - dbUtil = new DatabaseUtil(inst.getTargetContext()); - } - - @After - public void tearDown() throws RemoteException { - device.setOrientationNatural(); - } - - @Test - public void testPreConditions() { - Assert.assertNotNull(this.activity); - BBCTTestUtil.assertDatabaseCreated(this.inst.getTargetContext()); - Assert.assertTrue(this.dbUtil.containsAllBaseballCards(this.allCards)); - BBCTTestUtil.assertListContainsItems(this.allCards); - } - - @Test - public void testAddCardsMenuItem() { - BBCTTestUtil.testMenuItem(R.id.add_button, FragmentTags.EDIT_CARD); - } - - @Test - public void testFilterCardsMenuItem() { - BBCTTestUtil.testMenuItem(R.id.filter_menu, FragmentTags.FILTER_CARDS); - } - - @Test - public void testStateDestroyWithoutFilter() throws RemoteException { - device.setOrientationLeft(); - onView(withId(R.id.card_list)) - .check(matches(contains(allCards))); - } - - @Test - public void testStateDestroyWithFilter() throws RemoteException { - final int year = 1993; - onView(withId(R.id.filter_menu)).perform(click()); - BBCTTestUtil.sendKeysToCurrFieldFilterCards( - R.id.year_check, - R.id.year_input, - year + "" - ); - onView(withId(R.id.confirm_button)).perform(click()); - expectedCards = BBCTTestUtil.filterList(allCards, withYear(year)); - device.setOrientationLeft(); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - } - - @Test - public void testOnListItemClick() { - int cardIndex = 3; - BaseballCard expectedCard = allCards.get(cardIndex); - onView(atPosition(cardIndex, instanceOf(BaseballCardView.class))) - .perform(click()); - BBCTTestUtil.assertAllEditTextContents(expectedCard); - } - - @Test - public void testAddDuplicateCard() { - BaseballCard card = dataTestRule.getCard(0); - onView(withId(R.id.add_button)).perform(click()); - BBCTTestUtil.addCard(card); - onView(withText(R.string.duplicate_card_title)) - .check(matches(isDisplayed())); - onView(withText(R.string.duplicate_card_error)) - .check(matches(isDisplayed())); - onView(withText(android.R.string.ok)) - .check(matches(isDisplayed())) - .perform(click()); - onView(withText(R.string.duplicate_card_title)) - .check(doesNotExist()); - onView(withText(R.string.duplicate_card_error)) - .check(doesNotExist()); - } - - @Test - public void testAddCardToPopulatedDatabase() { - onView(withId(R.id.add_button)).perform(click()); - BBCTTestUtil.addCard(newCard); - // BBCTTestUtil.waitForToast(BBCTTestUtil.ADD_MESSAGE); - onView(withContentDescription(containsString("Navigate up"))).perform(click()); - expectedCards = new ArrayList<>(allCards); - expectedCards.add(newCard); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - } - - @Test - public void testAddCardMatchingCurrentFilter() { - final int year = 1993; - onView(withId(R.id.filter_menu)).perform(click()); - BBCTTestUtil.sendKeysToCurrFieldFilterCards( - R.id.year_check, - R.id.year_input, - year + "" - ); - onView(withId(R.id.confirm_button)).perform(click()); - onView(withId(R.id.add_button)).perform(click()); - BBCTTestUtil.addCard(newCard); - // BBCTTestUtil.waitForToast(activity, BBCTTestUtil.ADD_MESSAGE); - onView(withContentDescription(containsString("Navigate up"))) - .perform(click()); - expectedCards = BBCTTestUtil.filterList(allCards, withYear(year)); - expectedCards.add(newCard); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - } - - @Test - public void testAddCardNotMatchingCurrentFilter() { - final int year = 1993; - newCard = new BaseballCard( - false, - "Excellent", - "Codeguru Apps", - 1976, - "1", - 50000, - 1, - "Codeguru", - "Codeguru Devs", - "Catcher" - ); - onView(withId(R.id.filter_menu)).perform(click()); - BBCTTestUtil.sendKeysToCurrFieldFilterCards( - R.id.year_check, - R.id.year_input, - year + "" - ); - onView(withId(R.id.confirm_button)).perform(click()); - onView(withId(R.id.add_button)).perform(click()); - BBCTTestUtil.addCard(newCard); - // BBCTTestUtil.waitForToast(activity, BBCTTestUtil.ADD_MESSAGE); - onView(withContentDescription(containsString("Navigate up"))).perform(click()); - expectedCards = BBCTTestUtil.filterList(allCards, withYear(year)); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - } - - @Test - public void testAddCardAfterClearFilter() { - final int year = 1993; - onView(withId(R.id.filter_menu)).perform(click()); - BBCTTestUtil.sendKeysToCurrFieldFilterCards( - R.id.year_check, - R.id.year_input, - "" + year - ); - onView(withId(R.id.confirm_button)).perform(click()); - onView(withId(R.id.clear_filter_menu)).perform(click()); - onView(withId(R.id.add_button)).perform(click()); - BBCTTestUtil.addCard(newCard); - // BBCTTestUtil.waitForToast(activity, BBCTTestUtil.ADD_MESSAGE); - onView(withContentDescription(containsString("Navigate up"))).perform(click()); - expectedCards = new ArrayList<>(allCards); - expectedCards.add(newCard); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - } - - @Test - public void testDeleteAll() { - onView(first(withId(R.id.checkmark))).perform(click()); - onView(withId(R.id.select_all_menu)).perform(click()); - onView(withId(R.id.delete_menu)).perform(click()); - // BBCTTestUtil.waitForToast(activity, BBCTTestUtil.DELETE_MESSAGE); - expectedCards = new ArrayList<>(); - onView(withId(R.id.card_list)).check(matches(contains(expectedCards))); - } - - @Test - public void testDeleteCardUsingFilter() { - int cardIndex = 0; - final int year = 1993; - expectedCards = BBCTTestUtil.filterList(allCards, withYear(year)); - expectedCards.remove(cardIndex); - - onView(withId(R.id.filter_menu)).perform(click()); - BBCTTestUtil.sendKeysToCurrFieldFilterCards( - R.id.year_check, - R.id.year_input, - year + "" - ); - onView(withId(R.id.confirm_button)).perform(click()); - onView(first(withId(R.id.checkmark))) - .perform(click()); - onView(withId(R.id.delete_menu)) - .perform(click()); - // BBCTTestUtil.waitForToast(activity, BBCTTestUtil.DELETE_MESSAGE); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - } - - @Test - public void testDeleteCardNoFilter() { - int cardIndex = 0; - expectedCards = new ArrayList<>(allCards); - expectedCards.remove(cardIndex); - onView(first(withId(R.id.checkmark))) - .perform(click()); - onView(withId(R.id.delete_menu)) - .perform(click()); - // BBCTTestUtil.waitForToast(activity, BBCTTestUtil.DELETE_MESSAGE); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - } - - @Test - public void testYearFilter() { - final int year = 1993; - onView(withId(R.id.filter_menu)).perform(click()); - BBCTTestUtil.sendKeysToCurrFieldFilterCards( - R.id.year_check, - R.id.year_input, - year + "" - ); - onView(withId(R.id.confirm_button)).perform(click()); - expectedCards = BBCTTestUtil.filterList(allCards, withYear(year)); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - onView(withId(R.id.clear_filter_menu)) - .check(matches(isDisplayed())); - } - - @Test - public void testClearFilter() { - final int year = 1993; - onView(withId(R.id.filter_menu)).perform(click()); - BBCTTestUtil.sendKeysToCurrFieldFilterCards( - R.id.year_check, - R.id.year_input, - year + "" - ); - onView(withId(R.id.confirm_button)).perform(click()); - onView(withId(R.id.clear_filter_menu)).perform(click()); - onView(withId(R.id.card_list)) - .check(matches(contains(allCards))); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListWithoutDataTest.java b/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListWithoutDataTest.java deleted file mode 100644 index afc1194b2..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/BaseballCardListWithoutDataTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Activity; -import android.app.Instrumentation; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.ActivityTestRule; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import bbct.android.common.R; -import bbct.android.common.activity.MainActivity; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.BBCTTestUtil; -import bbct.android.common.test.BaseballCardCsvFileReader; -import bbct.android.common.test.DatabaseUtil; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static bbct.android.common.test.matcher.RecyclerViewMatcher.contains; -import static org.hamcrest.Matchers.containsString; - -abstract public class BaseballCardListWithoutDataTest { - @Rule - public ActivityTestRule activityTestRule; - - private static final String DATA_ASSET = "three_cards.csv"; - - private Instrumentation inst = null; - private Activity activity = null; - private BaseballCardCsvFileReader cardInput = null; - private DatabaseUtil dbUtil = null; - - public BaseballCardListWithoutDataTest(Class activityClass) { - activityTestRule = new ActivityTestRule<>(activityClass); - } - - @Before - public void setUp() throws Exception { - this.inst = InstrumentationRegistry.getInstrumentation(); - this.activity = activityTestRule.getActivity(); - - InputStream cardInputStream = this.inst.getContext().getAssets() - .open(DATA_ASSET); - this.cardInput = new BaseballCardCsvFileReader(cardInputStream, true); - this.dbUtil = new DatabaseUtil(this.inst.getTargetContext()); - } - - @After - public void tearDown() throws Exception { - this.dbUtil.clearDatabase(); - this.cardInput.close(); - } - - @Test - public void testPreConditions() { - Assert.assertNotNull(this.activity); - - BBCTTestUtil.assertDatabaseCreated(this.inst.getTargetContext()); - Assert.assertTrue(this.dbUtil.isEmpty()); - } - - @Test - public void testAddCardToEmptyDatabase() throws Throwable { - BaseballCard card = this.cardInput.getNextBaseballCard(); - - onView(withId(R.id.add_button)) - .perform(click()); - BBCTTestUtil.addCard(card); - // BBCTTestUtil.waitForToast(activity, BBCTTestUtil.ADD_MESSAGE); - onView(withContentDescription(containsString("Navigate up"))).perform(click()); - - Assert.assertTrue(this.dbUtil.containsBaseballCard(card)); - - List cards = new ArrayList<>(); - cards.add(card); - onView(withId(R.id.card_list)) - .check(matches(contains(cards))); - } - - @Test - public void testAddMultipleCards() throws Throwable { - List cards = this.cardInput.getAllBaseballCards(); - - onView(withId(R.id.add_button)) - .perform(click()); - for (BaseballCard card : cards) { - BBCTTestUtil.addCard(card); - // BBCTTestUtil.waitForToast(this.solo, BBCTTestUtil.ADD_MESSAGE); - } - - onView(withContentDescription(containsString("Navigate up"))).perform(click()); - Assert.assertTrue(dbUtil.containsAllBaseballCards(cards)); - onView(withId(R.id.card_list)) - .check(matches(contains(cards))); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/DetailsNavigateNextTest.java b/android/src/androidTest/java/bbct/android/common/fragment/DetailsNavigateNextTest.java deleted file mode 100644 index 1c9d2b56b..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/DetailsNavigateNextTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2017 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.view.KeyEvent; - -import androidx.annotation.IdRes; - -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.test.rule.SupportFragmentTestRule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.pressKey; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.hasFocus; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static bbct.android.common.test.ViewActions.requestFocus; - -public class DetailsNavigateNextTest { - @Rule - public SupportFragmentTestRule fragmentTestRule - = new SupportFragmentTestRule(new BaseballCardDetails()); - - @Test - public void brandNext() { - testNext(R.id.brand_text, R.id.year_text); - } - - @Test - public void yearNext() { - testNext(R.id.year_text, R.id.number_text); - } - - @Test - public void numberNext() { - testNext(R.id.number_text, R.id.value_text); - } - - @Test - public void valueNext() { - testNext(R.id.value_text, R.id.count_text); - } - - @Test - public void countNext() { - testNext(R.id.count_text, R.id.player_name_text); - } - - @Test - public void playerNameNext() { - testNext(R.id.player_name_text, R.id.team_text); - } - - private void testNext(@IdRes int startingTextView, @IdRes int nextTextView) { - onView(withId(startingTextView)) - .check(matches(isDisplayed())) - .perform(requestFocus()) - .check(matches(hasFocus())) - .perform(pressKey(KeyEvent.KEYCODE_ENTER)); - onView(withId(nextTextView)) - .check(matches(hasFocus())); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/FilterCardsCombinationTest.java b/android/src/androidTest/java/bbct/android/common/fragment/FilterCardsCombinationTest.java deleted file mode 100644 index d810d9f17..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/FilterCardsCombinationTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Instrumentation; -import android.test.ActivityInstrumentationTestCase2; -import android.util.Log; - -import junit.framework.Test; -import junit.framework.TestSuite; - -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.hamcrest.Matcher; - -import java.io.InputStream; -import java.lang.reflect.Constructor; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import bbct.android.common.R; -import bbct.android.common.activity.MainActivity; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.BBCTTestUtil; -import bbct.android.common.test.BaseballCardCsvFileReader; -import bbct.android.common.test.DatabaseUtil; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static bbct.android.common.test.matcher.RecyclerViewMatcher.contains; - -abstract public class FilterCardsCombinationTest extends - ActivityInstrumentationTestCase2 { - private static final String TAG = FilterCardsCombinationTest.class.getName(); - private static final String CARD_DATA = "cards.csv"; - private static final String TEST_NAME = "testFilter"; - private final Set inputFieldsMask; - - private List allCards; - private BaseballCard testCard; - private DatabaseUtil dbUtil = null; - - public static > Test suite(Class testClass) - throws ReflectiveOperationException { - TestSuite suite = new TestSuite(); - Set options = EnumSet.allOf(BBCTTestUtil.FilterOption.class); - - for (BBCTTestUtil.FilterOption option : options) { - Set mask = new HashSet<>(); - mask.add(option); - - if (!mask.isEmpty()) { - Constructor ctor = testClass.getConstructor(Set.class); - suite.addTest(ctor.newInstance(mask)); - } - } - - return suite; - } - - public FilterCardsCombinationTest(Class activityClass, Set inputFieldsFlags) { - super(activityClass); - - this.setName(TEST_NAME); - this.inputFieldsMask = inputFieldsFlags; - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - Instrumentation inst = this.getInstrumentation(); - InputStream cardInputStream = inst.getContext().getAssets().open(CARD_DATA); - BaseballCardCsvFileReader cardInput = new BaseballCardCsvFileReader( - cardInputStream, true); - this.allCards = cardInput.getAllBaseballCards(); - this.testCard = this.allCards.get(1); - cardInput.close(); - - this.dbUtil = new DatabaseUtil(inst.getTargetContext()); - this.dbUtil.populateTable(this.allCards); - - inst.setInTouchMode(true); - getActivity(); - } - - @Override - public void tearDown() throws Exception { - this.dbUtil.deleteDatabase(); - - super.tearDown(); - } - - public void testFilter() { - Log.d(TAG, "inputFieldsMask=" + inputFieldsMask); - - BBCTTestUtil.testMenuItem(R.id.filter_menu, FragmentTags.FILTER_CARDS); - - final Set mask = inputFieldsMask; - final BaseballCard test = testCard; - Matcher cardMatcher = new BaseMatcher() { - @Override - public void describeTo(Description description) { - description.appendText("matching card"); - } - - @Override - public boolean matches(Object obj) { - BaseballCard card = (BaseballCard)obj; - boolean condition = true; - - if (mask.contains(BBCTTestUtil.FilterOption.BRAND)) { - condition = card.brand.equals(test.brand); - } - - if (mask.contains(BBCTTestUtil.FilterOption.YEAR)) { - condition = condition && card.year.equals(test.year); - } - - if (mask.contains(BBCTTestUtil.FilterOption.NUMBER)) { - condition = condition && card.number.equals(test.number); - } - - if (mask.contains(BBCTTestUtil.FilterOption.PLAYER_NAME)) { - condition = condition && card.playerName.equals(test.playerName); - } - - if (mask.contains(BBCTTestUtil.FilterOption.TEAM)) { - condition = condition && card.team.equals(test.team); - } - - return condition; - } - }; - - BBCTTestUtil.sendKeysToFilterCards(testCard, inputFieldsMask); - onView(withId(R.id.confirm_button)).perform(click()); - List expectedCards = BBCTTestUtil.filterList(allCards, cardMatcher); - onView(withId(R.id.card_list)) - .check(matches(contains(expectedCards))); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/fragment/FilterCardsTest.java b/android/src/androidTest/java/bbct/android/common/fragment/FilterCardsTest.java deleted file mode 100644 index ac710ba21..000000000 --- a/android/src/androidTest/java/bbct/android/common/fragment/FilterCardsTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Activity; -import android.os.RemoteException; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.uiautomator.UiDevice; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.test.rule.SupportFragmentTestRule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.hasFocus; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; - -public class FilterCardsTest { - @Rule - public SupportFragmentTestRule fragmentTestRule - = new SupportFragmentTestRule(new FilterCards()); - - private Activity activity = null; - private UiDevice device; - - @Before - public void setUp() { - activity = fragmentTestRule.getActivity(); - device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); - } - - @After - public void tearDown() throws RemoteException { - device.setOrientationNatural(); - } - - @Test - public void testPreConditions() { - Assert.assertNotNull(this.activity); - onView(withId(R.id.confirm_button)).check(matches(not(isEnabled()))); - } - - @Test - public void testTitle() { - String filterCardsTitle = this.activity.getString(R.string.filter_cards_title); - onView(withText(containsString(filterCardsTitle))).check(matches(isDisplayed())); - } - - private void testCheckBox(int checkId, int inputId) { - onView(withId(checkId)).perform(click()); - onView(withId(inputId)).check(matches(allOf(isEnabled(), hasFocus()))); - onView(withId(R.id.confirm_button)).check(matches(isDisplayed())); - } - - @Test - public void testBrandCheckBox() { - this.testCheckBox(R.id.brand_check, R.id.brand_input); - } - - @Test - public void testYearCheckBox() { - this.testCheckBox(R.id.year_check, R.id.year_input); - } - - @Test - public void testNumberCheckBox() { - this.testCheckBox(R.id.number_check, R.id.number_input); - } - - @Test - public void testPlayerNameCheckBox() { - this.testCheckBox(R.id.player_name_check, R.id.player_name_input); - } - - @Test - public void testTeamCheckBox() { - this.testCheckBox(R.id.team_check, R.id.team_input); - } - - @Test - public void testSaveInstanceState() throws RemoteException { - this.testNumberCheckBox(); - device.setOrientationLeft(); - onView(withId(R.id.number_input)).check(matches(isEnabled())); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/functional/LaunchTest.java b/android/src/androidTest/java/bbct/android/common/functional/LaunchTest.java deleted file mode 100644 index de2998f9c..000000000 --- a/android/src/androidTest/java/bbct/android/common/functional/LaunchTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.functional; - -import androidx.test.uiautomator.UiObject; -import androidx.test.uiautomator.UiSelector; - -import org.junit.Assert; -import org.junit.Test; - -public class LaunchTest extends UiAutomatorTest { - - @Test - public void testLaunch() { - String packageName = inst.getTargetContext().getPackageName(); - UiObject appValidation = device.findObject(new UiSelector().packageName(packageName)); - Assert.assertTrue("Could not open test app", appValidation.exists()); - } - -} diff --git a/android/src/androidTest/java/bbct/android/common/functional/Screenshots.java b/android/src/androidTest/java/bbct/android/common/functional/Screenshots.java deleted file mode 100644 index 730f1e27e..000000000 --- a/android/src/androidTest/java/bbct/android/common/functional/Screenshots.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.functional; - -import android.util.Log; -import android.widget.CheckBox; -import android.widget.EditText; - -import androidx.test.uiautomator.UiObject; -import androidx.test.uiautomator.UiObjectNotFoundException; -import androidx.test.uiautomator.UiSelector; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.rule.DataTestRule; -import tools.fastlane.screengrab.Screengrab; -import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; - -public class Screenshots extends UiAutomatorTest { - @Rule - public DataTestRule dataTestRule = new DataTestRule(); - - private static final String TAG = Screenshots.class.getName(); - private static final long TIMEOUT = 5000; - private static final String YEAR_STRING = "1993"; - public static final int YEAR_INSTANCE = 1; - - private int screenshotCount; - private BaseballCard card; - - @Before - public void setUp() throws UiObjectNotFoundException { - super.setUp(); - screenshotCount = 1; - card = dataTestRule.getCard(0); - Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); - } - - @Test - public void takeScreenshots() throws Throwable { - UiSelector addSelector = new UiSelector().description(context.getString(R.string.add_menu)); - UiObject addMenu = device.findObject(addSelector); - addMenu.click(); - device.waitForWindowUpdate(context.getPackageName(), TIMEOUT); - takeScreenshot("NewCard"); - - device.pressBack(); - device.waitForWindowUpdate(context.getPackageName(), TIMEOUT); - takeScreenshot("CardList"); - - UiSelector playerNameSelector = new UiSelector().text(card.playerName); - UiObject listItem = device.findObject(playerNameSelector); - listItem.click(); - device.waitForWindowUpdate(context.getPackageName(), TIMEOUT); - device.pressBack(); - takeScreenshot("CardDetails"); - - device.pressBack(); - UiSelector filterSelector = new UiSelector().description(context.getString(R.string.filter_menu)); - UiObject filterMenu = device.findObject(filterSelector); - filterMenu.click(); - device.waitForWindowUpdate(context.getPackageName(), TIMEOUT); - UiSelector yearCheckBoxSelector = new UiSelector().className(CheckBox.class).instance(YEAR_INSTANCE); - UiObject yearCheckBox = device.findObject(yearCheckBoxSelector); - yearCheckBox.click(); - UiSelector yearTextViewSelector = new UiSelector().className(EditText.class).instance(YEAR_INSTANCE); - UiObject yearTextView = device.findObject(yearTextViewSelector); - yearTextView.setText(YEAR_STRING); - device.waitForIdle(); - takeScreenshot("FilterCards"); - - UiSelector saveSelector = new UiSelector().description(context.getString(R.string.save_menu)); - UiObject saveMenu = device.findObject(saveSelector); - saveMenu.click(); - device.waitForWindowUpdate(context.getPackageName(), TIMEOUT); - takeScreenshot("FilteredList"); - - UiSelector overflowSelector = new UiSelector().description("More options"); - UiObject overflowMenu = device.findObject(overflowSelector); - overflowMenu.click(); - device.waitForWindowUpdate(context.getPackageName(), TIMEOUT); - UiSelector aboutSelector = new UiSelector().text(context.getString(R.string.about_menu)); - UiObject aboutMenu = device.findObject(aboutSelector); - aboutMenu.click(); - device.waitForWindowUpdate(context.getPackageName(), TIMEOUT); - takeScreenshot("About"); - } - - private void takeScreenshot(String description) { - String screenshotName = String.format("%02d-%s", screenshotCount++, - description); - Log.d("screenshot", screenshotName); - Screengrab.screenshot(screenshotName); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/functional/UiAutomatorTest.java b/android/src/androidTest/java/bbct/android/common/functional/UiAutomatorTest.java deleted file mode 100644 index b95395cb2..000000000 --- a/android/src/androidTest/java/bbct/android/common/functional/UiAutomatorTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2015 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.functional; - -import android.app.Instrumentation; -import android.content.Context; -import android.content.Intent; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.uiautomator.By; -import androidx.test.uiautomator.UiDevice; -import androidx.test.uiautomator.UiObject; -import androidx.test.uiautomator.UiObjectNotFoundException; -import androidx.test.uiautomator.UiSelector; -import androidx.test.uiautomator.Until; - -import org.junit.After; -import org.junit.Before; - -import bbct.android.common.R; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsNull.notNullValue; - -public abstract class UiAutomatorTest { - private static final int LAUNCH_TIMEOUT = 5000; - - protected UiDevice device; - protected Instrumentation inst; - protected Context context; - - private String targetPackage; - - @Before - public void setUp() throws UiObjectNotFoundException { - inst = InstrumentationRegistry.getInstrumentation(); - device = UiDevice.getInstance(inst); - context = inst.getTargetContext(); - targetPackage = context.getPackageName(); - startApp(); - } - - @After - public void tearDown() { - device.pressHome(); - } - - private void startApp() { - // Start from the home screen - device.pressHome(); - - // Wait for launcher - final String launcherPackage = device.getLauncherPackageName(); - assertThat(launcherPackage, notNullValue()); - device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); - - // Launch the app - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - final Intent intent = context.getPackageManager() - .getLaunchIntentForPackage(targetPackage); - // Clear out any previous instances - assert intent != null; - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - context.startActivity(intent); - - // Wait for the app to appear - device.wait(Until.hasObject(By.pkg(targetPackage).depth(0)), LAUNCH_TIMEOUT); - } - - protected void clickLaterButton() throws UiObjectNotFoundException { - UiSelector laterSelector = new UiSelector().text(context.getString(R.string.later)); - UiObject laterButton = device.findObject(laterSelector); - laterButton.click(); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/functional/package-info.java b/android/src/androidTest/java/bbct/android/common/functional/package-info.java deleted file mode 100644 index d9322cb37..000000000 --- a/android/src/androidTest/java/bbct/android/common/functional/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2015 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.functional; diff --git a/android/src/androidTest/java/bbct/android/common/functional/survey/Survey1DialogTest.java b/android/src/androidTest/java/bbct/android/common/functional/survey/Survey1DialogTest.java deleted file mode 100644 index 81abb9741..000000000 --- a/android/src/androidTest/java/bbct/android/common/functional/survey/Survey1DialogTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.functional.survey; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.Uri; - -import androidx.test.espresso.intent.Intents; -import androidx.test.platform.app.InstrumentationRegistry; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.SharedPreferenceKeys; -import bbct.android.common.activity.MainActivity; -import bbct.android.common.test.rule.Survey1SharedPreferencesTestRule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.intent.Intents.intended; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasData; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.startsWith; - -public class Survey1DialogTest { - @Rule - public Survey1SharedPreferencesTestRule prefsRule = new Survey1SharedPreferencesTestRule(); - - private SharedPreferences prefs; - private Context context; - - @Before - public void setUp() { - context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - startApp(); - Intents.init(); - prefs = prefsRule.getPrefs(); - } - - @After - public void tearDown() { - Intents.release(); - } - - @Test - public void testPreconditions() { - Assert.assertFalse(prefs.contains(SharedPreferenceKeys.SURVEY_TAKEN_PREF)); - Assert.assertFalse(prefs.contains(SharedPreferenceKeys.SURVEY1_DATE)); - Assert.assertTrue(prefs.contains(SharedPreferenceKeys.INSTALL_DATE)); - } - - @Test - public void testTakeSurveyNow() { - onView(withText(R.string.survey1)) - .check(matches(isDisplayed())); - onView(withText(R.string.now)) - .check(matches(isDisplayed())) - .perform(click()); - Uri surveyUri = Uri.parse(MainActivity.SURVEY1_URI); - intended(allOf(hasAction(Intent.ACTION_VIEW), hasData(surveyUri))); - startApp(); - Assert.assertTrue(prefs.contains(SharedPreferenceKeys.SURVEY1_DATE)); - onView(withText(startsWith("BBCT"))) - .check(matches(isDisplayed())); - onView(withText(R.string.survey1)) - .check(doesNotExist()); - } - - @Test - public void testTakeSurveyLater() { - onView(withText(R.string.survey1)) - .check(matches(isDisplayed())); - onView(withText(R.string.later)) - .check(matches(isDisplayed())) - .perform(click()); - startApp(); - Assert.assertFalse(prefs.contains(SharedPreferenceKeys.SURVEY_TAKEN_PREF)); - onView(withText(R.string.survey1)) - .check(matches(isDisplayed())); - } - - private void startApp() { - String packageName = context.getPackageName(); - Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName); - assert intent != null; - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - context.startActivity(intent); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/functional/survey/Survey2DialogTest.java b/android/src/androidTest/java/bbct/android/common/functional/survey/Survey2DialogTest.java deleted file mode 100644 index 298f89cea..000000000 --- a/android/src/androidTest/java/bbct/android/common/functional/survey/Survey2DialogTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.functional.survey; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.Uri; - -import androidx.test.espresso.intent.Intents; -import androidx.test.platform.app.InstrumentationRegistry; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.SharedPreferenceKeys; -import bbct.android.common.activity.MainActivity; -import bbct.android.common.test.rule.Survey2SharedPreferencesTestRule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.intent.Intents.intended; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasData; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.startsWith; - -public class Survey2DialogTest { - @Rule - public Survey2SharedPreferencesTestRule prefsRule = new Survey2SharedPreferencesTestRule(); - - private SharedPreferences prefs; - private Context context; - - @Before - public void setUp() { - context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - startApp(); - Intents.init(); - prefs = prefsRule.getPrefs(); - } - - @After - public void tearDown() { - Intents.release(); - } - - @Test - public void testPreconditions() { - Assert.assertFalse(prefs.contains(SharedPreferenceKeys.SURVEY2_DATE)); - Assert.assertTrue(prefs.contains(SharedPreferenceKeys.SURVEY1_DATE)); - } - - @Test - public void testTakeSurveyNow() { - onView(withText(R.string.survey2)) - .check(matches(isDisplayed())); - onView(withText(R.string.now)) - .check(matches(isDisplayed())) - .perform(click()); - Uri surveyUri = Uri.parse(MainActivity.SURVEY2_URI); - intended(allOf(hasAction(Intent.ACTION_VIEW), hasData(surveyUri))); - startApp(); - Assert.assertTrue(prefs.contains(SharedPreferenceKeys.SURVEY2_DATE)); - onView(withText(startsWith("BBCT"))) - .check(matches(isDisplayed())); - onView(withText(R.string.survey1)) - .check(doesNotExist()); - } - - @Test - public void testTakeSurveyLater() { - onView(withText(R.string.survey2)) - .check(matches(isDisplayed())); - onView(withText(R.string.later)) - .check(matches(isDisplayed())) - .perform(click()); - startApp(); - Assert.assertFalse(prefs.contains(SharedPreferenceKeys.SURVEY_TAKEN_PREF)); - onView(withText(R.string.survey2)) - .check(matches(isDisplayed())); - } - - private void startApp() { - String packageName = context.getPackageName(); - Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName); - assert intent != null; - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - context.startActivity(intent); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/layout/BaseballCardDetailsLayoutTest.java b/android/src/androidTest/java/bbct/android/common/layout/BaseballCardDetailsLayoutTest.java deleted file mode 100644 index 2f2bb522b..000000000 --- a/android/src/androidTest/java/bbct/android/common/layout/BaseballCardDetailsLayoutTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.layout; - -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.fragment.BaseballCardDetails; -import bbct.android.common.test.rule.SupportFragmentTestRule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.hasFocus; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static org.hamcrest.Matchers.allOf; - -public class BaseballCardDetailsLayoutTest { - @Rule - public SupportFragmentTestRule fragmentTestRule - = new SupportFragmentTestRule(new BaseballCardDetails()); - - @Test - public void testAutographedCheckBox() { - onView(withId(R.id.autograph)).check(matches(allOf(isDisplayed(), isNotChecked()))); - } - - @Test - public void testBrandEditText() { - onView(withId(R.id.brand_text)).check(matches(allOf(isDisplayed(), hasFocus()))); - } - -} diff --git a/android/src/androidTest/java/bbct/android/common/layout/FilterCardsLayoutTest.java b/android/src/androidTest/java/bbct/android/common/layout/FilterCardsLayoutTest.java deleted file mode 100644 index fec4b0160..000000000 --- a/android/src/androidTest/java/bbct/android/common/layout/FilterCardsLayoutTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2014 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.layout; - -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.fragment.FilterCards; -import bbct.android.common.test.rule.SupportFragmentTestRule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; -import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.not; - -public class FilterCardsLayoutTest { - @Rule - public SupportFragmentTestRule fragmentTestRule - = new SupportFragmentTestRule(new FilterCards()); - - @Test - public void testBrandCheckBox() { - testCheckBox(R.id.brand_check); - } - - @Test - public void testYearCheckBox() { - testCheckBox(R.id.year_check); - } - - @Test - public void testNumberCheckBox() { - testCheckBox(R.id.number_check); - } - - @Test - public void testPlayerNameCheckBox() { - testCheckBox(R.id.player_name_check); - } - - @Test - public void testTeamCheckBox() { - testCheckBox(R.id.team_check); - } - - private void testCheckBox(int id) { - onView(withId(id)).check(matches(allOf(isDisplayed(), isNotChecked()))); - } - - @Test - public void testBrandEditText() { - testEditText(R.id.brand_input); - } - - @Test - public void testYearEditText() { - testEditText(R.id.year_input); - } - - @Test - public void testNumberEditText() { - testEditText(R.id.number_input); - } - - @Test - public void testPlayerNameEditText() { - testEditText(R.id.player_name_input); - } - - @Test - public void testTeamEditText() { - testEditText(R.id.team_input); - } - - private void testEditText(int id) { - onView(withId(id)).check(matches(allOf(isDisplayed(), not(isEnabled()), withText("")))); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromAboutTest.java b/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromAboutTest.java deleted file mode 100644 index 0b83b274b..000000000 --- a/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromAboutTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2018 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.navigation; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.ActivityTestRule; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.activity.MainActivity; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; - - -abstract public class NavigateUpFromAboutTest { - @Rule - public ActivityTestRule activityActivityTestRule; - private Context context = null; - - public NavigateUpFromAboutTest(Class activityClass) { - this.activityActivityTestRule = new ActivityTestRule<>(activityClass); - } - - @Before - public void setUp() { - context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - } - - @Test - public void testNavigateToBaseballCardDetailsThenAboutFragment() { - String expectedTitle = context.getString(R.string.app_name); - - // navigate to BaseballCardDetails - onView(withId(R.id.add_button)) - .perform(click()); - - // navigate to About - navigateToAboutViaContextMenu(); - - // Navigate Up - onView( - withContentDescription( - R.string.abc_action_bar_up_description) - ).perform(click()); - onView(allOf(withText(expectedTitle), isDisplayed())); - } - - @Test - public void testNavigateToFilterThenAboutFragment() { - String expectedTitle = context.getString(R.string.app_name); - - // navigate to FilterCards - onView(allOf(withContentDescription(R.string.filter_cards_title), isDisplayed())) - .perform(click()); - - navigateToAboutViaContextMenu(); - - // Navigate Up - onView(allOf(withContentDescription(R.string - .abc_action_bar_up_description), isDisplayed())) - .perform(click()); - onView(allOf(withText(expectedTitle), isDisplayed())); - } - - @Test - public void testNavigateUp() { - String initialTitle = context.getString(R.string.app_name); - navigateToAboutViaContextMenu(); - String aboutTitle = context.getString(R.string.about_title); - String expectedTitle = context.getString(R.string.bbct_title, - aboutTitle); - onView(withText(expectedTitle)) - .check(matches(isDisplayed())); - onView(allOf(withContentDescription( - R.string.abc_action_bar_up_description), isDisplayed())) - .perform(click()); - onView(withText(initialTitle)) - .check(matches(isDisplayed())); - } - - private void navigateToAboutViaContextMenu() { - openActionBarOverflowOrOptionsMenu(context); - String aboutTitle = context.getString(R.string.about_title); - String expectedTitle = context.getString(R.string.app_name, aboutTitle); - - onView(allOf(withText(aboutTitle), isDisplayed())) - .perform(click()); - onView(withText(expectedTitle)) - .check(matches(isDisplayed())); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromBaseballCardDetailsTest.java b/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromBaseballCardDetailsTest.java deleted file mode 100644 index 8f3b55f4a..000000000 --- a/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromBaseballCardDetailsTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2018 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.navigation; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.ActivityTestRule; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.activity.MainActivity; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; - - -abstract public class NavigateUpFromBaseballCardDetailsTest { - @Rule - public ActivityTestRule activityActivityTestRule; - private Context context = null; - - public NavigateUpFromBaseballCardDetailsTest(Class activityClass) { - this.activityActivityTestRule = new ActivityTestRule<>(activityClass); - } - - @Before - public void setUp() { - context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - } - - @Test - public void testNavigateUp() { - String cardDetailsTitle = context.getString(R.string.card_details_title); - String expectedTitle = context.getString(R.string.bbct_title, cardDetailsTitle); - - onView(withId(R.id.add_button)) - .perform(click()); - onView(withText(expectedTitle)) - .check(matches(isDisplayed())); - onView(allOf(withContentDescription(R.string.abc_action_bar_up_description), isDisplayed())) - .perform(click()); - onView(withText(R.string.app_name)) - .check(matches(isDisplayed())); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromFilterCardsTest.java b/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromFilterCardsTest.java deleted file mode 100644 index a59fa89c1..000000000 --- a/android/src/androidTest/java/bbct/android/common/navigation/NavigateUpFromFilterCardsTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2018 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.navigation; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.ActivityTestRule; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import bbct.android.common.R; -import bbct.android.common.activity.MainActivity; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; - - -abstract public class NavigateUpFromFilterCardsTest { - @Rule - public ActivityTestRule activityActivityTestRule; - private Context context = null; - - public NavigateUpFromFilterCardsTest(Class activityClass) { - this.activityActivityTestRule = new ActivityTestRule<>(activityClass); - } - - @Before - public void setUp() { - context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - } - - @Test - public void testNavigateUp() { - String expectedTitle = context.getString(R.string.app_name); - onView(allOf(withContentDescription(R.string.filter_cards_title), isDisplayed())) - .perform(click()); - onView(allOf(withContentDescription(R.string.abc_action_bar_up_description), isDisplayed())) - .perform(click()); - onView(allOf(withText(expectedTitle), isDisplayed())); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/provider/BaseballCardProviderTest.java b/android/src/androidTest/java/bbct/android/common/provider/BaseballCardProviderTest.java deleted file mode 100644 index 6917f0ffe..000000000 --- a/android/src/androidTest/java/bbct/android/common/provider/BaseballCardProviderTest.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2014-16 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.provider; - -import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.ContentValues; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.net.Uri; -import android.test.ProviderTestCase2; - -import org.junit.Assert; - -import java.util.ArrayList; -import java.util.List; - -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.DatabaseUtil; - -public abstract class BaseballCardProviderTest extends ProviderTestCase2 { - private static final String CREATE_TABLE = - "CREATE TABLE baseball_cards" - + " (_id INTEGER PRIMARY KEY AUTOINCREMENT," - + " autographed INTEGER, condition TEXT," - + " brand TEXT, year INTEGER," - + " number INTEGER, value INTEGER," - + " card_count INTEGER, player_name TEXT," - + " team TEXT, player_position TEXT," - + " UNIQUE (brand, year, number));\n"; - private static final String INSERT_DATA = - "BEGIN TRANSACTION;\n" - + "INSERT INTO \"baseball_cards\" VALUES(1,0,'Excellent','Topps',1991,278,10000,1,'Alex Fernandez','White Sox','Pitcher');\n" - + "INSERT INTO \"baseball_cards\" VALUES(2,0,'Excellent','Topps',1974,175,10000,1,'Bob Stanley','Red Sox','Pitcher');\n" - + "INSERT INTO \"baseball_cards\" VALUES(3,0,'Excellent','Topps',1985,201,10000,1,'Vince Coleman','Cardinals','Left Field');\n" - + "INSERT INTO \"baseball_cards\" VALUES(4,0,'Excellent','TMG',1993,5,10000,1,'Ken Griffey Jr.','All-Star','Center Field');\n" - + "INSERT INTO \"baseball_cards\" VALUES(5,0,'Excellent','Upper Deck',1993,18,10000,1,'Dave Hollins','Phillies','Third Base');\n" - + "INSERT INTO \"baseball_cards\" VALUES(6,0,'Excellent','Upper Deck',1990,189,10000,1,'Tom Browning','Reds','Pitcher');\n" - + "INSERT INTO \"baseball_cards\" VALUES(7,0,'Excellent','Topps',1982,121,10000,1,'Ed Lynch','Mets','Pitcher');\n" - + "COMMIT;\n"; - private static final List CARDS = new ArrayList<>(); - - static { - CARDS.add( - new BaseballCard( - false, "Excellent", "Topps", 1991, "278", - 10000, 1, "Alex Fernandez", "White Sox", "Pitcher" - ) - ); - CARDS.add( - new BaseballCard( - false, "Excellent", "Topps", 1974, "175", - 10000, 1, "Bob Stanley", "Red Sox", "Pitcher" - ) - ); - CARDS.add( - new BaseballCard( - false, "Excellent", "Topps", 1985, "201", - 10000, 1, "Vince Coleman", "Cardinals", "Left Field" - ) - ); - CARDS.add( - new BaseballCard( - false, "Excellent", "TMG", 1993, "5", 10000, - 1, "Ken Griffey Jr.", "All-Star", "Center Field" - ) - ); - CARDS.add( - new BaseballCard( - false, "Excellent", "Upper Deck", 1993, "18", - 10000, 1, "Dave Hollins", "Phillies", "Third Base" - ) - ); - CARDS.add( - new BaseballCard( - false, "Excellent", "Upper Deck", 1990, "189", - 10000, 1, "Tom Browning", "Reds", "Pitcher" - ) - ); - CARDS.add( - new BaseballCard( - false, "Excellent", "Topps", 1982, "121", - 10000, 1, "Ed Lynch", "Mets", "Pitcher" - ) - ); - } - - private final Uri contentUri; - - private ContentResolver resolver = null; - - public BaseballCardProviderTest(Class providerClass, String authority, Uri contentUri) { - super(providerClass, authority); - this.contentUri = contentUri; - } - - @Override - public void setUp() throws Exception { - super.setUp(); - DatabaseUtils.createDbFromSqlStatements( - this.getMockContext(), - BaseballCardSQLHelper.DATABASE_NAME, - BaseballCardSQLHelper.SCHEMA_VERSION, - CREATE_TABLE + INSERT_DATA - ); - this.resolver = this.getMockContentResolver(); - } - - @Override - public void tearDown() throws Exception { - this.getMockContext() - .deleteDatabase( - BaseballCardSQLHelper.DATABASE_NAME - ); - super.tearDown(); - } - - public void testPreConditions() { - DatabaseUtil dbUtil = new DatabaseUtil(this.getMockContext()); - Assert.assertTrue( - dbUtil.containsAllBaseballCards(BaseballCardProviderTest.CARDS) - ); - } - - public void testQueryAll() { - Cursor cursor = this.resolver.query( - contentUri, - BaseballCardContract.PROJECTION, - null, - null, - null - ); - Assert.assertNotNull(cursor); - - List actual = BaseballCardContract - .getAllBaseballCardsFromCursor(cursor); - Assert.assertTrue(BaseballCardProviderTest.CARDS.containsAll(actual)); - Assert.assertTrue(actual.containsAll(BaseballCardProviderTest.CARDS)); - } - - public void testQueryId() { - Uri uri = ContentUris.withAppendedId(contentUri, 1); - Cursor cursor = this.resolver.query( - uri, - BaseballCardContract.PROJECTION, - null, - null, - null - ); - Assert.assertNotNull(cursor); - Assert.assertEquals(1, cursor.getCount()); - } - - public void testInsert() { - BaseballCard newCard = new BaseballCard( - true, - "Mint", - "Code Guru Apps", - 2013, - "1", - 25, - 1, - "Code Guru", - "Code Guru Devs", - "Pitcher" - ); - Uri result = this.resolver.insert( - contentUri, - BaseballCardContract.getContentValues(newCard) - ); - Assert.assertNotNull(result); - } - - public void testUpdateValue() { - ContentValues values = new ContentValues(); - int newValue = 50000; - values.put(BaseballCardContract.VALUE_COL_NAME, newValue); - int affected = this.resolver.update( - contentUri, - values, - null, - null - ); - Assert.assertEquals(CARDS.size(), affected); - - Cursor cursor = this.resolver.query( - contentUri, - BaseballCardContract.PROJECTION, - null, - null, - null - ); - - if (cursor != null) { - while (!cursor.moveToNext()) { - int value = cursor.getInt( - cursor.getColumnIndex(BaseballCardContract.VALUE_COL_NAME) - ); - Assert.assertEquals(value, newValue); - } - cursor.close(); - } - } - - public void testDeleteAll() { - int affected = this.resolver.delete( - contentUri, - null, - null - ); - Assert.assertEquals(CARDS.size(), affected); - } - - public void testGetTypeItem() { - String expected = BaseballCardContract.BASEBALL_CARD_ITEM_MIME_TYPE; - String actual = this.resolver.getType( - Uri.withAppendedPath(contentUri, "/1") - ); - Assert.assertEquals(expected, actual); - } - - public void testGetTypeList() { - String expected = BaseballCardContract.BASEBALL_CARD_LIST_MIME_TYPE; - String actual = this.resolver.getType(contentUri); - Assert.assertEquals(expected, actual); - } - -} diff --git a/android/src/androidTest/java/bbct/android/common/provider/BaseballCardSQLHelperTest.java b/android/src/androidTest/java/bbct/android/common/provider/BaseballCardSQLHelperTest.java deleted file mode 100644 index 6d80eaabf..000000000 --- a/android/src/androidTest/java/bbct/android/common/provider/BaseballCardSQLHelperTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.provider; - -import android.app.Instrumentation; -import android.database.sqlite.SQLiteDatabase; -import android.test.InstrumentationTestCase; -import android.util.Log; - -import org.junit.Assert; - -import java.io.InputStream; - -import bbct.android.common.test.BBCTTestUtil; -import bbct.android.common.test.BaseballCardCsvFileReader; -import bbct.android.common.test.DatabaseUtil; - -public class BaseballCardSQLHelperTest extends InstrumentationTestCase { - - @Override - public void setUp() throws Exception { - Log.d(TAG, this.getName()); - - super.setUp(); - - this.inst = this.getInstrumentation(); - this.sqlHelper = new BaseballCardSQLHelper(this.inst.getTargetContext()); - this.db = this.sqlHelper.getWritableDatabase(); - this.dbUtil = new DatabaseUtil(this.inst.getTargetContext()); - - InputStream input = this.inst.getContext().getAssets().open(CARD_DATA); - BaseballCardCsvFileReader reader = new BaseballCardCsvFileReader(input, - true); - reader.close(); - } - - @Override - public void tearDown() throws Exception { - this.dbUtil.clearDatabase(); - - super.tearDown(); - } - - public void testOnCreate() { - Assert.assertNotNull(this.db); - BBCTTestUtil.assertDatabaseCreated(this.inst.getTargetContext()); - Assert.assertTrue(this.dbUtil.isEmpty()); - } - - public void testOnUpgrade() { - int oldVersion = 0; - int newVersion = 1; - this.sqlHelper.onUpgrade(this.dbUtil.getDatabase(), oldVersion, - newVersion); - Assert.fail("Check that the database is not modified."); - } - - private Instrumentation inst = null; - private BaseballCardSQLHelper sqlHelper = null; - private SQLiteDatabase db = null; - private DatabaseUtil dbUtil = null; - - private static final String CARD_DATA = "cards.csv"; - private static final String TAG = BaseballCardSQLHelperTest.class.getName(); -} diff --git a/android/src/androidTest/java/bbct/android/common/test/BBCTTestUtil.java b/android/src/androidTest/java/bbct/android/common/test/BBCTTestUtil.java deleted file mode 100644 index 5aca0d697..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/BBCTTestUtil.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test; - -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.clearText; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.scrollTo; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.action.ViewActions.typeTextIntoFocusedView; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.RootMatchers.withDecorView; -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.hasFocus; -import static androidx.test.espresso.matcher.ViewMatchers.isChecked; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withSpinnerText; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; - -import android.app.Activity; -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.util.Log; - -import androidx.test.espresso.ViewInteraction; -import androidx.test.espresso.contrib.RecyclerViewActions; -import androidx.test.espresso.matcher.ViewMatchers; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.uiautomator.UiDevice; - -import org.hamcrest.Matcher; -import org.junit.Assert; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import bbct.android.common.R; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.provider.BaseballCardSQLHelper; - -final public class BBCTTestUtil { - private static final String TAG = BBCTTestUtil.class.getName(); - public static final String ADD_MESSAGE = "Card added successfully"; - public static final String DELETE_MESSAGE = "Cards deleted successfully"; - - private BBCTTestUtil() { - } - - public static void assertListContainsItems(List expectedItems) { - for (BaseballCard card : expectedItems) { - onView(ViewMatchers.withId(R.id.card_list)) - .perform( - RecyclerViewActions.scrollTo( - allOf( - hasDescendant(withText(card.brand)), - hasDescendant(withText(Integer.toString(card.year))), - hasDescendant(withText(card.number)), - hasDescendant(withText(card.playerName)) - ) - ) - ); - } - } - - public static void testMenuItem(int menuId, String fragmentTag) { - onView(withId(menuId)).perform(click()); - } - - public static void addCard(BaseballCard card) { - BBCTTestUtil.sendKeysToCardDetails(card); - onView(withId(R.id.save_button)) - .perform(click()); - } - - public static void waitForToast(Activity activity, String message) { - onView(withText(message)) - .inRoot(withDecorView(not(activity.getWindow().getDecorView()))) - .check(matches(isDisplayed())); - } - - public static void sendKeysToCardDetails(BaseballCard card) { - BBCTTestUtil.sendKeysToCardDetails(card, EnumSet.allOf(EditTexts.class)); - } - - public static void sendKeysToCardDetails(BaseballCard card, Set fieldFlags) { - Log.d(TAG, "sendKeysToCardDetails()"); - - UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); - - if (fieldFlags.contains(EditTexts.AUTOGRAPHED)) { - if (card.autographed) { - onView(withId(R.id.autograph)) - .perform(scrollTo(), click()) - .check(matches(isChecked())); - } - } - - if (fieldFlags.contains(EditTexts.CONDITION)) { - onView(withId(R.id.condition)) - .perform(scrollTo(), click()); - onData(allOf(instanceOf(String.class), is(card.condition))) - .perform(click()); - onView(withId(R.id.condition)) - .check(matches(withSpinnerText(card.condition))); - } - - onView(withId(R.id.brand_text)).check(matches(hasFocus())); - if (fieldFlags.contains(EditTexts.BRAND)) { - onView(withId(R.id.brand_text)) - .perform(scrollTo(), clearText(), typeTextIntoFocusedView(card.brand)) - .check(matches(withText(card.brand))); - } - device.pressEnter(); - - onView(withId(R.id.year_text)).check(matches(hasFocus())); - if (fieldFlags.contains(EditTexts.YEAR)) { - String yearStr = Integer.toString(card.year); - onView(withId(R.id.year_text)) - .perform(scrollTo(), typeTextIntoFocusedView(yearStr)) - .check(matches(withText(yearStr))); - } - device.pressEnter(); - - onView(withId(R.id.number_text)).check(matches(hasFocus())); - if (fieldFlags.contains(EditTexts.NUMBER)) { - String numberStr = card.number; - onView(withId(R.id.number_text)) - .perform(scrollTo(), typeTextIntoFocusedView(numberStr)) - .check(matches(withText(numberStr.replaceAll("[^a-zA-Z0-9]+", "")))); - } - device.pressEnter(); - - onView(withId(R.id.value_text)).check(matches(hasFocus())); - if (fieldFlags.contains(EditTexts.VALUE)) { - String valueStr = String.format("%.2f", card.value / 100.0); - onView(withId(R.id.value_text)) - .perform(scrollTo(), typeTextIntoFocusedView(valueStr)) - .check(matches(withText(valueStr))); - } - device.pressEnter(); - - onView(withId(R.id.count_text)).check(matches(hasFocus())); - if (fieldFlags.contains(EditTexts.COUNT)) { - String countStr = Integer.toString(card.quantity); - onView(withId(R.id.count_text)) - .perform(scrollTo(), typeTextIntoFocusedView(countStr)) - .check(matches(withText(countStr))); - } - device.pressEnter(); - - onView(withId(R.id.player_name_text)).check(matches(hasFocus())); - if (fieldFlags.contains(EditTexts.PLAYER_NAME)) { - onView(withId(R.id.player_name_text)) - .perform(scrollTo(), typeTextIntoFocusedView(card.playerName)) - .check(matches(withText(card.playerName))); - } - device.pressEnter(); - - onView(withId(R.id.team_text)).check(matches(hasFocus())); - if (fieldFlags.contains(EditTexts.TEAM)) { - onView(withId(R.id.team_text)) - .perform(scrollTo(), typeTextIntoFocusedView(card.team)) - .check(matches(withText(card.team))); - } - device.pressEnter(); - - if (fieldFlags.contains(EditTexts.PLAYER_POSITION)) { - onView(withId(R.id.player_position_text)) - .perform(scrollTo(), click()); - onData(allOf(instanceOf(String.class), is(card.position))) - .perform(click()); - onView(withId(R.id.player_position_text)) - .check(matches(withSpinnerText(card.position))); - } - } - - public static void assertAllEditTextContents(BaseballCard expectedCard) { - ViewInteraction autographView = onView(withId(R.id.autograph)); - - if (expectedCard.autographed) { - autographView.check(matches(isChecked())); - } else { - autographView.check(matches(isNotChecked())); - } - - onView(withId(R.id.condition)) - .check(matches(withSpinnerText(expectedCard.condition))); - onView(withId(R.id.brand_text)) - .check(matches(withText(expectedCard.brand))); - String yearStr = Integer.toString(expectedCard.year); - onView(withId(R.id.year_text)) - .check(matches(withText(yearStr))); - String numberStr = expectedCard.number; - onView(withId(R.id.number_text)) - .check(matches(withText(numberStr))); - String valueStr = String.format("%.2f", expectedCard.value / 100.0); - onView(withId(R.id.value_text)) - .check(matches(withText(valueStr))); - String countStr = Integer.toString(expectedCard.quantity); - onView(withId(R.id.count_text)) - .check(matches(withText(countStr))); - onView(withId(R.id.player_name_text)) - .check(matches(withText(expectedCard.playerName))); - onView(withId(R.id.player_position_text)) - .check(matches(withSpinnerText(expectedCard.position))); - } - - public static void assertDatabaseCreated(Context targetContext) { - DatabaseUtil dbUtil = new DatabaseUtil(targetContext); - SQLiteDatabase db = dbUtil.getDatabase(); - Assert.assertNotNull(db); - Assert.assertEquals(BaseballCardSQLHelper.SCHEMA_VERSION, db.getVersion()); - - // TODO How do I check that a table exists in the database? - // TODO How do I check that a table has the correct columns? - } - - public static void sendKeysToFilterCards(BaseballCard testCard, Set fieldFlags) { - if (fieldFlags.contains(FilterOption.BRAND)) { - sendKeysToCurrFieldFilterCards( - R.id.brand_check, - R.id.brand_input, - testCard.brand - ); - } - - if (fieldFlags.contains(FilterOption.YEAR)) { - sendKeysToCurrFieldFilterCards( - R.id.year_check, - R.id.year_input, - Integer.toString(testCard.year) - ); - } - - if (fieldFlags.contains(FilterOption.NUMBER)) { - sendKeysToCurrFieldFilterCards( - R.id.number_check, - R.id.number_input, - testCard.number - ); - } - - if (fieldFlags.contains(FilterOption.PLAYER_NAME)) { - sendKeysToCurrFieldFilterCards( - R.id.player_name_check, - R.id.player_name_input, - testCard.playerName - ); - } - - if (fieldFlags.contains(FilterOption.TEAM)) { - sendKeysToCurrFieldFilterCards( - R.id.team_check, - R.id.team_input, - testCard.team - ); - } - } - - public static void sendKeysToCurrFieldFilterCards(int checkId, int editTextId, String input) { - onView(withId(checkId)).perform(click()); - onView(withId(editTextId)).check(matches(isDisplayed())).perform(typeText(input)); - } - - public static List filterList( - List list, - Matcher cardMatcher - ) { - List filteredList = new ArrayList<>(); - - for (BaseballCard obj : list) { - if (cardMatcher.matches(obj)) { - filteredList.add(obj); - } - } - - return filteredList; - } - - public static Set> powerSet(Set input) { - Log.d(TAG, "powerSet()"); - Log.d(TAG, "input=" + input); - - Set copy = new HashSet<>(input); - if (copy.isEmpty()) { - Set> power = new HashSet<>(); - power.add(new HashSet<>()); - return power; - } - - Iterator itr = copy.iterator(); - T elem = itr.next(); - itr.remove(); - - Log.d(TAG, "elem=" + elem); - - Set> power = powerSet(copy); - - Log.d(TAG, "power=" + power); - - Set> powerCopy = new HashSet<>(); - - for (Set set : power) { - Set setCopy = new HashSet<>(set); - setCopy.add(elem); - powerCopy.add(setCopy); - } - - power.addAll(powerCopy); - - Log.d(TAG, "power=" + power); - - return power; - } - - public enum EditTexts { - AUTOGRAPHED, CONDITION, BRAND, YEAR, NUMBER, VALUE, COUNT, PLAYER_NAME, TEAM, - PLAYER_POSITION - } - - public enum FilterOption { - BRAND, YEAR, NUMBER, PLAYER_NAME, TEAM - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/BaseballCardCsvFileReader.java b/android/src/androidTest/java/bbct/android/common/test/BaseballCardCsvFileReader.java deleted file mode 100644 index abe2efbc6..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/BaseballCardCsvFileReader.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -import bbct.android.common.database.BaseballCard; - -/** - * This class reads baseball card data from an input stream which is formatted - * as comma-separated values. - */ -public class BaseballCardCsvFileReader { - private final BufferedReader in; - - /** - * Create a {@link BaseballCardCsvFileReader} object which reads baseball - * card data as comma-separated values from the given {@link InputStream}. - * The input may contain column headers, which will be ignored. - * - * @param in - * The {@link InputStream} containing the comma-separated values. - * @param hasColHeaders - * Whether or not the input contains column headers. - * @throws IOException - * If an error occurs while reading the input. - */ - public BaseballCardCsvFileReader(InputStream in, boolean hasColHeaders) - throws IOException { - this.in = new BufferedReader(new InputStreamReader(in)); - - if (hasColHeaders) { - this.in.readLine(); - } - } - - /** - * Reads baseball card data from the next line of comma-separated values. - * - * @return A {@link BaseballCard} containing the data from the input stream. - * @throws IOException - * If an error occurs while reading the input. - */ - public BaseballCard getNextBaseballCard() throws IOException { - String line = this.in.readLine(); - String[] data = line.split(","); - boolean autographed = Boolean.parseBoolean(data[0]); - String condition = data[1]; - String brand = data[2]; - int year = Integer.parseInt(data[3]); - String number = data[4]; - int value = 10000; - int count = 1; - String playerName = data[5]; - String team = data[6]; - String playerPosition = data[7]; - - return new BaseballCard(autographed, condition, brand, year, number, - value, count, playerName, team, playerPosition); - } - - /** - * Determine if the input stream contains more baseball card data. If the - * input stream is ready for an input operation, then this function returns - * true. The validity of the data is determined only after - * calling {@link #getNextBaseballCard() } or {@link #getAllBaseballCards() - * }. - * - * @return true if the input stream is ready for an input - * operation; false, otherwise. - * @throws IOException - * If an error occurs while reading the input. - */ - public boolean hasNextBaseballCard() throws IOException { - return this.in.ready(); - } - - /** - * Reads all the baseball card data from the input stream. - * - * @return A list of {@link BaseballCard} objects containing all of the - * baseball card data from the input stream. - * @throws IOException - * If an error occurs while reading the input. - */ - public List getAllBaseballCards() throws IOException { - List cards = new ArrayList<>(); - while (this.hasNextBaseballCard()) { - cards.add(this.getNextBaseballCard()); - } - - return cards; - } - - /** - * Close the input stream. - * - * @throws IOException - * If an error occurs while reading the input. - */ - public void close() throws IOException { - this.in.close(); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/DatabaseUtil.java b/android/src/androidTest/java/bbct/android/common/test/DatabaseUtil.java deleted file mode 100644 index ecad6dc06..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/DatabaseUtil.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; - -import java.util.List; - -import bbct.android.common.database.BaseballCard; -import bbct.android.common.provider.BaseballCardContract; -import bbct.android.common.provider.BaseballCardSQLHelper; - -public class DatabaseUtil { - private static final String DB_NAME = BaseballCardSQLHelper.DATABASE_NAME; - private static final String TABLE_NAME = BaseballCardContract.TABLE_NAME; - private static final String TAG = DatabaseUtil.class.getName(); - - private final Context context; - private final SQLiteDatabase db; - - public DatabaseUtil(Context context) { - String sqlCreate = "CREATE TABLE IF NOT EXISTS " + BaseballCardContract.TABLE_NAME + "(" - + BaseballCardContract.ID_COL_NAME + " INTEGER PRIMARY KEY AUTOINCREMENT," - + BaseballCardContract.BRAND_COL_NAME + " TEXT, " - + BaseballCardContract.YEAR_COL_NAME + " INTEGER, " - + BaseballCardContract.NUMBER_COL_NAME + " TEXT, " - + BaseballCardContract.VALUE_COL_NAME + " INTEGER, " - + BaseballCardContract.COUNT_COL_NAME + " INTEGER, " - + BaseballCardContract.PLAYER_NAME_COL_NAME + " TEXT, " - + BaseballCardContract.TEAM_COL_NAME + " TEXT, " - + BaseballCardContract.PLAYER_POSITION_COL_NAME + " TEXT," - + BaseballCardContract.AUTOGRAPHED_COL_NAME + " INTEGER," - + BaseballCardContract.CONDITION_COL_NAME + " TEXT," - + "UNIQUE (" + BaseballCardContract.BRAND_COL_NAME + ", " + BaseballCardContract.YEAR_COL_NAME + ", " + BaseballCardContract.NUMBER_COL_NAME + "))"; - - this.context = context; - this.db = this.context.openOrCreateDatabase(DB_NAME, SQLiteDatabase.OPEN_READWRITE, null); - this.db.execSQL(sqlCreate); - } - - public SQLiteDatabase getDatabase() { - return this.db; - } - - public void deleteDatabase() { - this.db.close(); - this.context.deleteDatabase(DB_NAME); - } - - public void clearDatabase() { - this.db.delete(BaseballCardContract.TABLE_NAME, null, null); - this.db.close(); - } - - public long insertBaseballCard(BaseballCard card) { - ContentValues cv = BaseballCardContract.getContentValues(card); - - return this.db.insert(TABLE_NAME, null, cv); - } - - public void populateTable(List cards) { - for (BaseballCard card : cards) { - this.insertBaseballCard(card); - } - } - - public boolean containsBaseballCard(BaseballCard card) { - String[] columns = {BaseballCardContract.ID_COL_NAME}; - String selection = BaseballCardContract.BRAND_COL_NAME + " = ?" - + " AND " + BaseballCardContract.YEAR_COL_NAME + " = ?" - + " AND " + BaseballCardContract.NUMBER_COL_NAME + " = ?" - + " AND " + BaseballCardContract.VALUE_COL_NAME + " = ?" - + " AND " + BaseballCardContract.COUNT_COL_NAME + " = ?" - + " AND " + BaseballCardContract.PLAYER_NAME_COL_NAME + " = ?" - + " AND " + BaseballCardContract.PLAYER_POSITION_COL_NAME + " = ?"; - String[] selectionArgs = {card.brand, Integer.toString(card.year), card.number, - Integer.toString(card.value), Integer.toString(card.quantity), card.playerName, card.position}; - Cursor cursor = this.db.query(TABLE_NAME, columns, selection, selectionArgs, null, null, null); - boolean result = cursor.getCount() == 1; - cursor.close(); - return result; - } - - public boolean containsAllBaseballCards(List cards) { - for (BaseballCard card : cards) { - if (!this.containsBaseballCard(card)) { - return false; - } - } - - return true; - } - - public boolean isEmpty() { - String[] columns = {BaseballCardContract.ID_COL_NAME}; - Cursor cursor = this.db.query(TABLE_NAME, columns, null, null, null, null, null); - boolean result = cursor.getCount() == 0; - cursor.close(); - return result; - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/ViewActions.java b/android/src/androidTest/java/bbct/android/common/test/ViewActions.java deleted file mode 100644 index b674ed0f6..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/ViewActions.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2017 codeguru getConstraints() { - return isFocusable(); - } - - @Override - public String getDescription() { - return "focus request"; - } - - @Override - public void perform(UiController uiController, View view) { - view.requestFocus(); - } - }; - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/matcher/BaseballCardMatchers.java b/android/src/androidTest/java/bbct/android/common/test/matcher/BaseballCardMatchers.java deleted file mode 100644 index bf985bc80..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/matcher/BaseballCardMatchers.java +++ /dev/null @@ -1,24 +0,0 @@ -package bbct.android.common.test.matcher; - -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.hamcrest.Matcher; - -import bbct.android.common.database.BaseballCard; - -public class BaseballCardMatchers { - public static Matcher withYear(final int year) { - return new BaseMatcher() { - @Override - public void describeTo(Description description) { - description.appendText("Card year " + year); - } - - @Override - public boolean matches(Object obj) { - BaseballCard card = (BaseballCard)obj; - return card.year == year; - } - }; - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/matcher/Matchers.java b/android/src/androidTest/java/bbct/android/common/test/matcher/Matchers.java deleted file mode 100644 index e8b1d9241..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/matcher/Matchers.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru hasErrorText(int errorRes) { - return new ErrorTextMatcher(errorRes); - } - - private static class ErrorTextMatcher extends TypeSafeMatcher { - private final int errorRes; - - private ErrorTextMatcher(int errorRes) { - this.errorRes = checkNotNull(errorRes); - } - - @Override - public boolean matchesSafely(View view) { - if (!(view instanceof EditText)) { - return false; - } - EditText editText = (EditText) view; - String expectedError = editText.getResources().getString(errorRes); - return expectedError.equals(editText.getError().toString()); - } - - @Override - public void describeTo(Description description) { - description.appendText("with string id: " + errorRes); - } - } - - public static Matcher first(final Matcher matcher) { - return new TypeSafeMatcher() { - private boolean isFirst = true; - - @Override - protected boolean matchesSafely(T item) { - if (isFirst && matcher.matches(item)) { - isFirst = false; - return true; - } - - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText("No items matched"); - } - }; - } - - public static Matcher atPosition(int position, final Matcher matcher) { - return new TypeSafeMatcher() { - private int counter = 0; - - @Override - protected boolean matchesSafely(T item) { - if (matcher.matches(item)) { - return counter++ == position; - } - - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText("No items matched"); - } - }; - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/matcher/RecyclerViewMatcher.java b/android/src/androidTest/java/bbct/android/common/test/matcher/RecyclerViewMatcher.java deleted file mode 100644 index ac7b4856e..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/matcher/RecyclerViewMatcher.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * See https://github.com/dannyroa/espresso-samples - */ - -package bbct.android.common.test.matcher; - -import android.content.res.Resources; -import android.view.View; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -import androidx.recyclerview.widget.RecyclerView; - -import java.util.List; - -import bbct.android.common.database.BaseballCard; -import bbct.android.common.view.BaseballCardAdapter; - -public class RecyclerViewMatcher { - public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) { - return new RecyclerViewMatcher(recyclerViewId); - } - - private final int recyclerViewId; - - private RecyclerViewMatcher(int recyclerViewId) { - this.recyclerViewId = recyclerViewId; - } - - public Matcher atPosition(final int position) { - return atPositionOnView(position, -1); - } - - public Matcher atPositionOnView(final int position, final int targetViewId) { - return new TypeSafeMatcher() { - Resources resources = null; - View childView; - View targetView; - - public void describeTo(Description description) { - String idDescription = Integer.toString(recyclerViewId); - if (this.resources != null) { - try { - idDescription = this.resources.getResourceName(recyclerViewId); - } catch (Resources.NotFoundException var4) { - idDescription = String.format( - "%s (resource name not found)", - recyclerViewId - ); - } - } - - description.appendText(String.format("with id: %s", idDescription)); - } - - public boolean matchesSafely(View view) { - this.resources = view.getResources(); - - if (childView == null) { - RecyclerView recyclerView = - view.getRootView().findViewById(recyclerViewId); - if (recyclerView != null && recyclerView.getId() == recyclerViewId) { - RecyclerView.ViewHolder viewHolder = - recyclerView.findViewHolderForAdapterPosition(position); - - if (viewHolder != null) { - childView = viewHolder.itemView; - } else { - return false; - } - } else { - return false; - } - } - - if (targetViewId == -1) { - return view == childView; - } else { - if (targetView == null) { - targetView = childView.findViewById(targetViewId); - } - return view == targetView; - } - } - }; - } - - public static Matcher contains(List cards) { - return new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(View view) { - RecyclerView recyclerView = (RecyclerView) view; - BaseballCardAdapter adapter = - (BaseballCardAdapter) recyclerView.getAdapter(); - return adapter != null && adapter.getCards().equals(cards); - } - - @Override - public void describeTo(Description description) { - description.appendText("RecyclerView doesn't match: "); - description.appendValueList("(", ",", ")", cards); - } - }; - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/package-info.java b/android/src/androidTest/java/bbct/android/common/test/package-info.java deleted file mode 100644 index 39dab0e9b..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test; diff --git a/android/src/androidTest/java/bbct/android/common/test/rule/DataTestRule.java b/android/src/androidTest/java/bbct/android/common/test/rule/DataTestRule.java deleted file mode 100644 index c73026885..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/rule/DataTestRule.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test.rule; - -import android.app.Instrumentation; - -import androidx.test.platform.app.InstrumentationRegistry; - -import org.junit.rules.ExternalResource; - -import java.io.IOException; -import java.io.InputStream; -import java.util.List; - -import bbct.android.common.database.BaseballCard; -import bbct.android.common.test.BaseballCardCsvFileReader; -import bbct.android.common.test.DatabaseUtil; - -public class DataTestRule extends ExternalResource { - private static final String TAG = DataTestRule.class.getName(); - - private static final String CARD_DATA = "cards.csv"; - private DatabaseUtil dbUtil; - private List allCards; - - public BaseballCard getCard(int index) { - return allCards.get(index); - } - - public List getAllCards() { - return allCards; - } - - @Override - protected void before() throws IOException { - Instrumentation inst = InstrumentationRegistry.getInstrumentation(); - - // Create the database and populate table with test data - InputStream cardInputStream = inst.getContext().getAssets().open(CARD_DATA); - BaseballCardCsvFileReader cardInput = new BaseballCardCsvFileReader( - cardInputStream, true); - allCards = cardInput.getAllBaseballCards(); - cardInput.close(); - - dbUtil = new DatabaseUtil(inst.getTargetContext()); - dbUtil.populateTable(allCards); - } - - @Override - protected void after() { - dbUtil.clearDatabase(); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/rule/SharedPreferencesTestRule.java b/android/src/androidTest/java/bbct/android/common/test/rule/SharedPreferencesTestRule.java deleted file mode 100644 index cecfb71fa..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/rule/SharedPreferencesTestRule.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test.rule; - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.test.platform.app.InstrumentationRegistry; - -import org.junit.rules.ExternalResource; - -import bbct.android.common.SharedPreferenceKeys; - -public class SharedPreferencesTestRule extends ExternalResource { - SharedPreferences prefs; - - @Override - protected void before() throws Throwable { - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - prefs = context.getSharedPreferences(SharedPreferenceKeys.PREFS, Context.MODE_PRIVATE); - } - - @Override - protected void after() { - prefs.edit().clear().apply(); - } - - public SharedPreferences getPrefs() { - return prefs; - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/rule/SupportFragmentTestRule.java b/android/src/androidTest/java/bbct/android/common/test/rule/SupportFragmentTestRule.java deleted file mode 100644 index c3c331a19..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/rule/SupportFragmentTestRule.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2017 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test.rule; - -import androidx.fragment.app.Fragment; -import androidx.test.rule.ActivityTestRule; - -import bbct.android.common.activity.FragmentTestActivity; - -public class SupportFragmentTestRule extends ActivityTestRule { - private final Fragment fragment; - - public SupportFragmentTestRule(Fragment fragment) { - super(FragmentTestActivity.class); - this.fragment = fragment; - } - - public Fragment getFragment() { - return fragment; - } - - @Override - protected void afterActivityLaunched() { - super.afterActivityLaunched(); - - getActivity().replaceFragment(fragment); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/rule/Survey1SharedPreferencesTestRule.java b/android/src/androidTest/java/bbct/android/common/test/rule/Survey1SharedPreferencesTestRule.java deleted file mode 100644 index 8fe8c2856..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/rule/Survey1SharedPreferencesTestRule.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test.rule; - -import android.annotation.SuppressLint; -import bbct.android.common.SharedPreferenceKeys; -import java.text.DateFormat; -import java.util.Calendar; -import java.util.Date; - -import static bbct.android.common.activity.MainActivity.SURVEY_DELAY; - -public class Survey1SharedPreferencesTestRule extends SharedPreferencesTestRule { - @SuppressLint("CommitPrefEdits") - @Override - protected void before() throws Throwable { - super.before(); - - DateFormat dateFormat = DateFormat.getDateInstance(); - Date today = new Date(); - Calendar cal = Calendar.getInstance(); - cal.setTime(today); - cal.add(Calendar.DATE, -SURVEY_DELAY); - prefs.edit().putString(SharedPreferenceKeys.INSTALL_DATE, dateFormat.format(cal.getTime())).commit(); - } -} diff --git a/android/src/androidTest/java/bbct/android/common/test/rule/Survey2SharedPreferencesTestRule.java b/android/src/androidTest/java/bbct/android/common/test/rule/Survey2SharedPreferencesTestRule.java deleted file mode 100644 index 79a9e9cad..000000000 --- a/android/src/androidTest/java/bbct/android/common/test/rule/Survey2SharedPreferencesTestRule.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.test.rule; - -import android.annotation.SuppressLint; -import bbct.android.common.SharedPreferenceKeys; -import java.text.DateFormat; -import java.util.Calendar; -import java.util.Date; - -import static bbct.android.common.activity.MainActivity.SURVEY_DELAY; - -public class Survey2SharedPreferencesTestRule extends SharedPreferencesTestRule { - @SuppressLint("CommitPrefEdits") - @Override - protected void before() throws Throwable { - super.before(); - - DateFormat dateFormat = DateFormat.getDateInstance(); - Date today = new Date(); - Calendar cal = Calendar.getInstance(); - cal.setTime(today); - cal.add(Calendar.DATE, -SURVEY_DELAY); - prefs.edit().putString(SharedPreferenceKeys.SURVEY1_DATE, dateFormat.format(cal.getTime())).commit(); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityFilterTest.java b/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityFilterTest.java deleted file mode 100644 index 8b3ec547f..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityFilterTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.lite.activity; - -import bbct.android.common.fragment.FilterCardsCombinationTest; -import bbct.android.common.test.BBCTTestUtil; - -import java.util.Set; -import junit.framework.Test; - -public class LiteActivityFilterTest extends FilterCardsCombinationTest { - public LiteActivityFilterTest(Set inputFieldsFlags) { - super(LiteActivity.class, inputFieldsFlags); - } - - public static Test suite() throws ReflectiveOperationException { - return FilterCardsCombinationTest.suite(LiteActivityFilterTest.class); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromAboutTest.java b/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromAboutTest.java deleted file mode 100644 index 4dee4e1ba..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromAboutTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2018 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.lite.activity; - -import bbct.android.common.navigation.NavigateUpFromAboutTest; - -public class LiteActivityNavigateUpFromAboutTest extends NavigateUpFromAboutTest { - public LiteActivityNavigateUpFromAboutTest() { - super(LiteActivity.class); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromBaseballCardDetailsTest.java b/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromBaseballCardDetailsTest.java deleted file mode 100644 index a0f4cd484..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromBaseballCardDetailsTest.java +++ /dev/null @@ -1,9 +0,0 @@ -package bbct.android.lite.activity; - -import bbct.android.common.navigation.NavigateUpFromBaseballCardDetailsTest; - -public class LiteActivityNavigateUpFromBaseballCardDetailsTest extends NavigateUpFromBaseballCardDetailsTest { - public LiteActivityNavigateUpFromBaseballCardDetailsTest() { - super(LiteActivity.class); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromFilterCardsTest.java b/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromFilterCardsTest.java deleted file mode 100644 index 9266b96b4..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityNavigateUpFromFilterCardsTest.java +++ /dev/null @@ -1,9 +0,0 @@ -package bbct.android.lite.activity; - -import bbct.android.common.navigation.NavigateUpFromFilterCardsTest; - -public class LiteActivityNavigateUpFromFilterCardsTest extends NavigateUpFromFilterCardsTest { - public LiteActivityNavigateUpFromFilterCardsTest() { - super(LiteActivity.class); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityWithDataTest.java b/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityWithDataTest.java deleted file mode 100644 index ff26abb41..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityWithDataTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.lite.activity; - -import bbct.android.common.fragment.BaseballCardListWithDataTest; - -public class LiteActivityWithDataTest extends BaseballCardListWithDataTest { - public LiteActivityWithDataTest() { - super(LiteActivity.class); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityWithoutDataTest.java b/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityWithoutDataTest.java deleted file mode 100644 index b5708c04f..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/activity/LiteActivityWithoutDataTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.lite.activity; - -import bbct.android.common.fragment.BaseballCardListWithoutDataTest; - -public class LiteActivityWithoutDataTest extends BaseballCardListWithoutDataTest { - public LiteActivityWithoutDataTest() { - super(LiteActivity.class); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/fragment/LiteActivitySelectionTest.java b/android/src/androidTestLite/java/bbct/android/lite/fragment/LiteActivitySelectionTest.java deleted file mode 100644 index 719f0fb67..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/fragment/LiteActivitySelectionTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package bbct.android.lite.fragment; - -import bbct.android.common.fragment.BaseballCardListSelectionTest; -import bbct.android.lite.activity.LiteActivity; - -public class LiteActivitySelectionTest extends BaseballCardListSelectionTest { - public LiteActivitySelectionTest() { - super(LiteActivity.class); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/provider/LiteProviderTest.java b/android/src/androidTestLite/java/bbct/android/lite/provider/LiteProviderTest.java deleted file mode 100644 index e69221db5..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/provider/LiteProviderTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package bbct.android.lite.provider; - -import bbct.android.common.provider.BaseballCardContract; -import bbct.android.common.provider.BaseballCardProviderTest; -import bbct.android.lite.provider.LiteProvider; - -public class LiteProviderTest extends BaseballCardProviderTest { - public LiteProviderTest() { - super( - LiteProvider.class, - BaseballCardContract.LITE_AUTHORITY, - BaseballCardContract.LITE_URI - ); - } -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/suite/GoodTests.java b/android/src/androidTestLite/java/bbct/android/lite/suite/GoodTests.java deleted file mode 100644 index 1de3c89bc..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/suite/GoodTests.java +++ /dev/null @@ -1,11 +0,0 @@ -package bbct.android.lite.suite; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ - NavigateUpTestSuite.class -}) -public class GoodTests { -} diff --git a/android/src/androidTestLite/java/bbct/android/lite/suite/NavigateUpTestSuite.java b/android/src/androidTestLite/java/bbct/android/lite/suite/NavigateUpTestSuite.java deleted file mode 100644 index 895aa67d1..000000000 --- a/android/src/androidTestLite/java/bbct/android/lite/suite/NavigateUpTestSuite.java +++ /dev/null @@ -1,17 +0,0 @@ -package bbct.android.lite.suite; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -import bbct.android.lite.activity.LiteActivityNavigateUpFromAboutTest; -import bbct.android.lite.activity.LiteActivityNavigateUpFromBaseballCardDetailsTest; -import bbct.android.lite.activity.LiteActivityNavigateUpFromFilterCardsTest; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ - LiteActivityNavigateUpFromAboutTest.class, - LiteActivityNavigateUpFromBaseballCardDetailsTest.class, - LiteActivityNavigateUpFromFilterCardsTest.class -}) -public class NavigateUpTestSuite { -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityFilterTest.java b/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityFilterTest.java deleted file mode 100644 index 075d3d26a..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityFilterTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.premium.activity; - -import bbct.android.common.activity.MainActivity; -import bbct.android.common.fragment.FilterCardsCombinationTest; -import bbct.android.common.test.BBCTTestUtil; -import java.util.Set; -import junit.framework.Test; - -public class MainActivityFilterTest extends FilterCardsCombinationTest { - public MainActivityFilterTest(Set inputFieldsFlags) { - super(MainActivity.class, inputFieldsFlags); - } - - public static Test suite() throws ReflectiveOperationException { - return FilterCardsCombinationTest.suite(MainActivityFilterTest.class); - } -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromAboutTest.java b/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromAboutTest.java deleted file mode 100644 index ca854c299..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromAboutTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package bbct.android.premium.activity; - -import bbct.android.common.activity.MainActivity; -import bbct.android.common.navigation.NavigateUpFromAboutTest; - -public class MainActivityNavigateUpFromAboutTest extends NavigateUpFromAboutTest { - public MainActivityNavigateUpFromAboutTest() { - super(MainActivity.class); - } -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromBaseballCardDetailsTest.java b/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromBaseballCardDetailsTest.java deleted file mode 100644 index d008c5024..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromBaseballCardDetailsTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package bbct.android.premium.activity; - -import bbct.android.common.activity.MainActivity; -import bbct.android.common.navigation.NavigateUpFromBaseballCardDetailsTest; - -public class MainActivityNavigateUpFromBaseballCardDetailsTest extends NavigateUpFromBaseballCardDetailsTest { - public MainActivityNavigateUpFromBaseballCardDetailsTest() { - super(MainActivity.class); - } -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromFilterCardsTest.java b/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromFilterCardsTest.java deleted file mode 100644 index 816f9654c..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityNavigateUpFromFilterCardsTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package bbct.android.premium.activity; - -import bbct.android.common.activity.MainActivity; -import bbct.android.common.navigation.NavigateUpFromFilterCardsTest; - -public class MainActivityNavigateUpFromFilterCardsTest extends NavigateUpFromFilterCardsTest { - public MainActivityNavigateUpFromFilterCardsTest() { - super(MainActivity.class); - } -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityWithDataTest.java b/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityWithDataTest.java deleted file mode 100644 index 3ec6a63d3..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityWithDataTest.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.premium.activity; - -import bbct.android.common.activity.MainActivity; -import bbct.android.common.fragment.BaseballCardListWithDataTest; - -public class MainActivityWithDataTest extends BaseballCardListWithDataTest { - public MainActivityWithDataTest() { - super(MainActivity.class); - } -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityWithoutDataTest.java b/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityWithoutDataTest.java deleted file mode 100644 index 37884a6dc..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/activity/MainActivityWithoutDataTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.premium.activity; - -import androidx.test.runner.AndroidJUnit4; - -import org.junit.runner.RunWith; - -import bbct.android.common.activity.MainActivity; -import bbct.android.common.fragment.BaseballCardListWithoutDataTest; - -@RunWith(AndroidJUnit4.class) -public class MainActivityWithoutDataTest extends BaseballCardListWithoutDataTest { - - public MainActivityWithoutDataTest() { - super(MainActivity.class); - } - -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/fragment/MainActivitySelectionTest.java b/android/src/androidTestPremium/java/bbct/android/premium/fragment/MainActivitySelectionTest.java deleted file mode 100644 index 606911337..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/fragment/MainActivitySelectionTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package bbct.android.premium.fragment; - -import bbct.android.common.activity.MainActivity; -import bbct.android.common.fragment.BaseballCardListSelectionTest; - -public class MainActivitySelectionTest extends BaseballCardListSelectionTest { - public MainActivitySelectionTest() { - super(MainActivity.class); - } -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/provider/PremiumProviderTest.java b/android/src/androidTestPremium/java/bbct/android/premium/provider/PremiumProviderTest.java deleted file mode 100644 index ce17f0e38..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/provider/PremiumProviderTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package bbct.android.premium.provider; - -import bbct.android.common.provider.BaseballCardContract; -import bbct.android.common.provider.BaseballCardProviderTest; -import bbct.android.premium.provider.PremiumProvider; - -public class PremiumProviderTest extends BaseballCardProviderTest { - public PremiumProviderTest() { - super( - PremiumProvider.class, - BaseballCardContract.PREMIUM_AUTHORITY, - BaseballCardContract.PREMIUM_URI - ); - } -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/suite/GoodTests.java b/android/src/androidTestPremium/java/bbct/android/premium/suite/GoodTests.java deleted file mode 100644 index 23b783b9b..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/suite/GoodTests.java +++ /dev/null @@ -1,11 +0,0 @@ -package bbct.android.premium.suite; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ - NavigateUpTestSuite.class -}) -public class GoodTests { -} diff --git a/android/src/androidTestPremium/java/bbct/android/premium/suite/NavigateUpTestSuite.java b/android/src/androidTestPremium/java/bbct/android/premium/suite/NavigateUpTestSuite.java deleted file mode 100644 index 1114638db..000000000 --- a/android/src/androidTestPremium/java/bbct/android/premium/suite/NavigateUpTestSuite.java +++ /dev/null @@ -1,17 +0,0 @@ -package bbct.android.premium.suite; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -import bbct.android.premium.activity.MainActivityNavigateUpFromAboutTest; -import bbct.android.premium.activity.MainActivityNavigateUpFromBaseballCardDetailsTest; -import bbct.android.premium.activity.MainActivityNavigateUpFromFilterCardsTest; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ - MainActivityNavigateUpFromAboutTest.class, - MainActivityNavigateUpFromBaseballCardDetailsTest.class, - MainActivityNavigateUpFromFilterCardsTest.class -}) -public class NavigateUpTestSuite { -} diff --git a/android/src/debug/AndroidManifest.xml b/android/src/debug/AndroidManifest.xml deleted file mode 100644 index f306629b8..000000000 --- a/android/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - diff --git a/android/src/lite/AndroidManifest.xml b/android/src/lite/AndroidManifest.xml deleted file mode 100644 index 6a92d9948..000000000 --- a/android/src/lite/AndroidManifest.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/src/lite/java/bbct/android/lite/activity/LiteActivity.java b/android/src/lite/java/bbct/android/lite/activity/LiteActivity.java deleted file mode 100644 index 37b63c562..000000000 --- a/android/src/lite/java/bbct/android/lite/activity/LiteActivity.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-19 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.lite.activity; - -import android.os.Bundle; -import android.text.method.LinkMovementMethod; -import android.widget.TextView; - -import com.google.android.gms.ads.AdRequest; -import com.google.android.gms.ads.AdView; -import com.google.android.gms.ads.MobileAds; - -import bbct.android.common.R; -import bbct.android.common.activity.MainActivity; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class LiteActivity extends MainActivity { - - @BindView(R.id.ad_view) - AdView adView; - @BindView(R.id.premium_text) - TextView premiumText; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - ButterKnife.bind(this); - - premiumText.setMovementMethod(LinkMovementMethod.getInstance()); - - MobileAds.initialize(this, initializationStatus -> {}); - AdRequest adRequest = new AdRequest.Builder().build(); - adView.loadAd(adRequest); - } -} diff --git a/android/src/lite/java/bbct/android/lite/provider/LiteProvider.java b/android/src/lite/java/bbct/android/lite/provider/LiteProvider.java deleted file mode 100644 index 68c7b8bd1..000000000 --- a/android/src/lite/java/bbct/android/lite/provider/LiteProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2014 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.lite.provider; - -import bbct.android.common.provider.BaseballCardContract; -import bbct.android.common.provider.BaseballCardProvider; - -public class LiteProvider extends BaseballCardProvider { - - static { - uriMatcher.addURI(BaseballCardContract.LITE_AUTHORITY, - BaseballCardContract.TABLE_NAME, ALL_CARDS); - uriMatcher.addURI(BaseballCardContract.LITE_AUTHORITY, - BaseballCardContract.TABLE_NAME + "/#", CARD_ID); - uriMatcher.addURI(BaseballCardContract.LITE_AUTHORITY, - BaseballCardContract.TABLE_NAME + "/distinct", DISTINCT); - } - -} diff --git a/android/src/lite/res/layout/main.xml b/android/src/lite/res/layout/main.xml deleted file mode 100644 index e12d73b16..000000000 --- a/android/src/lite/res/layout/main.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - diff --git a/android/src/lite/res/values/strings.xml b/android/src/lite/res/values/strings.xml deleted file mode 100644 index b6feb73fc..000000000 --- a/android/src/lite/res/values/strings.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - BBCT Lite - BBCT Lite - %1$s - If you enjoy using BBCT, get the ad-free premium edition for only $1.99USD. - BBCT Lite Data - - Read baseball card data. - BBCT Read - Write baseball card data. - BBCT Write - - diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml deleted file mode 100644 index 1f007c663..000000000 --- a/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/android/src/main/java/bbct/android/common/SharedPreferenceKeys.java b/android/src/main/java/bbct/android/common/SharedPreferenceKeys.java deleted file mode 100644 index 77476ed3a..000000000 --- a/android/src/main/java/bbct/android/common/SharedPreferenceKeys.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common; - -public interface SharedPreferenceKeys { - String PREFS = "bbct.prefs"; - String SURVEY_TAKEN_PREF = "survey"; - String INSTALL_DATE = "install_date"; - String SURVEY1_DATE = "survey1_date"; - String SURVEY2_DATE = "survey2_date"; -} diff --git a/android/src/main/java/bbct/android/common/activity/FragmentTestActivity.java b/android/src/main/java/bbct/android/common/activity/FragmentTestActivity.java deleted file mode 100644 index 1e550117d..000000000 --- a/android/src/main/java/bbct/android/common/activity/FragmentTestActivity.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2014 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.activity; - -import android.os.Bundle; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.fragment.app.Fragment; - -import bbct.android.common.R; - -public class FragmentTestActivity extends AppCompatActivity { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.fragment_activity); - } - - public void replaceFragment(Fragment fragment) { - this.getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, fragment) - .commit(); - } - -} diff --git a/android/src/main/java/bbct/android/common/activity/MainActivity.java b/android/src/main/java/bbct/android/common/activity/MainActivity.java deleted file mode 100644 index f59a1447d..000000000 --- a/android/src/main/java/bbct/android/common/activity/MainActivity.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.activity; - -import android.content.SharedPreferences; -import android.os.Bundle; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; - -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; - -import java.text.DateFormat; -import java.text.ParseException; -import java.util.Calendar; -import java.util.Date; - -import bbct.android.common.R; -import bbct.android.common.SharedPreferenceKeys; -import bbct.android.common.activity.util.DialogUtil; -import bbct.android.common.fragment.About; -import bbct.android.common.fragment.BaseballCardList; -import bbct.android.common.fragment.FragmentTags; - -public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener { - public static final int SURVEY_DELAY = 7; - public static final String SURVEY1_URI = "https://docs.google.com/forms/d/1wj3d3SiZ7U81_ZRp0zwgH0l2b2Az3A9XkYJbgQFdO9I/viewform"; - public static final String SURVEY2_URI = "https://docs.google.com/forms/d/e/1FAIpQLSfg0TPyKcWlGSOlhhDd_4qIjYG9htOjJ5pwjRYtc71zxPw-ag/viewform"; - - private static final String TAG = MainActivity.class.getName(); - - private SharedPreferences prefs; - private FragmentManager fragmentManager; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - this.setContentView(R.layout.main); - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - fragmentManager = getSupportFragmentManager(); - - if (savedInstanceState == null) { - fragmentManager.beginTransaction() - .add(R.id.fragment_holder, new BaseballCardList(), FragmentTags.CARD_LIST) - .addToBackStack(FragmentTags.CARD_LIST) - .commit(); - - fragmentManager.addOnBackStackChangedListener(this); - } - - prefs = getSharedPreferences(SharedPreferenceKeys.PREFS, MODE_PRIVATE); - showSurvey1Dialog(); - showSurvey2Dialog(); - } - - private void showSurvey1Dialog() { - DateFormat dateFormat = DateFormat.getDateInstance(); - Date today = new Date(); - final String todayStr = dateFormat.format(today); - - if (!prefs.contains(SharedPreferenceKeys.INSTALL_DATE)) { - prefs.edit().putString(SharedPreferenceKeys.INSTALL_DATE, todayStr).apply(); - } - - if (!prefs.contains(SharedPreferenceKeys.SURVEY1_DATE)) { - String installDate = prefs.getString(SharedPreferenceKeys.INSTALL_DATE, today.toString()); - - try { - Calendar cal = Calendar.getInstance(); - cal.setTime(dateFormat.parse(installDate)); - cal.add(Calendar.DATE, SURVEY_DELAY); - if (today.after(cal.getTime())) { - DialogUtil.showSurveyDialog(this, todayStr, R.string.survey1, - SharedPreferenceKeys.SURVEY1_DATE, SURVEY1_URI); - } - } catch (ParseException e) { - Log.d(TAG, "Error parsing install date"); - e.printStackTrace(); - } - } - } - - private void showSurvey2Dialog() { - DateFormat dateFormat = DateFormat.getDateInstance(); - Date today = new Date(); - final String todayStr = dateFormat.format(today); - - if (prefs.contains(SharedPreferenceKeys.SURVEY1_DATE) - && !prefs.contains(SharedPreferenceKeys.SURVEY2_DATE)) { - String survey1Date = prefs.getString(SharedPreferenceKeys.SURVEY1_DATE, today.toString()); - - try { - Calendar cal = Calendar.getInstance(); - cal.setTime(dateFormat.parse(survey1Date)); - cal.add(Calendar.DATE, SURVEY_DELAY); - if (today.after(cal.getTime())) { - DialogUtil.showSurveyDialog(this, todayStr, R.string.survey2, - SharedPreferenceKeys.SURVEY2_DATE, SURVEY2_URI); - } - } catch (ParseException e) { - Log.d(TAG, "Error parsing install date"); - e.printStackTrace(); - } - } else if (prefs.contains(SharedPreferenceKeys.SURVEY_TAKEN_PREF)) { - prefs.edit().putString(SharedPreferenceKeys.SURVEY1_DATE, todayStr).apply(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - this.getMenuInflater().inflate(R.menu.main, menu); - - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onSupportNavigateUp() { - this.onBackPressed(); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int menuId = item.getItemId(); - switch (menuId) { - case R.id.about_menu: - fragmentManager - .beginTransaction() - .replace(R.id.fragment_holder, new About(), FragmentTags.ABOUT) - .addToBackStack(FragmentTags.ABOUT) - .commit(); - return true; - } - - return super.onOptionsItemSelected(item); - } - - @Override - protected void onResume() { - super.onResume(); - this.updateUpButtonVisibility(); - } - - @Override - public void onBackStackChanged() { - this.updateUpButtonVisibility(); - } - - private void updateUpButtonVisibility() { - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(fragmentManager.getBackStackEntryCount() > 1); - } - } - - @Override - public void onBackPressed() { - Fragment currentFragment = fragmentManager - .findFragmentById(R.id.fragment_holder); - if (currentFragment instanceof About) { - fragmentManager.popBackStack(FragmentTags.CARD_LIST, 0); - } else { - super.onBackPressed(); - } - } -} diff --git a/android/src/main/java/bbct/android/common/activity/package-info.java b/android/src/main/java/bbct/android/common/activity/package-info.java deleted file mode 100644 index aab5c3ddf..000000000 --- a/android/src/main/java/bbct/android/common/activity/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.activity; diff --git a/android/src/main/java/bbct/android/common/activity/util/DialogUtil.java b/android/src/main/java/bbct/android/common/activity/util/DialogUtil.java deleted file mode 100644 index 541176e99..000000000 --- a/android/src/main/java/bbct/android/common/activity/util/DialogUtil.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.activity.util; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.util.Log; - -import java.net.URISyntaxException; - -import bbct.android.common.R; -import bbct.android.common.SharedPreferenceKeys; - -public class DialogUtil { - private static final String TAG = DialogUtil.class.getName(); - - public static void showErrorDialog(Context context, int titleId, int errorId) { - AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context); - dialogBuilder.setTitle(titleId); - dialogBuilder.setMessage(errorId); - dialogBuilder.setPositiveButton(android.R.string.ok, (dialog, which) -> { }); - dialogBuilder.show(); - } - - public static void showSurveyDialog(final Context context, final String todayStr, int surveyMessage, - final String surveyDateKey, final String surveyUri) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setMessage(surveyMessage); - builder.setPositiveButton(R.string.now, (dialog, id) -> { - SharedPreferences prefs = context.getSharedPreferences( - SharedPreferenceKeys.PREFS, - Context.MODE_PRIVATE - ); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(surveyDateKey, todayStr); - editor.apply(); - - try { - Intent surveyIntent = Intent.parseUri(surveyUri, 0); - context.startActivity(surveyIntent); - } catch (URISyntaxException e) { - Log.e(TAG, "Error parsing URI for survey", e); - } - }); - builder.setNegativeButton(R.string.later, null); - builder.show(); - } -} diff --git a/android/src/main/java/bbct/android/common/database/BaseballCard.java b/android/src/main/java/bbct/android/common/database/BaseballCard.java deleted file mode 100644 index 397b83a44..000000000 --- a/android/src/main/java/bbct/android/common/database/BaseballCard.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This file is part of BBCT. - * - * Copyright 2012-14 codeguru - * - * BBCT is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.database; - -import androidx.annotation.NonNull; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.PrimaryKey; - -@Entity(tableName = "baseball_cards") -public class BaseballCard { - @PrimaryKey - public Long _id; - public Boolean autographed; - public String condition; - public String brand; - public Integer year; - public String number; - public Integer value; - @ColumnInfo(name = "card_count") - public Integer quantity; - @ColumnInfo(name = "player_name") - public String playerName; - public String team; - @ColumnInfo(name = "player_position") - public String position; - - public BaseballCard(boolean autographed, String condition, String brand, - int year, String number, int value, int quantity, - String playerName, String team, String position) { - this.autographed = autographed; - this.condition = condition; - this.brand = brand; - this.year = year; - this.number = number; - this.quantity = quantity; - this.value = value; - this.playerName = playerName; - this.team = team; - this.position= position; - } - - @Override - public boolean equals(Object o) { - if (o instanceof BaseballCard) { - BaseballCard c = (BaseballCard) o; - - return this.autographed.equals(c.autographed) - && this.condition.equals(c.condition) - && this.brand.equals(c.brand) - && this.year.equals(c.year) - && this.number.equals(c.number) - && this.value.equals(c.value) - && this.quantity.equals(c.quantity) - && this.playerName.equals(c.playerName) - && this.team.equals(c.team) - && this.position.equals(c.position); - } - - return false; - } - - @Override - public int hashCode() { - // Might throw NPE if any of this.condition, this.brand, - // this.playerName, this.team, or this.position is null. - int hash = 7; - hash = 67 * hash + this.autographed.hashCode(); - hash = 67 * hash + this.condition.hashCode(); - hash = 67 * hash + this.brand.hashCode(); - hash = 67 * hash + this.year; - hash = 67 * hash + this.number.hashCode(); - hash = 67 * hash + this.value; - hash = 67 * hash + this.quantity; - hash = 67 * hash + this.playerName.hashCode(); - hash = 67 * hash + this.team.hashCode(); - hash = 67 * hash + this.position.hashCode(); - return hash; - } - - @Override - @NonNull - public String toString() { - return "BaseballCard{" - + "brand=" + brand + - ", year=" + year - + ", number=" + number + - ", value=" + value - + ", quantity=" + quantity - + ", playerName=" + playerName - + ", position=" + position - + '}'; - } -} diff --git a/android/src/main/java/bbct/android/common/database/BaseballCardDao.java b/android/src/main/java/bbct/android/common/database/BaseballCardDao.java deleted file mode 100644 index 781a534f5..000000000 --- a/android/src/main/java/bbct/android/common/database/BaseballCardDao.java +++ /dev/null @@ -1,49 +0,0 @@ -package bbct.android.common.database; - -import androidx.lifecycle.LiveData; -import androidx.room.Dao; -import androidx.room.Delete; -import androidx.room.Insert; -import androidx.room.Query; -import androidx.room.Update; - -import java.util.List; - -@Dao -public interface BaseballCardDao { - @Insert - void insertBaseballCard(BaseballCard card); - - @Update - void updateBaseballCard(BaseballCard card); - - @Delete - void deleteBaseballCards(List cards); - - @Query("SELECT * FROM baseball_cards") - LiveData> getBaseballCards(); - - @Query( - "SELECT * FROM baseball_cards " + - "WHERE brand LIKE :brand " + - " AND (year = :year OR -1 = :year) " + - " AND number LIKE :number " + - " AND player_name LIKE :playerName " + - " AND team LIKE :team" - ) - LiveData> getBaseballCards( - String brand, int year, String number, String playerName, String team - ); - - @Query("SELECT * FROM baseball_cards WHERE _id = :id") - BaseballCard getBaseballCard(long id); - - @Query("SELECT DISTINCT(brand) FROM baseball_cards") - LiveData> getBrands(); - - @Query("SELECT DISTINCT(player_name) FROM baseball_cards") - LiveData> getPlayerNames(); - - @Query("SELECT DISTINCT(team) FROM baseball_cards") - LiveData> getTeams(); -} diff --git a/android/src/main/java/bbct/android/common/database/InsertCardTask.java b/android/src/main/java/bbct/android/common/database/InsertCardTask.java deleted file mode 100644 index 5044bacc4..000000000 --- a/android/src/main/java/bbct/android/common/database/InsertCardTask.java +++ /dev/null @@ -1,49 +0,0 @@ -package bbct.android.common.database; - -import android.database.SQLException; -import android.os.AsyncTask; - -import bbct.android.common.fragment.BaseballCardDetails; - -public class InsertCardTask extends AsyncTask { - private static final int STATUS_OK = 1; - private static final int STATUS_DUPLICATE = 2; - private static final int STATUS_OTHER = 3; - - private final BaseballCardDetails fragment; - private final BaseballCardDao dao; - - public InsertCardTask(BaseballCardDetails fragment, BaseballCardDao dao) { - this.fragment = fragment; - this.dao = dao; - } - - @Override - protected Integer doInBackground(BaseballCard... baseballCards) { - try { - dao.insertBaseballCard(baseballCards[0]); - return STATUS_OK; - } catch (SQLException e) { - String message = e.getMessage(); - if (message.startsWith("UNIQUE constraint failed")) { - return STATUS_DUPLICATE; - } - - return STATUS_OTHER; - } - } - - @Override - protected void onPostExecute(Integer status) { - switch (status) { - case STATUS_OK: - fragment.insertSuccessful(); - break; - case STATUS_DUPLICATE: - fragment.insertFailed(); - break; - case STATUS_OTHER: - break; - } - } -} diff --git a/android/src/main/java/bbct/android/common/exception/SQLHelperCreationException.java b/android/src/main/java/bbct/android/common/exception/SQLHelperCreationException.java deleted file mode 100644 index 6b0debe63..000000000 --- a/android/src/main/java/bbct/android/common/exception/SQLHelperCreationException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.exception; - -@SuppressWarnings("serial") -public class SQLHelperCreationException extends Exception { - public SQLHelperCreationException(Throwable cause) { - super(cause); - } -} diff --git a/android/src/main/java/bbct/android/common/exception/package-info.java b/android/src/main/java/bbct/android/common/exception/package-info.java deleted file mode 100644 index b3398b891..000000000 --- a/android/src/main/java/bbct/android/common/exception/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.exception; diff --git a/android/src/main/java/bbct/android/common/fragment/About.java b/android/src/main/java/bbct/android/common/fragment/About.java deleted file mode 100644 index f0ab67d58..000000000 --- a/android/src/main/java/bbct/android/common/fragment/About.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Activity; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; - -import bbct.android.common.R; - -public class About extends Fragment { - - private static final String TAG = About.class.getName(); - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.about, container, false); - - String aboutTitle = this.getString(R.string.about_title); - String title = this.getString(R.string.bbct_title, aboutTitle); - Activity activity = requireActivity(); - activity.setTitle(title); - - TextView versionLabel = view.findViewById(R.id.version_label); - String versionNumber = this.getString(R.string.version_number); - String versionString = this.getString(R.string.version_text, versionNumber); - - Log.d(TAG, "versionLabel=" + versionLabel); - Log.d(TAG, "versionString=" + versionString); - - versionLabel.setText(versionString); - - return view; - } -} diff --git a/android/src/main/java/bbct/android/common/fragment/BaseballCardDetails.java b/android/src/main/java/bbct/android/common/fragment/BaseballCardDetails.java deleted file mode 100644 index 5a31502f9..000000000 --- a/android/src/main/java/bbct/android/common/fragment/BaseballCardDetails.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.Context; -import android.os.AsyncTask; -import android.os.Bundle; -import android.util.Log; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; -import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.Observer; - -import com.google.android.material.floatingactionbutton.FloatingActionButton; - -import java.util.List; -import java.util.Locale; -import java.util.Objects; - -import bbct.android.common.R; -import bbct.android.common.activity.util.DialogUtil; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.database.BaseballCardDao; -import bbct.android.common.database.BaseballCardDatabase; -import bbct.android.common.database.InsertCardTask; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class BaseballCardDetails extends Fragment { - private static final String ID = "id"; - private static final String TAG = BaseballCardDetails.class.getName(); - - @BindView(R.id.autograph) - CheckBox autographCheckBox = null; - @BindView(R.id.condition) - Spinner conditionSpinner = null; - @BindView(R.id.brand_text) - AutoCompleteTextView brandText = null; - @BindView(R.id.year_text) - EditText yearText = null; - @BindView(R.id.number_text) - EditText numberText = null; - @BindView(R.id.value_text) - EditText valueText = null; - @BindView(R.id.count_text) - EditText countText = null; - @BindView(R.id.player_name_text) - AutoCompleteTextView playerNameText = null; - @BindView(R.id.team_text) - AutoCompleteTextView teamText = null; - @BindView(R.id.player_position_text) - Spinner playerPositionSpinner = null; - @BindView(R.id.save_button) - FloatingActionButton saveButton = null; - - private ArrayAdapter conditionAdapter; - private ArrayAdapter positionsAdapter; - private boolean isUpdating = false; - private long id; - - public static BaseballCardDetails getInstance(long id) { - Bundle args = new Bundle(); - args.putLong(ID, id); - BaseballCardDetails details = new BaseballCardDetails(); - details.setArguments(args); - - return details; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - this.setHasOptionsMenu(true); - } - - @Override - public View onCreateView( - @NonNull LayoutInflater inflater, - ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.card_details, container, false); - ButterKnife.bind(this, view); - final Activity activity = requireActivity(); - String cardDetailsTitle = this.getString(R.string.card_details_title); - String title = this.getString(R.string.bbct_title, cardDetailsTitle); - activity.setTitle(title); - - saveButton.setOnClickListener(v -> onSave()); - - brandText.setOnKeyListener((v, keyCode, event) -> { - Log.d(TAG, "onKey() in Brand TextView"); - Log.d(TAG, "keyCode = " + keyCode); - - if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) { - Log.d(TAG, "focus on Year"); - yearText.requestFocus(); - return true; - } - - return false; - }); - - playerNameText.setOnKeyListener((v, keyCode, event) -> { - Log.d(TAG, "onKey() in Player Name TextView"); - Log.d(TAG, "keyCode = " + keyCode); - - if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) { - Log.d(TAG, "focus on Team"); - teamText.requestFocus(); - return true; - } - - return false; - }); - - teamText.setOnKeyListener((v, keyCode, event) -> { - Log.d(TAG, "onKey() in Team TextView"); - Log.d(TAG, "keyCode = " + keyCode); - - if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) { - Log.d(TAG, "hide keyboard"); - InputMethodManager imm = Objects.requireNonNull( - (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE)); - imm.hideSoftInputFromWindow(teamText.getWindowToken(), 0); - playerPositionSpinner.requestFocus(); - return true; - } - - return false; - }); - - createAdapters(activity); - populateTextEdits(); - - return view; - } - - private void createAdapters(final Activity activity) { - this.conditionAdapter = this.populateSpinnerAdapter(R.array.condition); - this.conditionSpinner.setAdapter(this.conditionAdapter); - - final ArrayAdapter brandAdapter = new ArrayAdapter<>( - activity, - android.R.layout.simple_list_item_1 - ); - this.brandText.setAdapter(brandAdapter); - - final ArrayAdapter playerNameAdapter = new ArrayAdapter<>( - activity, - android.R.layout.simple_list_item_1 - ); - this.playerNameText.setAdapter(playerNameAdapter); - - final ArrayAdapter teamAdapter = new ArrayAdapter<>( - activity, - android.R.layout.simple_list_item_1 - ); - this.teamText.setAdapter(teamAdapter); - - BaseballCardDatabase database = - BaseballCardDatabase.getInstance(activity); - BaseballCardDao dao = database.getBaseballCardDao(); - LiveData> brands = dao.getBrands(); - brands.observe( - getViewLifecycleOwner(), - new ListObserver(brandAdapter) - ); - - LiveData> playerNames = dao.getPlayerNames(); - playerNames.observe( - getViewLifecycleOwner(), - new ListObserver(playerNameAdapter) - ); - - LiveData> teams = dao.getTeams(); - teams.observe( - getViewLifecycleOwner(), - new ListObserver(teamAdapter) - ); - - this.positionsAdapter = this.populateSpinnerAdapter(R.array.positions); - this.playerPositionSpinner.setAdapter(this.positionsAdapter); - } - - @SuppressLint("StaticFieldLeak") - private void populateTextEdits() { - Bundle args = getArguments(); - if (args != null) { - id = args.getLong(ID); - new AsyncTask() { - @Override - protected BaseballCard doInBackground(Long... args) { - long id = args[0]; - Activity activity = requireActivity(); - BaseballCardDatabase database = - BaseballCardDatabase.getInstance(activity); - BaseballCardDao dao = database.getBaseballCardDao(); - return dao.getBaseballCard(id); - } - - @Override - protected void onPostExecute(BaseballCard card) { - setCard(card); - } - }.execute(id); - } - } - - private void setCard(BaseballCard card) { - this.isUpdating = true; - this.autographCheckBox.setChecked(card.autographed); - - int selectedCondition = this.conditionAdapter.getPosition(card.condition); - this.conditionSpinner.setSelection(selectedCondition); - - this.brandText.setText(card.brand); - this.yearText.setText(String.format(Locale.getDefault(), "%d", card.year)); - this.numberText.setText(card.number); - this.valueText.setText(String.format(Locale.getDefault(), "%.2f", card.value / 100.0)); - this.countText.setText(String.format(Locale.getDefault(), "%d", card.quantity)); - this.playerNameText.setText(card.playerName); - this.teamText.setText(card.team); - - int selectedPosition = this.positionsAdapter.getPosition(card.position); - this.playerPositionSpinner.setSelection(selectedPosition); - } - - private ArrayAdapter populateSpinnerAdapter(int arrayId) { - Activity activity = requireActivity(); - ArrayAdapter adapter = ArrayAdapter.createFromResource( - activity, arrayId, android.R.layout.simple_spinner_item); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - - return adapter; - } - - private BaseballCard getBaseballCard() { - Log.d(TAG, "getBaseballCard()"); - - EditText[] allEditTexts = {this.brandText, this.yearText, - this.numberText, this.valueText, this.countText, - this.playerNameText, this.teamText}; - int[] errorIds = {R.string.brand_input_error, - R.string.year_input_error, R.string.number_input_error, - R.string.value_input_error, R.string.count_input_error, - R.string.player_name_input_error, R.string.team_input_error}; - boolean validInput = true; - - boolean autographed = this.autographCheckBox.isChecked(); - String condition = (String) this.conditionSpinner.getSelectedItem(); - String playerPosition = (String) this.playerPositionSpinner - .getSelectedItem(); - - for (int i = allEditTexts.length - 1; i >= 0; --i) { - String input = allEditTexts[i].getText().toString(); - if (input.equals("")) { - allEditTexts[i].requestFocus(); - allEditTexts[i].setError(this.getString(errorIds[i])); - validInput = false; - } - } - - if (validInput) { - String brand = this.brandText.getText().toString(); - String yearStr = this.yearText.getText().toString(); - int year = Integer.parseInt(yearStr); - String number = this.numberText.getText().toString(); - String valueStr = this.valueText.getText().toString(); - double value = Double.parseDouble(valueStr); - String countStr = this.countText.getText().toString(); - int count = Integer.parseInt(countStr); - String team = this.teamText.getText().toString(); - String playerName = this.playerNameText.getText().toString(); - return new BaseballCard(autographed, condition, brand, year, - number, (int) (value * 100), count, playerName, team, - playerPosition); - } else { - return null; - } - } - - private void resetInput() { - this.autographCheckBox.setChecked(false); - this.brandText.setText(""); - this.yearText.setText(""); - this.numberText.setText(""); - this.valueText.setText(""); - this.countText.setText(""); - this.playerNameText.setText(""); - this.teamText.setText(""); - this.playerPositionSpinner.setSelection(-1); - } - - private void onSave() { - final BaseballCard newCard = this.getBaseballCard(); - Activity activity = requireActivity(); - BaseballCardDatabase database = BaseballCardDatabase.getInstance(activity); - final BaseballCardDao dao = database.getBaseballCardDao(); - - if (newCard != null) { - if (this.isUpdating) { - newCard._id = id; - new Thread() { - @Override - public void run() { - dao.updateBaseballCard(newCard); - FragmentActivity activity = requireActivity(); - activity.getSupportFragmentManager().popBackStack(); - } - }.start(); - } else { - new InsertCardTask(this, dao).execute(newCard); - } - } - } - - public void insertSuccessful() { - Activity activity = requireActivity(); - this.resetInput(); - this.brandText.requestFocus(); - Toast.makeText(activity, R.string.card_added_message, - Toast.LENGTH_LONG).show(); - } - - public void insertFailed() { - Activity activity = requireActivity(); - // Is duplicate card the only reason this exception - // will be thrown? - DialogUtil.showErrorDialog(activity, - R.string.duplicate_card_title, - R.string.duplicate_card_error); - } -} - -class ListObserver implements Observer> { - private final ArrayAdapter adapter; - - ListObserver(ArrayAdapter adapter) { - this.adapter = adapter; - } - - @Override - public void onChanged(@Nullable List strings) { - if (strings != null) { - adapter.clear(); - adapter.addAll(strings); - adapter.notifyDataSetChanged(); - } - } -} diff --git a/android/src/main/java/bbct/android/common/fragment/BaseballCardList.java b/android/src/main/java/bbct/android/common/fragment/BaseballCardList.java deleted file mode 100644 index 90ae38631..000000000 --- a/android/src/main/java/bbct/android/common/fragment/BaseballCardList.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Activity; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.lifecycle.LiveData; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.google.android.material.floatingactionbutton.FloatingActionButton; - -import java.util.List; -import java.util.Objects; - -import bbct.android.common.R; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.database.BaseballCardDao; -import bbct.android.common.database.BaseballCardDatabase; -import bbct.android.common.view.BaseballCardActionModeCallback; -import bbct.android.common.view.BaseballCardAdapter; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class BaseballCardList extends Fragment { - private static final String FILTER_PARAMS = "filterParams"; - private static final String TAG = BaseballCardList.class.getName(); - - @BindView(R.id.card_list) - RecyclerView cardList; - @BindView(R.id.add_button) - FloatingActionButton addButton; - - private BaseballCardAdapter adapter = null; - private Bundle filterParams = null; - private final BaseballCardActionModeCallback callback = - new BaseballCardActionModeCallback(this); - - public static BaseballCardList getInstance(Bundle filterArgs) { - BaseballCardList cardList = new BaseballCardList(); - - Bundle args = new Bundle(); - args.putBundle(FILTER_PARAMS, filterArgs); - cardList.setArguments(args); - - return cardList; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Bundle args = this.getArguments(); - - if (savedInstanceState != null) { - this.filterParams = savedInstanceState.getBundle(FILTER_PARAMS); - } else if (args != null) { - this.filterParams = args.getBundle(FILTER_PARAMS); - } - - this.setHasOptionsMenu(true); - } - - @Override - public void onResume() { - super.onResume(); - Activity activity = requireActivity(); - activity.setTitle(R.string.app_name); - } - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.card_list, container, false); - ButterKnife.bind(this, view); - setUpRecyclerView(); - - final FragmentActivity activity = requireActivity(); - addButton.setOnClickListener(v -> { - BaseballCardDetails details = new BaseballCardDetails(); - activity.getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_holder, details, FragmentTags.EDIT_CARD) - .addToBackStack(FragmentTags.EDIT_CARD) - .commit(); - }); - - applyFilter(filterParams); - - return view; - } - - private void setUpRecyclerView() { - RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this.getActivity()); - cardList.setLayoutManager(layoutManager); - FragmentActivity activity = requireActivity(); - adapter = new BaseballCardAdapter(activity, callback); - cardList.setAdapter(adapter); - } - - @Override - public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.list, menu); - } - - @Override - public void onPrepareOptionsMenu(Menu menu) { - Log.d(TAG, "onPrepareOptionsMenu()"); - - MenuItem filter = menu.findItem(R.id.filter_menu); - MenuItem clearFilter = menu.findItem(R.id.clear_filter_menu); - if (this.filterParams == null) { - filter.setVisible(true); - filter.setEnabled(true); - - clearFilter.setVisible(false); - clearFilter.setEnabled(false); - } else { - filter.setVisible(false); - filter.setEnabled(false); - - clearFilter.setVisible(true); - clearFilter.setEnabled(true); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int itemId = item.getItemId(); - - FragmentActivity activity = requireActivity(); - switch (itemId) { - case R.id.filter_menu: - FilterCards filterCards = new FilterCards(); - activity.getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_holder, filterCards, FragmentTags.FILTER_CARDS) - .addToBackStack(FragmentTags.FILTER_CARDS) - .commit(); - return true; - case R.id.clear_filter_menu: - this.filterParams = null; - this.applyFilter(null); - activity.invalidateOptionsMenu(); - return true; - default: - Log.e(TAG, "onOptionsItemSelected(): Invalid menu code: " + itemId); - // TODO Throw exception? - break; - } - - return super.onOptionsItemSelected(item); - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - - outState.putBundle(FILTER_PARAMS, this.filterParams); - } - - public void deleteSelectedCards() { - final Activity activity = requireActivity(); - final List cards = adapter.getSelectedItems(); - - new Thread(() -> { - BaseballCardDatabase database = - BaseballCardDatabase.getInstance(activity); - database.getBaseballCardDao().deleteBaseballCards(cards); - }).start(); - - Toast.makeText( - activity, - R.string.card_deleted_message, - Toast.LENGTH_LONG - ).show(); - } - - private void applyFilter(Bundle filterParams) { - LiveData> cards; - final Activity activity = requireActivity(); - BaseballCardDatabase database = - BaseballCardDatabase.getInstance(activity); - BaseballCardDao dao = database.getBaseballCardDao(); - - if (filterParams == null) { - cards = dao.getBaseballCards(); - } else { - String format = "%%%s%%"; - String brand = filterParams.getString( - FilterCards.BRAND_EXTRA, ""); - String year = filterParams.getString( - FilterCards.YEAR_EXTRA, "-1"); - String number = filterParams.getString( - FilterCards.NUMBER_EXTRA, ""); - String playerName = filterParams.getString( - FilterCards.PLAYER_NAME_EXTRA, ""); - String team = filterParams.getString( - FilterCards.TEAM_EXTRA, ""); - - cards = dao.getBaseballCards( - String.format(format, brand), - Integer.parseInt(year), - String.format(format, number), - String.format(format, playerName), - String.format(format, team) - ); - } - - cards.observe(getViewLifecycleOwner(), cards1 -> adapter.setCards(Objects.requireNonNull(cards1))); - } - - public void setAllSelected(boolean isSelected) { - adapter.setAllSelected(isSelected); - } -} diff --git a/android/src/main/java/bbct/android/common/fragment/FilterCards.java b/android/src/main/java/bbct/android/common/fragment/FilterCards.java deleted file mode 100644 index 92499c056..000000000 --- a/android/src/main/java/bbct/android/common/fragment/FilterCards.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -import android.app.Activity; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.EditText; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; - -import com.google.android.material.floatingactionbutton.FloatingActionButton; - -import java.util.ArrayList; - -import bbct.android.common.R; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class FilterCards extends Fragment { - - private static final String FILTERED_LIST = "Filtered List"; - private static final String INPUT_EXTRA = "input"; - - public static final String BRAND_EXTRA = "brand"; - public static final String YEAR_EXTRA = "year"; - public static final String NUMBER_EXTRA = "number"; - public static final String PLAYER_NAME_EXTRA = "playerName"; - public static final String TEAM_EXTRA = "team"; - - private static final int[] CHECKBOXES = { R.id.brand_check, - R.id.year_check, R.id.number_check, R.id.player_name_check, - R.id.team_check }; - - private static final int[] TEXT_FIELDS = { R.id.brand_input, - R.id.year_input, R.id.number_input, R.id.player_name_input, - R.id.team_input }; - - private static final String[] EXTRAS = { BRAND_EXTRA, YEAR_EXTRA, NUMBER_EXTRA, - PLAYER_NAME_EXTRA, TEAM_EXTRA }; - - @BindView(R.id.confirm_button) - FloatingActionButton confirmButton; - - private final View.OnClickListener onCheckBoxClick = new View.OnClickListener() { - @Override - public void onClick(View v) { - EditText input = null; - - Activity activity = requireActivity(); - for (int i = 0; i < CHECKBOXES.length; i++) { - if (v.getId() == CHECKBOXES[i]) { - input = activity.findViewById(TEXT_FIELDS[i]); - } - } - - if (input != null) { - toggleTextField(input); - } - confirmButton.setEnabled(numberChecked() > 0); - } - }; - private final ArrayList enabledFields = new ArrayList<>(); - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - this.setHasOptionsMenu(true); - } - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.filter_cards, container, false); - ButterKnife.bind(this, view); - - confirmButton.setEnabled(false); - confirmButton.setOnClickListener(v -> onConfirm()); - - // set title - String format = this.getString(R.string.bbct_title); - String filterCardsTitle = this.getString(R.string.filter_cards_title); - String title = String.format(format, filterCardsTitle); - Activity activity = requireActivity(); - activity.setTitle(title); - - for (int id : CHECKBOXES) { - View checkBox = view.findViewById(id); - checkBox.setOnClickListener(this.onCheckBoxClick); - } - - // restore input fields state - if (savedInstanceState != null) { - ArrayList enabledFields = savedInstanceState - .getIntegerArrayList(INPUT_EXTRA); - if (enabledFields != null) { - for (int i : enabledFields) { - CheckBox cb = view.findViewById(CHECKBOXES[i]); - cb.setChecked(true); - EditText et = view.findViewById(TEXT_FIELDS[i]); - et.setEnabled(true); - } - } - } - - return view; - } - - @Override - public void onPause() { - super.onPause(); - - enabledFields.clear(); - Activity activity = requireActivity(); - for (int i = 0; i < TEXT_FIELDS.length; i++) { - EditText et = activity.findViewById(TEXT_FIELDS[i]); - if (et.isEnabled()) { - enabledFields.add(i); - } - } - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - - outState.putIntegerArrayList(INPUT_EXTRA, enabledFields); - } - - private void toggleTextField(EditText et) { - if (et.isEnabled()) { - et.setEnabled(false); - } else { - et.setEnabled(true); - et.requestFocus(); - } - } - - private int numberChecked() { - int count = 0; - Activity activity = requireActivity(); - for (int id : CHECKBOXES) { - CheckBox cb = activity.findViewById(id); - if (cb != null && cb.isChecked()) { - count++; - } - } - - return count; - } - - private void onConfirm() { - Bundle filterArgs = new Bundle(); - FragmentActivity activity = requireActivity(); - for (int i = 0; i < TEXT_FIELDS.length; i++) { - EditText input = activity.findViewById(TEXT_FIELDS[i]); - if (input.isEnabled() && input.getText().toString().length() > 0) { - String key = EXTRAS[i]; - filterArgs.putString(key, input.getText().toString()); - } - } - - BaseballCardList cardList = BaseballCardList.getInstance(filterArgs); - activity.getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_holder, cardList) - .addToBackStack(FILTERED_LIST) - .commit(); - } - -} diff --git a/android/src/main/java/bbct/android/common/fragment/FragmentTags.java b/android/src/main/java/bbct/android/common/fragment/FragmentTags.java deleted file mode 100644 index b6ae1f93a..000000000 --- a/android/src/main/java/bbct/android/common/fragment/FragmentTags.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.fragment; - -public interface FragmentTags { - - String EDIT_CARD = "Edit Card"; - String FILTER_CARDS = "Filter Cards"; - String CARD_LIST = "Card List"; - String ABOUT = "About"; - -} diff --git a/android/src/main/java/bbct/android/common/package-info.java b/android/src/main/java/bbct/android/common/package-info.java deleted file mode 100644 index ce3518926..000000000 --- a/android/src/main/java/bbct/android/common/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common; diff --git a/android/src/main/java/bbct/android/common/provider/BaseballCardContract.java b/android/src/main/java/bbct/android/common/provider/BaseballCardContract.java deleted file mode 100644 index d674e2471..000000000 --- a/android/src/main/java/bbct/android/common/provider/BaseballCardContract.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.provider; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -import java.util.ArrayList; -import java.util.List; - -import bbct.android.common.database.BaseballCard; - -public final class BaseballCardContract { - - public static final String TABLE_NAME = "baseball_cards"; - - public static final String AUTHORITY = "bbct.android.common.provider"; - - public static final String LITE_AUTHORITY = "bbct.android.lite.provider"; - - public static final String PREMIUM_AUTHORITY = "bbct.android.premium.provider"; - - public static final Uri CONTENT_URI = new Uri.Builder().scheme("content") - .authority(AUTHORITY).path(TABLE_NAME).build(); - - public static final Uri LITE_URI = new Uri.Builder().scheme("content") - .authority(LITE_AUTHORITY).path(TABLE_NAME).build(); - - public static final Uri PREMIUM_URI = new Uri.Builder().scheme("content") - .authority(PREMIUM_AUTHORITY).path(TABLE_NAME).build(); - - public static final String BASEBALL_CARD_LIST_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE - + "/baseball_card"; - - public static final String BASEBALL_CARD_ITEM_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE - + "/baseball_card"; - - public static final String ID_COL_NAME = "_id"; - - public static final String AUTOGRAPHED_COL_NAME = "autographed"; - - public static final String CONDITION_COL_NAME = "condition"; - - public static final String BRAND_COL_NAME = "brand"; - - public static final String YEAR_COL_NAME = "year"; - - public static final String NUMBER_COL_NAME = "number"; - - public static final String VALUE_COL_NAME = "value"; - - public static final String COUNT_COL_NAME = "card_count"; - - public static final String PLAYER_NAME_COL_NAME = "player_name"; - - public static final String TEAM_COL_NAME = "team"; - - public static final String PLAYER_POSITION_COL_NAME = "player_position"; - - public static final String[] PROJECTION = { ID_COL_NAME, - AUTOGRAPHED_COL_NAME, CONDITION_COL_NAME, BRAND_COL_NAME, - YEAR_COL_NAME, NUMBER_COL_NAME, VALUE_COL_NAME, COUNT_COL_NAME, - PLAYER_NAME_COL_NAME, TEAM_COL_NAME, PLAYER_POSITION_COL_NAME }; - - public static final String INT_SELECTION_FORMAT = "%s = ?"; - - public static final String YEAR_SELECTION = String.format( - INT_SELECTION_FORMAT, YEAR_COL_NAME); - - public static final String NUMBER_SELECTION = String.format( - INT_SELECTION_FORMAT, NUMBER_COL_NAME); - - public static final String STRING_SELECTION_FORMAT = "%s LIKE ?"; - - public static final Object BRAND_SELECTION = String.format( - STRING_SELECTION_FORMAT, BRAND_COL_NAME); - - public static final String PLAYER_NAME_SELECTION = String.format( - STRING_SELECTION_FORMAT, PLAYER_NAME_COL_NAME); - - public static final String TEAM_SELECTION = String.format( - STRING_SELECTION_FORMAT, TEAM_COL_NAME); - - public static ContentValues getContentValues(BaseballCard card) { - ContentValues cv = new ContentValues(7); - cv.put(BaseballCardContract.AUTOGRAPHED_COL_NAME, card.autographed); - cv.put(BaseballCardContract.CONDITION_COL_NAME, card.condition); - cv.put(BaseballCardContract.BRAND_COL_NAME, card.brand); - cv.put(BaseballCardContract.YEAR_COL_NAME, card.year); - cv.put(BaseballCardContract.NUMBER_COL_NAME, card.number); - cv.put(BaseballCardContract.VALUE_COL_NAME, card.value); - cv.put(BaseballCardContract.COUNT_COL_NAME, card.quantity); - cv.put(BaseballCardContract.PLAYER_NAME_COL_NAME, card.playerName); - cv.put(BaseballCardContract.TEAM_COL_NAME, card.team); - cv.put(BaseballCardContract.PLAYER_POSITION_COL_NAME, - card.position); - return cv; - } - - public static Uri getUri(String packageName) { - if (packageName.equals("bbct.android")) { - return LITE_URI; - } else if (packageName.equals("bbct.android.premium")) { - return PREMIUM_URI; - } - - return CONTENT_URI; - } - - public static BaseballCard getBaseballCardFromCursor(Cursor cursor) { - boolean autographed = cursor.getInt(cursor - .getColumnIndex(BaseballCardContract.AUTOGRAPHED_COL_NAME)) != 0; - String condition = cursor.getString(cursor - .getColumnIndex(BaseballCardContract.CONDITION_COL_NAME)); - String brand = cursor.getString(cursor - .getColumnIndex(BaseballCardContract.BRAND_COL_NAME)); - int year = cursor.getInt(cursor - .getColumnIndex(BaseballCardContract.YEAR_COL_NAME)); - String number = cursor.getString(cursor - .getColumnIndex(BaseballCardContract.NUMBER_COL_NAME)); - int value = cursor.getInt(cursor - .getColumnIndex(BaseballCardContract.VALUE_COL_NAME)); - int quantity = cursor.getInt(cursor - .getColumnIndex(BaseballCardContract.COUNT_COL_NAME)); - String name = cursor.getString(cursor - .getColumnIndex(BaseballCardContract.PLAYER_NAME_COL_NAME)); - String team = cursor.getString(cursor - .getColumnIndex(BaseballCardContract.TEAM_COL_NAME)); - String position = cursor.getString(cursor - .getColumnIndex(BaseballCardContract.PLAYER_POSITION_COL_NAME)); - - return new BaseballCard(autographed, condition, brand, year, number, - value, quantity, name, team, position); - } - - public static List getAllBaseballCardsFromCursor(Cursor cursor) { - List cards = new ArrayList<>(); - - while (cursor.moveToNext()) { - BaseballCard card = BaseballCardContract.getBaseballCardFromCursor(cursor); - cards.add(card); - } - - return cards; - } - -} diff --git a/android/src/main/java/bbct/android/common/provider/BaseballCardProvider.java b/android/src/main/java/bbct/android/common/provider/BaseballCardProvider.java deleted file mode 100644 index ec1aa097f..000000000 --- a/android/src/main/java/bbct/android/common/provider/BaseballCardProvider.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.provider; - -import android.content.ContentProvider; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.Context; -import android.content.UriMatcher; -import android.database.Cursor; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.NonNull; - -import java.util.Arrays; - -import bbct.android.common.R; - -public abstract class BaseballCardProvider extends ContentProvider { - - protected static final int ALL_CARDS = 1; - protected static final int CARD_ID = 2; - protected static final int DISTINCT = 3; - - private Context context; - private BaseballCardSQLHelper sqlHelper = null; - private static final String TAG = BaseballCardProvider.class.getName(); - - public static final UriMatcher uriMatcher = new UriMatcher( - UriMatcher.NO_MATCH); - - static { - uriMatcher.addURI(BaseballCardContract.AUTHORITY, - BaseballCardContract.TABLE_NAME, ALL_CARDS); - uriMatcher.addURI(BaseballCardContract.AUTHORITY, - BaseballCardContract.TABLE_NAME + "/#", CARD_ID); - uriMatcher.addURI(BaseballCardContract.AUTHORITY, - BaseballCardContract.TABLE_NAME + "/distinct", DISTINCT); - } - - @Override - public boolean onCreate() { - Log.d(TAG, "onCreate()"); - - context = this.getContext(); - this.sqlHelper = this.getSQLHelper(context); - - return true; - } - - protected BaseballCardSQLHelper getSQLHelper(Context context) { - return new BaseballCardSQLHelper(context); - } - - @Override - public Cursor query(@NonNull Uri uri, String[] projection, String selection, - String[] selectionArgs, String sortOrder) { - Log.d(TAG, "query()"); - Log.d(TAG, " uri=" + uri); - Log.d(TAG, " projection=" + Arrays.toString(projection)); - Log.d(TAG, " selection=" + selection); - Log.d(TAG, " selectionArgs=" + Arrays.toString(selectionArgs)); - Log.d(TAG, " sortOrder=" + sortOrder); - - Cursor cursor; - SQLiteDatabase db = this.sqlHelper.getReadableDatabase(); - - switch (uriMatcher.match(uri)) { - case DISTINCT: - if (!projection[0].equals(BaseballCardContract.ID_COL_NAME)) { - throw new SQLException("First column in the projection must be '_id'"); - } - - // Assume projection[1] == the "distinct" column - cursor = db.query(true, BaseballCardContract.TABLE_NAME, - projection, selection, selectionArgs, projection[1], - null, sortOrder, null); - break; - - case ALL_CARDS: - cursor = db.query(BaseballCardContract.TABLE_NAME, projection, - selection, selectionArgs, null, null, sortOrder, null); - break; - - case CARD_ID: - String where = this.getWhereWithId(selection); - long id = ContentUris.parseId(uri); - String[] whereArgs = this.getWhereArgsWithId(selectionArgs, id); - cursor = db.query(BaseballCardContract.TABLE_NAME, projection, - where, whereArgs, null, null, sortOrder); - break; - - default: - String errorFormat = context.getString(R.string.invalid_uri_error); - String error = String.format(errorFormat, uri.toString()); - throw new IllegalArgumentException(error); - } - - cursor.setNotificationUri(context.getContentResolver(), uri); - return cursor; - } - - @Override - public String getType(@NonNull Uri uri) { - switch (uriMatcher.match(uri)) { - case ALL_CARDS: - case DISTINCT: - return BaseballCardContract.BASEBALL_CARD_LIST_MIME_TYPE; - - case CARD_ID: - return BaseballCardContract.BASEBALL_CARD_ITEM_MIME_TYPE; - - default: - String errorFormat = context.getString( - R.string.invalid_uri_error); - String error = String.format(errorFormat, uri.toString()); - throw new IllegalArgumentException(error); - } - } - - @Override - public Uri insert(@NonNull Uri uri, ContentValues values) { - if (uriMatcher.match(uri) != ALL_CARDS) { - String errorFormat = context.getString( - R.string.invalid_uri_error); - String error = String.format(errorFormat, uri.toString()); - throw new IllegalArgumentException(error); - } - - long row = this.sqlHelper.getWritableDatabase().insert( - BaseballCardContract.TABLE_NAME, null, values); - - if (row > 0) { - Uri newUri = ContentUris.withAppendedId(uri, row); - context.getContentResolver().notifyChange(newUri, null); - return newUri; - } - - throw new SQLException("Failed to insert row into " + uri); - } - - @Override - public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) { - int affected; - SQLiteDatabase db = this.sqlHelper.getWritableDatabase(); - - switch (uriMatcher.match(uri)) { - case ALL_CARDS: - affected = db.delete(BaseballCardContract.TABLE_NAME, - selection, selectionArgs); - break; - - case CARD_ID: - String where = this.getWhereWithId(selection); - long id = ContentUris.parseId(uri); - String[] whereArgs = this.getWhereArgsWithId(selectionArgs, id); - affected = db.delete(BaseballCardContract.TABLE_NAME, where, - whereArgs); - break; - - default: - String errorFormat = context.getString( - R.string.invalid_uri_error); - String error = String.format(errorFormat, uri.toString()); - throw new IllegalArgumentException(error); - } - - context.getContentResolver().notifyChange(uri, null); - return affected; - } - - @Override - public int update(@NonNull Uri uri, ContentValues values, String selection, - String[] selectionArgs) { - SQLiteDatabase db = this.sqlHelper.getWritableDatabase(); - - int affected; - - switch (uriMatcher.match(uri)) { - case ALL_CARDS: - affected = db.update(BaseballCardContract.TABLE_NAME, values, - selection, selectionArgs); - break; - - case CARD_ID: - String where = this.getWhereWithId(selection); - long id = ContentUris.parseId(uri); - String[] whereArgs = this.getWhereArgsWithId(selectionArgs, id); - affected = db.update(BaseballCardContract.TABLE_NAME, values, - where, whereArgs); - break; - - default: - String errorFormat = context.getString( - R.string.invalid_uri_error); - String error = String.format(errorFormat, uri.toString()); - throw new IllegalArgumentException(error); - } - - context.getContentResolver().notifyChange(uri, null); - return affected; - } - - @Override - public void shutdown() { - sqlHelper.close(); - } - - private String getWhereWithId(String selection) { - String idSelection = BaseballCardContract.ID_COL_NAME + " = ?"; - return TextUtils.isEmpty(selection) ? idSelection : idSelection - + " AND (" + selection + ")"; - - } - - private String[] getWhereArgsWithId(String[] selectionArgs, long id) { - int argCount = selectionArgs == null ? 1 : selectionArgs.length + 1; - String[] whereArgs = new String[argCount]; - whereArgs[0] = Long.toString(id); - - if (selectionArgs != null) { - System.arraycopy(selectionArgs, 0, whereArgs, 1, selectionArgs.length); - } - - return whereArgs; - } -} diff --git a/android/src/main/java/bbct/android/common/provider/BaseballCardSQLHelper.java b/android/src/main/java/bbct/android/common/provider/BaseballCardSQLHelper.java deleted file mode 100644 index 6a6d9dfc2..000000000 --- a/android/src/main/java/bbct/android/common/provider/BaseballCardSQLHelper.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.provider; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.util.Log; - -// TODO: Write JUnit tests. -public class BaseballCardSQLHelper extends SQLiteOpenHelper { - - public static final String DATABASE_NAME = "bbct.db"; - - /** - * Current schema version. - */ - public static final int SCHEMA_VERSION = 6; - /** - * Original schema version. - */ - public static final int ORIGINAL_SCHEMA = 1; - /** - * Schema version when attempting to add the team field. This version was - * buggy. - */ - public static final int BAD_TEAM_SCHEMA = 2; - /** - * Schema version which correctly added the team field.N - */ - public static final int TEAM_SCHEMA = 3; - - /** - * Schema version which adds Autographed and Condition fields. - */ - public static final int AUTO_AND_CONDITION_SCHEMA = 4; - - public static final int ROOM_SCHEMA = 5; - - public static final int ALPHA_NUMERIC_SCHEMA = 6; - - public BaseballCardSQLHelper(Context context) { - super(context, DATABASE_NAME, null, SCHEMA_VERSION); - - Log.d(TAG, "ctor"); - } - - @Override - public void onCreate(SQLiteDatabase db) { - Log.d(TAG, "onCreate()"); - - String sqlCreate = "CREATE TABLE IF NOT EXISTS " - + BaseballCardContract.TABLE_NAME + "(" - + BaseballCardContract.ID_COL_NAME - + " INTEGER PRIMARY KEY AUTOINCREMENT," - + BaseballCardContract.BRAND_COL_NAME + " TEXT, " - + BaseballCardContract.YEAR_COL_NAME + " INTEGER, " - + BaseballCardContract.NUMBER_COL_NAME + " TEXT, " - + BaseballCardContract.VALUE_COL_NAME + " INTEGER, " - + BaseballCardContract.COUNT_COL_NAME + " INTEGER, " - + BaseballCardContract.PLAYER_NAME_COL_NAME + " TEXT, " - + BaseballCardContract.TEAM_COL_NAME + " TEXT, " - + BaseballCardContract.PLAYER_POSITION_COL_NAME + " TEXT," - + BaseballCardContract.AUTOGRAPHED_COL_NAME + " INTEGER," - + BaseballCardContract.CONDITION_COL_NAME + " TEXT," - + "UNIQUE (" + BaseballCardContract.BRAND_COL_NAME + ", " - + BaseballCardContract.YEAR_COL_NAME + ", " - + BaseballCardContract.NUMBER_COL_NAME + "))"; - - db.execSQL(sqlCreate); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if (oldVersion < TEAM_SCHEMA) { - String sqlUpgrade = "ALTER TABLE " - + BaseballCardContract.TABLE_NAME + " ADD COLUMN " - + BaseballCardContract.TEAM_COL_NAME + " VARCHAR(50)"; - db.execSQL(sqlUpgrade); - } - - if (oldVersion < AUTO_AND_CONDITION_SCHEMA) { - String addAutographed = "ALTER TABLE " - + BaseballCardContract.TABLE_NAME + " ADD COLUMN " - + BaseballCardContract.AUTOGRAPHED_COL_NAME + " INTEGER;"; - String addCondition = "ALTER TABLE " - + BaseballCardContract.TABLE_NAME + " ADD COLUMN " - + BaseballCardContract.CONDITION_COL_NAME + " TEXT"; - db.execSQL(addAutographed); - db.execSQL(addCondition); - } - } - - private static final String TAG = BaseballCardSQLHelper.class.getName(); -} diff --git a/android/src/main/java/bbct/android/common/provider/package-info.java b/android/src/main/java/bbct/android/common/provider/package-info.java deleted file mode 100644 index ab1dab137..000000000 --- a/android/src/main/java/bbct/android/common/provider/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.provider; diff --git a/android/src/main/java/bbct/android/common/view/BaseballCardActionModeCallback.java b/android/src/main/java/bbct/android/common/view/BaseballCardActionModeCallback.java deleted file mode 100644 index 46db9a595..000000000 --- a/android/src/main/java/bbct/android/common/view/BaseballCardActionModeCallback.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.view; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.os.Build; -import android.view.ActionMode; -import android.view.Menu; -import android.view.MenuItem; - -import bbct.android.common.R; -import bbct.android.common.fragment.BaseballCardList; - -@TargetApi(Build.VERSION_CODES.HONEYCOMB) -public class BaseballCardActionModeCallback implements ActionMode.Callback { - - private final BaseballCardList listFragment; - private ActionMode actionMode; - private boolean isStarted; - - public BaseballCardActionModeCallback(BaseballCardList listFragment) { - this.listFragment = listFragment; - } - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - Activity activity = listFragment.requireActivity(); - activity.getMenuInflater().inflate(R.menu.context, menu); - actionMode = mode; - isStarted = true; - return true; - } - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - return false; - } - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - switch (item.getItemId()) { - case R.id.delete_menu: - listFragment.deleteSelectedCards(); - actionMode.finish(); - return true; - case R.id.select_all_menu: - listFragment.setAllSelected(true); - return true; - } - - return false; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - isStarted = false; - actionMode = null; - listFragment.setAllSelected(false); - } - - public boolean isStarted() { - return isStarted; - } - - public void finish() { - actionMode.finish(); - } -} diff --git a/android/src/main/java/bbct/android/common/view/BaseballCardAdapter.java b/android/src/main/java/bbct/android/common/view/BaseballCardAdapter.java deleted file mode 100644 index a8ae953d7..000000000 --- a/android/src/main/java/bbct/android/common/view/BaseballCardAdapter.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.view; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.recyclerview.widget.RecyclerView; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import bbct.android.common.R; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.fragment.BaseballCardDetails; -import bbct.android.common.fragment.FragmentTags; - -public class BaseballCardAdapter extends RecyclerView.Adapter> { - private final FragmentActivity activity; - private final BaseballCardActionModeCallback callback; - private List cards = new ArrayList<>(); - private List selected = new ArrayList<>(); - - public class BaseballCardViewHolder - extends RecyclerView.ViewHolder - implements View.OnClickListener { - public final T view; - public long id = -1; - - BaseballCardViewHolder(T view) { - super(view); - this.view = view; - this.view.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - Fragment details = BaseballCardDetails.getInstance(id); - activity.getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_holder, details, FragmentTags.EDIT_CARD) - .addToBackStack(FragmentTags.EDIT_CARD) - .commit(); - } - } - - public BaseballCardAdapter(@NonNull FragmentActivity activity, - @NonNull BaseballCardActionModeCallback callback) { - this.activity = activity; - this.callback = callback; - } - - @NonNull - @Override - public BaseballCardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - BaseballCardView view = new BaseballCardView(parent.getContext()); - return new BaseballCardViewHolder<>(view); - } - - @Override - public void onBindViewHolder(@NonNull final BaseballCardViewHolder holder, int position) { - holder.id = getItemId(position); - BaseballCardView cardView = (BaseballCardView) holder.view; - cardView.setBaseballCard(cards.get(position)); - cardView.setChecked(selected.get(position)); - - CheckBox ctv = cardView.findViewById(R.id.checkmark); - ctv.setOnCheckedChangeListener((buttonView, isChecked) -> { - int position1 = holder.getAdapterPosition(); - setItemSelected(position1, isChecked); - - if (isChecked && !callback.isStarted()) { - activity.startActionMode(callback); - } else if (callback.isStarted() && getSelectedCount() == 0) { - callback.finish(); - } - }); - - cardView.setOnLongClickListener(v -> { - CheckableLinearLayout check = (CheckableLinearLayout)v; - check.setChecked(true); - return true; - }); - } - - @Override - public int getItemCount() { - return cards.size(); - } - - @Override - public long getItemId(int position) { - return cards.get(position)._id; - } - - public void setCards(@NonNull List cards) { - this.cards = cards; - this.selected = - new ArrayList<>(Collections.nCopies(cards.size(), false)); - notifyDataSetChanged(); - } - - public void setAllSelected(boolean isSelected) { - for (int i = 0; i < getItemCount(); ++i) { - setItemSelected(i, isSelected); - } - notifyDataSetChanged(); - } - - private void setItemSelected(int position, boolean isSelected) { - selected.set(position, isSelected); - } - - public List getSelectedItems() { - List selectedCards = new ArrayList<>(); - for (int i = 0; i < selected.size(); ++i) { - if (selected.get(i)) { - selectedCards.add(cards.get(i)); - } - } - - return selectedCards; - } - - public List getCards() { - return cards; - } - - private int getSelectedCount() { - int count = 0; - for (boolean selectedItem : selected) { - if (selectedItem) { - count++; - } - } - return count; - } -} diff --git a/android/src/main/java/bbct/android/common/view/BaseballCardView.java b/android/src/main/java/bbct/android/common/view/BaseballCardView.java deleted file mode 100644 index 2755000c0..000000000 --- a/android/src/main/java/bbct/android/common/view/BaseballCardView.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.view; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.ViewGroup; -import android.widget.TextView; - -import java.util.Locale; - -import bbct.android.common.R; -import bbct.android.common.database.BaseballCard; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class BaseballCardView extends CheckableLinearLayout { - @BindView(R.id.brand) - TextView brand; - @BindView(R.id.year) - TextView year; - @BindView(R.id.number) - TextView number; - @BindView(R.id.player_name) - TextView player; - - public BaseballCardView(Context context) { - this(context, null); - } - - public BaseballCardView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public BaseballCardView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - ViewGroup root = (ViewGroup) ViewGroup.inflate(context, R.layout.baseball_card, this); - mCheckable = root.findViewById(R.id.checkmark); - - ButterKnife.bind(root); - } - - public void setBaseballCard(BaseballCard card) { - Locale locale = Locale.getDefault(); - brand.setText(card.brand); - year.setText(String.format(locale, "%d", card.year)); - number.setText(card.number); - player.setText(card.playerName); - } -} diff --git a/android/src/main/java/bbct/android/common/view/CheckableLinearLayout.java b/android/src/main/java/bbct/android/common/view/CheckableLinearLayout.java deleted file mode 100644 index 40ae3b76c..000000000 --- a/android/src/main/java/bbct/android/common/view/CheckableLinearLayout.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.view; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.Checkable; -import android.widget.LinearLayout; - -import bbct.android.common.R; -import butterknife.BindView; - -public class CheckableLinearLayout extends LinearLayout implements Checkable { - @BindView(R.id.checkmark) - Checkable mCheckable; - - public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - public void setChecked(boolean checked) { - mCheckable.setChecked(checked); - } - - @Override - public boolean isChecked() { - return mCheckable.isChecked(); - } - - @Override - public void toggle() { - mCheckable.toggle(); - } -} diff --git a/android/src/main/res/drawable-hdpi/cancel.png b/android/src/main/res/drawable-hdpi/cancel.png deleted file mode 100644 index 81444d5b2..000000000 Binary files a/android/src/main/res/drawable-hdpi/cancel.png and /dev/null differ diff --git a/android/src/main/res/drawable-hdpi/check.png b/android/src/main/res/drawable-hdpi/check.png deleted file mode 100755 index 659bd3ff4..000000000 Binary files a/android/src/main/res/drawable-hdpi/check.png and /dev/null differ diff --git a/android/src/main/res/drawable-hdpi/delete.png b/android/src/main/res/drawable-hdpi/delete.png deleted file mode 100644 index dea2b0348..000000000 Binary files a/android/src/main/res/drawable-hdpi/delete.png and /dev/null differ diff --git a/android/src/main/res/drawable-hdpi/ic_menu_about.png b/android/src/main/res/drawable-hdpi/ic_menu_about.png deleted file mode 100644 index 672a24df3..000000000 Binary files a/android/src/main/res/drawable-hdpi/ic_menu_about.png and /dev/null differ diff --git a/android/src/main/res/drawable-hdpi/ic_plus.png b/android/src/main/res/drawable-hdpi/ic_plus.png deleted file mode 100644 index e5565772a..000000000 Binary files a/android/src/main/res/drawable-hdpi/ic_plus.png and /dev/null differ diff --git a/android/src/main/res/drawable-hdpi/search.png b/android/src/main/res/drawable-hdpi/search.png deleted file mode 100644 index bf2c96409..000000000 Binary files a/android/src/main/res/drawable-hdpi/search.png and /dev/null differ diff --git a/android/src/main/res/drawable-ldpi/ic_menu_about.png b/android/src/main/res/drawable-ldpi/ic_menu_about.png deleted file mode 100644 index 42686ec79..000000000 Binary files a/android/src/main/res/drawable-ldpi/ic_menu_about.png and /dev/null differ diff --git a/android/src/main/res/drawable-mdpi/cancel.png b/android/src/main/res/drawable-mdpi/cancel.png deleted file mode 100644 index c11fc9ab8..000000000 Binary files a/android/src/main/res/drawable-mdpi/cancel.png and /dev/null differ diff --git a/android/src/main/res/drawable-mdpi/check.png b/android/src/main/res/drawable-mdpi/check.png deleted file mode 100755 index 4a5d8f62f..000000000 Binary files a/android/src/main/res/drawable-mdpi/check.png and /dev/null differ diff --git a/android/src/main/res/drawable-mdpi/delete.png b/android/src/main/res/drawable-mdpi/delete.png deleted file mode 100644 index cc41c80bb..000000000 Binary files a/android/src/main/res/drawable-mdpi/delete.png and /dev/null differ diff --git a/android/src/main/res/drawable-mdpi/ic_menu_about.png b/android/src/main/res/drawable-mdpi/ic_menu_about.png deleted file mode 100644 index 987e60030..000000000 Binary files a/android/src/main/res/drawable-mdpi/ic_menu_about.png and /dev/null differ diff --git a/android/src/main/res/drawable-mdpi/ic_plus.png b/android/src/main/res/drawable-mdpi/ic_plus.png deleted file mode 100644 index 36a5b40fc..000000000 Binary files a/android/src/main/res/drawable-mdpi/ic_plus.png and /dev/null differ diff --git a/android/src/main/res/drawable-mdpi/search.png b/android/src/main/res/drawable-mdpi/search.png deleted file mode 100644 index 616e6dff8..000000000 Binary files a/android/src/main/res/drawable-mdpi/search.png and /dev/null differ diff --git a/android/src/main/res/drawable-xhdpi/cancel.png b/android/src/main/res/drawable-xhdpi/cancel.png deleted file mode 100644 index 01f4a5bd5..000000000 Binary files a/android/src/main/res/drawable-xhdpi/cancel.png and /dev/null differ diff --git a/android/src/main/res/drawable-xhdpi/check.png b/android/src/main/res/drawable-xhdpi/check.png deleted file mode 100755 index add204762..000000000 Binary files a/android/src/main/res/drawable-xhdpi/check.png and /dev/null differ diff --git a/android/src/main/res/drawable-xhdpi/delete.png b/android/src/main/res/drawable-xhdpi/delete.png deleted file mode 100644 index b70443b6d..000000000 Binary files a/android/src/main/res/drawable-xhdpi/delete.png and /dev/null differ diff --git a/android/src/main/res/drawable-xhdpi/ic_menu_about.png b/android/src/main/res/drawable-xhdpi/ic_menu_about.png deleted file mode 100644 index 672a24df3..000000000 Binary files a/android/src/main/res/drawable-xhdpi/ic_menu_about.png and /dev/null differ diff --git a/android/src/main/res/drawable-xhdpi/ic_plus.png b/android/src/main/res/drawable-xhdpi/ic_plus.png deleted file mode 100644 index 265017dce..000000000 Binary files a/android/src/main/res/drawable-xhdpi/ic_plus.png and /dev/null differ diff --git a/android/src/main/res/drawable-xhdpi/search.png b/android/src/main/res/drawable-xhdpi/search.png deleted file mode 100644 index 19b53629c..000000000 Binary files a/android/src/main/res/drawable-xhdpi/search.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxhdpi/cancel.png b/android/src/main/res/drawable-xxhdpi/cancel.png deleted file mode 100644 index df42b4a13..000000000 Binary files a/android/src/main/res/drawable-xxhdpi/cancel.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxhdpi/check.png b/android/src/main/res/drawable-xxhdpi/check.png deleted file mode 100755 index c9cdfb1f8..000000000 Binary files a/android/src/main/res/drawable-xxhdpi/check.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxhdpi/delete.png b/android/src/main/res/drawable-xxhdpi/delete.png deleted file mode 100644 index 75e83e67e..000000000 Binary files a/android/src/main/res/drawable-xxhdpi/delete.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxhdpi/ic_plus.png b/android/src/main/res/drawable-xxhdpi/ic_plus.png deleted file mode 100644 index 567bbf6b8..000000000 Binary files a/android/src/main/res/drawable-xxhdpi/ic_plus.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxhdpi/search.png b/android/src/main/res/drawable-xxhdpi/search.png deleted file mode 100644 index 91e6d2bde..000000000 Binary files a/android/src/main/res/drawable-xxhdpi/search.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxxhdpi/cancel.png b/android/src/main/res/drawable-xxxhdpi/cancel.png deleted file mode 100644 index dfc6758cd..000000000 Binary files a/android/src/main/res/drawable-xxxhdpi/cancel.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxxhdpi/check.png b/android/src/main/res/drawable-xxxhdpi/check.png deleted file mode 100755 index 669c52aac..000000000 Binary files a/android/src/main/res/drawable-xxxhdpi/check.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxxhdpi/delete.png b/android/src/main/res/drawable-xxxhdpi/delete.png deleted file mode 100644 index c56573e25..000000000 Binary files a/android/src/main/res/drawable-xxxhdpi/delete.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxxhdpi/ic_plus.png b/android/src/main/res/drawable-xxxhdpi/ic_plus.png deleted file mode 100644 index 5213a1fae..000000000 Binary files a/android/src/main/res/drawable-xxxhdpi/ic_plus.png and /dev/null differ diff --git a/android/src/main/res/drawable-xxxhdpi/search.png b/android/src/main/res/drawable-xxxhdpi/search.png deleted file mode 100644 index c45a71b56..000000000 Binary files a/android/src/main/res/drawable-xxxhdpi/search.png and /dev/null differ diff --git a/android/src/main/res/drawable/checkmark.xml b/android/src/main/res/drawable/checkmark.xml deleted file mode 100644 index 0c6777291..000000000 --- a/android/src/main/res/drawable/checkmark.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/android/src/main/res/layout/about.xml b/android/src/main/res/layout/about.xml deleted file mode 100644 index d5c2bad1c..000000000 --- a/android/src/main/res/layout/about.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/src/main/res/layout/baseball_card.xml b/android/src/main/res/layout/baseball_card.xml deleted file mode 100644 index 41860b064..000000000 --- a/android/src/main/res/layout/baseball_card.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - diff --git a/android/src/main/res/layout/card_details.xml b/android/src/main/res/layout/card_details.xml deleted file mode 100644 index 6e288c839..000000000 --- a/android/src/main/res/layout/card_details.xml +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/src/main/res/layout/card_list.xml b/android/src/main/res/layout/card_list.xml deleted file mode 100644 index 0990f9404..000000000 --- a/android/src/main/res/layout/card_list.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - diff --git a/android/src/main/res/layout/filter_cards.xml b/android/src/main/res/layout/filter_cards.xml deleted file mode 100644 index 73821a12a..000000000 --- a/android/src/main/res/layout/filter_cards.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/src/main/res/layout/fragment_activity.xml b/android/src/main/res/layout/fragment_activity.xml deleted file mode 100644 index 2fd012594..000000000 --- a/android/src/main/res/layout/fragment_activity.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/android/src/main/res/layout/main.xml b/android/src/main/res/layout/main.xml deleted file mode 100644 index a4b59963c..000000000 --- a/android/src/main/res/layout/main.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - diff --git a/android/src/main/res/menu/context.xml b/android/src/main/res/menu/context.xml deleted file mode 100644 index 95384e9a2..000000000 --- a/android/src/main/res/menu/context.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - diff --git a/android/src/main/res/menu/list.xml b/android/src/main/res/menu/list.xml deleted file mode 100644 index 5501c9cfd..000000000 --- a/android/src/main/res/menu/list.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - diff --git a/android/src/main/res/menu/main.xml b/android/src/main/res/menu/main.xml deleted file mode 100644 index 201e6ec34..000000000 --- a/android/src/main/res/menu/main.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - diff --git a/android/src/main/res/values/analytics.xml b/android/src/main/res/values/analytics.xml deleted file mode 100644 index 0eaf10f2b..000000000 --- a/android/src/main/res/values/analytics.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - UA-38019406-1 - - - true - - - true - diff --git a/android/src/main/res/values/dimens.xml b/android/src/main/res/values/dimens.xml deleted file mode 100644 index 44031304a..000000000 --- a/android/src/main/res/values/dimens.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - 80dp - 50dp - 60dp - 100dp - - - 15sp - diff --git a/android/src/main/res/values/ids.xml b/android/src/main/res/values/ids.xml deleted file mode 100644 index 88e38163c..000000000 --- a/android/src/main/res/values/ids.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml deleted file mode 100644 index 8ada39ea2..000000000 --- a/android/src/main/res/values/styles.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - #5677fc - #ff3367d6 - #ff69f0ae - diff --git a/android/src/premium/AndroidManifest.xml b/android/src/premium/AndroidManifest.xml deleted file mode 100644 index 791dc293b..000000000 --- a/android/src/premium/AndroidManifest.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/src/premium/java/bbct/android/premium/provider/PremiumProvider.java b/android/src/premium/java/bbct/android/premium/provider/PremiumProvider.java deleted file mode 100644 index 2c390c574..000000000 --- a/android/src/premium/java/bbct/android/premium/provider/PremiumProvider.java +++ /dev/null @@ -1,24 +0,0 @@ -package bbct.android.premium.provider; - -import android.content.Context; -import bbct.android.common.provider.BaseballCardContract; -import bbct.android.common.provider.BaseballCardProvider; -import bbct.android.common.provider.BaseballCardSQLHelper; - -public class PremiumProvider extends BaseballCardProvider { - - static { - uriMatcher.addURI(BaseballCardContract.PREMIUM_AUTHORITY, - BaseballCardContract.TABLE_NAME, ALL_CARDS); - uriMatcher.addURI(BaseballCardContract.PREMIUM_AUTHORITY, - BaseballCardContract.TABLE_NAME + "/#", CARD_ID); - uriMatcher.addURI(BaseballCardContract.PREMIUM_AUTHORITY, - BaseballCardContract.TABLE_NAME + "/distinct", DISTINCT); - } - - @Override - protected BaseballCardSQLHelper getSQLHelper(Context context) { - return new PremiumSQLHelper(context); - } - -} diff --git a/android/src/premium/java/bbct/android/premium/provider/PremiumSQLHelper.java b/android/src/premium/java/bbct/android/premium/provider/PremiumSQLHelper.java deleted file mode 100644 index 4d3dc478e..000000000 --- a/android/src/premium/java/bbct/android/premium/provider/PremiumSQLHelper.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2012-14 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.premium.provider; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.database.Cursor; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import android.util.Log; - -import java.util.List; - -import bbct.android.common.R; -import bbct.android.common.database.BaseballCard; -import bbct.android.common.provider.BaseballCardContract; - -/** - * Overrides - * {@link bbct.android.common.provider.BaseballCardSQLHelper#onConfigure(SQLiteDatabase)} - * in order to import data from the Lite edition. - */ -public class PremiumSQLHelper extends - bbct.android.common.provider.BaseballCardSQLHelper { - private static final String TAG = PremiumSQLHelper.class.getName(); - private static final String LITE_PACKAGE = "bbct.android"; - private static final int MIN_LITE_VERSION = 3; - - private final Context context; - - public PremiumSQLHelper(Context context) { - super(context); - - Log.d(TAG, "ctor"); - - this.context = context; - } - - @Override - public void onCreate(SQLiteDatabase db) { - super.onCreate(db); - - Log.d(TAG, "onCreate()"); - - if (this.isLiteInstalled()) { - ContentResolver resolver = this.context.getContentResolver(); - Cursor results = resolver.query(BaseballCardContract.LITE_URI, - BaseballCardContract.PROJECTION, null, null, null); - - if (results != null) { - List cards = BaseballCardContract - .getAllBaseballCardsFromCursor(results); - this.insertAllBaseballCards(db, cards); - } else { - String errorMessage = this.context - .getString(R.string.import_error); - throw new SQLException(errorMessage); - } - } - - } - - private boolean isLiteInstalled() { - try { - PackageInfo liteInfo = this.context - .getPackageManager() - .getPackageInfo(LITE_PACKAGE, PackageManager.GET_ACTIVITIES); - if (liteInfo.versionCode < MIN_LITE_VERSION) { - String errorMessage = this.context - .getString(R.string.lite_update_message); - throw new SQLException(errorMessage); - } - - return true; - } catch (NameNotFoundException ex) { - Log.i(TAG, LITE_PACKAGE + " package not found", ex); - return false; - } - } - - private void insertAllBaseballCards(SQLiteDatabase db, - List cards) { - db.beginTransaction(); - try { - for (BaseballCard card : cards) { - db.insert(BaseballCardContract.TABLE_NAME, null, - BaseballCardContract.getContentValues(card)); - } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } -} diff --git a/android/src/premium/res/values/no_translate.xml b/android/src/premium/res/values/no_translate.xml deleted file mode 100644 index 3733e1c37..000000000 --- a/android/src/premium/res/values/no_translate.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - BBCT Premium - BBCT Premium - %1$s - - diff --git a/android/src/premium/res/values/strings.xml b/android/src/premium/res/values/strings.xml deleted file mode 100644 index cca282799..000000000 --- a/android/src/premium/res/values/strings.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Importing data from Lite Edition. - Cannot import data from Lite Edition. %1$s - Please update Lite Edition. - Lite Edition not installed. - - BBCT Premium Data - BBCT Read - Baseball Card data from BBCT Premium database - BBCT Write - Write Baseball Card data to BBCT Premium database - - diff --git a/android/src/test/java/bbct/android/common/activity/test/DetailsLayoutTest.java b/android/src/test/java/bbct/android/common/activity/test/DetailsLayoutTest.java deleted file mode 100644 index 672805ea6..000000000 --- a/android/src/test/java/bbct/android/common/activity/test/DetailsLayoutTest.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is part of BBCT for Android. - * - * Copyright 2016 codeguru - * - * BBCT for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * BBCT for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package bbct.android.common.activity.test; - -public class DetailsLayoutTest { -} diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..04a4440e3 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,101 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) + alias(libs.plugins.google.gms.google.services) + alias(libs.plugins.google.firebase.crashlytics) + alias(libs.plugins.compose.compiler) + alias(libs.plugins.google.devtools.ksp) + alias(libs.plugins.kotlin.plugin.serialization) + id("androidx.room") +} + +android { + namespace = "bbct.android" + compileSdk = 35 + + defaultConfig { + applicationId = "bbct.android" + minSdk = 24 + targetSdk = 35 + versionCode = 26 + versionName = "2025.01" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + compose = true + buildConfig = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.1" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } + flavorDimensions += listOf("tier") + productFlavors { + create("lite") { + dimension = "tier" + applicationId = "bbct.android" + } + create("premium") { + dimension = "tier" + applicationId = "bbct.android.premium" + } + } + room { + schemaDirectory("$projectDir/schemas") + } +} + +dependencies { + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + implementation(libs.androidx.navigation.compose) + implementation(libs.firebase.crashlytics) + implementation(libs.androidx.room.runtime) + implementation(libs.kotlinx.coroutines.core) + implementation(libs.androidx.room.ktx) + implementation(libs.lifecycle.viewmodel.compose) + implementation(libs.kotlinx.serialization.json) + implementation(libs.androidx.lifecycle.runtime.compose) + implementation(libs.play.services.ads) + ksp(libs.androidx.room.compiler) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + androidTestImplementation(libs.androidx.ui.test.junit4.android) + androidTestImplementation(libs.google.truth) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/android/schemas/bbct.android.common.database.BaseballCardDatabase/5.json b/app/schemas/bbct.android.data.BaseballCardDatabase/5.json similarity index 100% rename from android/schemas/bbct.android.common.database.BaseballCardDatabase/5.json rename to app/schemas/bbct.android.data.BaseballCardDatabase/5.json diff --git a/android/schemas/bbct.android.common.database.BaseballCardDatabase/6.json b/app/schemas/bbct.android.data.BaseballCardDatabase/6.json similarity index 100% rename from android/schemas/bbct.android.common.database.BaseballCardDatabase/6.json rename to app/schemas/bbct.android.data.BaseballCardDatabase/6.json diff --git a/app/schemas/bbct.android.data.BaseballCardDatabase/7.json b/app/schemas/bbct.android.data.BaseballCardDatabase/7.json new file mode 100644 index 000000000..effdc2396 --- /dev/null +++ b/app/schemas/bbct.android.data.BaseballCardDatabase/7.json @@ -0,0 +1,94 @@ +{ + "formatVersion": 1, + "database": { + "version": 7, + "identityHash": "1e7392f7aeba9fbe1179c3588d832937", + "entities": [ + { + "tableName": "baseball_cards", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER, `autographed` INTEGER NOT NULL, `condition` TEXT NOT NULL, `brand` TEXT NOT NULL, `year` INTEGER NOT NULL, `number` TEXT NOT NULL, `value` INTEGER, `card_count` INTEGER NOT NULL, `player_name` TEXT NOT NULL, `team` TEXT NOT NULL, `player_position` TEXT NOT NULL, PRIMARY KEY(`_id`))", + "fields": [ + { + "fieldPath": "_id", + "columnName": "_id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "autographed", + "columnName": "autographed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "condition", + "columnName": "condition", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "brand", + "columnName": "brand", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "year", + "columnName": "year", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "quantity", + "columnName": "card_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "playerName", + "columnName": "player_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "team", + "columnName": "team", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "player_position", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "_id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1e7392f7aeba9fbe1179c3588d832937')" + ] + } +} \ No newline at end of file diff --git a/android/src/androidTest/assets/cards.csv b/app/src/androidTest/assets/cards.csv similarity index 100% rename from android/src/androidTest/assets/cards.csv rename to app/src/androidTest/assets/cards.csv diff --git a/android/src/androidTest/assets/three_cards.csv b/app/src/androidTest/assets/three_cards.csv similarity index 100% rename from android/src/androidTest/assets/three_cards.csv rename to app/src/androidTest/assets/three_cards.csv diff --git a/app/src/androidTest/java/bbct/android/SmokeScreenTest.kt b/app/src/androidTest/java/bbct/android/SmokeScreenTest.kt new file mode 100644 index 000000000..54c8200fb --- /dev/null +++ b/app/src/androidTest/java/bbct/android/SmokeScreenTest.kt @@ -0,0 +1,14 @@ +package bbct.android + +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test + +class SmokeScreenTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("bbct.android", appContext.packageName) + } +} diff --git a/app/src/androidTest/java/bbct/android/data/LoadDataTest.kt b/app/src/androidTest/java/bbct/android/data/LoadDataTest.kt new file mode 100644 index 000000000..c91762791 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/data/LoadDataTest.kt @@ -0,0 +1,33 @@ +package bbct.android.data + +import androidx.room.Room.inMemoryDatabaseBuilder +import androidx.test.platform.app.InstrumentationRegistry +import bbct.android.test.BaseballCardCsvFileReader +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.junit.Test + +class LoadDataTest { + @Test + fun loadData() { + val instrumentation = InstrumentationRegistry.getInstrumentation() + val db = inMemoryDatabaseBuilder( + instrumentation.targetContext, + BaseballCardDatabase::class.java + ).build() + val csvReader = BaseballCardCsvFileReader( + instrumentation.context.assets.open("cards.csv"), + hasColHeaders = true + ) + + CoroutineScope(Dispatchers.IO).launch { + while (csvReader.hasNextBaseballCard()) { + val card = csvReader.getNextBaseballCard() + db.baseballCardDao.insertBaseballCard(card) + } + } + + db.close() + } +} diff --git a/app/src/androidTest/java/bbct/android/data/TestData.kt b/app/src/androidTest/java/bbct/android/data/TestData.kt new file mode 100644 index 000000000..ba7d3240d --- /dev/null +++ b/app/src/androidTest/java/bbct/android/data/TestData.kt @@ -0,0 +1,43 @@ +package bbct.android.data + +val cards = listOf( + BaseballCard( + _id = 1, + autographed = false, + condition = "Excellent", + brand = "Topps", + year = 1991, + number = "278", + value = 500, + quantity = 1, + playerName = "Alex Fernandez", + team = "White Sox", + position = "Pitcher" + ), + BaseballCard( + _id = 2, + autographed = true, + condition = "Mint", + brand = "Topps", + year = 1974, + number = "175", + value = 1000, + quantity = 1, + playerName = "Bob Stanley", + team = "Red Sox", + position = "Pitcher" + ), + BaseballCard( + _id = 3, + autographed = false, + condition = "Very Good", + brand = "Topps", + year = 1985, + number = "201", + value = 200, + quantity = 1, + playerName = "Vince Coleman", + team = "Cardinals", + position = "Left Field", + ), +) diff --git a/app/src/androidTest/java/bbct/android/rules/CardDatabaseTestRule.kt b/app/src/androidTest/java/bbct/android/rules/CardDatabaseTestRule.kt new file mode 100644 index 000000000..2730e4166 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/rules/CardDatabaseTestRule.kt @@ -0,0 +1,19 @@ +package bbct.android.rules + +import bbct.android.data.BaseballCardDatabase +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class CardDatabaseTestRule(filename: String, val db: BaseballCardDatabase) : + CardListTestRule(filename) { + override fun before() { + super.before() + + CoroutineScope(Dispatchers.IO).launch { + for (card in cards!!) { + db.baseballCardDao.insertBaseballCard(card) + } + } + } +} diff --git a/app/src/androidTest/java/bbct/android/rules/CardListTestRule.kt b/app/src/androidTest/java/bbct/android/rules/CardListTestRule.kt new file mode 100644 index 000000000..cf1e23320 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/rules/CardListTestRule.kt @@ -0,0 +1,22 @@ +package bbct.android.rules + +import androidx.test.platform.app.InstrumentationRegistry +import bbct.android.data.BaseballCard +import bbct.android.test.BaseballCardCsvFileReader +import org.junit.rules.ExternalResource + +open class CardListTestRule(private val filename: String) : ExternalResource() { + var cards: List? = null + + override fun before() { + val inst = InstrumentationRegistry.getInstrumentation() + + val cardInputStream = inst.context.assets.open(filename) + val cardInput: BaseballCardCsvFileReader = BaseballCardCsvFileReader( + cardInputStream, + true + ) + cards = cardInput.getAllBaseballCards() + cardInput.close() + } +} diff --git a/app/src/androidTest/java/bbct/android/test/BaseballCardCsvFileReader.kt b/app/src/androidTest/java/bbct/android/test/BaseballCardCsvFileReader.kt new file mode 100644 index 000000000..bfa789145 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/test/BaseballCardCsvFileReader.kt @@ -0,0 +1,115 @@ +package bbct.android.test + +import bbct.android.data.BaseballCard +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStream +import java.io.InputStreamReader +import java.util.ArrayList + +/** + * This class reads baseball card data from an input stream which is formatted + * as comma-separated values. + */ +class BaseballCardCsvFileReader( + input: InputStream, + hasColHeaders: Boolean +) { + private val input: BufferedReader = BufferedReader(InputStreamReader(input)) + + /** + * Create a [BaseballCardCsvFileReader] object which reads baseball + * card data as comma-separated values from the given [InputStream]. + * The input may contain column headers, which will be ignored. + * + * @param input The [InputStream] containing the comma-separated values. + * @param hasColHeaders Whether or not the input contains column headers. + * @throws IOException If an error occurs while reading the input. + */ + init { + if (hasColHeaders) { + this.input.readLine() + } + } + + /** + * Reads baseball card data from the next line of comma-separated values. + * + * @return A [BaseballCard] containing the data from the input stream. + * @throws IOException If an error occurs while reading the input. + */ + @Throws(IOException::class) + fun getNextBaseballCard(): BaseballCard { + val line = this.input.readLine() + val data = line + .split(",".toRegex()) + .dropLastWhile { it.isEmpty() } + .toTypedArray() + val autographed = data[0].toBoolean() + val condition = data[1] + val brand = data[2] + val year = data[3].toInt() + val number = data[4] + val value = 10000 + val count = 1 + val playerName = data[5] + val team = data[6] + val playerPosition = data[7] + + return BaseballCard( + null, + autographed, + condition, + brand, + year, + number, + value, + count, + playerName, + team, + playerPosition + ) + } + + /** + * Determine if the input stream contains more baseball card data. If the + * input stream is ready for an input operation, then this function returns + * `true`. The validity of the data is determined only after + * calling [.getNextBaseballCard] or [ ][.getAllBaseballCards]. + * + * @return `true` if the input stream is ready for an input + * operation; `false`, otherwise. + * @throws IOException If an error occurs while reading the input. + */ + @Throws(IOException::class) + fun hasNextBaseballCard(): Boolean { + return this.input.ready() + } + + /** + * Reads all the baseball card data from the input stream. + * + * @return A list of [BaseballCard] objects containing all of the + * baseball card data from the input stream. + * @throws IOException If an error occurs while reading the input. + */ + @Throws(IOException::class) + fun getAllBaseballCards(): List { + val cards: MutableList = ArrayList() + while (this.hasNextBaseballCard()) { + cards.add(this.getNextBaseballCard()) + } + + return cards.toList() + } + + /** + * Close the input stream. + * + * @throws IOException If an error occurs while reading the input. + */ + @Throws(IOException::class) + fun close() { + this.input.close() + } +} diff --git a/app/src/androidTest/java/bbct/android/test/Filters.kt b/app/src/androidTest/java/bbct/android/test/Filters.kt new file mode 100644 index 000000000..af578b776 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/test/Filters.kt @@ -0,0 +1,13 @@ +package bbct.android.test + +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.SemanticsProperties +import androidx.compose.ui.semantics.getOrNull +import androidx.compose.ui.test.SemanticsMatcher + + +fun hasRole(role: Role): SemanticsMatcher { + return SemanticsMatcher("hasRole $role") { + it.config.getOrNull(SemanticsProperties.Role) == role + } +} diff --git a/app/src/androidTest/java/bbct/android/test/TestBase.kt b/app/src/androidTest/java/bbct/android/test/TestBase.kt new file mode 100644 index 000000000..3fca475b8 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/test/TestBase.kt @@ -0,0 +1,66 @@ +package bbct.android.test + +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performScrollTo +import androidx.compose.ui.test.performTextReplacement +import bbct.android.data.BaseballCard +import org.junit.Rule + +abstract class TestBase { + @get:Rule + val composeTestRule = createComposeRule() + + fun enterCardData(card: BaseballCard) { + composeTestRule + .onNodeWithText("Condition") + .performScrollTo() + .assertIsDisplayed() + .performClick() + composeTestRule + .onNodeWithText(card.condition) + .performClick() + composeTestRule + .onNodeWithText("Brand") + .assertIsDisplayed() + .performTextReplacement(card.brand) + composeTestRule + .onNodeWithText("Year") + .assertIsDisplayed() + .performTextReplacement(card.year.toString()) + composeTestRule + .onNodeWithText("Number") + .assertIsDisplayed() + .performTextReplacement(card.number) + composeTestRule + .onNodeWithText("Value") + .assertIsDisplayed() + .performTextReplacement((card.value!! / 100.0f).toString()) + composeTestRule + .onNodeWithText("Quantity") + .assertIsDisplayed() + .performTextReplacement(card.quantity.toString()) + composeTestRule + .onNodeWithText("Player Name") + .assertIsDisplayed() + .performTextReplacement(card.playerName) + composeTestRule + .onNodeWithText("Team") + .assertIsDisplayed() + .performTextReplacement(card.team) + composeTestRule + .onNodeWithText("Position") + .assertIsDisplayed() + .performClick() + composeTestRule + .onNodeWithText(card.position) + .assertIsDisplayed() + .performClick() + composeTestRule + .onNodeWithContentDescription("Save") + .performClick() + } +} diff --git a/app/src/androidTest/java/bbct/android/ui/AppTest.kt b/app/src/androidTest/java/bbct/android/ui/AppTest.kt new file mode 100644 index 000000000..803f0626f --- /dev/null +++ b/app/src/androidTest/java/bbct/android/ui/AppTest.kt @@ -0,0 +1,27 @@ +package bbct.android.ui + +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import bbct.android.data.BaseballCardDatabase +import org.junit.Rule +import org.junit.Test + +class AppTest { + @get:Rule + val androidComposeTestRule = createComposeRule() + + @Test + fun testApp() { + androidComposeTestRule.setContent { + val db = BaseballCardDatabase.getInstance( + LocalContext.current, + BaseballCardDatabase.TEST_DATABASE_NAME + ) + App(db) + } + + androidComposeTestRule.onNodeWithText("BBCT").assertIsDisplayed() + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/bbct/android/ui/details/CreateTest.kt b/app/src/androidTest/java/bbct/android/ui/details/CreateTest.kt new file mode 100644 index 000000000..22ca87975 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/ui/details/CreateTest.kt @@ -0,0 +1,110 @@ +package bbct.android.ui.details + +import androidx.compose.ui.test.assert +import androidx.compose.ui.test.hasText +import androidx.compose.ui.test.onNodeWithText +import androidx.navigation.compose.rememberNavController +import androidx.room.Room.inMemoryDatabaseBuilder +import androidx.test.platform.app.InstrumentationRegistry +import bbct.android.data.BaseballCard +import bbct.android.data.BaseballCardDatabase +import bbct.android.test.TestBase +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import org.junit.Test + +class CreateTest : TestBase() { + @Test + fun testBaseballCardDetailsSaveCard() { + val card = BaseballCard( + autographed = false, + condition = "Mint", + brand = "Topps", + year = 1987, + number = "123", + value = 100, + quantity = 1, + playerName = "John Doe", + team = "Yankees", + position = "Pitcher" + ) + + val context = InstrumentationRegistry.getInstrumentation().targetContext + val db = inMemoryDatabaseBuilder( + context, + BaseballCardDatabase::class.java + ).build() + + composeTestRule.setContent { + val navController = rememberNavController() + CreateScreen( + navController, + db + ) + } + + enterCardData(card) + + CoroutineScope(Dispatchers.IO).launch { + val savedCard = db.baseballCardDao.baseballCards.first() + assertThat(savedCard).isNotEqualTo(listOf(card)) + } + } + + @Test + fun testBaseballCardDetailsSaveCardClearsFields() { + val card = BaseballCard( + autographed = false, + condition = "Mint", + brand = "Topps", + year = 1987, + number = "123", + value = 100, + quantity = 1, + playerName = "John Doe", + team = "Yankees", + position = "Pitcher" + ) + + val context = InstrumentationRegistry.getInstrumentation().targetContext + val db = inMemoryDatabaseBuilder( + context, + BaseballCardDatabase::class.java + ).build() + + composeTestRule.setContent { + val navController = rememberNavController() + CreateScreen( + navController, + db + ) + } + + enterCardData(card) + + composeTestRule + .onNodeWithText("Brand") + .assert(hasText("")) + composeTestRule + .onNodeWithText("Year") + .assert(hasText("")) + composeTestRule + .onNodeWithText("Number") + .assert(hasText("")) + composeTestRule + .onNodeWithText("Value") + .assert(hasText("")) + composeTestRule + .onNodeWithText("Quantity") + .assert(hasText("")) + composeTestRule + .onNodeWithText("Player Name") + .assert(hasText("")) + composeTestRule + .onNodeWithText("Team") + .assert(hasText("")) + } +} diff --git a/app/src/androidTest/java/bbct/android/ui/details/EditTest.kt b/app/src/androidTest/java/bbct/android/ui/details/EditTest.kt new file mode 100644 index 000000000..93a7d46df --- /dev/null +++ b/app/src/androidTest/java/bbct/android/ui/details/EditTest.kt @@ -0,0 +1,49 @@ +package bbct.android.ui.details + +import androidx.navigation.compose.rememberNavController +import androidx.room.Room.inMemoryDatabaseBuilder +import androidx.test.platform.app.InstrumentationRegistry +import bbct.android.data.BaseballCardDatabase +import bbct.android.data.cards +import bbct.android.test.TestBase +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.flow.single +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class EditTest : TestBase() { + @Test + fun testBaseballCardEdit() { + runTest { + val card = cards[0] + val editCard = cards[2] + + val context = InstrumentationRegistry.getInstrumentation().targetContext + val db = inMemoryDatabaseBuilder( + context, + BaseballCardDatabase::class.java + ).build() + + launch { + db.baseballCardDao.insertBaseballCard(card) + } + + composeTestRule.setContent { + val navController = rememberNavController() + EditScreen( + navController = navController, + db = db, + cardId = card._id!! + ) + } + + enterCardData(editCard) + + launch { + val savedCard = db.baseballCardDao.baseballCards.single() + assertThat(savedCard).isEqualTo(listOf(editCard)) + } + } + } +} diff --git a/app/src/androidTest/java/bbct/android/ui/filter/FilterTest.kt b/app/src/androidTest/java/bbct/android/ui/filter/FilterTest.kt new file mode 100644 index 000000000..4f282b2aa --- /dev/null +++ b/app/src/androidTest/java/bbct/android/ui/filter/FilterTest.kt @@ -0,0 +1,105 @@ +package bbct.android.ui.filter + +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTextInput +import bbct.android.data.cards +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class FilterTest { + @get:Rule + val composeTestRule = createComposeRule() + + @Before + fun setUp() { + composeTestRule.setContent { + FilterScreen( + onApplyFilter = { }, + onClose = { }) + } + } + + @Test + fun testBaseballCardFilterFieldsAreVisible() { + composeTestRule + .onNodeWithText("Brand") + .assertIsDisplayed() + composeTestRule + .onNodeWithText("Year") + .assertIsDisplayed() + composeTestRule + .onNodeWithText("Number") + .assertIsDisplayed() + composeTestRule + .onNodeWithText("Player Name") + .assertIsDisplayed() + composeTestRule + .onNodeWithText("Team") + .assertIsDisplayed() + } + + @Test + fun testFilterByBrand() { + composeTestRule + .onNodeWithText("Brand") + .assertIsDisplayed() + .performTextInput(cards[0].brand) + composeTestRule + .onNodeWithContentDescription("Filter Cards") + .assertIsDisplayed() + .performClick() + } + + @Test + fun testFilterByYear() { + composeTestRule + .onNodeWithText("Year") + .assertIsDisplayed() + .performTextInput(cards[0].year.toString()) + composeTestRule + .onNodeWithContentDescription("Filter Cards") + .assertIsDisplayed() + .performClick() + } + + @Test + fun testFilterByNumber() { + composeTestRule + .onNodeWithText("Number") + .assertIsDisplayed() + .performTextInput(cards[0].number) + composeTestRule + .onNodeWithContentDescription("Filter Cards") + .assertIsDisplayed() + .performClick() + } + + @Test + fun testFilterByPlayerName() { + composeTestRule + .onNodeWithText("Player Name") + .assertIsDisplayed() + .performTextInput(cards[0].playerName) + composeTestRule + .onNodeWithContentDescription("Filter Cards") + .assertIsDisplayed() + .performClick() + } + + @Test + fun testFilterByTeam() { + composeTestRule + .onNodeWithText("Team") + .assertIsDisplayed() + .performTextInput(cards[0].team) + composeTestRule + .onNodeWithContentDescription("Filter Cards") + .assertIsDisplayed() + .performClick() + } +} diff --git a/app/src/androidTest/java/bbct/android/ui/list/BaseballCardListTest.kt b/app/src/androidTest/java/bbct/android/ui/list/BaseballCardListTest.kt new file mode 100644 index 000000000..52635c1e6 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/ui/list/BaseballCardListTest.kt @@ -0,0 +1,67 @@ +package bbct.android.ui.list + +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.navigation.compose.rememberNavController +import bbct.android.rules.CardListTestRule +import bbct.android.test.hasRole +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class BaseballCardListTest { + @get:Rule + val composeTestRule = createComposeRule() + + @get:Rule + val cardListRule = CardListTestRule("three_cards.csv") + + private var cardListState = mutableListOf() + + @Before + fun setup() { + cardListState = cardListRule.cards!! + .map { + SelectedState( + it, + false + ) + } + .toMutableList() + composeTestRule.setContent { + val navController = rememberNavController() + BaseballCardList( + navController = navController, + cards = cardListState, + onCardChanged = { index, card -> cardListState[index] = card }, + ) + } + } + + @Test + fun testDisplaysCards() { + for ((i, card) in cardListRule.cards!!.withIndex()) { + composeTestRule.onAllNodesWithText(card.brand)[i].assertIsDisplayed() + composeTestRule + .onNodeWithText("${card.year}") + .assertIsDisplayed() + composeTestRule + .onNodeWithText(card.number) + .assertIsDisplayed() + composeTestRule + .onNodeWithText(card.playerName) + .assertIsDisplayed() + } + } + + @Test + fun testSelectCard() { + assert(!cardListState[0].selected) + composeTestRule.onAllNodes(hasRole(Role.Checkbox))[0].performClick() + assert(cardListState[0].selected) + } +} diff --git a/app/src/androidTest/java/bbct/android/ui/list/ListScreenTest.kt b/app/src/androidTest/java/bbct/android/ui/list/ListScreenTest.kt new file mode 100644 index 000000000..a3cfc4417 --- /dev/null +++ b/app/src/androidTest/java/bbct/android/ui/list/ListScreenTest.kt @@ -0,0 +1,76 @@ +package bbct.android.ui.list + +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTextInput +import androidx.navigation.compose.rememberNavController +import androidx.room.Room.inMemoryDatabaseBuilder +import androidx.test.platform.app.InstrumentationRegistry +import bbct.android.data.BaseballCardDatabase +import bbct.android.rules.CardDatabaseTestRule +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class ListScreenTest { + val context = InstrumentationRegistry.getInstrumentation().targetContext + val db = inMemoryDatabaseBuilder( + context, + BaseballCardDatabase::class.java + ).build() + + @get:Rule + val composeTestRule = createComposeRule() + + @get:Rule + val cardDatabaseTestRule = CardDatabaseTestRule( + "cards.csv", + db + ) + + @Before + fun setup() { + composeTestRule.setContent { + var navController = rememberNavController() + ListScreen( + navController, + db + ) + } + } + + @Test + fun testFilterCardsByYear() { + composeTestRule + .onNodeWithContentDescription("Filter Cards") + .performClick() + composeTestRule + .onNodeWithText("Filter Cards") + .assertIsDisplayed() + composeTestRule + .onNodeWithText("Year") + .performTextInput("1993") + composeTestRule + .onNodeWithContentDescription("Apply Filter") + .performClick() + + val filteredCards = cardDatabaseTestRule.cards!!.filter { it.year == 1993 } + for (card in filteredCards) { + composeTestRule + .onNodeWithText(card.brand) + .assertIsDisplayed() + composeTestRule + .onNodeWithText(card.year.toString()) + .assertIsDisplayed() + composeTestRule + .onNodeWithText(card.number) + .assertIsDisplayed() + composeTestRule + .onNodeWithText(card.playerName) + .assertIsDisplayed() + } + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..c1d9ff3c0 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/assets/cards.csv b/app/src/main/assets/cards.csv new file mode 100644 index 000000000..9c1befbd2 --- /dev/null +++ b/app/src/main/assets/cards.csv @@ -0,0 +1,8 @@ +Autographed,Condition,Brand,Year,Number,Player Name,Team,Player Position +false,Excellent,Topps,1991,278,Alex Fernandez,White Sox,Pitcher +true,Mint,Topps,1974,175,Bob Stanley,Red Sox,Pitcher +false,Very Good,Topps,1985,201,Vince Coleman,Cardinals,Left Field +true,Gem Mint,TMG,1993,5,Ken Griffey Jr.,All-Star,Center Field +true,Excellent,Upper Deck,1993,18,Dave Hollins,Phillies,Third Base +false,Good,Upper Deck,1990,189,Tom Browning,Reds,Pitcher +false,Near Mint,Topps,1982,121,Ed Lynch,Mets,Pitcher diff --git a/app/src/main/java/bbct/android/MainActivity.kt b/app/src/main/java/bbct/android/MainActivity.kt new file mode 100644 index 000000000..8ba03260f --- /dev/null +++ b/app/src/main/java/bbct/android/MainActivity.kt @@ -0,0 +1,40 @@ +package bbct.android + +import android.os.Bundle +import android.util.Log +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import bbct.android.data.BaseballCardDatabase +import bbct.android.ui.App +import com.google.android.gms.ads.MobileAds +import com.google.firebase.Firebase +import com.google.firebase.crashlytics.crashlytics +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + Firebase.crashlytics.setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG) + + super.onCreate(savedInstanceState) + enableEdgeToEdge() + val db = BaseballCardDatabase.getInstance( + this, + BaseballCardDatabase.DATABASE_NAME + ) + setContent { + App(db) + } + val backgroundScope = CoroutineScope(Dispatchers.IO) + backgroundScope.launch { + // Initialize the Google Mobile Ads SDK on a background thread. + Log.d( + "MainActivity", + "Initializing Google Mobile Ads SDK..." + ) + MobileAds.initialize(this@MainActivity) {} + } + } +} diff --git a/app/src/main/java/bbct/android/data/BaseballCard.kt b/app/src/main/java/bbct/android/data/BaseballCard.kt new file mode 100644 index 000000000..454ea2b46 --- /dev/null +++ b/app/src/main/java/bbct/android/data/BaseballCard.kt @@ -0,0 +1,24 @@ +package bbct.android.data + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "baseball_cards") +data class BaseballCard( + @PrimaryKey + val _id: Long? = null, + val autographed: Boolean, + val condition: String, + val brand: String, + val year: Int, + val number: String, + val value: Int?, + @ColumnInfo(name = "card_count") + val quantity: Int, + @ColumnInfo(name = "player_name") + val playerName: String, + val team: String, + @ColumnInfo(name = "player_position") + val position: String, +) diff --git a/app/src/main/java/bbct/android/data/BaseballCardContract.kt b/app/src/main/java/bbct/android/data/BaseballCardContract.kt new file mode 100644 index 000000000..106a1e666 --- /dev/null +++ b/app/src/main/java/bbct/android/data/BaseballCardContract.kt @@ -0,0 +1,253 @@ +/* + * This file is part of BBCT for Android. + * + * Copyright 2012-14 codeguru + * + * BBCT for Android is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BBCT for Android is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package bbct.android.data + +import android.content.ContentResolver +import android.content.ContentValues +import android.database.Cursor +import android.net.Uri + +object BaseballCardContract { + const val TABLE_NAME: String = "baseball_cards" + + const val AUTHORITY: String = "bbct.android.common.provider" + + const val LITE_AUTHORITY: String = "bbct.android.lite.provider" + + const val PREMIUM_AUTHORITY: String = "bbct.android.premium.provider" + + val CONTENT_URI: Uri = Uri + .Builder() + .scheme("content") + .authority(AUTHORITY) + .path(TABLE_NAME) + .build() + + val LITE_URI: Uri = Uri + .Builder() + .scheme("content") + .authority(LITE_AUTHORITY) + .path(TABLE_NAME) + .build() + + val PREMIUM_URI: Uri = Uri + .Builder() + .scheme("content") + .authority(PREMIUM_AUTHORITY) + .path(TABLE_NAME) + .build() + + const val BASEBALL_CARD_LIST_MIME_TYPE: String = (ContentResolver.CURSOR_DIR_BASE_TYPE + + "/baseball_card") + + const val BASEBALL_CARD_ITEM_MIME_TYPE: String = (ContentResolver.CURSOR_ITEM_BASE_TYPE + + "/baseball_card") + + const val ID_COL_NAME: String = "_id" + + const val AUTOGRAPHED_COL_NAME: String = "autographed" + + const val CONDITION_COL_NAME: String = "condition" + + const val BRAND_COL_NAME: String = "brand" + + const val YEAR_COL_NAME: String = "year" + + const val NUMBER_COL_NAME: String = "number" + + const val VALUE_COL_NAME: String = "value" + + const val COUNT_COL_NAME: String = "card_count" + + const val PLAYER_NAME_COL_NAME: String = "player_name" + + const val TEAM_COL_NAME: String = "team" + + const val PLAYER_POSITION_COL_NAME: String = "player_position" + + val PROJECTION: Array = arrayOf( + ID_COL_NAME, + AUTOGRAPHED_COL_NAME, + CONDITION_COL_NAME, + BRAND_COL_NAME, + YEAR_COL_NAME, + NUMBER_COL_NAME, + VALUE_COL_NAME, + COUNT_COL_NAME, + PLAYER_NAME_COL_NAME, + TEAM_COL_NAME, + PLAYER_POSITION_COL_NAME + ) + + const val INT_SELECTION_FORMAT: String = "%s = ?" + + val YEAR_SELECTION: String = String.format( + INT_SELECTION_FORMAT, + YEAR_COL_NAME + ) + + val NUMBER_SELECTION: String = String.format( + INT_SELECTION_FORMAT, + NUMBER_COL_NAME + ) + + const val STRING_SELECTION_FORMAT: String = "%s LIKE ?" + + val BRAND_SELECTION: Any = String.format( + STRING_SELECTION_FORMAT, + BRAND_COL_NAME + ) + + val PLAYER_NAME_SELECTION: String = String.format( + STRING_SELECTION_FORMAT, + PLAYER_NAME_COL_NAME + ) + + val TEAM_SELECTION: String = String.format( + STRING_SELECTION_FORMAT, + TEAM_COL_NAME + ) + + fun getContentValues(card: BaseballCard): ContentValues { + val cv = ContentValues(7) + cv.put( + AUTOGRAPHED_COL_NAME, + card.autographed + ) + cv.put( + CONDITION_COL_NAME, + card.condition + ) + cv.put( + BRAND_COL_NAME, + card.brand + ) + cv.put( + YEAR_COL_NAME, + card.year + ) + cv.put( + NUMBER_COL_NAME, + card.number + ) + cv.put( + VALUE_COL_NAME, + card.value + ) + cv.put( + COUNT_COL_NAME, + card.quantity + ) + cv.put( + PLAYER_NAME_COL_NAME, + card.playerName + ) + cv.put( + TEAM_COL_NAME, + card.team + ) + cv.put( + PLAYER_POSITION_COL_NAME, + card.position + ) + return cv + } + + fun getUri(packageName: String): Uri { + if (packageName == "bbct.android") { + return LITE_URI + } else if (packageName == "bbct.android.premium") { + return PREMIUM_URI + } + + return CONTENT_URI + } + + fun getBaseballCardFromCursor(cursor: Cursor): BaseballCard { + val id = cursor.getLong( + cursor + .getColumnIndex(ID_COL_NAME) + ) + val autographed = cursor.getInt( + cursor + .getColumnIndex(AUTOGRAPHED_COL_NAME) + ) != 0 + val condition = cursor.getString( + cursor + .getColumnIndex(CONDITION_COL_NAME) + ) + val brand = cursor.getString( + cursor + .getColumnIndex(BRAND_COL_NAME) + ) + val year = cursor.getInt( + cursor + .getColumnIndex(YEAR_COL_NAME) + ) + val number = cursor.getString( + cursor + .getColumnIndex(NUMBER_COL_NAME) + ) + val value = cursor.getInt( + cursor + .getColumnIndex(VALUE_COL_NAME) + ) + val quantity = cursor.getInt( + cursor + .getColumnIndex(COUNT_COL_NAME) + ) + val name = cursor.getString( + cursor + .getColumnIndex(PLAYER_NAME_COL_NAME) + ) + val team = cursor.getString( + cursor + .getColumnIndex(TEAM_COL_NAME) + ) + val position = cursor.getString( + cursor + .getColumnIndex(PLAYER_POSITION_COL_NAME) + ) + + return BaseballCard( + id, + autographed, + condition, + brand, + year, + number, + value, + quantity, + name, + team, + position + ) + } + + fun getAllBaseballCardsFromCursor(cursor: Cursor): List { + val cards: MutableList = ArrayList() + + while (cursor.moveToNext()) { + val card = getBaseballCardFromCursor(cursor) + cards.add(card) + } + + return cards + } +} diff --git a/app/src/main/java/bbct/android/data/BaseballCardCsvFileReader.kt b/app/src/main/java/bbct/android/data/BaseballCardCsvFileReader.kt new file mode 100644 index 000000000..5c16be8f6 --- /dev/null +++ b/app/src/main/java/bbct/android/data/BaseballCardCsvFileReader.kt @@ -0,0 +1,114 @@ +package bbct.android.data + +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStream +import java.io.InputStreamReader +import java.util.ArrayList + +/** + * This class reads baseball card data from an input stream which is formatted + * as comma-separated values. + */ +class BaseballCardCsvFileReader( + input: InputStream, + hasColHeaders: Boolean +) { + private val input: BufferedReader = BufferedReader(InputStreamReader(input)) + + /** + * Create a [BaseballCardCsvFileReader] object which reads baseball + * card data as comma-separated values from the given [InputStream]. + * The input may contain column headers, which will be ignored. + * + * @param input The [InputStream] containing the comma-separated values. + * @param hasColHeaders Whether or not the input contains column headers. + * @throws IOException If an error occurs while reading the input. + */ + init { + if (hasColHeaders) { + this.input.readLine() + } + } + + /** + * Reads baseball card data from the next line of comma-separated values. + * + * @return A [BaseballCard] containing the data from the input stream. + * @throws IOException If an error occurs while reading the input. + */ + @Throws(IOException::class) + fun getNextBaseballCard(): BaseballCard { + val line = this.input.readLine() + val data = line + .split(",".toRegex()) + .dropLastWhile { it.isEmpty() } + .toTypedArray() + val autographed = data[0].toBoolean() + val condition = data[1] + val brand = data[2] + val year = data[3].toInt() + val number = data[4] + val value = 10000 + val count = 1 + val playerName = data[5] + val team = data[6] + val playerPosition = data[7] + + return BaseballCard( + null, + autographed, + condition, + brand, + year, + number, + value, + count, + playerName, + team, + playerPosition + ) + } + + /** + * Determine if the input stream contains more baseball card data. If the + * input stream is ready for an input operation, then this function returns + * `true`. The validity of the data is determined only after + * calling [.getNextBaseballCard] or [ ][.getAllBaseballCards]. + * + * @return `true` if the input stream is ready for an input + * operation; `false`, otherwise. + * @throws IOException If an error occurs while reading the input. + */ + @Throws(IOException::class) + fun hasNextBaseballCard(): Boolean { + return this.input.ready() + } + + /** + * Reads all the baseball card data from the input stream. + * + * @return A list of [BaseballCard] objects containing all of the + * baseball card data from the input stream. + * @throws IOException If an error occurs while reading the input. + */ + @Throws(IOException::class) + fun getAllBaseballCards(): MutableList { + val cards: MutableList = ArrayList() + while (this.hasNextBaseballCard()) { + cards.add(this.getNextBaseballCard()) + } + + return cards + } + + /** + * Close the input stream. + * + * @throws IOException If an error occurs while reading the input. + */ + @Throws(IOException::class) + fun close() { + this.input.close() + } +} diff --git a/app/src/main/java/bbct/android/data/BaseballCardDao.kt b/app/src/main/java/bbct/android/data/BaseballCardDao.kt new file mode 100644 index 000000000..beb767444 --- /dev/null +++ b/app/src/main/java/bbct/android/data/BaseballCardDao.kt @@ -0,0 +1,51 @@ +package bbct.android.data + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query +import androidx.room.Update +import kotlinx.coroutines.flow.Flow + +@Dao +interface BaseballCardDao { + @Insert + suspend fun insertBaseballCard(card: BaseballCard) + + @Update + suspend fun updateBaseballCard(card: BaseballCard) + + @Delete + suspend fun deleteBaseballCards(cards: List) + + @get:Query("SELECT * FROM baseball_cards") + val baseballCards: Flow> + + @Query( + "SELECT * FROM baseball_cards " + + "WHERE brand LIKE :brand " + + " AND (year = :year OR -1 = :year) " + + " AND number LIKE :number " + + " AND player_name LIKE :playerName " + + " AND team LIKE :team" + ) + fun getBaseballCards( + brand: String, + year: Int, + number: String, + playerName: String, + team: String, + ): Flow> + + @Query("SELECT * FROM baseball_cards WHERE _id = :id") + suspend fun getBaseballCard(id: Long): BaseballCard + + @get:Query("SELECT DISTINCT(brand) FROM baseball_cards") + val brands: Flow> + + @get:Query("SELECT DISTINCT(player_name) FROM baseball_cards") + val playerNames: Flow> + + @get:Query("SELECT DISTINCT(team) FROM baseball_cards") + val teams: Flow> +} diff --git a/android/src/main/java/bbct/android/common/database/BaseballCardDatabase.java b/app/src/main/java/bbct/android/data/BaseballCardDatabase.kt similarity index 50% rename from android/src/main/java/bbct/android/common/database/BaseballCardDatabase.java rename to app/src/main/java/bbct/android/data/BaseballCardDatabase.kt index eeceb3549..ec5f5ef1d 100644 --- a/android/src/main/java/bbct/android/common/database/BaseballCardDatabase.java +++ b/app/src/main/java/bbct/android/data/BaseballCardDatabase.kt @@ -1,36 +1,53 @@ -package bbct.android.common.database; +package bbct.android.data -import android.content.Context; +import android.content.Context +import androidx.room.AutoMigration +import androidx.room.Database +import androidx.room.Room.databaseBuilder +import androidx.room.RoomDatabase +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase -import androidx.annotation.NonNull; -import androidx.room.Database; -import androidx.room.Room; -import androidx.room.RoomDatabase; -import androidx.room.migration.Migration; -import androidx.sqlite.db.SupportSQLiteDatabase; +const val ORIGINAL_SCHEMA = 1 +const val BAD_TEAM_SCHEMA = 2 +const val TEAM_SCHEMA = 3 +const val AUTO_AND_CONDITION_SCHEMA = 4 +const val ROOM_SCHEMA = 5 +const val ALPHA_NUMERIC_SCHEMA = 6 +const val NOT_NULL_SCHEMA = 7 -import bbct.android.common.provider.BaseballCardContract; -import bbct.android.common.provider.BaseballCardSQLHelper; +@Database( + version = NOT_NULL_SCHEMA, + entities = [BaseballCard::class], + autoMigrations = [ + AutoMigration( + from = ALPHA_NUMERIC_SCHEMA, + to = NOT_NULL_SCHEMA + ) + ] +) +abstract class BaseballCardDatabase : RoomDatabase() { + abstract val baseballCardDao: BaseballCardDao -@Database(version = BaseballCardSQLHelper.ALPHA_NUMERIC_SCHEMA, entities = {BaseballCard.class}) -public abstract class BaseballCardDatabase extends RoomDatabase { - private static BaseballCardDatabase instance = null; - private static final String DATABASE_NAME = "bbct.db"; + companion object { + internal const val DATABASE_NAME = "bbct.db" + internal const val TEST_DATABASE_NAME = "bbct_test.db" - private static final Migration MIGRATION_4_5 = new Migration( - BaseballCardSQLHelper.AUTO_AND_CONDITION_SCHEMA, - BaseballCardSQLHelper.ROOM_SCHEMA) { - @Override - public void migrate(@NonNull SupportSQLiteDatabase database) { + private val MIGRATION_4_5: Migration = object : Migration( + AUTO_AND_CONDITION_SCHEMA, + ROOM_SCHEMA + ) { + override fun migrate(db: SupportSQLiteDatabase) { + } } - }; - - private static final Migration MIGRATION_5_6 = new Migration( - BaseballCardSQLHelper.ROOM_SCHEMA, BaseballCardSQLHelper.ALPHA_NUMERIC_SCHEMA) { - @Override - public void migrate(SupportSQLiteDatabase database) { - String temp_table_name = BaseballCardContract.TABLE_NAME + "_new"; - database.execSQL("CREATE TABLE IF NOT EXISTS " + private val MIGRATION_5_6: Migration = object : Migration( + ROOM_SCHEMA, + ALPHA_NUMERIC_SCHEMA + ) { + override fun migrate(db: SupportSQLiteDatabase) { + val temp_table_name = BaseballCardContract.TABLE_NAME + "_new" + db.execSQL( + "CREATE TABLE IF NOT EXISTS " + temp_table_name + "(" + BaseballCardContract.ID_COL_NAME + " INTEGER PRIMARY KEY AUTOINCREMENT," @@ -46,9 +63,10 @@ public void migrate(SupportSQLiteDatabase database) { + BaseballCardContract.CONDITION_COL_NAME + " TEXT," + "UNIQUE (" + BaseballCardContract.BRAND_COL_NAME + ", " + BaseballCardContract.YEAR_COL_NAME + ", " - + BaseballCardContract.NUMBER_COL_NAME + "))"); - database.execSQL( - "INSERT INTO " + temp_table_name + " (" + + BaseballCardContract.NUMBER_COL_NAME + "))" + ) + db.execSQL( + "INSERT INTO " + temp_table_name + " (" + BaseballCardContract.ID_COL_NAME + ", " + BaseballCardContract.BRAND_COL_NAME + ", " + BaseballCardContract.YEAR_COL_NAME + ", " @@ -72,27 +90,37 @@ public void migrate(SupportSQLiteDatabase database) { + BaseballCardContract.PLAYER_POSITION_COL_NAME + ", " + BaseballCardContract.AUTOGRAPHED_COL_NAME + ", " + BaseballCardContract.CONDITION_COL_NAME - + " FROM " + BaseballCardContract.TABLE_NAME); + + " FROM " + BaseballCardContract.TABLE_NAME + ) - database.execSQL("DROP TABLE " + BaseballCardContract.TABLE_NAME); - database.execSQL( - "ALTER TABLE " + temp_table_name + " RENAME TO " + BaseballCardContract.TABLE_NAME - ); + db.execSQL("DROP TABLE " + BaseballCardContract.TABLE_NAME) + db.execSQL( + "ALTER TABLE " + temp_table_name + " RENAME TO " + BaseballCardContract.TABLE_NAME + ) + } } - }; + private var instances: MutableMap = HashMap() - public static BaseballCardDatabase getInstance(Context context) { - if (instance == null) { - instance = Room.databaseBuilder( - context.getApplicationContext(), - BaseballCardDatabase.class, - DATABASE_NAME) - .addMigrations(MIGRATION_4_5, MIGRATION_5_6) - .build(); - } + fun getInstance( + context: Context, + dbName: String, + ): BaseballCardDatabase { + var instance = instances[dbName] + if (instance == null) { + instance = databaseBuilder( + context.applicationContext, + BaseballCardDatabase::class.java, + dbName + ) + .addMigrations( + MIGRATION_4_5, + MIGRATION_5_6 + ) + .build() + instances[dbName] = instance + } - return instance; + return instance + } } - - abstract public BaseballCardDao getBaseballCardDao(); } diff --git a/app/src/main/java/bbct/android/ui/AboutScreen.kt b/app/src/main/java/bbct/android/ui/AboutScreen.kt new file mode 100644 index 000000000..61822809c --- /dev/null +++ b/app/src/main/java/bbct/android/ui/AboutScreen.kt @@ -0,0 +1,86 @@ +package bbct.android.ui + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import bbct.android.BuildConfig +import bbct.android.R + +@Composable +fun AboutScreen( + navController: NavController, +) { + Scaffold( + topBar = { + TopBar( + title = { + Text( + text = stringResource( + id = R.string.bbct_title, + stringResource(id = R.string.about_title) + ) + ) + }, + navigationIcon = { BackButton(navController = navController) }) + }, + modifier = Modifier.fillMaxSize() + ) { innerPadding -> + About(modifier = Modifier.padding(innerPadding)) + } +} + +@Composable +fun About(modifier: Modifier = Modifier) { + //https://stackoverflow.com/a/69549929/2781626 + Column(modifier = modifier.padding(12.dp)) { + Row { + Column { + Image( + painter = painterResource(id = R.drawable.baseball), + contentDescription = stringResource( + id = R.string.app_name + ), + ) + } + Column( + Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(id = R.string.app_name), + fontSize = 26.sp + ) + Text( + text = stringResource( + id = R.string.version_text, + BuildConfig.VERSION_NAME + ) + ) + } + } + Spacer(modifier = Modifier.padding(10.dp)) + Text(text = stringResource(id = R.string.copyright)) + Spacer(modifier = Modifier.padding(10.dp)) + Text(text = stringResource(id = R.string.about)) + Spacer(modifier = Modifier.padding(10.dp)) + Text(text = stringResource(id = R.string.email)) + Spacer(modifier = Modifier.padding(10.dp)) + Text(text = stringResource(id = R.string.website)) + Spacer(modifier = Modifier.padding(10.dp)) + Text(text = stringResource(id = R.string.license)) + } +} diff --git a/app/src/main/java/bbct/android/ui/App.kt b/app/src/main/java/bbct/android/ui/App.kt new file mode 100644 index 000000000..1695f7bad --- /dev/null +++ b/app/src/main/java/bbct/android/ui/App.kt @@ -0,0 +1,54 @@ +package bbct.android.ui + +import androidx.compose.runtime.Composable +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import androidx.navigation.toRoute +import bbct.android.data.BaseballCardDatabase +import bbct.android.ui.details.CreateScreen +import bbct.android.ui.details.EditScreen +import bbct.android.ui.list.ListScreen +import bbct.android.ui.navigation.AboutDestination +import bbct.android.ui.navigation.BaseballCardCreateDestination +import bbct.android.ui.navigation.BaseballCardEditDestination +import bbct.android.ui.navigation.BaseballCardListDestination +import bbct.android.ui.theme.AppTheme + +@Composable +fun App(db: BaseballCardDatabase) { + val navController = rememberNavController() + + AppTheme { + NavHost( + navController = navController, + startDestination = BaseballCardListDestination, + ) { + composable { + ListScreen( + navController, + db, + ) + } + composable { + CreateScreen( + navController, + db, + ) + } + composable { backStackEntry -> + var destination: BaseballCardEditDestination = backStackEntry.toRoute() + EditScreen( + navController, + db, + destination.cardId, + ) + } + composable { + AboutScreen( + navController + ) + } + } + } +} diff --git a/app/src/main/java/bbct/android/ui/TopBar.kt b/app/src/main/java/bbct/android/ui/TopBar.kt new file mode 100644 index 000000000..2086c38fa --- /dev/null +++ b/app/src/main/java/bbct/android/ui/TopBar.kt @@ -0,0 +1,227 @@ +package bbct.android.ui + +import android.content.Context +import android.util.Log +import androidx.compose.animation.Crossfade +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Clear +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.navigation.NavController +import bbct.android.BuildConfig +import bbct.android.R +import bbct.android.data.BaseballCardCsvFileReader +import bbct.android.data.BaseballCardDatabase +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +@Composable +@OptIn(ExperimentalMaterial3Api::class) +fun TopBar( + navigationIcon: @Composable () -> Unit = {}, + title: @Composable () -> Unit, + actions: @Composable RowScope.() -> Unit = {}, + windowInsets: WindowInsets = TopAppBarDefaults.windowInsets +) { + TopAppBar( + title = title, + actions = actions, + navigationIcon = navigationIcon, + windowInsets = windowInsets, + ) +} + +@Composable +fun BackButton(navController: NavController) { + IconButton(onClick = { navController.popBackStack() }) { + Icon( + Icons.AutoMirrored.Default.ArrowBack, + contentDescription = stringResource(id = R.string.back) + ) + } +} + +@Composable +fun CloseButton(onClose: () -> Unit) { + IconButton(onClick = onClose) { + Icon( + Icons.Default.Close, + contentDescription = stringResource(id = R.string.close), + ) + } +} + +@Composable +fun ListMenu( + isAnySelected: Boolean, + isFiltered: Boolean, + onFilterCards: () -> Unit, + onClearFilter: () -> Unit, + onAbout: () -> Unit, + onDeleteCards: () -> Unit, + onSelectAll: () -> Unit, +) { + Crossfade( + isAnySelected, + label = "SelectedCrossfade" + ) { target -> + Row { + if (target) { + SelectedMenu( + onDeleteCards = onDeleteCards, + onSelectAll = onSelectAll, + ) + } else { + MainMenu( + isFiltered = isFiltered, + onFilterCards = onFilterCards, + onAbout = onAbout, + onClearFilter = onClearFilter, + ) + } + } + } +} + +@Composable +fun MainMenu( + isFiltered: Boolean, + onFilterCards: () -> Unit, + onClearFilter: () -> Unit, + onAbout: () -> Unit, +) { + Crossfade( + isFiltered, + label = "FilteredCrossfade" + ) { + if (it) { + ClearFilterButton(onClearFilter) + } else { + FilterCardsButton(onFilterCards) + } + } + OverflowMenu(onAbout) +} + +@Composable +private fun FilterCardsButton(onFilterCards: () -> Unit) { + IconButton(onClick = onFilterCards) { + Icon( + Icons.Default.Search, + contentDescription = stringResource(id = R.string.filter_menu) + ) + } +} + +@Composable +private fun ClearFilterButton(onClearFilter: () -> Unit) { + IconButton(onClick = onClearFilter) { + Icon( + Icons.Default.Clear, + contentDescription = stringResource(id = R.string.clear_filter_menu) + ) + } +} + +@Composable +fun OverflowMenu(onAbout: () -> Unit) { + var showMenu by remember { mutableStateOf(false) } + + IconButton(onClick = { showMenu = !showMenu }) { + Icon( + Icons.Default.MoreVert, + contentDescription = stringResource(id = R.string.more) + ) + } + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false } + ) { + if (BuildConfig.DEBUG) { + val context = LocalContext.current + DropdownMenuItem( + text = { Text(text = stringResource(id = R.string.add_cards)) }, + onClick = { addCards(context) } + ) + } + + DropdownMenuItem( + text = { Text(text = stringResource(id = R.string.about_menu)) }, + onClick = onAbout + ) + } +} + +@Composable +fun SelectedMenu( + onDeleteCards: () -> Unit, + onSelectAll: () -> Unit, +) { + DeleteCardsButton(onDeleteCards) + SelectAllButton(onSelectAll) +} + +@Composable +private fun DeleteCardsButton(onDeleteCards: () -> Unit) { + IconButton(onClick = onDeleteCards) { + Icon( + Icons.Default.Delete, + contentDescription = stringResource(id = R.string.delete_menu) + ) + } +} + +@Composable +private fun SelectAllButton(onSelectAll: () -> Unit) { + IconButton(onClick = onSelectAll) { + Icon( + painterResource(id = R.drawable.select_all), + contentDescription = stringResource(id = R.string.select_all_menu) + ) + } +} + +fun addCards(context: Context) { + val db = BaseballCardDatabase.getInstance( + context = context, + dbName = "bbct.db" + ) + val csvReader = BaseballCardCsvFileReader( + context.assets.open("cards.csv"), + hasColHeaders = true + ) + + CoroutineScope(Dispatchers.IO).launch { + while (csvReader.hasNextBaseballCard()) { + val card = csvReader.getNextBaseballCard() + Log.d( + "Add Cards Menu", + "Adding card: $card" + ) + db.baseballCardDao.insertBaseballCard(card) + } + } +} diff --git a/app/src/main/java/bbct/android/ui/components/AutoComplete.kt b/app/src/main/java/bbct/android/ui/components/AutoComplete.kt new file mode 100644 index 000000000..09504d13b --- /dev/null +++ b/app/src/main/java/bbct/android/ui/components/AutoComplete.kt @@ -0,0 +1,68 @@ +package bbct.android.ui.components + +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AutoComplete( + label: @Composable () -> Unit, + options: List, + value: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier, + keyboardOptions: KeyboardOptions = KeyboardOptions.Default, + isError: Boolean = false, +) { + var expanded by remember { mutableStateOf(false) } + var filteredOpts by remember { mutableStateOf(options) } + + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { expanded = !expanded }) { + TextField( + label = label, + value = value, + onValueChange = { + onValueChange(it) + filteredOpts = options.filter { option -> + option + .lowercase() + .contains(it.lowercase()) + } + expanded = true + }, + isError = isError, + colors = ExposedDropdownMenuDefaults.textFieldColors(), + modifier = modifier.menuAnchor(), + keyboardOptions = keyboardOptions, + ) + if (!filteredOpts.isEmpty()) { + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false }) { + filteredOpts.forEach { option -> + DropdownMenuItem( + text = { Text(text = option) }, + onClick = { + onValueChange(option) + filteredOpts = emptyList() + expanded = false + } + ) + } + } + } + } +} diff --git a/app/src/main/java/bbct/android/ui/components/Select.kt b/app/src/main/java/bbct/android/ui/components/Select.kt new file mode 100644 index 000000000..4ae8b69fd --- /dev/null +++ b/app/src/main/java/bbct/android/ui/components/Select.kt @@ -0,0 +1,59 @@ +package bbct.android.ui.components + +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun Select( + label: @Composable () -> Unit, + options: Array, + selected: String, + onSelectedChange: (String) -> Unit, + modifier: Modifier = Modifier, + isError: Boolean = false, +) { + var expanded by remember { mutableStateOf(false) } + + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { expanded = !expanded }) { + TextField( + label = label, + readOnly = true, + value = selected, + onValueChange = { /* Do nothing */ }, + isError = isError, + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon( + expanded = expanded + ) + }, + colors = ExposedDropdownMenuDefaults.textFieldColors(), + modifier = modifier.menuAnchor() + ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false }) { + options.forEach { option -> + DropdownMenuItem( + text = { Text(text = option) }, + onClick = { + onSelectedChange(option) + expanded = false + } + ) + } + } + } +} diff --git a/app/src/main/java/bbct/android/ui/details/DetailsScreen.kt b/app/src/main/java/bbct/android/ui/details/DetailsScreen.kt new file mode 100644 index 000000000..9d2199641 --- /dev/null +++ b/app/src/main/java/bbct/android/ui/details/DetailsScreen.kt @@ -0,0 +1,373 @@ +package bbct.android.ui.details + +import androidx.compose.foundation.focusGroup +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check +import androidx.compose.material3.Checkbox +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringArrayResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavController +import bbct.android.R +import bbct.android.data.BaseballCardDatabase +import bbct.android.ui.BackButton +import bbct.android.ui.OverflowMenu +import bbct.android.ui.TopBar +import bbct.android.ui.components.AutoComplete +import bbct.android.ui.components.Select +import bbct.android.ui.navigation.AboutDestination +import kotlinx.coroutines.launch + +@Composable +fun CreateScreen( + navController: NavController, + db: BaseballCardDatabase, +) { + val viewModel: DetailsViewModel = viewModel() + val scope = rememberCoroutineScope() + val snackbarHostState = remember { SnackbarHostState() } + + Scaffold( + snackbarHost = { + SnackbarHost(hostState = snackbarHostState) + }, + topBar = { + TopBar( + navigationIcon = { BackButton(navController = navController) }, + title = { + Text( + stringResource( + id = R.string.bbct_title, + stringResource(id = R.string.create_card_title) + ) + ) + }, + actions = { OverflowMenu(onAbout = { navController.navigate(AboutDestination) }) }, + ) + }, + floatingActionButton = { + CreateCardButton( + db, + viewModel.detailsState, + viewModel.errors, + viewModel::validate, + onSuccess = { scope.launch { snackbarHostState.showSnackbar("Card created") } }, + onFailure = { scope.launch { snackbarHostState.showSnackbar("Failed to create card") } }, + ) + }, + modifier = Modifier + .fillMaxSize() + .imePadding() + ) { innerPadding -> + Details( + state = viewModel.detailsState, + db = db, + errors = viewModel.errors, + onValidate = viewModel::validate, + modifier = Modifier.padding(innerPadding), + ) + } +} + +@Composable +fun EditScreen( + navController: NavController, + db: BaseballCardDatabase, + cardId: Long, +) { + val viewModel: DetailsViewModel = viewModel() + + LaunchedEffect(cardId) { + val card = db.baseballCardDao.getBaseballCard(cardId) + viewModel.detailsState.value = DetailsState(card) + } + + Scaffold( + topBar = { + TopBar( + navigationIcon = { BackButton(navController = navController) }, + title = { + Text( + stringResource( + id = R.string.bbct_title, + stringResource(id = R.string.edit_card_title) + ) + ) + }, + actions = { OverflowMenu(onAbout = { navController.navigate(AboutDestination) }) }, + ) + }, + floatingActionButton = { + UpdateCardButton( + navController, + db, + viewModel.detailsState, + viewModel.errors, + viewModel::validate, + ) + }, + modifier = Modifier + .fillMaxSize() + .imePadding() + ) { innerPadding -> + Details( + state = viewModel.detailsState, + db = db, + errors = viewModel.errors, + onValidate = viewModel::validate, + modifier = Modifier.padding(innerPadding), + ) + } +} + +@Composable +fun Details( + state: MutableState, + db: BaseballCardDatabase, + errors: MutableState, + onValidate: () -> Unit, + modifier: Modifier = Modifier, +) { + val brands = db.baseballCardDao.brands.collectAsState(initial = emptyList()) + var playerNames = db.baseballCardDao.playerNames.collectAsState(initial = emptyList()) + var teams = db.baseballCardDao.teams.collectAsState(initial = emptyList()) + + val conditions = stringArrayResource(R.array.condition) + val positions = stringArrayResource(R.array.positions) + + val scrollState = rememberScrollState() + val textFieldModifier = Modifier.fillMaxWidth() + + Column( + modifier = modifier + .focusGroup() + .padding(12.dp) + .verticalScroll(scrollState), + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Checkbox( + checked = state.value.autographed, + onCheckedChange = { state.value = state.value.copy(autographed = it) }, + ) + Text(text = stringResource(id = R.string.autographed)) + } + Select( + label = { Text(stringResource(id = R.string.condition)) }, + options = conditions, + selected = state.value.condition, + onSelectedChange = { + state.value = state.value.copy(condition = it) + onValidate() + }, + isError = !errors.value.brand.isValid, + modifier = textFieldModifier, + ) + AutoComplete( + label = { Text(text = stringResource(id = R.string.brand)) }, + options = brands.value, + value = state.value.brand, + onValueChange = { + state.value = state.value.copy(brand = it) + onValidate() + }, + isError = !errors.value.brand.isValid, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + modifier = textFieldModifier, + ) + TextField( + label = { Text(text = stringResource(id = R.string.year)) }, + value = state.value.year, + onValueChange = { + state.value = state.value.copy(year = it) + onValidate() + }, + isError = !errors.value.year.isValid, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next, + keyboardType = KeyboardType.Number + ), + modifier = textFieldModifier, + ) + TextField( + label = { Text(text = stringResource(id = R.string.number)) }, + value = state.value.number, + onValueChange = { + state.value = state.value.copy(number = it) + onValidate() + }, + isError = !errors.value.number.isValid, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + modifier = textFieldModifier, + ) + TextField( + label = { Text(text = stringResource(id = R.string.value)) }, + value = state.value.value ?: "", + onValueChange = { + state.value = state.value.copy(value = it) + onValidate() + }, + isError = !errors.value.value.isValid, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next, + keyboardType = KeyboardType.Number + ), + modifier = textFieldModifier, + ) + TextField( + label = { Text(text = stringResource(id = R.string.quantity)) }, + value = state.value.quantity, + onValueChange = { + state.value = state.value.copy(quantity = it) + onValidate() + }, + isError = !errors.value.quantity.isValid, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next, + keyboardType = KeyboardType.Number + ), + modifier = textFieldModifier, + ) + AutoComplete( + label = { Text(text = stringResource(id = R.string.player_name)) }, + options = playerNames.value, + value = state.value.playerName, + onValueChange = { + state.value = state.value.copy(playerName = it) + onValidate() + }, + isError = !errors.value.playerName.isValid, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + modifier = textFieldModifier, + ) + AutoComplete( + label = { Text(text = stringResource(id = R.string.team)) }, + options = teams.value, + value = state.value.team, + onValueChange = { + state.value = state.value.copy(team = it) + onValidate() + }, + isError = !errors.value.team.isValid, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + modifier = textFieldModifier, + ) + Select( + label = { Text(stringResource(id = R.string.player_position)) }, + options = positions, + selected = state.value.position, + onSelectedChange = { + state.value = state.value.copy(position = it) + onValidate() + }, + isError = !errors.value.brand.isValid, + modifier = textFieldModifier, + ) + } +} + +@Composable +fun CreateCardButton( + db: BaseballCardDatabase, + state: MutableState, + errors: MutableState, + onValidate: () -> Unit, + onSuccess: () -> Unit, + onFailure: () -> Unit, +) { + val scope = rememberCoroutineScope() + FloatingActionButton(onClick = { + onValidate() + if (errors.value.isValid) { + scope.launch { + createCard( + db, + state.value, + onSuccess, + onFailure, + ) + state.value = DetailsState() + } + } + }) { + Icon( + Icons.Default.Check, + contentDescription = stringResource(id = R.string.save_menu) + ) + } +} + +suspend fun createCard( + db: BaseballCardDatabase, + cardState: DetailsState, + onSuccess: () -> Unit, + onFailure: () -> Unit, +) { + try { + db.baseballCardDao.insertBaseballCard(cardState.toBaseballCard()) + onSuccess() + } catch (e: Exception) { + onFailure() + } +} + +@Composable +fun UpdateCardButton( + navController: NavController, + db: BaseballCardDatabase, + state: MutableState, + errors: MutableState, + onValidate: () -> Unit, +) { + val scope = rememberCoroutineScope() + FloatingActionButton(onClick = { + onValidate() + if (errors.value.isValid) { + scope.launch { + updateCard( + db, + state.value + ) + navController.popBackStack() + } + } + }) { + Icon( + Icons.Default.Check, + contentDescription = stringResource(id = R.string.save_menu) + ) + } +} + +suspend fun updateCard( + db: BaseballCardDatabase, + cardState: DetailsState, +) { + db.baseballCardDao.updateBaseballCard(cardState.toBaseballCard()) +} diff --git a/app/src/main/java/bbct/android/ui/details/DetailsState.kt b/app/src/main/java/bbct/android/ui/details/DetailsState.kt new file mode 100644 index 000000000..bcf9f191b --- /dev/null +++ b/app/src/main/java/bbct/android/ui/details/DetailsState.kt @@ -0,0 +1,47 @@ +package bbct.android.ui.details + +import bbct.android.data.BaseballCard + +data class DetailsState( + var id: Long? = null, + var autographed: Boolean = false, + var condition: String = "", + var brand: String = "", + var year: String = "", + var number: String = "", + var value: String? = null, + var quantity: String = "", + var playerName: String = "", + var team: String = "", + var position: String = "", +) { + constructor(card: BaseballCard) : this( + card._id, + card.autographed, + card.condition, + card.brand, + card.year.toString(), + card.number, + if (card.value == null) null else (card.value / 100.0).toString(), + card.quantity.toString(), + card.playerName, + card.team, + card.position + ) + + fun toBaseballCard(): BaseballCard { + return BaseballCard( + _id = id, + autographed = autographed, + condition = condition, + brand = brand, + year = year.toInt(), + number = number, + value = if (value == null) null else (value!!.toDouble() * 100).toInt(), + quantity = quantity.toInt(), + playerName = playerName, + team = team, + position = position + ) + } +} diff --git a/app/src/main/java/bbct/android/ui/details/DetailsViewModel.kt b/app/src/main/java/bbct/android/ui/details/DetailsViewModel.kt new file mode 100644 index 000000000..3ddc8e2b9 --- /dev/null +++ b/app/src/main/java/bbct/android/ui/details/DetailsViewModel.kt @@ -0,0 +1,90 @@ +package bbct.android.ui.details + +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel + +data class FormFieldError(var message: String? = null, var isValid: Boolean = true) + +data class DetailsErrors( + var condition: FormFieldError = FormFieldError(), + var brand: FormFieldError = FormFieldError(), + var year: FormFieldError = FormFieldError(), + var number: FormFieldError = FormFieldError(), + var value: FormFieldError = FormFieldError(), + var quantity: FormFieldError = FormFieldError(), + var playerName: FormFieldError = FormFieldError(), + var team: FormFieldError = FormFieldError(), + var position: FormFieldError = FormFieldError(), +) { + val isValid: Boolean + get() { + return condition.isValid && brand.isValid && year.isValid && number.isValid && value.isValid && quantity.isValid && playerName.isValid && team.isValid && position.isValid + } +} + +class DetailsViewModel : ViewModel() { + var detailsState = mutableStateOf(DetailsState()) + var errors = mutableStateOf(DetailsErrors()) + + fun validate() { + val baseballCard = detailsState.value + val errors = DetailsErrors() + + if (baseballCard.condition.isBlank()) { + errors.condition = FormFieldError("Condition is required") + errors.condition.isValid = false + } + + if (baseballCard.brand.isBlank()) { + errors.brand = FormFieldError("Brand is required") + errors.brand.isValid = false + } + + if (baseballCard.year.isBlank()) { + errors.year = FormFieldError("Year is required") + errors.year.isValid = false + } + + if (baseballCard.year.toIntOrNull() == null) { + errors.year = FormFieldError("Year must be a number") + errors.year.isValid = false + } + + if (baseballCard.number.isBlank()) { + errors.number = FormFieldError("Number is required") + errors.number.isValid = false + } + + if (baseballCard.value != null && baseballCard.value?.toDoubleOrNull() == null) { + errors.value = FormFieldError("Value must be a number") + errors.value.isValid = false + } + + if (baseballCard.quantity.isBlank()) { + errors.quantity = FormFieldError("Quantity is required") + errors.quantity.isValid = false + } + + if (baseballCard.quantity.toIntOrNull() == null) { + errors.quantity = FormFieldError("Quantity must be a number") + errors.quantity.isValid = false + } + + if (baseballCard.playerName.isBlank()) { + errors.playerName = FormFieldError("Player name is required") + errors.playerName.isValid = false + } + + if (baseballCard.team.isBlank()) { + errors.team = FormFieldError("Team is required") + errors.team.isValid = false + } + + if (baseballCard.position.isBlank()) { + errors.position = FormFieldError("Position is required") + errors.position.isValid = false + } + + this.errors.value = errors + } +} diff --git a/app/src/main/java/bbct/android/ui/filter/FilterScreen.kt b/app/src/main/java/bbct/android/ui/filter/FilterScreen.kt new file mode 100644 index 000000000..13395ded7 --- /dev/null +++ b/app/src/main/java/bbct/android/ui/filter/FilterScreen.kt @@ -0,0 +1,120 @@ +package bbct.android.ui.filter + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import bbct.android.R +import bbct.android.ui.CloseButton +import bbct.android.ui.TopBar + +@Composable +fun FilterScreen( + onApplyFilter: (FilterState) -> Unit, + onClose: () -> Unit, +) { + var filterState = remember { mutableStateOf(FilterState()) } + Scaffold( + topBar = { + TopBar( + navigationIcon = { CloseButton(onClose) }, + title = { + Text( + stringResource( + id = R.string.filter_cards_title, + ) + ) + }, + actions = { ApplyFilterButton(onApplyFilter = { onApplyFilter(filterState.value) }) }, + windowInsets = WindowInsets(0.dp), + ) + }, + modifier = Modifier + .imePadding() + ) { innerPadding -> + Filter( + filterState, + modifier = Modifier.padding(innerPadding) + ) + } +} + +@Composable +fun Filter( + filterState: MutableState, + modifier: Modifier = Modifier, +) { + val textFieldModifier = Modifier.fillMaxWidth() + + Column(modifier = modifier.padding(12.dp)) { + TextField( + label = { Text(text = stringResource(id = R.string.brand)) }, + value = filterState.value.brand, + onValueChange = { filterState.value = filterState.value.copy(brand = it) }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + modifier = textFieldModifier, + ) + TextField( + label = { Text(text = stringResource(id = R.string.year)) }, + value = if (filterState.value.year == -1) "" else filterState.value.year.toString(), + onValueChange = { + val year = if (it == "") -1 else it.toInt() + filterState.value = filterState.value.copy(year = year) + }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next, + keyboardType = KeyboardType.Number + ), + modifier = textFieldModifier, + ) + TextField( + label = { Text(text = stringResource(id = R.string.number)) }, + value = filterState.value.number, + onValueChange = { filterState.value = filterState.value.copy(number = it) }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + modifier = textFieldModifier, + ) + TextField( + label = { Text(text = stringResource(id = R.string.player_name)) }, + value = filterState.value.playerName, + onValueChange = { filterState.value = filterState.value.copy(playerName = it) }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + modifier = textFieldModifier, + ) + TextField( + label = { Text(text = stringResource(id = R.string.team)) }, + value = filterState.value.team, + onValueChange = { filterState.value = filterState.value.copy(team = it) }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + modifier = textFieldModifier, + ) + } +} + +@Composable +fun ApplyFilterButton(onApplyFilter: () -> Unit) { + IconButton(onClick = onApplyFilter) { + Icon( + Icons.Default.Check, + contentDescription = stringResource(id = R.string.filter_menu) + ) + } +} diff --git a/app/src/main/java/bbct/android/ui/filter/FilterState.kt b/app/src/main/java/bbct/android/ui/filter/FilterState.kt new file mode 100644 index 000000000..a45631784 --- /dev/null +++ b/app/src/main/java/bbct/android/ui/filter/FilterState.kt @@ -0,0 +1,12 @@ +package bbct.android.ui.filter + +import kotlinx.serialization.Serializable + +@Serializable +data class FilterState( + var brand: String = "", + var year: Int = -1, + var number: String = "", + var playerName: String = "", + var team: String = "", +) diff --git a/app/src/main/java/bbct/android/ui/filter/FilterViewModel.kt b/app/src/main/java/bbct/android/ui/filter/FilterViewModel.kt new file mode 100644 index 000000000..14540754e --- /dev/null +++ b/app/src/main/java/bbct/android/ui/filter/FilterViewModel.kt @@ -0,0 +1,10 @@ +package bbct.android.ui.filter + +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel + +class FilterViewModel : ViewModel() { + val filterState: MutableState = + mutableStateOf(FilterState()) +} diff --git a/app/src/main/java/bbct/android/ui/list/ListScreen.kt b/app/src/main/java/bbct/android/ui/list/ListScreen.kt new file mode 100644 index 000000000..01f64333d --- /dev/null +++ b/app/src/main/java/bbct/android/ui/list/ListScreen.kt @@ -0,0 +1,250 @@ +package bbct.android.ui.list + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.Checkbox +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshots.SnapshotStateList +import androidx.compose.runtime.toMutableStateList +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.viewinterop.AndroidView +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavController +import bbct.android.BuildConfig +import bbct.android.R +import bbct.android.data.BaseballCard +import bbct.android.data.BaseballCardDatabase +import bbct.android.ui.ListMenu +import bbct.android.ui.TopBar +import bbct.android.ui.filter.FilterScreen +import bbct.android.ui.filter.FilterState +import bbct.android.ui.navigation.AboutDestination +import bbct.android.ui.navigation.BaseballCardCreateDestination +import bbct.android.ui.navigation.BaseballCardEditDestination +import com.google.android.gms.ads.AdRequest +import com.google.android.gms.ads.AdSize +import com.google.android.gms.ads.AdView +import kotlinx.coroutines.launch + +data class SelectedState( + var card: BaseballCard, + var selected: Boolean, +) + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ListScreen( + navController: NavController, + db: BaseballCardDatabase, +) { + val scope = rememberCoroutineScope() + val viewModel: ListViewModel = + viewModel(factory = ListViewModelFactory(db.baseballCardDao)) + val cards by viewModel.baseballCards.collectAsStateWithLifecycle(initialValue = emptyList()) + val stateList by remember { + derivedStateOf { + cards + .map { card -> + SelectedState( + card, + false + ) + } + .toMutableStateList() + } + } + val isAnySelected by remember { + derivedStateOf { + stateList.any { it.selected } + } + } + val sheetState = rememberModalBottomSheetState() + var showFilterBottomSheet by remember { mutableStateOf(false) } + + Scaffold( + topBar = { + TopBar( + title = { Text(stringResource(id = R.string.app_name)) }, + actions = { + ListMenu( + isAnySelected = isAnySelected, + isFiltered = viewModel.isFiltered.value, + onFilterCards = { showFilterBottomSheet = true }, + onClearFilter = { viewModel.applyFilter(FilterState()) }, + onAbout = { navController.navigate(AboutDestination) }, + onDeleteCards = { + scope.launch { + deleteCards( + db, + stateList + ) + } + }, + onSelectAll = { selectAll(stateList) }, + ) + } + ) + }, + floatingActionButton = { AddCardButton(navController) }, + modifier = Modifier.fillMaxSize() + ) { innerPadding -> + Column(modifier = Modifier.padding(innerPadding)) { + @Suppress("KotlinConstantConditions") + if (BuildConfig.APPLICATION_ID == "bbct.android") { + AdBanner() + } + + BaseballCardList( + navController = navController, + cards = stateList, + onCardChanged = { index, card -> stateList[index] = card }, + ) + + if (showFilterBottomSheet) { + ModalBottomSheet( + onDismissRequest = { showFilterBottomSheet = false }, + sheetState = sheetState + ) { + FilterScreen( + onApplyFilter = { filter -> + viewModel.applyFilter(filter) + showFilterBottomSheet = false + }, + onClose = { showFilterBottomSheet = false } + ) + } + } + } + } +} + +@Composable +private fun AdBanner(modifier: Modifier = Modifier) { + AndroidView( + modifier = modifier.fillMaxWidth(), + factory = { context -> + AdView(context).apply { + setAdSize(AdSize.BANNER) + adUnitId = context.getString(R.string.banner_ad_unit_id) + loadAd( + AdRequest + .Builder() + .build() + ) + } + } + ) +} + +private suspend fun deleteCards( + db: BaseballCardDatabase, + cards: List, +) { + db.baseballCardDao.deleteBaseballCards( + cards + .filter { it.selected } + .map { it.card }) +} + +private fun selectAll(stateList: SnapshotStateList) { + stateList.forEachIndexed { i, card -> + stateList[i] = card.copy(selected = true) + } +} + +@Composable +fun BaseballCardList( + navController: NavController, + cards: List, + onCardChanged: (Int, SelectedState) -> Unit, + modifier: Modifier = Modifier, +) { + LazyColumn( + modifier = modifier, + ) { + itemsIndexed( + items = cards, + key = { _, state -> state.card._id!! } + ) { i, state -> + BaseballCardRow( + navController = navController, + state = state, + onSelectedChange = { + onCardChanged( + i, + state.copy(selected = it) + ) + } + ) + } + } +} + +@Composable +fun BaseballCardRow( + navController: NavController, + state: SelectedState, + onSelectedChange: (Boolean) -> Unit, +) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clickable { + navController.navigate(BaseballCardEditDestination(state.card._id!!)) + } + ) { + Checkbox( + checked = state.selected, + onCheckedChange = onSelectedChange, + ) + Text( + text = state.card.brand, + modifier = Modifier.weight(0.2f) + ) + Text( + text = "${state.card.year}", + modifier = Modifier.weight(0.15f) + ) + Text( + text = state.card.number, + modifier = Modifier.weight(0.15f) + ) + Text( + text = state.card.playerName, + modifier = Modifier.weight(0.5f) + ) + } +} + +@Composable +fun AddCardButton(navController: NavController) { + FloatingActionButton(onClick = { navController.navigate(BaseballCardCreateDestination) }) { + Icon( + Icons.Default.Add, + contentDescription = stringResource(id = R.string.add_menu) + ) + } +} diff --git a/app/src/main/java/bbct/android/ui/list/ListViewModel.kt b/app/src/main/java/bbct/android/ui/list/ListViewModel.kt new file mode 100644 index 000000000..b72e8892d --- /dev/null +++ b/app/src/main/java/bbct/android/ui/list/ListViewModel.kt @@ -0,0 +1,74 @@ +package bbct.android.ui.list + +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.snapshotFlow +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.CreationExtras +import bbct.android.data.BaseballCard +import bbct.android.data.BaseballCardDao +import bbct.android.ui.filter.FilterState +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.launch + +@OptIn(ExperimentalCoroutinesApi::class) +class ListViewModel(val baseballCardDao: BaseballCardDao) : ViewModel() { + val filterState = mutableStateOf(FilterState()) + val isFiltered = mutableStateOf(false) + var baseballCards = MutableStateFlow>(emptyList()) + + init { + viewModelScope.launch { + snapshotFlow { + filterState.value + }.flatMapLatest { filter -> + getBaseballCards( + filter.brand, + filter.year, + filter.number, + filter.playerName, + filter.team + ) + }.collect { baseballCards.value = it } + } + } + + private fun getBaseballCards( + brand: String, + year: Int, + number: String, + playerName: String, + team: String, + ): Flow> { + return baseballCardDao.getBaseballCards( + "%$brand%", + year, + "%$number%", + "%$playerName%", + "%$team%", + ) + } + + fun applyFilter(filter: FilterState) { + filterState.value = filter + isFiltered.value = filter != FilterState() + } +} + +@Suppress("UNCHECKED_CAST") +class ListViewModelFactory(private val baseballCardDao: BaseballCardDao) : + ViewModelProvider.Factory { + override fun create( + modelClass: Class, + extras: CreationExtras, + ): T { + if (modelClass.isAssignableFrom(ListViewModel::class.java)) { + return ListViewModel(baseballCardDao) as T + } + throw IllegalArgumentException("Unknown ViewModel class") + } +} diff --git a/app/src/main/java/bbct/android/ui/navigation/Destinations.kt b/app/src/main/java/bbct/android/ui/navigation/Destinations.kt new file mode 100644 index 000000000..06f472844 --- /dev/null +++ b/app/src/main/java/bbct/android/ui/navigation/Destinations.kt @@ -0,0 +1,18 @@ +package bbct.android.ui.navigation + +import kotlinx.serialization.Serializable + +@Serializable +object BaseballCardListDestination + +@Serializable +object BaseballCardCreateDestination + +@Serializable +data class BaseballCardEditDestination(val cardId: Long) + +@Serializable +object BaseballCardFilterDestination + +@Serializable +object AboutDestination diff --git a/app/src/main/java/bbct/android/ui/theme/Color.kt b/app/src/main/java/bbct/android/ui/theme/Color.kt new file mode 100644 index 000000000..81e4e3e8f --- /dev/null +++ b/app/src/main/java/bbct/android/ui/theme/Color.kt @@ -0,0 +1,226 @@ +package bbct.android.ui.theme + +import androidx.compose.ui.graphics.Color + +val primaryLight = Color(0xFF495D92) +val onPrimaryLight = Color(0xFFFFFFFF) +val primaryContainerLight = Color(0xFFDAE2FF) +val onPrimaryContainerLight = Color(0xFF001848) +val secondaryLight = Color(0xFF585E71) +val onSecondaryLight = Color(0xFFFFFFFF) +val secondaryContainerLight = Color(0xFFDCE2F9) +val onSecondaryContainerLight = Color(0xFF151B2C) +val tertiaryLight = Color(0xFF735471) +val onTertiaryLight = Color(0xFFFFFFFF) +val tertiaryContainerLight = Color(0xFFFED7F9) +val onTertiaryContainerLight = Color(0xFF2B122B) +val errorLight = Color(0xFFBA1A1A) +val onErrorLight = Color(0xFFFFFFFF) +val errorContainerLight = Color(0xFFFFDAD6) +val onErrorContainerLight = Color(0xFF410002) +val backgroundLight = Color(0xFFFAF8FF) +val onBackgroundLight = Color(0xFF1A1B21) +val surfaceLight = Color(0xFFFAF8FF) +val onSurfaceLight = Color(0xFF1A1B21) +val surfaceVariantLight = Color(0xFFE1E2EC) +val onSurfaceVariantLight = Color(0xFF45464F) +val outlineLight = Color(0xFF757780) +val outlineVariantLight = Color(0xFFC5C6D0) +val scrimLight = Color(0xFF000000) +val inverseSurfaceLight = Color(0xFF2F3036) +val inverseOnSurfaceLight = Color(0xFFF1F0F7) +val inversePrimaryLight = Color(0xFFB2C5FF) +val surfaceDimLight = Color(0xFFDAD9E0) +val surfaceBrightLight = Color(0xFFFAF8FF) +val surfaceContainerLowestLight = Color(0xFFFFFFFF) +val surfaceContainerLowLight = Color(0xFFF4F3FA) +val surfaceContainerLight = Color(0xFFEEEDF4) +val surfaceContainerHighLight = Color(0xFFE8E7EF) +val surfaceContainerHighestLight = Color(0xFFE3E2E9) + +val primaryLightMediumContrast = Color(0xFF2C4174) +val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +val primaryContainerLightMediumContrast = Color(0xFF5F73AA) +val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val secondaryLightMediumContrast = Color(0xFF3C4255) +val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +val secondaryContainerLightMediumContrast = Color(0xFF6E7488) +val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val tertiaryLightMediumContrast = Color(0xFF553955) +val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +val tertiaryContainerLightMediumContrast = Color(0xFF8B6A88) +val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val errorLightMediumContrast = Color(0xFF8C0009) +val onErrorLightMediumContrast = Color(0xFFFFFFFF) +val errorContainerLightMediumContrast = Color(0xFFDA342E) +val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +val backgroundLightMediumContrast = Color(0xFFFAF8FF) +val onBackgroundLightMediumContrast = Color(0xFF1A1B21) +val surfaceLightMediumContrast = Color(0xFFFAF8FF) +val onSurfaceLightMediumContrast = Color(0xFF1A1B21) +val surfaceVariantLightMediumContrast = Color(0xFFE1E2EC) +val onSurfaceVariantLightMediumContrast = Color(0xFF41424B) +val outlineLightMediumContrast = Color(0xFF5D5F67) +val outlineVariantLightMediumContrast = Color(0xFF797A83) +val scrimLightMediumContrast = Color(0xFF000000) +val inverseSurfaceLightMediumContrast = Color(0xFF2F3036) +val inverseOnSurfaceLightMediumContrast = Color(0xFFF1F0F7) +val inversePrimaryLightMediumContrast = Color(0xFFB2C5FF) +val surfaceDimLightMediumContrast = Color(0xFFDAD9E0) +val surfaceBrightLightMediumContrast = Color(0xFFFAF8FF) +val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +val surfaceContainerLowLightMediumContrast = Color(0xFFF4F3FA) +val surfaceContainerLightMediumContrast = Color(0xFFEEEDF4) +val surfaceContainerHighLightMediumContrast = Color(0xFFE8E7EF) +val surfaceContainerHighestLightMediumContrast = Color(0xFFE3E2E9) + +val primaryLightHighContrast = Color(0xFF041F51) +val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +val primaryContainerLightHighContrast = Color(0xFF2C4174) +val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +val secondaryLightHighContrast = Color(0xFF1C2233) +val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +val secondaryContainerLightHighContrast = Color(0xFF3C4255) +val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +val tertiaryLightHighContrast = Color(0xFF321932) +val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +val tertiaryContainerLightHighContrast = Color(0xFF553955) +val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +val errorLightHighContrast = Color(0xFF4E0002) +val onErrorLightHighContrast = Color(0xFFFFFFFF) +val errorContainerLightHighContrast = Color(0xFF8C0009) +val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +val backgroundLightHighContrast = Color(0xFFFAF8FF) +val onBackgroundLightHighContrast = Color(0xFF1A1B21) +val surfaceLightHighContrast = Color(0xFFFAF8FF) +val onSurfaceLightHighContrast = Color(0xFF000000) +val surfaceVariantLightHighContrast = Color(0xFFE1E2EC) +val onSurfaceVariantLightHighContrast = Color(0xFF22242B) +val outlineLightHighContrast = Color(0xFF41424B) +val outlineVariantLightHighContrast = Color(0xFF41424B) +val scrimLightHighContrast = Color(0xFF000000) +val inverseSurfaceLightHighContrast = Color(0xFF2F3036) +val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +val inversePrimaryLightHighContrast = Color(0xFFE7EBFF) +val surfaceDimLightHighContrast = Color(0xFFDAD9E0) +val surfaceBrightLightHighContrast = Color(0xFFFAF8FF) +val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +val surfaceContainerLowLightHighContrast = Color(0xFFF4F3FA) +val surfaceContainerLightHighContrast = Color(0xFFEEEDF4) +val surfaceContainerHighLightHighContrast = Color(0xFFE8E7EF) +val surfaceContainerHighestLightHighContrast = Color(0xFFE3E2E9) + +val primaryDark = Color(0xFFB2C5FF) +val onPrimaryDark = Color(0xFF182E60) +val primaryContainerDark = Color(0xFF304578) +val onPrimaryContainerDark = Color(0xFFDAE2FF) +val secondaryDark = Color(0xFFC0C6DD) +val onSecondaryDark = Color(0xFF2A3042) +val secondaryContainerDark = Color(0xFF404659) +val onSecondaryContainerDark = Color(0xFFDCE2F9) +val tertiaryDark = Color(0xFFE1BBDD) +val onTertiaryDark = Color(0xFF422741) +val tertiaryContainerDark = Color(0xFF5A3D59) +val onTertiaryContainerDark = Color(0xFFFED7F9) +val errorDark = Color(0xFFFFB4AB) +val onErrorDark = Color(0xFF690005) +val errorContainerDark = Color(0xFF93000A) +val onErrorContainerDark = Color(0xFFFFDAD6) +val backgroundDark = Color(0xFF121318) +val onBackgroundDark = Color(0xFFE3E2E9) +val surfaceDark = Color(0xFF121318) +val onSurfaceDark = Color(0xFFE3E2E9) +val surfaceVariantDark = Color(0xFF45464F) +val onSurfaceVariantDark = Color(0xFFC5C6D0) +val outlineDark = Color(0xFF8F909A) +val outlineVariantDark = Color(0xFF45464F) +val scrimDark = Color(0xFF000000) +val inverseSurfaceDark = Color(0xFFE3E2E9) +val inverseOnSurfaceDark = Color(0xFF2F3036) +val inversePrimaryDark = Color(0xFF495D92) +val surfaceDimDark = Color(0xFF121318) +val surfaceBrightDark = Color(0xFF38393F) +val surfaceContainerLowestDark = Color(0xFF0D0E13) +val surfaceContainerLowDark = Color(0xFF1A1B21) +val surfaceContainerDark = Color(0xFF1E1F25) +val surfaceContainerHighDark = Color(0xFF282A2F) +val surfaceContainerHighestDark = Color(0xFF33343A) + +val primaryDarkMediumContrast = Color(0xFFB8CAFF) +val onPrimaryDarkMediumContrast = Color(0xFF00133D) +val primaryContainerDarkMediumContrast = Color(0xFF7B8FC8) +val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +val secondaryDarkMediumContrast = Color(0xFFC4CAE1) +val onSecondaryDarkMediumContrast = Color(0xFF101626) +val secondaryContainerDarkMediumContrast = Color(0xFF8A90A5) +val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +val tertiaryDarkMediumContrast = Color(0xFFE5BFE1) +val onTertiaryDarkMediumContrast = Color(0xFF250D26) +val tertiaryContainerDarkMediumContrast = Color(0xFFA886A5) +val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +val errorDarkMediumContrast = Color(0xFFFFBAB1) +val onErrorDarkMediumContrast = Color(0xFF370001) +val errorContainerDarkMediumContrast = Color(0xFFFF5449) +val onErrorContainerDarkMediumContrast = Color(0xFF000000) +val backgroundDarkMediumContrast = Color(0xFF121318) +val onBackgroundDarkMediumContrast = Color(0xFFE3E2E9) +val surfaceDarkMediumContrast = Color(0xFF121318) +val onSurfaceDarkMediumContrast = Color(0xFFFCFAFF) +val surfaceVariantDarkMediumContrast = Color(0xFF45464F) +val onSurfaceVariantDarkMediumContrast = Color(0xFFC9CAD4) +val outlineDarkMediumContrast = Color(0xFFA1A2AC) +val outlineVariantDarkMediumContrast = Color(0xFF81838C) +val scrimDarkMediumContrast = Color(0xFF000000) +val inverseSurfaceDarkMediumContrast = Color(0xFFE3E2E9) +val inverseOnSurfaceDarkMediumContrast = Color(0xFF292A2F) +val inversePrimaryDarkMediumContrast = Color(0xFF32467A) +val surfaceDimDarkMediumContrast = Color(0xFF121318) +val surfaceBrightDarkMediumContrast = Color(0xFF38393F) +val surfaceContainerLowestDarkMediumContrast = Color(0xFF0D0E13) +val surfaceContainerLowDarkMediumContrast = Color(0xFF1A1B21) +val surfaceContainerDarkMediumContrast = Color(0xFF1E1F25) +val surfaceContainerHighDarkMediumContrast = Color(0xFF282A2F) +val surfaceContainerHighestDarkMediumContrast = Color(0xFF33343A) + +val primaryDarkHighContrast = Color(0xFFFCFAFF) +val onPrimaryDarkHighContrast = Color(0xFF000000) +val primaryContainerDarkHighContrast = Color(0xFFB8CAFF) +val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +val secondaryDarkHighContrast = Color(0xFFFCFAFF) +val onSecondaryDarkHighContrast = Color(0xFF000000) +val secondaryContainerDarkHighContrast = Color(0xFFC4CAE1) +val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +val tertiaryDarkHighContrast = Color(0xFFFFF9FA) +val onTertiaryDarkHighContrast = Color(0xFF000000) +val tertiaryContainerDarkHighContrast = Color(0xFFE5BFE1) +val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +val errorDarkHighContrast = Color(0xFFFFF9F9) +val onErrorDarkHighContrast = Color(0xFF000000) +val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +val onErrorContainerDarkHighContrast = Color(0xFF000000) +val backgroundDarkHighContrast = Color(0xFF121318) +val onBackgroundDarkHighContrast = Color(0xFFE3E2E9) +val surfaceDarkHighContrast = Color(0xFF121318) +val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +val surfaceVariantDarkHighContrast = Color(0xFF45464F) +val onSurfaceVariantDarkHighContrast = Color(0xFFFCFAFF) +val outlineDarkHighContrast = Color(0xFFC9CAD4) +val outlineVariantDarkHighContrast = Color(0xFFC9CAD4) +val scrimDarkHighContrast = Color(0xFF000000) +val inverseSurfaceDarkHighContrast = Color(0xFFE3E2E9) +val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +val inversePrimaryDarkHighContrast = Color(0xFF10275A) +val surfaceDimDarkHighContrast = Color(0xFF121318) +val surfaceBrightDarkHighContrast = Color(0xFF38393F) +val surfaceContainerLowestDarkHighContrast = Color(0xFF0D0E13) +val surfaceContainerLowDarkHighContrast = Color(0xFF1A1B21) +val surfaceContainerDarkHighContrast = Color(0xFF1E1F25) +val surfaceContainerHighDarkHighContrast = Color(0xFF282A2F) +val surfaceContainerHighestDarkHighContrast = Color(0xFF33343A) + + + + + + + diff --git a/app/src/main/java/bbct/android/ui/theme/Theme.kt b/app/src/main/java/bbct/android/ui/theme/Theme.kt new file mode 100644 index 000000000..8ca2a9b29 --- /dev/null +++ b/app/src/main/java/bbct/android/ui/theme/Theme.kt @@ -0,0 +1,280 @@ +package bbct.android.ui.theme + +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext + +private val lightScheme = lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, +) + +private val darkScheme = darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, +) + +private val mediumContrastLightColorScheme = lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, +) + +private val highContrastLightColorScheme = lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, +) + +private val mediumContrastDarkColorScheme = darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, +) + +private val highContrastDarkColorScheme = darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, +) + +@Immutable +data class ColorFamily( + val color: Color, + val onColor: Color, + val colorContainer: Color, + val onColorContainer: Color +) + +val unspecified_scheme = ColorFamily( + Color.Unspecified, + Color.Unspecified, + Color.Unspecified, + Color.Unspecified +) + +@Composable +fun AppTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable() () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> darkScheme + else -> lightScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = AppTypography, + content = content + ) +} diff --git a/app/src/main/java/bbct/android/ui/theme/Type.kt b/app/src/main/java/bbct/android/ui/theme/Type.kt new file mode 100644 index 000000000..eedf2eaa2 --- /dev/null +++ b/app/src/main/java/bbct/android/ui/theme/Type.kt @@ -0,0 +1,9 @@ +package bbct.android.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +val AppTypography = Typography() diff --git a/android/src/main/res/drawable-hdpi/baseball.png b/app/src/main/res/drawable-hdpi/baseball.png similarity index 100% rename from android/src/main/res/drawable-hdpi/baseball.png rename to app/src/main/res/drawable-hdpi/baseball.png diff --git a/android/src/main/res/drawable-hdpi/select_all.png b/app/src/main/res/drawable-hdpi/select_all.png similarity index 100% rename from android/src/main/res/drawable-hdpi/select_all.png rename to app/src/main/res/drawable-hdpi/select_all.png diff --git a/android/src/main/res/drawable-ldpi/baseball.png b/app/src/main/res/drawable-ldpi/baseball.png similarity index 100% rename from android/src/main/res/drawable-ldpi/baseball.png rename to app/src/main/res/drawable-ldpi/baseball.png diff --git a/android/src/main/res/drawable-mdpi/baseball.png b/app/src/main/res/drawable-mdpi/baseball.png similarity index 100% rename from android/src/main/res/drawable-mdpi/baseball.png rename to app/src/main/res/drawable-mdpi/baseball.png diff --git a/android/src/main/res/drawable-mdpi/select_all.png b/app/src/main/res/drawable-mdpi/select_all.png similarity index 100% rename from android/src/main/res/drawable-mdpi/select_all.png rename to app/src/main/res/drawable-mdpi/select_all.png diff --git a/android/src/main/res/drawable-xhdpi/baseball.png b/app/src/main/res/drawable-xhdpi/baseball.png similarity index 100% rename from android/src/main/res/drawable-xhdpi/baseball.png rename to app/src/main/res/drawable-xhdpi/baseball.png diff --git a/android/src/main/res/drawable-xhdpi/select_all.png b/app/src/main/res/drawable-xhdpi/select_all.png similarity index 100% rename from android/src/main/res/drawable-xhdpi/select_all.png rename to app/src/main/res/drawable-xhdpi/select_all.png diff --git a/android/src/main/res/drawable-xxhdpi/baseball.png b/app/src/main/res/drawable-xxhdpi/baseball.png similarity index 100% rename from android/src/main/res/drawable-xxhdpi/baseball.png rename to app/src/main/res/drawable-xxhdpi/baseball.png diff --git a/android/src/main/res/drawable-xxhdpi/select_all.png b/app/src/main/res/drawable-xxhdpi/select_all.png similarity index 100% rename from android/src/main/res/drawable-xxhdpi/select_all.png rename to app/src/main/res/drawable-xxhdpi/select_all.png diff --git a/android/src/main/res/drawable-xxxhdpi/select_all.png b/app/src/main/res/drawable-xxxhdpi/select_all.png similarity index 100% rename from android/src/main/res/drawable-xxxhdpi/select_all.png rename to app/src/main/res/drawable-xxxhdpi/select_all.png diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 000000000..07d5da9cb --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 000000000..2b068d114 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..6f3b755bf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..6f3b755bf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 000000000..c209e78ec Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 000000000..b2dfe3d1b Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 000000000..4f0f1d64e Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 000000000..62b611da0 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 000000000..948a3070f Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 000000000..1b9a6956b Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 000000000..28d4b77f9 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 000000000..9287f5083 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 000000000..aa7d6427e Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 000000000..9126ae37c Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..f8c6127d3 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/android/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml similarity index 85% rename from android/src/main/res/values/strings.xml rename to app/src/main/res/values/strings.xml index c1dc04502..a4172f5cc 100644 --- a/android/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,4 @@ - - + BBCT + BBCT - %1$s BBCT Data - Card Details + Create Card + Edit Card Filter Cards About Duplicate Card - - Condition: - Autographed? - Brand: - Year: - Number: - Value: - Quantity: - Player Name: - Team: - Position: - - + + Autographed + Condition Brand Year Number Value - Count + Quantity Player Name Position Team @@ -71,8 +63,7 @@ Version %1$s - 1.1.1 - Copyright 2012–20 by codeguru + Copyright 2012–25 by codeguru Email: <bbct-list@lists.sourceforge.net> Website: <https://github.com/BaseballCardTracker/bbct/wiki> This software is licensed under the GPL. Visit\nhttp://www.gnu.org/licenses/ for a copy of the license. @@ -124,5 +115,10 @@ Now Later + Back + More + Close + Add Cards + ca-app-pub-4313300967266958/2573166425 diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 000000000..77d7f5e76 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +