diff --git a/.gitignore b/.gitignore index 524f096..10cfdbf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,10 @@ -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* +*.iml +.gradle +/local.properties +/.idea +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /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 0000000..aad530d --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,67 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "com.ofthemasses.self_management_app" + compileSdk = 34 + + defaultConfig { + applicationId = "com.ofthemasses.self_management_app" + minSdk = 24 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + 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 + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.1" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") + implementation("androidx.activity:activity-compose:1.7.0") + implementation(platform("androidx.compose:compose-bom:2023.08.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.material:material-icons-extended-android:1.6.2") + implementation("androidx.viewpager2:viewpager2:1.0.0") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00")) + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + debugImplementation("androidx.compose.ui:ui-tooling") + debugImplementation("androidx.compose.ui:ui-test-manifest") +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /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/app/src/androidTest/java/com/ofthemasses/self_management_app/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/ofthemasses/self_management_app/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..43f8d09 --- /dev/null +++ b/app/src/androidTest/java/com/ofthemasses/self_management_app/ExampleInstrumentedTest.kt @@ -0,0 +1,22 @@ +package com.ofthemasses.self_management_app + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.* +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.ofthemasses.self_management_app", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..6d6a4fa --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/ofthemasses/self_management_app/MainActivity.kt b/app/src/main/java/com/ofthemasses/self_management_app/MainActivity.kt new file mode 100644 index 0000000..84fcc72 --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/MainActivity.kt @@ -0,0 +1,41 @@ +package com.ofthemasses.self_management_app + +import android.os.Bundle +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.viewpager2.adapter.FragmentStateAdapter +import androidx.viewpager2.widget.ViewPager2 +import com.ofthemasses.self_management_app.fragments.FullListFragment +import com.ofthemasses.self_management_app.fragments.NextToDoFragment + +class MainActivity : FragmentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + val viewPager: ViewPager2 = findViewById(R.id.viewPager) + val adapter = ViewPagerAdapter(this) + adapter.addFragment(NextToDoFragment()) + adapter.addFragment(FullListFragment()) + viewPager.adapter = adapter + } +} + +class ViewPagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) { + private val fragments: MutableList = mutableListOf() + + fun addFragment(fragment: Fragment) { + fragments.add(fragment) + } + + override fun getItemCount(): Int { + return fragments.size + } + + override fun createFragment(position: Int): Fragment { + return fragments[position] + } +} diff --git a/app/src/main/java/com/ofthemasses/self_management_app/diary/DiaryEntry.kt b/app/src/main/java/com/ofthemasses/self_management_app/diary/DiaryEntry.kt new file mode 100644 index 0000000..617bdec --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/diary/DiaryEntry.kt @@ -0,0 +1,19 @@ +package com.ofthemasses.self_management_app.diary + +data class DiaryEntry( + val date: String, + val description: String, + val toDos: ArrayList>, + val sections: ArrayList> +) { + fun getTodoByIndex(index: Int, statusFilter: Int? = null): ToDo? { + val flattenedTodos = toDos.flatten() + + if (index < 0 || index >= flattenedTodos.size) return null + + if (statusFilter == null) { + return flattenedTodos.filterNotNull().getOrNull(index) + } + return flattenedTodos.filterNotNull().filter { it.status == statusFilter }.getOrNull(index) + } +} diff --git a/app/src/main/java/com/ofthemasses/self_management_app/diary/DiarySerializer.kt b/app/src/main/java/com/ofthemasses/self_management_app/diary/DiarySerializer.kt new file mode 100644 index 0000000..a5a7462 --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/diary/DiarySerializer.kt @@ -0,0 +1,190 @@ +package com.ofthemasses.self_management_app.diary + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.Settings +import android.util.Log +import androidx.annotation.RequiresApi +import com.ofthemasses.self_management_app.BuildConfig +import java.io.File +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +class DiarySerializer : Activity() { + + companion object { + private val STORAGE_PERM_CODE = 100 + + private val DIARY_FOLDER_PATH = + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).toString() + + "/Vimwiki/diary/" + + private var instance: DiarySerializer? = null + + private var DiaryEntries = HashMap() + + @RequiresApi(Build.VERSION_CODES.O) + fun deserializeToday(): DiaryEntry { + val curDate = LocalDateTime.now().minusHours(1) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") + val curDateString = formatter.format(curDate) + + val file = File(String.format("%s%s.md", DIARY_FOLDER_PATH, curDateString)) + return deserializeMarkdown(file) + } + + fun serializeDiaryEntry(entry: DiaryEntry): Boolean { + val entryBuilder = StringBuilder() + + entryBuilder + .appendLine(String.format("# %s", entry.date)) + .appendLine() + .appendLine(String.format("### %s", entry.description)) + .appendLine() + .appendLine("## To-Do List") + + entry.toDos.forEachIndexed { index, section -> + if (index != 0) entryBuilder.appendLine("---") + section.forEach { todo -> + val formattedTodo = + when (todo?.status) { + -1 -> "- ~~${todo.name}~~" + 0 -> "- [ ] ${todo.name}" + 1 -> "- [X] ${todo.name}" + else -> "" + } + entryBuilder.appendLine(formattedTodo) + } + } + + entry.sections.forEach { (title, description) -> + entryBuilder.appendLine(title).append(description) + } + + try { + File(String.format("%s%s.md", DIARY_FOLDER_PATH, entry.date)) + .writeText(entryBuilder.toString()) + return true + } catch (e: Exception) { + return false + } + } + + @RequiresApi(Build.VERSION_CODES.R) + fun checkPermission(activity: Activity?): Boolean { + if (activity == null) { + return false + } + + if (!Environment.isExternalStorageManager()) { + val uri = Uri.parse("package:${BuildConfig.APPLICATION_ID}") + activity.startActivity(Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri)) + + return Environment.isExternalStorageManager() + } + + return true + } + + private fun applicationContext(): Context { + return instance!!.applicationContext + } + + private fun deserializeMarkdown(file: File): DiaryEntry { + val date = file.nameWithoutExtension + + if (DiaryEntries.containsKey(date)) { + return DiaryEntries[date]!! + } + + var description = "" + val toDos = ArrayList>() + toDos.add(ArrayList()) + val sections = ArrayList>() + + var handlingTodos = false + var handlingSections = false + var index = 0 + var todoSection = 0 + var sectionIndex = -1 + try { + file.forEachLine { line -> + if (handlingTodos) { + handlingTodos = !line.startsWith("##") + handlingSections = !handlingTodos + if (!handlingSections) todoSection = handleTodo(line, todoSection, toDos) + } + + if (handlingSections) { + sectionIndex = handleSection(line, sectionIndex, sections) + } + + if (index == 2) { + description = line.drop(4) + } + + if (index == 4) { + handlingTodos = true + } + index++ + } + } catch (e: Exception) { + Log.e(e.message!!, e.stackTraceToString()) + } + + val entry = DiaryEntry(date, description, toDos, sections) + + DiaryEntries[date] = entry + + return entry + } + + private fun handleTodo(line: String, section: Int, todos: ArrayList>): Int { + if (line.startsWith("---")) { + todos.add(ArrayList()) + return section + 1 + } + + if (!line.startsWith('-')) { + todos[section].add(null) + return section + } + + val todoString = line.drop(2) + + when (todoString.substring(0, 2)) { + "~~" -> { + todos[section].add(ToDo(-1, todoString.drop(2).substringBefore("~~"))) + } + "[ " -> { + todos[section].add(ToDo(0, todoString.drop(4))) + } + "[X", + "[x" -> { + todos[section].add(ToDo(1, todoString.drop(4))) + } + } + + return section + } + + private fun handleSection( + line: String, + sectionIndex: Int, + sections: ArrayList> + ): Int { + if (line.startsWith("##")) { + sections.add(Pair(line, "")) + return sectionIndex + 1 + } + + val section = sections[sectionIndex] + sections[sectionIndex] = section.copy(second = section.second + line + "\n") + return sectionIndex + } + } +} diff --git a/app/src/main/java/com/ofthemasses/self_management_app/diary/ToDo.kt b/app/src/main/java/com/ofthemasses/self_management_app/diary/ToDo.kt new file mode 100644 index 0000000..facbac9 --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/diary/ToDo.kt @@ -0,0 +1,3 @@ +package com.ofthemasses.self_management_app.diary + +data class ToDo(var status: Int, val name: String) diff --git a/app/src/main/java/com/ofthemasses/self_management_app/fragments/FullListFragment.kt b/app/src/main/java/com/ofthemasses/self_management_app/fragments/FullListFragment.kt new file mode 100644 index 0000000..09783e2 --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/fragments/FullListFragment.kt @@ -0,0 +1,147 @@ +package com.ofthemasses.self_management_app.fragments + +import android.app.Activity +import android.os.Build +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.RequiresApi +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.sharp.Close +import androidx.compose.material.icons.sharp.Done +import androidx.compose.material.icons.sharp.FiberManualRecord +import androidx.compose.material3.Divider +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.unit.dp +import androidx.core.content.ContentProviderCompat.requireContext +import androidx.fragment.app.Fragment +import com.ofthemasses.self_management_app.diary.DiaryEntry +import com.ofthemasses.self_management_app.diary.DiarySerializer +import com.ofthemasses.self_management_app.diary.ToDo +import com.ofthemasses.self_management_app.ui.theme.SelfmanagementappTheme + +class FullListFragment : Fragment() { + @RequiresApi(Build.VERSION_CODES.R) + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return ComposeView(requireContext()).apply { + setContent { + SelfmanagementappTheme { + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { + FullListView(activity = requireActivity()) + } + } + } + } + } +} + +@RequiresApi(Build.VERSION_CODES.R) +@Composable +fun FullListView(activity: Activity? = null) { + if (!DiarySerializer.checkPermission(activity)) { + // TODO Make it so this waits for permission to be activated + DiarySerializer.checkPermission(activity) + } + + val entry = DiarySerializer.deserializeToday() + val todos: ArrayList> = entry.toDos + Column() { + Spacer( + modifier = + Modifier.height(100.dp).fillMaxWidth().background(MaterialTheme.colorScheme.primary)) + LazyColumn { + items(todos.size) { index -> + todos[index].forEachIndexed { index, todo -> + todo?.let { notNullTodo -> ToDoEntry(notNullTodo, entry) } + } + + if (index < todos.size - 1) { + Spacer(modifier = Modifier.height(20.dp)) + Divider() + } + } + } + } +} + +@Composable +fun ToDoEntry(todo: ToDo, entry: DiaryEntry) { + // TODO these placeholders should be replaced by an empty value + var icon = remember { mutableStateOf(Icons.Sharp.FiberManualRecord) } + var tint = remember { mutableStateOf(Color.White) } + + // TODO this cannot be the only way to give the colours to the ToDoIcon function.. + val tickColour = MaterialTheme.colorScheme.secondary + val dotColour = MaterialTheme.colorScheme.tertiary + + icon.value = ToDoIcon(todo) + tint.value = ToDoTint(todo, tickColour, dotColour) + + Box( + modifier = + Modifier.fillMaxWidth() + .background(if (todo.status == -1) MaterialTheme.colorScheme.outline else Color.White) + .padding(10.dp) + .clickable { + todo.status = 1 + DiarySerializer.serializeDiaryEntry(entry) + icon.value = ToDoIcon(todo) + tint.value = ToDoTint(todo, tickColour, dotColour) + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + modifier = Modifier.padding(start = 4.dp), + imageVector = icon.value, + tint = tint.value, + contentDescription = null) + Text( + modifier = Modifier.padding(start = 10.dp), + text = todo.name, + style = MaterialTheme.typography.bodyLarge) + } + } + Divider() +} + +fun ToDoIcon(todo: ToDo): ImageVector { + return when (todo.status) { + 0 -> Icons.Sharp.FiberManualRecord + 1 -> Icons.Sharp.Done + else -> Icons.Sharp.Close + } +} + +fun ToDoTint(todo: ToDo, tick: Color, dot: Color): Color { + return when (todo.status) { + 0 -> tick + 1 -> dot + else -> Color.White + } +} diff --git a/app/src/main/java/com/ofthemasses/self_management_app/fragments/NextToDoFragment.kt b/app/src/main/java/com/ofthemasses/self_management_app/fragments/NextToDoFragment.kt new file mode 100644 index 0000000..3d67c94 --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/fragments/NextToDoFragment.kt @@ -0,0 +1,113 @@ +package com.ofthemasses.self_management_app.fragments + +import android.app.Activity +import android.os.Build +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.RequiresApi +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.height +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Divider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +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.platform.ComposeView +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.fragment.app.Fragment +import com.ofthemasses.self_management_app.diary.DiarySerializer +import com.ofthemasses.self_management_app.ui.theme.SelfmanagementappTheme + +class NextToDoFragment : Fragment() { + @RequiresApi(Build.VERSION_CODES.R) + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return ComposeView(requireContext()).apply { + setContent { + SelfmanagementappTheme { + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { + NextToDoView(activity = requireActivity()) + } + } + } + } + } +} + +@RequiresApi(Build.VERSION_CODES.R) +@Composable +fun NextToDoView(activity: Activity? = null) { + var mainCardText by remember { mutableStateOf("No TODO") } + var upcomingCardText by remember { mutableStateOf("No TODO") } + + if (!DiarySerializer.checkPermission(activity)) { + // TODO Make it so this waits for permission to be activated + DiarySerializer.checkPermission(activity) + } + + // TODO Update these variables while the app is running to avoid having to re open app + val entry = DiarySerializer.deserializeToday() + + var todo = entry.getTodoByIndex(0, 0) + if (todo != null) mainCardText = todo.name + + var upcomingTodo = entry.getTodoByIndex(1, 0) + if (upcomingTodo != null) upcomingCardText = upcomingTodo.name + + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Spacer( + modifier = + Modifier.height(100.dp).fillMaxWidth().background(MaterialTheme.colorScheme.primary)) + Divider(modifier = Modifier.height(2.dp)) + Box( + modifier = + Modifier.size(width = 300.dp, height = 500.dp).clickable { + if (todo == null) { + return@clickable + } + + todo!!.status = 1 + todo = upcomingTodo + mainCardText = upcomingCardText + upcomingTodo = entry.getTodoByIndex(1, 0) + upcomingCardText = upcomingTodo?.name ?: "No TODO" + DiarySerializer.serializeDiaryEntry(entry) + }, + contentAlignment = Alignment.Center, + ) { + Text( + text = mainCardText, + style = MaterialTheme.typography.headlineLarge, + textAlign = TextAlign.Center) + } + Divider(modifier = Modifier.height(2.dp)) + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text( + text = upcomingCardText, + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center) + } + } +} diff --git a/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Color.kt b/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Color.kt new file mode 100644 index 0000000..aa4f75b --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Color.kt @@ -0,0 +1,10 @@ +package com.ofthemasses.self_management_app.ui.theme + +import androidx.compose.ui.graphics.Color + +val MorningBackground = Color(0XFFFFFFFF) + +val MorningPrimary = Color(0xFF6CA6CD) +val MorningSecondary = Color(0xFFFFA500) +val MorningTertiary = Color(0xFF76F030) +val MorningOutline = Color(0XFFF2F2F2) diff --git a/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Theme.kt b/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Theme.kt new file mode 100644 index 0000000..580dbe6 --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Theme.kt @@ -0,0 +1,32 @@ +package com.ofthemasses.self_management_app.ui.theme + +import android.app.Activity +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.MaterialTheme.colorScheme +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.LocalView + +val ColorScheme = + lightColorScheme( + background = MorningBackground, + primary = MorningPrimary, + secondary = MorningSecondary, + tertiary = MorningTertiary, + outlineVariant = MorningOutline) + +@Composable +fun SelfmanagementappTheme(content: @Composable () -> Unit) { + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = ColorScheme.primary.toArgb() + } + } + + MaterialTheme(colorScheme = ColorScheme, typography = Typography, content = content) +} diff --git a/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Type.kt b/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Type.kt new file mode 100644 index 0000000..1d83d39 --- /dev/null +++ b/app/src/main/java/com/ofthemasses/self_management_app/ui/theme/Type.kt @@ -0,0 +1,35 @@ +package com.ofthemasses.self_management_app.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 + +// Set of Material typography styles to start with +val Typography = + Typography( + bodyLarge = + TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ + ) 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 0000000..07d5da9 --- /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 0000000..2b068d1 --- /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/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..bb59cde --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,11 @@ + + + + + \ 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 0000000..6f3b755 --- /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 0000000..6f3b755 --- /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 0000000..c209e78 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 0000000..b2dfe3d 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 0000000..4f0f1d6 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 0000000..62b611d 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 0000000..948a307 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 0000000..1b9a695 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 0000000..28d4b77 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 0000000..9287f50 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 0000000..aa7d642 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 0000000..9126ae3 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 0000000..f8c6127 --- /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/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..18daed0 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + self-management-app + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..257c332 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +