diff --git a/app/build.gradle b/app/build.gradle index 90626cb..af3ca8b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,7 +13,7 @@ android { minSdk 27 targetSdk 33 versionCode 1 - versionName "1.0" + versionName "e1.0.0.b7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -50,16 +50,23 @@ android { dependencies { def activity_version = '1.8.0' + def lifecycle_version = "2.6.2" + def arch_version = "2.2.0" + def roomVersion = '2.3.0' + def nav_version = "2.7.4" //Fragment + def fragment_version = "1.6.1" + + implementation 'androidx.appcompat:appcompat:1.6.1' implementation "androidx.activity:activity-ktx:$activity_version" - implementation 'androidx.core:core-ktx:1.9.0' + implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2' implementation 'androidx.activity:activity-compose:1.8.0' implementation platform('androidx.compose:compose-bom:2023.03.00') implementation 'androidx.compose.ui:ui' implementation 'androidx.compose.ui:ui-graphics' implementation 'androidx.compose.ui:ui-tooling-preview' - implementation 'androidx.compose.material3:material3' + implementation 'androidx.compose.material3:material3:1.1.2' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' @@ -71,11 +78,9 @@ dependencies { implementation 'androidx.room:room-ktx:2.5.2' implementation 'androidx.navigation:navigation-runtime-ktx:2.7.4' - def lifecycle_version = "2.6.2" - def arch_version = "2.2.0" - def roomVersion = '2.3.0' - + implementation('androidx.constraintlayout:constraintlayout-compose-android:1.1.0-alpha13') implementation 'androidx.core:core-splashscreen:1.0.1' + implementation "androidx.navigation:navigation-compose:$nav_version" // ViewModel @@ -89,8 +94,7 @@ dependencies { // Lifecycle utilities for Compose implementation "androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version" - //Fragment - def fragment_version = "1.6.1" + // Kotlin implementation "androidx.fragment:fragment-ktx:$fragment_version" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a65e438..dc4d621 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,6 +27,10 @@ + + \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/MainActivity.kt b/app/src/main/java/com/menagerie/ophelia/MainActivity.kt index 08daf3c..3549945 100644 --- a/app/src/main/java/com/menagerie/ophelia/MainActivity.kt +++ b/app/src/main/java/com/menagerie/ophelia/MainActivity.kt @@ -1,87 +1,27 @@ package com.menagerie.ophelia -import android.app.Activity -import android.app.Application import android.os.Bundle -import android.util.Log +import android.view.Window import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ListItem -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.menagerie.ophelia.database.polycule.BioListViewModel import com.menagerie.ophelia.database.polycule.PolyculeApplication -import com.menagerie.ophelia.database.polycule.PolyculeRepository -import com.menagerie.ophelia.database.polycule.entity.Bio +import com.menagerie.ophelia.database.polycule.PolyculeDatabaseManager import com.menagerie.ophelia.ui.theme.OpheliaTheme +import com.menagerie.ophelia.view.PolyculeApp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContent { OpheliaTheme { - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colorScheme.background - ) { - val repository = (application as PolyculeApplication).repository - Greeting("Android", repository) + val repository = (application as PolyculeApplication).repository + PolyculeDatabaseManager.polyculeRepository = repository + Surface { + PolyculeApp() } } } } } - -@Composable -fun Greeting(name: String, repository: PolyculeRepository, modifier: Modifier = Modifier) { - Log.d("Tawni", "Test") - val mBioListViewModel: BioListViewModel = viewModel( - factory = BioListViewModel.BioListViewModelFactory(repository) - ) - - - val items = mBioListViewModel.allBios.observeAsState(listOf()).value - - - - Column( - modifier = Modifier.padding(16.dp) - ) { - Text(text = "FUCKING FINAALLLLLLYY") - Spacer(modifier = Modifier.padding(16.dp)) - BioList(list = items, mBioListViewModel = mBioListViewModel) - Spacer(modifier = Modifier.padding(16.dp)) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun BioList( - list: List, - mBioListViewModel: BioListViewModel -) { - Log.d("Test" ,"${list.size}") - LazyColumn() { - items(list) {bio -> - - ListItem( - headlineText = {Text(text = bio.name)} - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/BioListViewModel.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/BioListViewModel.kt deleted file mode 100644 index b538ead..0000000 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/BioListViewModel.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.menagerie.ophelia.database.polycule - -import androidx.lifecycle.LiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.asLiveData -import androidx.lifecycle.viewModelScope -import com.menagerie.ophelia.database.polycule.entity.Bio -import kotlinx.coroutines.launch - - -class BioListViewModel(private val repository: PolyculeRepository) : ViewModel() { - - val allBios: LiveData> = repository.getAllBios().asLiveData() - - fun insert(bio: Bio) = viewModelScope.launch { - repository.upsertBio(bio) - } - - class BioListViewModelFactory( - private val repository: PolyculeRepository) : - ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(BioListViewModel::class.java)) { - @Suppress("UNCHECKED_CAST") - return BioListViewModel(repository) as T - } - throw IllegalArgumentException("Unknown ViewModel Class") - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeApplication.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeApplication.kt index d192ef1..5e7ebda 100644 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeApplication.kt +++ b/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeApplication.kt @@ -8,6 +8,6 @@ class PolyculeApplication : Application() { private val applicationScope = CoroutineScope(SupervisorJob()) - val database by lazy { PolyculeDatabase.getDatabase(this, applicationScope)} - val repository by lazy { PolyculeRepository(database.bioDao())} + val database by lazy { PolyculeDatabase.getDatabase(this, applicationScope) } + val repository by lazy { PolyculeRepository(database.bioDao()) } } \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeDatabase.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeDatabase.kt index 201b123..12ef002 100644 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeDatabase.kt +++ b/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeDatabase.kt @@ -1,6 +1,7 @@ package com.menagerie.ophelia.database.polycule import android.content.Context +import androidx.compose.ui.tooling.preview.datasource.LoremIpsum import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase @@ -8,12 +9,11 @@ import androidx.sqlite.db.SupportSQLiteDatabase import com.menagerie.ophelia.database.polycule.entity.Bio import com.menagerie.ophelia.database.polycule.entity.BioDao import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.count import kotlinx.coroutines.launch @Database( - version = 1, + version = 3, exportSchema = false, entities = [ Bio::class @@ -50,28 +50,30 @@ abstract class PolyculeDatabase : RoomDatabase() { private class PolyculeDatabaseCallback( private val scope: CoroutineScope ) : Callback() { - override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) INSTANCE?.let { database -> scope.launch { - populateDatabase(database.bioDao()) + //populateDatabase(database.bioDao()) } } } suspend fun populateDatabase(bioDao: BioDao) { var bio = Bio( - name = "Azea") + name = "Azea", + ) bioDao.insert(bio) - bio = Bio( - name = "Darkwood Mill") + + bio = Bio( + name = "Darkwood Mill", + ) bioDao.insert(bio) - bio = Bio( - name = "Blizzard") + + bio = Bio( + name = "Blizzard", + ) bioDao.insert(bio) - val count = bioDao.getAllAlphabetisedBios().count() } } - } \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeDatabaseManager.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeDatabaseManager.kt index 68119ac..e89bc9d 100644 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeDatabaseManager.kt +++ b/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeDatabaseManager.kt @@ -1,13 +1,5 @@ package com.menagerie.ophelia.database.polycule -import com.menagerie.ophelia.database.polycule.entity.Bio - -//Todo: Move repo access to manager to limit passing it around object PolyculeDatabaseManager { - - lateinit var polyculeRepository : PolyculeRepository - - suspend fun post(bio: Bio) { - polyculeRepository.upsertBio(bio) - } + lateinit var polyculeRepository: PolyculeRepository } \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeRepository.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeRepository.kt index db94018..011ecc6 100644 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeRepository.kt +++ b/app/src/main/java/com/menagerie/ophelia/database/polycule/PolyculeRepository.kt @@ -1,29 +1,38 @@ package com.menagerie.ophelia.database.polycule +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.asLiveData import com.menagerie.ophelia.database.polycule.entity.Bio import com.menagerie.ophelia.database.polycule.entity.BioDao import kotlinx.coroutines.flow.Flow - class PolyculeRepository( private val bioDao: BioDao ) { - - suspend fun upsertBio(bio: Bio): Long { - return 0 - //return bioDao.findOrInsert(bio) + suspend fun upsertBio(bio: Bio) { + bioDao.upsert(bio) } fun getAlphabetisedBios(): Flow> { return bioDao.getAllAlphabetisedBios() } + fun getBio(bioId: Long): Flow { + return bioDao.getBio(bioId) + } + fun getAllBios(): Flow> { return bioDao.getAllBios() } - suspend fun insert(bio : Bio) { + suspend fun insert(bio: Bio) { bioDao.insert(bio) } + suspend fun delete(bio: Bio) { + bioDao.delete(bio) + } + + fun hasPolycule() = false } \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/Bio.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/Bio.kt index 796e2a3..23063c9 100644 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/Bio.kt +++ b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/Bio.kt @@ -3,11 +3,18 @@ package com.menagerie.ophelia.database.polycule.entity import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey +import com.menagerie.ophelia.R @Entity( tableName = "bio_table", ) data class Bio( - @PrimaryKey - @ColumnInfo(name = "name") val name: String, + @PrimaryKey(autoGenerate = true) val id: Long = 0, + @ColumnInfo(name = "name") var name: String = "", + @ColumnInfo(name = "subject_pronoun") val subjective: String = "", + @ColumnInfo(name = "object_pronoun") val objective: String = "", + @ColumnInfo(name = "possess_pronoun") val possessive: String = "", + @ColumnInfo(name = "reflex_pronoun") val reflexive: String = "", + @ColumnInfo(name="tags") var tags: Int = 0, + @ColumnInfo(name = "pfpRes") val pfpRes: Int = R.drawable.ic_app_logo, ) \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/BioDao.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/BioDao.kt index c92bbfa..efc1099 100644 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/BioDao.kt +++ b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/BioDao.kt @@ -1,19 +1,24 @@ package com.menagerie.ophelia.database.polycule.entity import androidx.room.Dao +import androidx.room.Delete import androidx.room.Insert import androidx.room.Query import androidx.room.Update +import androidx.room.Upsert import kotlinx.coroutines.flow.Flow @Dao abstract class BioDao { @Insert - abstract suspend fun insert(newBio: Bio) + abstract suspend fun insert(newBio: Bio): Long + + @Delete + abstract suspend fun delete(bio: Bio) @Update - abstract suspend fun update(existingBio: Bio) : Int + abstract suspend fun update(existingBio: Bio) @Query("SELECT * FROM bio_table ORDER BY name ASC") abstract fun getAllAlphabetisedBios(): Flow> @@ -21,4 +26,9 @@ abstract class BioDao { @Query("SELECT * FROM bio_table") abstract fun getAllBios(): Flow> + @Query("SELECT * FROM bio_table WHERE id = :bioId") + abstract fun getBio(bioId: Long): Flow + + @Upsert + abstract suspend fun upsert(bio: Bio): Long } \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/Identity.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/Identity.kt deleted file mode 100644 index f63e5e9..0000000 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/Identity.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.menagerie.ophelia.database.polycule.entity - -import android.graphics.drawable.Icon -import androidx.room.Entity -import androidx.room.PrimaryKey - -@Entity( - foreignKeys = [ - - ], - indices = [ - - ] -) -class Identity ( - @PrimaryKey(autoGenerate = true) val id: Long = 0, - val uniqueId: Long = 0, - val name: String = "", - val icon: Icon, - ) \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/IdentityDao.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/IdentityDao.kt deleted file mode 100644 index a613ac8..0000000 --- a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/IdentityDao.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.menagerie.ophelia.database.polycule.entity - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.Query -import androidx.room.Update - -@Dao -abstract class IdentityDao { - @Insert - abstract suspend fun insert(identity: Identity): Long - - @Update - abstract suspend fun update(idenity: Identity) - - @Query("SELECT * FROM Identity WHERE uniqueId = :uniqueId") - abstract suspend fun findByIdentity(uniqueId : Long): Identity? - - -} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/viewmodel/BioDetailViewModel.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/viewmodel/BioDetailViewModel.kt new file mode 100644 index 0000000..b89ac55 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/viewmodel/BioDetailViewModel.kt @@ -0,0 +1,12 @@ +package com.menagerie.ophelia.database.polycule.entity.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.asLiveData +import com.menagerie.ophelia.database.polycule.PolyculeDatabaseManager + +class BioDetailViewModel( + id: Long +) : ViewModel() { + var bio = PolyculeDatabaseManager.polyculeRepository.getBio(id).asLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/viewmodel/BioListViewModel.kt b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/viewmodel/BioListViewModel.kt new file mode 100644 index 0000000..48cc364 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/database/polycule/entity/viewmodel/BioListViewModel.kt @@ -0,0 +1,49 @@ +package com.menagerie.ophelia.database.polycule.entity.viewmodel + +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.asLiveData +import androidx.lifecycle.viewModelScope +import com.menagerie.ophelia.database.polycule.PolyculeDatabaseManager +import com.menagerie.ophelia.database.polycule.entity.Bio +import kotlinx.coroutines.launch + + +class BioListViewModel() : ViewModel() { + + val allBios: LiveData> = + PolyculeDatabaseManager.polyculeRepository.getAllBios().asLiveData() + + fun upsert(bio: Bio) = viewModelScope.launch { + PolyculeDatabaseManager.polyculeRepository.upsertBio(bio) + } + + fun delete(bio: Bio) = viewModelScope.launch { + PolyculeDatabaseManager.polyculeRepository.delete(bio) + } + + class BioListViewModelFactory() : + ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(BioListViewModel::class.java)) { + @Suppress("UNCHECKED_CAST") + return BioListViewModel() as T + } + throw IllegalArgumentException("Unknown ViewModel Class") + } + } + class InputBioViewModel : ViewModel() { + private val _bio: MutableLiveData = MutableLiveData(Bio()) + val bio: LiveData = _bio + fun onNameChange(name: String) { + val newBio = Bio( + name = name, + ) + _bio.value = newBio + } + } +} + diff --git a/app/src/main/java/com/menagerie/ophelia/ui/theme/Color.kt b/app/src/main/java/com/menagerie/ophelia/ui/theme/Color.kt index 4362bf0..e388112 100644 --- a/app/src/main/java/com/menagerie/ophelia/ui/theme/Color.kt +++ b/app/src/main/java/com/menagerie/ophelia/ui/theme/Color.kt @@ -1,11 +1,65 @@ package com.menagerie.ophelia.ui.theme - import androidx.compose.ui.graphics.Color -val Purple80 = Color(0xFFD0BCFF) -val PurpleGrey80 = Color(0xFFCCC2DC) -val Pink80 = Color(0xFFEFB8C8) +val md_theme_light_primary = Color(0xFF366A21) +val md_theme_light_onPrimary = Color(0xFFFFFFFF) +val md_theme_light_primaryContainer = Color(0xFFB6F398) +val md_theme_light_onPrimaryContainer = Color(0xFF052100) +val md_theme_light_secondary = Color(0xFF55624C) +val md_theme_light_onSecondary = Color(0xFFFFFFFF) +val md_theme_light_secondaryContainer = Color(0xFFD8E7CB) +val md_theme_light_onSecondaryContainer = Color(0xFF131F0D) +val md_theme_light_tertiary = Color(0xFF386667) +val md_theme_light_onTertiary = Color(0xFFFFFFFF) +val md_theme_light_tertiaryContainer = Color(0xFFBBEBEC) +val md_theme_light_onTertiaryContainer = Color(0xFF002021) +val md_theme_light_error = Color(0xFFBA1A1A) +val md_theme_light_errorContainer = Color(0xFFFFDAD6) +val md_theme_light_onError = Color(0xFFFFFFFF) +val md_theme_light_onErrorContainer = Color(0xFF410002) +val md_theme_light_background = Color(0xFFFDFDF6) +val md_theme_light_onBackground = Color(0xFF1A1C18) +val md_theme_light_outline = Color(0xFF73796E) +val md_theme_light_inverseOnSurface = Color(0xFFF1F1EA) +val md_theme_light_inverseSurface = Color(0xFF2F312D) +val md_theme_light_inversePrimary = Color(0xFF9BD67F) +val md_theme_light_surfaceTint = Color(0xFF366A21) +val md_theme_light_outlineVariant = Color(0xFFC3C8BB) +val md_theme_light_scrim = Color(0xFF000000) +val md_theme_light_surface = Color(0xFFD8D8C4) +val md_theme_light_onSurface = Color(0xFF1A1C18) +val md_theme_light_surfaceVariant = Color(0xFFDFE4D7) +val md_theme_light_onSurfaceVariant = Color(0xFF43483F) -val Purple40 = Color(0xFF6650a4) -val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) \ No newline at end of file +val md_theme_dark_primary = Color(0xFF9BD67F) +val md_theme_dark_onPrimary = Color(0xFF0E3900) +val md_theme_dark_primaryContainer = Color(0xFF1E5108) +val md_theme_dark_onPrimaryContainer = Color(0xFFB6F398) +val md_theme_dark_secondary = Color(0xFFBCCBB0) +val md_theme_dark_onSecondary = Color(0xFF273421) +val md_theme_dark_secondaryContainer = Color(0xFF3D4B36) +val md_theme_dark_onSecondaryContainer = Color(0xFFD8E7CB) +val md_theme_dark_tertiary = Color(0xFFA0CFD0) +val md_theme_dark_onTertiary = Color(0xFF003738) +val md_theme_dark_tertiaryContainer = Color(0xFF1E4E4F) +val md_theme_dark_onTertiaryContainer = Color(0xFFBBEBEC) +val md_theme_dark_error = Color(0xFFFFB4AB) +val md_theme_dark_errorContainer = Color(0xFF93000A) +val md_theme_dark_onError = Color(0xFF690005) +val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) +val md_theme_dark_background = Color(0xFF1C1C18) +val md_theme_dark_onBackground = Color(0xFFE3E3DC) +val md_theme_dark_outline = Color(0xFF8D9287) +val md_theme_dark_inverseOnSurface = Color(0xFF1A1C18) +val md_theme_dark_inverseSurface = Color(0xFFE3E3DC) +val md_theme_dark_inversePrimary = Color(0xFF366A21) +val md_theme_dark_surfaceTint = Color(0xFF9BD67F) +val md_theme_dark_outlineVariant = Color(0xFF43483F) +val md_theme_dark_scrim = Color(0xFF000000) +val md_theme_dark_surface = Color(0xFF2B2822) +val md_theme_dark_onSurface = Color(0xFFC6C7C0) +val md_theme_dark_surfaceVariant = Color(0xFF43483F) +val md_theme_dark_onSurfaceVariant = Color(0xFFC3C8BB) + + +val seed = Color(0xFF5E9546) \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/ui/theme/Theme.kt b/app/src/main/java/com/menagerie/ophelia/ui/theme/Theme.kt index 11df8bb..a27b901 100644 --- a/app/src/main/java/com/menagerie/ophelia/ui/theme/Theme.kt +++ b/app/src/main/java/com/menagerie/ophelia/ui/theme/Theme.kt @@ -1,54 +1,93 @@ package com.menagerie.ophelia.ui.theme import android.app.Activity -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.SideEffect import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat -private val DarkColorScheme = darkColorScheme( - primary = Purple80, - secondary = PurpleGrey80, - tertiary = Pink80 -) private val LightColorScheme = lightColorScheme( - primary = Purple40, - secondary = PurpleGrey40, - tertiary = Pink40 + primary = md_theme_light_primary, + onPrimary = md_theme_light_onPrimary, + primaryContainer = md_theme_light_primaryContainer, + onPrimaryContainer = md_theme_light_onPrimaryContainer, + secondary = md_theme_light_secondary, + onSecondary = md_theme_light_onSecondary, + secondaryContainer = md_theme_light_secondaryContainer, + onSecondaryContainer = md_theme_light_onSecondaryContainer, + tertiary = md_theme_light_tertiary, + onTertiary = md_theme_light_onTertiary, + tertiaryContainer = md_theme_light_tertiaryContainer, + onTertiaryContainer = md_theme_light_onTertiaryContainer, + error = md_theme_light_error, + errorContainer = md_theme_light_errorContainer, + onError = md_theme_light_onError, + onErrorContainer = md_theme_light_onErrorContainer, + background = md_theme_light_background, + onBackground = md_theme_light_onBackground, + outline = md_theme_light_outline, + inverseOnSurface = md_theme_light_inverseOnSurface, + inverseSurface = md_theme_light_inverseSurface, + inversePrimary = md_theme_light_inversePrimary, + surfaceTint = md_theme_light_surfaceTint, + outlineVariant = md_theme_light_outlineVariant, + scrim = md_theme_light_scrim, + surface = md_theme_light_surface, + onSurface = md_theme_light_onSurface, + surfaceVariant = md_theme_light_surfaceVariant, + onSurfaceVariant = md_theme_light_onSurfaceVariant, +) - /* Other default colors to override - background = Color(0xFFFFFBFE), - surface = Color(0xFFFFFBFE), - onPrimary = Color.White, - onSecondary = Color.White, - onTertiary = Color.White, - onBackground = Color(0xFF1C1B1F), - onSurface = Color(0xFF1C1B1F), - */ + +private val DarkColorScheme = darkColorScheme( + primary = md_theme_dark_primary, + onPrimary = md_theme_dark_onPrimary, + primaryContainer = md_theme_dark_primaryContainer, + onPrimaryContainer = md_theme_dark_onPrimaryContainer, + secondary = md_theme_dark_secondary, + onSecondary = md_theme_dark_onSecondary, + secondaryContainer = md_theme_dark_secondaryContainer, + onSecondaryContainer = md_theme_dark_onSecondaryContainer, + tertiary = md_theme_dark_tertiary, + onTertiary = md_theme_dark_onTertiary, + tertiaryContainer = md_theme_dark_tertiaryContainer, + onTertiaryContainer = md_theme_dark_onTertiaryContainer, + error = md_theme_dark_error, + errorContainer = md_theme_dark_errorContainer, + onError = md_theme_dark_onError, + onErrorContainer = md_theme_dark_onErrorContainer, + background = md_theme_dark_background, + onBackground = md_theme_dark_onBackground, + outline = md_theme_dark_outline, + inverseOnSurface = md_theme_dark_inverseOnSurface, + inverseSurface = md_theme_dark_inverseSurface, + inversePrimary = md_theme_dark_inversePrimary, + surfaceTint = md_theme_dark_surfaceTint, + outlineVariant = md_theme_dark_outlineVariant, + scrim = md_theme_dark_scrim, + surface = md_theme_dark_surface, + onSurface = md_theme_dark_onSurface, + surfaceVariant = md_theme_dark_surfaceVariant, + onSurfaceVariant = md_theme_dark_onSurfaceVariant, ) @Composable fun OpheliaTheme( darkTheme: Boolean = isSystemInDarkTheme(), // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, - content: @Composable () -> Unit + 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) - } +// dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { +// val context = LocalContext.current +// if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) +// } darkTheme -> DarkColorScheme else -> LightColorScheme diff --git a/app/src/main/java/com/menagerie/ophelia/ui/theme/Type.kt b/app/src/main/java/com/menagerie/ophelia/ui/theme/Type.kt index e16738e..fe80251 100644 --- a/app/src/main/java/com/menagerie/ophelia/ui/theme/Type.kt +++ b/app/src/main/java/com/menagerie/ophelia/ui/theme/Type.kt @@ -4,17 +4,26 @@ 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.text.style.TextDecoration import androidx.compose.ui.unit.sp // Set of Material typography styles to start with val Typography = Typography( bodyLarge = TextStyle( - fontFamily = FontFamily.Default, + fontFamily = FontFamily.Serif, fontWeight = FontWeight.Normal, fontSize = 16.sp, lineHeight = 24.sp, letterSpacing = 0.5.sp - ) + ), + displayLarge = TextStyle( + fontFamily = FontFamily.Cursive, + fontWeight = FontWeight.Bold, + fontSize = 64.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp, + textDecoration = TextDecoration.Underline + ), /* Other default text styles to override titleLarge = TextStyle( fontFamily = FontFamily.Default, diff --git a/app/src/main/java/com/menagerie/ophelia/view/HomeScreen.kt b/app/src/main/java/com/menagerie/ophelia/view/HomeScreen.kt new file mode 100644 index 0000000..590b4db --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/HomeScreen.kt @@ -0,0 +1,67 @@ +package com.menagerie.ophelia.view + +import android.content.res.Configuration +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +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.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +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.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.menagerie.ophelia.R +import com.menagerie.ophelia.ui.theme.OpheliaTheme + +@Composable +fun HomeScreen( + onClick: () -> Unit, + +) { + val text = if(true) R.string.welcome else R.string.welcome_back + HeaderText(text, onClick) +} + +@Composable +fun HeaderText( + text: Int, + onClick: () -> Unit +) { + Box( + modifier = Modifier + .fillMaxSize() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 10.dp) + .align(Alignment.Center), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Spacer(modifier = Modifier.weight(1f)) + Text( + text = stringResource(id = R.string.app_name), + style = MaterialTheme.typography.displayLarge + ) + Text( + text = stringResource(id = R.string.app_tag) + ) + Spacer(modifier = Modifier.weight(1f)) + Button( + modifier = Modifier.padding(12.dp), + onClick = onClick + ) { + Text(text = stringResource(id = text)) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/NewUserStartScreen.kt b/app/src/main/java/com/menagerie/ophelia/view/NewUserStartScreen.kt new file mode 100644 index 0000000..05e40ef --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/NewUserStartScreen.kt @@ -0,0 +1,45 @@ +package com.menagerie.ophelia.view + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +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.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun NewUserStartScreen( + onGo: () -> Unit = {}, +) { + + Scaffold { + Column { + OpheliaFace( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 12.dp) + ) + OpheliaWelcome(modifier = Modifier.weight(1f)) + Button( + onClick = onGo, + modifier = Modifier + .padding(12.dp) + .align(Alignment.End) + ) { + Text(text = "Go") + } + } + } +} + +@Preview +@Composable +fun NewUserPreview(){ + NewUserStartScreen() +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/Ophelia.kt b/app/src/main/java/com/menagerie/ophelia/view/Ophelia.kt new file mode 100644 index 0000000..d1efe41 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/Ophelia.kt @@ -0,0 +1,168 @@ +package com.menagerie.ophelia.view + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.modifier.modifierLocalConsumer +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringArrayResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.unit.dp +import com.menagerie.ophelia.R + +@Composable +fun OpheliaSpanStyle(): SpanStyle { + val fontFamily = FontFamily( + Font(R.font.calligraffitti) + ) + + return SpanStyle( + letterSpacing = MaterialTheme.typography.bodyLarge.letterSpacing, + fontFamily = fontFamily, + fontSize = MaterialTheme.typography.bodyLarge.fontSize) +} + +@Composable +fun OpheliaFace( + modifier: Modifier +) { + Image( + modifier = modifier, + painter = painterResource(id = R.drawable.ophelia_foreground), + contentDescription = OpheliaSays() + ) +} + +@Composable +fun OpheliaSaysArray( + id: Int, + separator: String = "\n\n" +): AnnotatedString { + return buildAnnotatedString { + pushStyle(OpheliaSpanStyle()) + append(stringArrayResource(id = id).joinToString(separator = separator)) + toAnnotatedString() + } +} + +@Composable +fun OpheliaSays( + say: String +): AnnotatedString { + return buildAnnotatedString { + pushStyle(OpheliaSpanStyle()) + append(say) + toAnnotatedString() + } +} + +@Composable +fun OpheliaSays(): String { + return stringResource(id = R.string.ophelia_says) +} + + +@Composable +fun OpheliaWelcome( + modifier: Modifier +) { + Box( + modifier = modifier + .fillMaxSize() + .padding(24.dp) + ) { + Text( + text = OpheliaSaysArray(id = R.array.welcome_blurb) + ) + } +} + +@Composable +fun OpheliaWhatsYourName( + modifier: Modifier +) { + Box( + modifier = modifier + .fillMaxWidth() + .padding(12.dp) + ) { + Text(text = OpheliaSaysArray(id = R.array.whats_your_name)) + } +} + +@Composable +fun OpheliaPronounsIntroduction( + modifier: Modifier, + name: String +) { + Box( + modifier = modifier + .fillMaxWidth() + .padding(12.dp) + ) { + Column { + val context = LocalContext.current + Text(text = OpheliaSays(context.resources.getString(R.string.introduction_with_name, name))) + Text(text = OpheliaSaysArray(id = R.array.introduction_to_pronouns)) + } + } +} + +@Composable +fun OpheliaTagsIntroduction( + modifier: Modifier, +) { + Box( + modifier = modifier + .fillMaxWidth() + .padding(12.dp) + ) { + Column { + Text(text = OpheliaSaysArray(R.array.introduction_to_tags)) + } + } +} + +@Composable +fun OpheliaNewUserFinalCheck( + modifier: Modifier, +){ + Box( + modifier = modifier + .fillMaxWidth() + .padding(12.dp) + ) { + Column { + Text(text = OpheliaSays(stringResource(id = R.string.final_check_in))) + } + } +} + +@Composable +fun OpheliaNewUserPolycule( + modifier: Modifier, +) { + Box( + modifier = modifier + .fillMaxWidth() + .padding(12.dp) + ) { + Column { + Text(text = OpheliaSaysArray(id = R.array.introduction_to_polycules)) + } + } +} diff --git a/app/src/main/java/com/menagerie/ophelia/view/PolyculeApp.kt b/app/src/main/java/com/menagerie/ophelia/view/PolyculeApp.kt new file mode 100644 index 0000000..9590961 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/PolyculeApp.kt @@ -0,0 +1,108 @@ +package com.menagerie.ophelia.view + +import androidx.compose.runtime.Composable +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.NavType +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import androidx.navigation.navArgument +import com.menagerie.ophelia.database.polycule.PolyculeDatabaseManager +import com.menagerie.ophelia.view.biographies.AddBiography +import com.menagerie.ophelia.view.biographies.AddEditBio +import com.menagerie.ophelia.view.biographies.BioDetailsScreen +import com.menagerie.ophelia.view.biographies.EditBiography +import com.menagerie.ophelia.view.newUser.AddNameScreen +import com.menagerie.ophelia.view.newUser.AddPronounsScreen +import com.menagerie.ophelia.view.newUser.AddTagsScreen +import com.menagerie.ophelia.view.newUser.ConfirmBio +import com.menagerie.ophelia.view.polycule.AddPolyculeScreen +import com.menagerie.ophelia.view.polycule.PolyculeHomeView + +@Composable +fun PolyculeApp() { + val navController = rememberNavController() + PolyculeNavHost( + navController = navController + ) +} + +@Composable +fun PolyculeNavHost( + navController: NavHostController +) { + NavHost( + navController = navController, + startDestination = "confirmBio" + ) { + polyculeGraph(navController) + welcomeGraph(navController) + composable("home") { + HomeScreen() { + navController.navigate("newUserStart") + } + } + } +} + +fun NavGraphBuilder.welcomeGraph(navController: NavHostController) { + composable("newUserStart") { + NewUserStartScreen { navController.navigate("newUserName") } + } + composable("newUserName") { + AddNameScreen { navController.navigate("newUserPronouns") } + } + composable("newUserPronouns") { + AddPronounsScreen { navController.navigate("newUserTags") } + } + composable("newUserTags") { + AddTagsScreen { navController.navigate("confirmBio") } + } + composable("confirmBio") { + ConfirmBio { + navController.popBackStack() + navController.navigate("polyculeHome") + } + } + composable("makePolycule") { + AddPolyculeScreen() + } +} + +fun NavGraphBuilder.polyculeGraph(navController: NavController) { + composable("polyculeHome") { + PolyculeHomeView( + onBioClick = { + navController.navigate("bioDetail/${it.id}") + }, + onAddClick = { + navController.navigate("addBio") {} + } + ) + } + composable( + "bioDetail/{bioId}", + arguments = listOf(navArgument("bioId") { + type = NavType.LongType + }) + ) { + BioDetailsScreen( + id = it.arguments?.getLong("bioId") ?: 0, + onBackClick = { navController.navigateUp() }, + onEditClick = { id -> navController.navigate("editBio/${id}")} + ) + } + composable("addBio") { + AddBiography() + } + composable( + "editBio/{bioId}", + arguments = listOf(navArgument("bioId") { + type = NavType.LongType + }) + ){ + EditBiography(bioId = it.arguments?.getLong("bioId") ?: 0) { navController.navigateUp() } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/biographies/AddEditBio.kt b/app/src/main/java/com/menagerie/ophelia/view/biographies/AddEditBio.kt new file mode 100644 index 0000000..0d1e45e --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/biographies/AddEditBio.kt @@ -0,0 +1,341 @@ +package com.menagerie.ophelia.view.biographies + +import android.annotation.SuppressLint +import android.widget.Toast +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FilterChip +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusDirection +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewmodel.compose.viewModel +import com.menagerie.ophelia.R +import com.menagerie.ophelia.database.polycule.entity.Bio +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioDetailViewModel +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioListViewModel +import com.menagerie.ophelia.view.components.InputFieldState +import com.menagerie.ophelia.view.components.fab.FABComponent +import com.menagerie.ophelia.view.newUser.Tags + +fun insertBioInDB(bio: Bio?, mBioListViewModel: BioListViewModel) { + bio?.let { + mBioListViewModel.upsert(it) + } +} + +@Composable +fun FinishBiography( + bioId: Long, + onGo: () -> Unit +) { + val mBioDetailViewModel = BioDetailViewModel(bioId) + val bio = mBioDetailViewModel.bio.observeAsState().value + + if (bio != null) { + val inputViewModel = InputEditViewModel(bio) + val ioBio: Bio by inputViewModel.bio.observeAsState(bio) + AddEditBio( + ioBio = ioBio, + btnLabel = stringResource(id = R.string.finish), + toast = stringResource(id = R.string.bio_finish_toast), + onGo, + ) + } +} + +@Composable +fun EditBiography( + bioId: Long, + onGo: () -> Unit +) { + val mBioDetailViewModel = BioDetailViewModel(bioId) + val bio = mBioDetailViewModel.bio.observeAsState().value + + if (bio != null) { + val inputViewModel = InputEditViewModel(bio) + val ioBio: Bio by inputViewModel.bio.observeAsState(bio) + AddEditBio( + ioBio = ioBio, + btnLabel = stringResource(id = R.string.edit_bio), + toast = stringResource(id = R.string.bio_edit_toast), + onGo, + ) + } +} + +@Composable +fun AddBiography() { + + val inputViewModel = InputAddViewModel() + val ioBio: Bio by inputViewModel.bio.observeAsState(Bio()) + AddEditBio( + ioBio = ioBio, + btnLabel = stringResource(id = R.string.edit_bio), + toast = stringResource(id = R.string.bio_edit_toast), + ) { + + } +} + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun AddEditBio( + ioBio: Bio, + btnLabel: String, + toast: String, + onGo: () -> Unit +) { + + val mBioListViewModel: BioListViewModel = viewModel( + factory = BioListViewModel.BioListViewModelFactory() + ) + val context = LocalContext.current + + var name by remember { mutableStateOf(ioBio.name) } + var sp by remember { mutableStateOf(ioBio.subjective) } + var op by remember { mutableStateOf(ioBio.objective) } + var pp by remember { mutableStateOf(ioBio.possessive) } + var rp by remember { mutableStateOf(ioBio.reflexive) } + var tags by remember { mutableIntStateOf(ioBio.tags) } + + Scaffold( + floatingActionButton = { + FABComponent(text = btnLabel, onClick = { + insertBioInDB( + Bio( + id = ioBio.id, + name = name, + subjective = sp, + objective = op, + possessive = pp, + reflexive = rp, + tags = tags, + ), + mBioListViewModel + ) + onGo() + Toast.makeText(context, toast, Toast.LENGTH_SHORT).show() + }) + } + ) + { + Column( + modifier = Modifier.padding(12.dp) + ) { + val modifier = Modifier + .width(164.dp) + .height(64.dp) + val focusManager = LocalFocusManager.current + InputFieldState( + value = name, + label = "name", + modifier = modifier, + keyboardActions = KeyboardActions( + onDone = { focusManager.moveFocus(FocusDirection.Next) } + ) + ) { name = it } + Box { + Column { + Row { + InputFieldState( + value = sp, + label = "objective", + modifier = modifier, + keyboardActions = KeyboardActions( + onDone = { focusManager.moveFocus(FocusDirection.Next) } + ) + ) { sp = it } + Text( + text = " / ", + style = MaterialTheme.typography.displayMedium + ) + InputFieldState( + value = op, + label = "subjective", + modifier = modifier, + keyboardActions = KeyboardActions( + onDone = { focusManager.moveFocus(FocusDirection.Next) } + ) + ) { op = it } + } + Row { + InputFieldState( + value = pp, + label = "possessive", + modifier = modifier, + keyboardActions = KeyboardActions( + onDone = { focusManager.moveFocus(FocusDirection.Next) } + ) + ) { pp = it } + Text( + text = " / ", + style = MaterialTheme.typography.displayMedium + ) + InputFieldState( + value = rp, + label = "reflexive", + modifier = modifier, + keyboardActions = KeyboardActions( + onDone = { focusManager.clearFocus() } + ) + ) { rp = it } + } + tagsBox( + tags = tags, + modifier = Modifier + .padding(12.dp) + .size(64.dp) + ) { + tags = it + } + } + } + } + } +} + +@Composable +fun tagsBox( + tags: Int, + modifier: Modifier, + onValChange: (Int) -> Unit +) { + + Row { + RememberableButton( + tagList = tags, + tag = Tags.TRANS, + painter = painterResource(id = R.drawable.trans_tag), + modifier = modifier, + onValChange = onValChange) + + RememberableButton( + tagList = tags, + tag = Tags.FURRY, + painter = painterResource(id = R.drawable.furry_tag), + modifier = modifier, + onValChange = onValChange) + + RememberableButton( + tagList = tags, + tag = Tags.ASEXUAL, + painter = painterResource(id = R.drawable.asexual_tag), + modifier = modifier, + onValChange = onValChange) + } + + + Row { + RememberableButton( + tagList = tags, + tag = Tags.BDSM, + painter = painterResource(id = R.drawable.bdsm_tag), + modifier = modifier, + onValChange = onValChange) + + RememberableButton( + tagList = tags, + tag = Tags.MONO, + painter = painterResource(id = R.drawable.mono_tag), + modifier = modifier, + onValChange = onValChange) + + RememberableButton( + tagList = tags, + tag = Tags.ALCOHOL, + painter = painterResource(id = R.drawable.liqour_tag), + modifier = modifier, + onValChange = onValChange) + } + + Row { + RememberableButton( + tagList = tags, + tag = Tags.WEED, + painter = painterResource(id = R.drawable.weed_tag), + modifier = modifier, + onValChange = onValChange) + + RememberableButton( + tagList = tags, + tag = Tags.THERIAN, + painter = painterResource(id = R.drawable.therian_tag), + modifier = modifier, + onValChange = onValChange) + + RememberableButton( + tagList = tags, + tag = Tags.PLURAL, + painter = painterResource(id = R.drawable.plural_tag), + modifier = modifier, + onValChange = onValChange) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun RememberableButton( + tagList: Int, + tag: Tags, + modifier: Modifier, + painter: Painter, + onValChange: (Int) -> Unit, +) { + var selected = tagList and tag.value == tag.value + + Box { + FilterChip( + selected = selected, + onClick = { onValChange(tagList xor tag.value) }, + modifier = modifier, + shape = CircleShape, + label = { + Icon( + modifier = Modifier.padding(horizontal = 4.dp), + painter = painter, + contentDescription = "" + ) + }, + ) + } +} + +class InputEditViewModel( + bio: Bio +) : ViewModel() { + private val _bio: MutableLiveData = MutableLiveData(bio) + val bio: LiveData = _bio +} + +class InputAddViewModel() : ViewModel() { + private val _bio: MutableLiveData = MutableLiveData(Bio()) + val bio: LiveData = _bio +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/biographies/BioCard.kt b/app/src/main/java/com/menagerie/ophelia/view/biographies/BioCard.kt new file mode 100644 index 0000000..ce1f33d --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/biographies/BioCard.kt @@ -0,0 +1,103 @@ +package com.menagerie.ophelia.view.biographies + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +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.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +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.MaterialTheme +import androidx.compose.material3.Text +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.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.menagerie.ophelia.R + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun BioCard( + name: String, + image: Int, + onBioClick: () -> Unit, + onDeleteClick: () -> Unit +) { + var expanded by remember { mutableStateOf(false) } + + Card( + onClick = onBioClick, + modifier = Modifier + .padding(10.dp) + .fillMaxWidth() + .wrapContentHeight(), + shape = MaterialTheme.shapes.medium, + elevation = CardDefaults.cardElevation( + defaultElevation = 6.dp + ), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surface + ), + border = BorderStroke(1.dp, Color.Black), + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + painter = painterResource(id = R.drawable.ic_app_logo), + contentDescription = null, + modifier = Modifier + .size(130.dp) + .padding(8.dp), + contentScale = ContentScale.Fit, + ) + Column(modifier = Modifier.padding(8.dp)) { + Text( + text = name, + style = MaterialTheme.typography.headlineSmall, + color = MaterialTheme.colorScheme.onSurface, + ) + } + Spacer(modifier = Modifier + .weight(1f) + .fillMaxSize()) + Box( + modifier = Modifier + .wrapContentSize(Alignment.TopStart) + ) + { + IconButton( + onClick = { expanded = true }) { + Icon( + Icons.Default.MoreVert, + contentDescription = "" + ) + } + DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { + DropdownMenuItem(text = { Text(text = "Delete") }, onClick = onDeleteClick) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/biographies/BioCardList.kt b/app/src/main/java/com/menagerie/ophelia/view/biographies/BioCardList.kt new file mode 100644 index 0000000..0f7eb27 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/biographies/BioCardList.kt @@ -0,0 +1,47 @@ +package com.menagerie.ophelia.view.biographies + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.menagerie.ophelia.database.polycule.entity.Bio +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioListViewModel + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun BioCardList( + bioList: List, + onBioClick: (Bio) -> Unit = {}, +) { + val mBioListViewModel: BioListViewModel = viewModel( + factory = BioListViewModel.BioListViewModelFactory() + ) + + Box(modifier = Modifier.padding()) { + LazyColumn( + modifier = Modifier.fillMaxWidth(), + contentPadding = PaddingValues(8.dp) + ) { + items(bioList) { bio -> + BioCard( + name = bio.name, + image = bio.pfpRes, + onBioClick = { onBioClick(bio) }, + onDeleteClick = { mBioListViewModel.delete(bio) }) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/biographies/BioDetailsScreen.kt b/app/src/main/java/com/menagerie/ophelia/view/biographies/BioDetailsScreen.kt new file mode 100644 index 0000000..6cb50fe --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/biographies/BioDetailsScreen.kt @@ -0,0 +1,122 @@ +package com.menagerie.ophelia.view.biographies + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import com.menagerie.ophelia.R +import com.menagerie.ophelia.database.polycule.entity.Bio +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioDetailViewModel +import com.menagerie.ophelia.view.components.fab.FABComponent +import com.menagerie.ophelia.view.components.utils.Dimens + +data class BioDetailCallbacks( + val onBackClick: () -> Unit, + val onEditClick: (Long) -> Unit +) + +@Composable +fun BioDetailsScreen( + id: Long, + onBackClick: () -> Unit, + onEditClick: (Long) -> Unit, +) { + val mBioDetailViewModel = BioDetailViewModel(id) + + val bio = mBioDetailViewModel.bio.observeAsState().value + + if (bio != null) { + Surface { + BioDetails( + bio, + BioDetailCallbacks( + onBackClick = onBackClick, + onEditClick = onEditClick, + ) + ) + } + } +} + +@Composable +fun BioDetails( + bio: Bio, + callbacks: BioDetailCallbacks, + modifier: Modifier = Modifier +) { + Box( + modifier + .fillMaxSize() + ) { + BioDetailContents( + bio = bio, + onEdit = callbacks.onEditClick + ) + } +} + +@Composable +fun BioDetailContents( + bio: Bio, + onEdit: (Long) -> Unit, +) { + Column { + InfoDetails( + bio = bio, + onEdit = onEdit, + modifier = Modifier + ) + } +} + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun InfoDetails( + bio: Bio, + onEdit: (Long) -> Unit, + modifier: Modifier = Modifier +) { + Scaffold( + floatingActionButton = { + FABComponent( + text = "${stringResource(id = R.string.edit_bio)}", + onClick = { onEdit(bio.id) } + ) + } + ) { + Column(modifier = modifier.padding(Dimens.PaddingLarge)) { + Text( + text = bio.name, + style = MaterialTheme.typography.displaySmall, + modifier = Modifier + .padding( + start = Dimens.PaddingSmall, + end = Dimens.PaddingSmall, + bottom = Dimens.PaddingNormal + ) + .align(Alignment.CenterHorizontally) + ) + Box( + Modifier + .align(Alignment.CenterHorizontally) + .padding( + start = Dimens.PaddingSmall, + end = Dimens.PaddingSmall, + bottom = Dimens.PaddingNormal + ) + ) { + Text(text = "${bio.subjective} / ${bio.objective} / ${bio.possessive} / ${bio.reflexive}") + } + } + } +} diff --git a/app/src/main/java/com/menagerie/ophelia/view/biographies/TagCard.kt b/app/src/main/java/com/menagerie/ophelia/view/biographies/TagCard.kt new file mode 100644 index 0000000..92a4079 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/biographies/TagCard.kt @@ -0,0 +1,86 @@ +package com.menagerie.ophelia.view.biographies + +import android.util.Log +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +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.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.dp + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun TagCard( + name: String, + painter: Painter, + details: String, + check: Boolean, + onClick: () -> Unit +) { + var checked by remember { mutableStateOf(check) } + + Card( + modifier = Modifier + .padding(8.dp) + .fillMaxWidth() + .wrapContentHeight(), + shape = MaterialTheme.shapes.medium, + elevation = CardDefaults.cardElevation( + defaultElevation = 6.dp + ), + colors = CardDefaults.cardColors( + containerColor = + if (checked) MaterialTheme.colorScheme.primaryContainer + else MaterialTheme.colorScheme.surface + ), + border = BorderStroke(1.dp, Color.Black), + onClick = { + checked = !checked + onClick() + }, + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + painter = painter, + contentDescription = null, + modifier = Modifier + .size(80.dp) + .padding(8.dp), + contentScale = ContentScale.Fit, + ) + Column(modifier = Modifier.padding(8.dp)) { + Text( + text = name, + style = MaterialTheme.typography.headlineSmall, + color = MaterialTheme.colorScheme.onSurface, + ) + //TODO: details blurbs +// Text( +// text = details, +// style = MaterialTheme.typography.headlineSmall, +// color = MaterialTheme.colorScheme.onSurface, +// ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/components/InputFieldComponent.kt b/app/src/main/java/com/menagerie/ophelia/view/components/InputFieldComponent.kt new file mode 100644 index 0000000..4ff51b6 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/components/InputFieldComponent.kt @@ -0,0 +1,69 @@ +package com.menagerie.ophelia.view.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusDirection +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.unit.dp + +@Composable +fun InputFieldComponent( + text: String, + onChange: (String) -> Unit, + modifier: Modifier = Modifier, + singleLine: Boolean = true, + label: String = "Some val", + keyboardActions: KeyboardActions = KeyboardActions.Default, +) { + OutlinedTextField( + value = text, + onValueChange = onChange, + label = { Text(text = label)}, + modifier = modifier, + singleLine = singleLine, + keyboardActions = keyboardActions, + ) +} + + +@Composable +fun InputFieldState( + value: String, + label: String, + modifier: Modifier, + keyboardActions: KeyboardActions = KeyboardActions.Default, + onVal: (String) -> Unit, +) { + + Column( + modifier = Modifier + ) { + InputField(value, label, modifier, onVal, keyboardActions) + Spacer(modifier = Modifier.padding(10.dp)) + } +} + +@Composable +fun InputField( + text: String, + label: String, + modifier: Modifier, + onValChange: ((String) -> Unit)?, + keyboardActions: KeyboardActions, +) { + if (onValChange != null) { + InputFieldComponent( + text = text, + onChange = onValChange, + label = label, + modifier = modifier, + keyboardActions = keyboardActions, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/components/fab/FABComponent.kt b/app/src/main/java/com/menagerie/ophelia/view/components/fab/FABComponent.kt new file mode 100644 index 0000000..457a110 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/components/fab/FABComponent.kt @@ -0,0 +1,20 @@ +package com.menagerie.ophelia.view.components.fab + +import androidx.compose.material3.ExtendedFloatingActionButton +import androidx.compose.material3.FloatingActionButtonDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.dp + +@Composable +fun FABComponent( + text: String, + onClick: () -> Unit +) { + ExtendedFloatingActionButton( + onClick = onClick, + elevation = FloatingActionButtonDefaults.elevation(8.dp) + ) { + Text(text = text) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/components/utils/Dimens.kt b/app/src/main/java/com/menagerie/ophelia/view/components/utils/Dimens.kt new file mode 100644 index 0000000..ecf7620 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/components/utils/Dimens.kt @@ -0,0 +1,25 @@ +package com.menagerie.ophelia.view.components.utils + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.menagerie.ophelia.R + + +object Dimens { +val PaddingSmall: Dp + @Composable get() = dimensionResource(R.dimen.margin_small) + +val PaddingNormal: Dp + @Composable get() = dimensionResource(R.dimen.margin_normal) + +val PaddingLarge: Dp = 24.dp + +val PlantDetailAppBarHeight: Dp + @Composable get() = dimensionResource(R.dimen.plant_detail_app_bar_height) + +val ToolbarIconPadding = 12.dp + +val ToolbarIconSize = 32.dp +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/components/utils/TextSnackbarContainer.kt b/app/src/main/java/com/menagerie/ophelia/view/components/utils/TextSnackbarContainer.kt new file mode 100644 index 0000000..71a2719 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/components/utils/TextSnackbarContainer.kt @@ -0,0 +1,61 @@ +package com.menagerie.ophelia.view.components.utils + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Shapes +import androidx.compose.material3.Snackbar +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun TextSnackbarContainer( + snackbarText: String, + showSnackbar: Boolean, + onDismissSnackbar: () -> Unit, + modifier: Modifier = Modifier, + snackbarHostState: SnackbarHostState = remember{ SnackbarHostState()}, + content: @Composable () -> Unit, +) { + Box(modifier) { + content() + + val onDismissState by rememberUpdatedState(onDismissSnackbar) + LaunchedEffect(showSnackbar, snackbarText) { + if (showSnackbar) { + try { + snackbarHostState.showSnackbar( + message = snackbarText, + duration = SnackbarDuration.Short + ) + } finally { + onDismissState() + } + } + } + + + MaterialTheme(shapes = Shapes()) { + SnackbarHost( + hostState = snackbarHostState, + modifier = modifier + .align(Alignment.BottomCenter) + .systemBarsPadding() + .padding(all = 8.dp), + ) { + Snackbar(it) + } + + } + } +} diff --git a/app/src/main/java/com/menagerie/ophelia/view/newUser/AddNameScreen.kt b/app/src/main/java/com/menagerie/ophelia/view/newUser/AddNameScreen.kt new file mode 100644 index 0000000..3d923f2 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/newUser/AddNameScreen.kt @@ -0,0 +1,81 @@ +package com.menagerie.ophelia.view.newUser + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Column +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.foundation.layout.width +import androidx.compose.material3.Button +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.menagerie.ophelia.database.polycule.entity.Bio +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioListViewModel +import com.menagerie.ophelia.view.OpheliaFace +import com.menagerie.ophelia.view.OpheliaWhatsYourName +import com.menagerie.ophelia.view.biographies.insertBioInDB +import com.menagerie.ophelia.view.components.InputFieldState + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun AddNameScreen( + onGo: () -> Unit, +) { + val inputViewModel = BioListViewModel.InputBioViewModel() + val mBioListViewModel: BioListViewModel = viewModel( + factory = BioListViewModel.BioListViewModelFactory() + ) + Scaffold { + Column( + modifier = Modifier.fillMaxSize() + ) { + val bio: Bio by inputViewModel.bio.observeAsState(Bio()) + + OpheliaFace( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 12.dp) + ) + LinearProgressIndicator( + progress = 0f, + modifier = Modifier.fillMaxWidth() + ) + OpheliaWhatsYourName(modifier = Modifier) + InputFieldState( + value = bio.name, + label = "name", + modifier = Modifier + .width(120.dp) + ) { inputViewModel.onNameChange(it) } + Spacer( + modifier = Modifier + .fillMaxSize() + .weight(1f) + + ) + Button( + modifier = Modifier + .align(Alignment.End), + onClick = { + insertBioInDB(inputViewModel.bio.value, mBioListViewModel) + onGo() + } + ) { + Text(text = "Continue") + } + } + } +} + diff --git a/app/src/main/java/com/menagerie/ophelia/view/newUser/AddPronounsScreen.kt b/app/src/main/java/com/menagerie/ophelia/view/newUser/AddPronounsScreen.kt new file mode 100644 index 0000000..baf47fa --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/newUser/AddPronounsScreen.kt @@ -0,0 +1,158 @@ +package com.menagerie.ophelia.view.newUser + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.material3.Button +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusDirection +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.menagerie.ophelia.database.polycule.entity.Bio +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioDetailViewModel +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioListViewModel +import com.menagerie.ophelia.view.OpheliaFace +import com.menagerie.ophelia.view.OpheliaPronounsIntroduction +import com.menagerie.ophelia.view.components.InputField + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun AddPronounsScreen( + onGo : () -> Unit +) { + val mBioDetailViewModel = BioDetailViewModel(1) + val mBioListViewModel: BioListViewModel = viewModel( + factory = BioListViewModel.BioListViewModelFactory() + ) + + val bio = mBioDetailViewModel.bio.observeAsState().value + + Scaffold { + if (bio != null) { + Column { + OpheliaFace( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 12.dp) + ) + LinearProgressIndicator( + progress = .33f, + modifier = Modifier.fillMaxWidth() + ) + OpheliaPronounsIntroduction(modifier = Modifier.weight(1f), name = bio.name) + PronounBox(Modifier.weight(1f)) { + val updateBio = Bio( + id = bio.id, + name = bio.name, + subjective = it[0], + objective = it[1], + possessive = it[2], + reflexive = it[3], + ) + mBioListViewModel.upsert(updateBio) + onGo() + } + } + } + } +} + +@Composable +fun PronounBox( + modifier: Modifier, + onClick: (List) -> Unit, +) { + var subject by remember { mutableStateOf("") } + var objec by remember { mutableStateOf("") } + var possess by remember { mutableStateOf("") } + var reflex by remember { mutableStateOf("") } + + + Box(modifier = Modifier.fillMaxWidth()) + { + Column { + val focusManager = LocalFocusManager.current + Row { + InputField( + text = subject, + label = "subjective", + modifier = modifier, + onValChange = { subject = it }, + keyboardActions = KeyboardActions( + onDone = { focusManager.moveFocus(FocusDirection.Next) } + ), + ) + Text( + text = " / ", + style = MaterialTheme.typography.displayMedium + ) + InputField( + text = objec, + label = "objective", + modifier = modifier, + onValChange = { objec = it }, + keyboardActions = KeyboardActions( + onDone = { focusManager.moveFocus(FocusDirection.Next) } + ), + ) + } + Row { + InputField( + text = possess, + label = "possessive", + modifier = modifier, + onValChange = { possess = it }, + keyboardActions = KeyboardActions( + onDone = { focusManager.moveFocus(FocusDirection.Next) } + ), + ) + Text( + text = " / ", + style = MaterialTheme.typography.displayMedium + ) + InputField( + text = reflex, + label = "reflexive", + modifier = modifier, + onValChange = { reflex = it }, + keyboardActions = KeyboardActions( + onDone = { focusManager.clearFocus() } + ), + ) + } + Spacer( + modifier = Modifier.size(60.dp) + ) + Button( + onClick = { + onClick(listOf(subject, objec, possess, reflex)) + }, + modifier = Modifier + .align( + alignment = Alignment.End + ) + .padding(8.dp) + ) { + Text(text = "Continue") + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/newUser/AddTagsScreen.kt b/app/src/main/java/com/menagerie/ophelia/view/newUser/AddTagsScreen.kt new file mode 100644 index 0000000..882ed58 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/newUser/AddTagsScreen.kt @@ -0,0 +1,195 @@ +package com.menagerie.ophelia.view.newUser + +import android.annotation.SuppressLint +import android.util.Log +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Button +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.menagerie.ophelia.R +import com.menagerie.ophelia.database.polycule.entity.Bio +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioDetailViewModel +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioListViewModel +import com.menagerie.ophelia.view.OpheliaFace +import com.menagerie.ophelia.view.OpheliaTagsIntroduction +import com.menagerie.ophelia.view.biographies.TagCard + +enum class Tags(val value: Int) +{ + TRANS(1), + FURRY(2), + ASEXUAL(4), + BDSM(8), + MONO(16), + ALCOHOL(32), + WEED(64), + THERIAN(128), + PLURAL(256), +} + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun AddTagsScreen( + onGo : () -> Unit +) { + Scaffold { + Column { + OpheliaFace( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 12.dp) + ) + LinearProgressIndicator( + progress = .66f, + modifier = Modifier.fillMaxWidth() + ) + OpheliaTagsIntroduction(modifier = Modifier.weight(1f)) + MakeDefaultTagCards(modifier = Modifier.weight(2f)) + Button( + onClick = onGo, + modifier = Modifier + .weight(.25f) + .align(Alignment.End)) { + Text(text = "Continue") + } + } + } +} + +@Composable +fun MakeDefaultTagCards( + modifier: Modifier, +) { + var flags by remember { mutableIntStateOf(0) } + + val mBioDetailViewModel = BioDetailViewModel(1) + val mBioListViewModel: BioListViewModel = viewModel( + factory = BioListViewModel.BioListViewModelFactory() + ) + + val bio = mBioDetailViewModel.bio.observeAsState().value + + if (bio != null) { + val updateBio = Bio( + id = bio.id, + name = bio.name, + subjective = bio.subjective, + objective = bio.objective, + possessive = bio.possessive, + reflexive = bio.reflexive, + tags = flags + ) + mBioListViewModel.upsert(updateBio) + + Box(modifier = modifier) { + LazyColumn { + item { + TagCard( + name = "Transgender", + painter = painterResource(id = R.drawable.trans_tag), + details = "", + check = flags and Tags.TRANS.value == Tags.TRANS.value + ) { + flags = flags xor Tags.TRANS.value + } + } + item { + TagCard( + name = "Furry", + painter = painterResource(id = R.drawable.furry_tag), + details = "", + check = flags and Tags.FURRY.value == Tags.FURRY.value + ) { + flags = flags xor Tags.FURRY.value + } + } + item { + TagCard( + name = "Therian", + painter = painterResource(id = R.drawable.therian_tag), + details = "", + check = flags and Tags.THERIAN.value == Tags.THERIAN.value + ) { + flags = flags xor Tags.THERIAN.value + } + } + item { + TagCard( + name = "Monogamous", + painter = painterResource(id = R.drawable.mono_tag), + details = "", + check = flags and Tags.MONO.value == Tags.MONO.value + ) { + flags = flags xor Tags.MONO.value + } + } + item { + TagCard( + name = "BDSM", + painter = painterResource(id = R.drawable.bdsm_tag), + details = "", + check = flags and Tags.BDSM.value == Tags.BDSM.value + ) { + flags = flags xor Tags.BDSM.value + } + } + item { + TagCard( + name = "Plural", + painter = painterResource(id = R.drawable.plural_tag), + details = "", + check = flags and Tags.PLURAL.value == Tags.PLURAL.value + ) { + flags = flags xor Tags.PLURAL.value + } + } + item { + TagCard( + name = "Asexual", + painter = painterResource(id = R.drawable.asexual_tag), + details = "", + check = flags and Tags.ASEXUAL.value == Tags.ASEXUAL.value + ) { + flags = flags xor Tags.ASEXUAL.value + } + } + item { + TagCard( + name = "Alcohol", + painter = painterResource(id = R.drawable.liqour_tag), + details = "", + check = flags and Tags.ALCOHOL.value == Tags.ALCOHOL.value + ) { + flags = flags xor Tags.ALCOHOL.value + } + } + item { + TagCard( + name = "Weed", + painter = painterResource(id = R.drawable.weed_tag), + details = "", + check = flags and Tags.WEED.value == Tags.WEED.value + ) { + flags = flags xor Tags.WEED.value + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/newUser/ConfirmBio.kt b/app/src/main/java/com/menagerie/ophelia/view/newUser/ConfirmBio.kt new file mode 100644 index 0000000..ada8fae --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/newUser/ConfirmBio.kt @@ -0,0 +1,40 @@ +package com.menagerie.ophelia.view.newUser + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.menagerie.ophelia.view.OpheliaFace +import com.menagerie.ophelia.view.OpheliaNewUserFinalCheck +import com.menagerie.ophelia.view.biographies.FinishBiography + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun ConfirmBio( + onGo: () -> Unit +) { + Scaffold { + Column { + OpheliaFace( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 12.dp) + ) + LinearProgressIndicator( + progress = 1f, + modifier = Modifier.fillMaxWidth() + ) + OpheliaNewUserFinalCheck(modifier = Modifier) + FinishBiography( + bioId = 1, + onGo = onGo, + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/polycule/AddPolyculeScreen.kt b/app/src/main/java/com/menagerie/ophelia/view/polycule/AddPolyculeScreen.kt new file mode 100644 index 0000000..45ce9dd --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/polycule/AddPolyculeScreen.kt @@ -0,0 +1,29 @@ +package com.menagerie.ophelia.view.polycule + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.menagerie.ophelia.view.OpheliaFace +import com.menagerie.ophelia.view.OpheliaNewUserPolycule + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun AddPolyculeScreen( +) { + Scaffold { + Column { + OpheliaFace( + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 12.dp) + ) + OpheliaNewUserPolycule(modifier = Modifier) + //TODO : Polycules + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/polycule/PolyculeHomeView.kt b/app/src/main/java/com/menagerie/ophelia/view/polycule/PolyculeHomeView.kt new file mode 100644 index 0000000..732baf7 --- /dev/null +++ b/app/src/main/java/com/menagerie/ophelia/view/polycule/PolyculeHomeView.kt @@ -0,0 +1,93 @@ +package com.menagerie.ophelia.view.polycule + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.Scaffold +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.runtime.Composable +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Modifier +import androidx.lifecycle.viewmodel.compose.viewModel +import com.menagerie.ophelia.database.polycule.entity.Bio +import com.menagerie.ophelia.database.polycule.entity.viewmodel.BioListViewModel +import com.menagerie.ophelia.view.biographies.BioCardList + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PolyculeHomeView( + modifier: Modifier = Modifier, + onBioClick: (Bio) -> Unit = {}, + onAddClick: () -> Unit, +) { + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() + Scaffold( + modifier = modifier, + topBar = { + PolyculeTopAppBar( + onFilterClick = { }, + scrollBehavior = scrollBehavior + ) + } + ) { + PolyculeHomeScreen( + onBioClick = onBioClick, + onAddClick = onAddClick, + modifier = modifier.padding(it) + ) + } +} + +@Composable +fun PolyculeHomeScreen( + onBioClick: (Bio) -> Unit, + onAddClick: () -> Unit = {}, + modifier: Modifier, +) { + val mBioListViewModel: BioListViewModel = viewModel( + factory = BioListViewModel.BioListViewModelFactory() + ) + val items = mBioListViewModel.allBios.observeAsState(listOf()).value + + Column( + modifier = modifier + ) { + BioCardList(bioList = items, onBioClick = onBioClick) + FloatingActionButton( + onClick = onAddClick + ) { + Icon(Icons.Filled.Add, "Add Bio") + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PolyculeTopAppBar( + onFilterClick: () -> Unit, + modifier: Modifier = Modifier, + scrollBehavior: TopAppBarScrollBehavior, +) { + TopAppBar( + title = { + Row( + Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + } + }, + modifier = modifier.statusBarsPadding(), + actions = {}, + scrollBehavior = scrollBehavior + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/menagerie/ophelia/view/splash/SplashActivity().kt b/app/src/main/java/com/menagerie/ophelia/view/splash/SplashActivity().kt index 5516a1f..55a81fe 100644 --- a/app/src/main/java/com/menagerie/ophelia/view/splash/SplashActivity().kt +++ b/app/src/main/java/com/menagerie/ophelia/view/splash/SplashActivity().kt @@ -12,7 +12,6 @@ import kotlinx.coroutines.delay @SuppressLint("CustomSplashScreen") class SplashActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { @@ -25,12 +24,13 @@ class SplashActivity : ComponentActivity() { lifecycleScope.launchWhenCreated { delay(1500) - val intent = Intent(this@SplashActivity, - MainActivity::class.java) + val intent = Intent( + this@SplashActivity, + MainActivity::class.java + ) startActivity(intent) finish() } } - } \ No newline at end of file diff --git a/app/src/main/res/drawable/asexual_tag.xml b/app/src/main/res/drawable/asexual_tag.xml new file mode 100644 index 0000000..ef6bfa4 --- /dev/null +++ b/app/src/main/res/drawable/asexual_tag.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/bdsm_tag.xml b/app/src/main/res/drawable/bdsm_tag.xml new file mode 100644 index 0000000..f059ad3 --- /dev/null +++ b/app/src/main/res/drawable/bdsm_tag.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_splash.xml b/app/src/main/res/drawable/bg_splash.xml index 3b23538..2bf4a4a 100644 --- a/app/src/main/res/drawable/bg_splash.xml +++ b/app/src/main/res/drawable/bg_splash.xml @@ -6,6 +6,6 @@ + android:src="@drawable/ic_app_logo"/> \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_splash_12.xml b/app/src/main/res/drawable/bg_splash_12.xml index 9567ad8..ee68be4 100644 --- a/app/src/main/res/drawable/bg_splash_12.xml +++ b/app/src/main/res/drawable/bg_splash_12.xml @@ -8,6 +8,6 @@ \ No newline at end of file diff --git a/app/src/main/res/drawable/furry_tag.xml b/app/src/main/res/drawable/furry_tag.xml new file mode 100644 index 0000000..df83859 --- /dev/null +++ b/app/src/main/res/drawable/furry_tag.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9..0000000 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/liqour_tag.xml b/app/src/main/res/drawable/liqour_tag.xml new file mode 100644 index 0000000..086654f --- /dev/null +++ b/app/src/main/res/drawable/liqour_tag.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/drawable/mono_tag.xml b/app/src/main/res/drawable/mono_tag.xml new file mode 100644 index 0000000..0a14708 --- /dev/null +++ b/app/src/main/res/drawable/mono_tag.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/plural_tag.xml b/app/src/main/res/drawable/plural_tag.xml new file mode 100644 index 0000000..8038fe7 --- /dev/null +++ b/app/src/main/res/drawable/plural_tag.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/app/src/main/res/drawable/therian_tag.xml b/app/src/main/res/drawable/therian_tag.xml new file mode 100644 index 0000000..d96049f --- /dev/null +++ b/app/src/main/res/drawable/therian_tag.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/trans_tag.xml b/app/src/main/res/drawable/trans_tag.xml new file mode 100644 index 0000000..7e45dca --- /dev/null +++ b/app/src/main/res/drawable/trans_tag.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/weed_tag.xml b/app/src/main/res/drawable/weed_tag.xml new file mode 100644 index 0000000..23ead7b --- /dev/null +++ b/app/src/main/res/drawable/weed_tag.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/font/alex_brush.xml b/app/src/main/res/font/alex_brush.xml new file mode 100644 index 0000000..f047b6c --- /dev/null +++ b/app/src/main/res/font/alex_brush.xml @@ -0,0 +1,7 @@ + + + diff --git a/app/src/main/res/font/allura.ttf b/app/src/main/res/font/allura.ttf new file mode 100644 index 0000000..6a426b5 Binary files /dev/null and b/app/src/main/res/font/allura.ttf differ diff --git a/app/src/main/res/font/calligraffitti.xml b/app/src/main/res/font/calligraffitti.xml new file mode 100644 index 0000000..e3d4fee --- /dev/null +++ b/app/src/main/res/font/calligraffitti.xml @@ -0,0 +1,7 @@ + + + diff --git a/app/src/main/res/font/mentho.xml b/app/src/main/res/font/mentho.xml new file mode 100644 index 0000000..69a1839 --- /dev/null +++ b/app/src/main/res/font/mentho.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml new file mode 100644 index 0000000..8e0008b --- /dev/null +++ b/app/src/main/res/navigation/nav_graph.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values-v31/themes.xml b/app/src/main/res/values-v31/themes.xml index 6f4f49c..120cbe6 100644 --- a/app/src/main/res/values-v31/themes.xml +++ b/app/src/main/res/values-v31/themes.xml @@ -1,6 +1,6 @@ -