From d904ac49e6b19b224202dc6b20285a91bf9dec30 Mon Sep 17 00:00:00 2001 From: DataDynamo99 <131844972+DataDynamo99@users.noreply.github.com> Date: Wed, 20 Nov 2024 20:44:03 -0800 Subject: [PATCH 1/3] Add files via upload last project todo list app --- .../android/pomodo/ExampleInstrumentedTest.kt | 24 +++ src/main/AndroidManifest.xml | 31 ++++ src/main/ic_launcher-playstore.png | Bin 0 -> 18427 bytes .../android/pomodo/Adapters/ToDoAdapter.kt | 76 ++++++++ .../bignerdranch/android/pomodo/AddNewTask.kt | 102 +++++++++++ .../android/pomodo/DialogCloseListener.kt | 8 + .../android/pomodo/MainActivity.kt | 152 ++++++++++++++++ .../android/pomodo/Model/ToDoModel.kt | 7 + .../android/pomodo/RecyclerItemTouchHelper.kt | 90 ++++++++++ .../android/pomodo/SplashActivity.kt | 23 +++ .../android/pomodo/Utils/DatabaseHandler.kt | 87 +++++++++ .../android/pomodo/ui/theme/Color.kt | 11 ++ .../android/pomodo/ui/theme/Theme.kt | 70 ++++++++ .../android/pomodo/ui/theme/Type.kt | 34 ++++ .../drawable-v24/ic_launcher_foreground.xml | 19 ++ .../gradient_ic_launcher_foreground.xml | 10 ++ src/main/res/drawable/ic_baseline_add_24.xml | 5 + src/main/res/drawable/ic_baseline_delete.xml | 6 + src/main/res/drawable/ic_baseline_edit.xml | 5 + .../res/drawable/ic_launcher_background.xml | 170 ++++++++++++++++++ src/main/res/drawable/logo.png | Bin 0 -> 4465 bytes src/main/res/layout/activity_main.xml | 38 ++++ src/main/res/layout/activity_splash.xml | 12 ++ src/main/res/layout/new_task.xml | 26 +++ src/main/res/layout/task_layout.xml | 43 +++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1404 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 831 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 2898 bytes src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 982 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1772 bytes src/main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1900 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 3918 bytes src/main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2884 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 5914 bytes src/main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3844 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 7778 bytes src/main/res/values/colors.xml | 23 +++ src/main/res/values/strings.xml | 6 + src/main/res/values/styles.xml | 24 +++ src/main/res/values/themes.xml | 5 + src/main/res/xml/backup_rules.xml | 13 ++ src/main/res/xml/data_extraction_rules.xml | 19 ++ .../android/pomodo/ExampleUnitTest.kt | 17 ++ 45 files changed, 1166 insertions(+) create mode 100644 src/androidTest/java/com/bignerdranch/android/pomodo/ExampleInstrumentedTest.kt create mode 100644 src/main/AndroidManifest.xml create mode 100644 src/main/ic_launcher-playstore.png create mode 100644 src/main/java/com/bignerdranch/android/pomodo/Adapters/ToDoAdapter.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/AddNewTask.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/DialogCloseListener.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/MainActivity.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/Model/ToDoModel.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/RecyclerItemTouchHelper.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/SplashActivity.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/Utils/DatabaseHandler.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/ui/theme/Color.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/ui/theme/Theme.kt create mode 100644 src/main/java/com/bignerdranch/android/pomodo/ui/theme/Type.kt create mode 100644 src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 src/main/res/drawable/gradient_ic_launcher_foreground.xml create mode 100644 src/main/res/drawable/ic_baseline_add_24.xml create mode 100644 src/main/res/drawable/ic_baseline_delete.xml create mode 100644 src/main/res/drawable/ic_baseline_edit.xml create mode 100644 src/main/res/drawable/ic_launcher_background.xml create mode 100644 src/main/res/drawable/logo.png create mode 100644 src/main/res/layout/activity_main.xml create mode 100644 src/main/res/layout/activity_splash.xml create mode 100644 src/main/res/layout/new_task.xml create mode 100644 src/main/res/layout/task_layout.xml create mode 100644 src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 src/main/res/values/colors.xml create mode 100644 src/main/res/values/strings.xml create mode 100644 src/main/res/values/styles.xml create mode 100644 src/main/res/values/themes.xml create mode 100644 src/main/res/xml/backup_rules.xml create mode 100644 src/main/res/xml/data_extraction_rules.xml create mode 100644 src/test/java/com/bignerdranch/android/pomodo/ExampleUnitTest.kt diff --git a/src/androidTest/java/com/bignerdranch/android/pomodo/ExampleInstrumentedTest.kt b/src/androidTest/java/com/bignerdranch/android/pomodo/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..b170ba9 --- /dev/null +++ b/src/androidTest/java/com/bignerdranch/android/pomodo/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.bignerdranch.android.pomodo + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * 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.bignerdranch.android.pomodo", appContext.packageName) + } +} \ No newline at end of file diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8012eea --- /dev/null +++ b/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/ic_launcher-playstore.png b/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..1641f5263cf798a112d3243439e95e44c703ae5b GIT binary patch literal 18427 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 a>(_1Z>+i^gUEtqf*L7}PDY;}D@jn2cbdyd1 literal 0 HcmV?d00001 diff --git a/src/main/java/com/bignerdranch/android/pomodo/Adapters/ToDoAdapter.kt b/src/main/java/com/bignerdranch/android/pomodo/Adapters/ToDoAdapter.kt new file mode 100644 index 0000000..eefddd4 --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/Adapters/ToDoAdapter.kt @@ -0,0 +1,76 @@ +package com.bignerdranch.android.pomodo.Adapters + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.CheckBox +import androidx.recyclerview.widget.RecyclerView +import com.bignerdranch.android.pomodo.AddNewTask +import com.bignerdranch.android.pomodo.DatabaseHandler +import com.bignerdranch.android.pomodo.MainActivity +import com.bignerdranch.android.pomodo.Model.ToDoModel +import com.bignerdranch.android.pomodo.R + +class ToDoAdapter(private val db: DatabaseHandler, private val activity: MainActivity) : + RecyclerView.Adapter() { + + private var todoList: MutableList = mutableListOf() // Change to MutableList + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val itemView = LayoutInflater.from(parent.context) + .inflate(R.layout.task_layout, parent, false) // Ensure task_layout exists in res/layout + return ViewHolder(itemView) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + db.openDatabase() + + val item = todoList[position] + holder.task.text = item.task + holder.task.isChecked = toBoolean(item.status) + holder.task.setOnCheckedChangeListener { _, isChecked -> + db.updateStatus(item.id, if (isChecked) 1 else 0) + } + } + + private fun toBoolean(n: Int): Boolean { + return n != 0 + } + + override fun getItemCount(): Int { + return todoList.size + } + + fun getContext(): Context { + return activity + } + + fun setTasks(todoList: List) { + this.todoList = todoList.toMutableList() // Ensure it's a MutableList + notifyDataSetChanged() + } + + fun deleteItem(position: Int) { + val item = todoList[position] + db.deleteTask(item.id) + todoList.removeAt(position) // Now you can modify todoList directly + notifyItemRemoved(position) + } + + fun editItem(position: Int) { + val item = todoList[position] + val bundle = Bundle().apply { + putInt("id", item.id) + putString("task", item.task) + } + val fragment = AddNewTask().apply { arguments = bundle } + // Ensure MainActivity extends FragmentActivity to use supportFragmentManager + fragment.show(activity.supportFragmentManager, AddNewTask.TAG) + } + + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val task: CheckBox = view.findViewById(R.id.todoCheckBox) // Ensure todoCheckBox exists in task_layout.xml + } +} diff --git a/src/main/java/com/bignerdranch/android/pomodo/AddNewTask.kt b/src/main/java/com/bignerdranch/android/pomodo/AddNewTask.kt new file mode 100644 index 0000000..5a28fdd --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/AddNewTask.kt @@ -0,0 +1,102 @@ +package com.bignerdranch.android.pomodo + + +import android.content.DialogInterface +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.Button +import android.widget.EditText +import androidx.core.content.ContextCompat +import androidx.core.widget.addTextChangedListener +import com.bignerdranch.android.pomodo.Model.ToDoModel +import com.google.android.material.bottomsheet.BottomSheetDialogFragment + + +class AddNewTask : BottomSheetDialogFragment() { + + private lateinit var newTaskText: EditText + private lateinit var newTaskSaveButton: Button + private lateinit var db: DatabaseHandler + + companion object { + const val TAG = "ActionBottomDialog" + + fun newInstance(): AddNewTask { + return AddNewTask() + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NORMAL, R.style.DialogStyle) // Ensuring DialogStyle is referenced correctly + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.new_task, container, false) + dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) + return view + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + newTaskText = view.findViewById(R.id.newTaskText) + newTaskSaveButton = view.findViewById(R.id.newTaskButton) + + var isUpdate = false + val bundle = arguments + if (bundle != null) { + isUpdate = true + val task = bundle.getString("task") + newTaskText.setText(task) + task?.let { + if (it.isNotEmpty()) { + newTaskSaveButton.setTextColor( + ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark) + ) + } + } + } + + db = DatabaseHandler(requireActivity()) + db.openDatabase() + + // Enable or disable the save button based on text input + newTaskText.addTextChangedListener { text -> + if (text.isNullOrEmpty()) { + newTaskSaveButton.isEnabled = false + newTaskSaveButton.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) + } else { + newTaskSaveButton.isEnabled = true + newTaskSaveButton.setTextColor(ContextCompat.getColor(requireContext(), R.color.colorPrimaryDark)) + } + } + + newTaskSaveButton.setOnClickListener { + val text = newTaskText.text.toString() + if (isUpdate) { + db.updateTask(bundle?.getInt("id") ?: 0, text) + } else { + val task = ToDoModel().apply { + this.task = text // Correctly setting task value + this.status = 0 // Correctly setting the status + } + db.insertTask(task) + } + dismiss() + } + } + + override fun onDismiss(dialog: DialogInterface) { + val activity = activity + if (activity is DialogCloseListener) { + activity.handleDialogClose(dialog) + } + } +} diff --git a/src/main/java/com/bignerdranch/android/pomodo/DialogCloseListener.kt b/src/main/java/com/bignerdranch/android/pomodo/DialogCloseListener.kt new file mode 100644 index 0000000..c5581de --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/DialogCloseListener.kt @@ -0,0 +1,8 @@ +package com.bignerdranch.android.pomodo + +import android.content.DialogInterface + +interface DialogCloseListener { + fun handleDialogClose(dialog: DialogInterface) +} + diff --git a/src/main/java/com/bignerdranch/android/pomodo/MainActivity.kt b/src/main/java/com/bignerdranch/android/pomodo/MainActivity.kt new file mode 100644 index 0000000..c298ea0 --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/MainActivity.kt @@ -0,0 +1,152 @@ +package com.bignerdranch.android.pomodo + +import android.os.Bundle +import androidx.activity.compose.setContent +import androidx.appcompat.app.AppCompatActivity +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.bignerdranch.android.pomodo.Model.ToDoModel +import com.bignerdranch.android.pomodo.ui.theme.PomoDoTheme + +class MainActivity : AppCompatActivity() { + + private lateinit var db: DatabaseHandler + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + db = DatabaseHandler(this) // Pass context here + db.openDatabase() + + setContent { + PomoDoTheme { + MainScreen(db = db) // Pass db to MainScreen composable + } + } + } + + @Composable + fun MainScreen(db: DatabaseHandler) { + var taskList by remember { mutableStateOf(listOf()) } + var showDialog by remember { mutableStateOf(false) } + + // Load tasks once + LaunchedEffect(Unit) { + taskList = db.getAllTasks().reversed() // Load tasks initially + } + + // Update task list after adding a task + val updateTasks = { + taskList = db.getAllTasks().reversed() + } + + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.SpaceBetween + ) { + TaskList(tasks = taskList) + + FloatingActionButton( + onClick = { showDialog = true }, + modifier = Modifier.padding(16.dp) + ) { + Text("+") + } + + if (showDialog) { + AddTaskDialog( + onDismiss = { showDialog = false }, + onTaskAdded = updateTasks, + db = db + ) + } + } + } + } + + @Composable + fun TaskList(tasks: List) { + LazyColumn { + items(tasks) { task -> + Text(task.task) // Display task + } + } + } + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + fun AddTaskDialog(onDismiss: () -> Unit, onTaskAdded: () -> Unit, db: DatabaseHandler) { + var newTaskText by remember { mutableStateOf("") } + + AlertDialog( + onDismissRequest = onDismiss, + confirmButton = { + Button( + onClick = { + if (newTaskText.isNotBlank()) { + val newTask = ToDoModel(task = newTaskText) + db.insertTask(newTask) // Insert new task + onTaskAdded() // Refresh task list + onDismiss() // Close dialog + } + } + ) { + Text("Add Task") + } + }, + dismissButton = { + Button(onClick = onDismiss) { + Text("Cancel") + } + }, + title = { Text("Add New Task") }, + text = { + TextField( + value = newTaskText, + onValueChange = { newTaskText = it }, + label = { Text("Task description") } + ) + } + ) + } +} + +// Mock DatabaseHandler for Preview (without Context) +class MockDatabaseHandler : DatabaseHandler(null) { + override fun getAllTasks(): List { + return listOf(ToDoModel(task = "Sample Task")) + } + + override fun insertTask(task: ToDoModel) { + // Mock inserting task, no database action needed for preview + } + + override fun openDatabase() { + // No need to mock openDatabase + } +} + +@Preview(showBackground = true) +@Composable +fun MainScreenPreview() { + PomoDoTheme { + // Use the mocked database + MainScreen(db = MockDatabaseHandler()) + } +} + +@Composable +fun MainScreen(db: MockDatabaseHandler) { + +} diff --git a/src/main/java/com/bignerdranch/android/pomodo/Model/ToDoModel.kt b/src/main/java/com/bignerdranch/android/pomodo/Model/ToDoModel.kt new file mode 100644 index 0000000..22f34bd --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/Model/ToDoModel.kt @@ -0,0 +1,7 @@ +package com.bignerdranch.android.pomodo.Model + +data class ToDoModel( + var id: Int = 0, // Change id to Int + var task: String = "", // This matches the property you're trying to access in task.task + var status: Int = 0 +) diff --git a/src/main/java/com/bignerdranch/android/pomodo/RecyclerItemTouchHelper.kt b/src/main/java/com/bignerdranch/android/pomodo/RecyclerItemTouchHelper.kt new file mode 100644 index 0000000..c1e1163 --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/RecyclerItemTouchHelper.kt @@ -0,0 +1,90 @@ +package com.bignerdranch.android.pomodo + +import android.app.AlertDialog +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.RecyclerView +import com.bignerdranch.android.pomodo.Adapters.ToDoAdapter + +class RecyclerItemTouchHelper(private val adapter: ToDoAdapter) : + ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) { + + override fun onMove( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + target: RecyclerView.ViewHolder + ): Boolean { + return false + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { + val position = viewHolder.adapterPosition + if (direction == ItemTouchHelper.LEFT) { + val builder = AlertDialog.Builder(adapter.getContext()) + builder.setTitle("Delete Task") + builder.setMessage("Are you sure you want to delete this Task?") + builder.setPositiveButton("Confirm") { _, _ -> + adapter.deleteItem(position) + } + builder.setNegativeButton(android.R.string.cancel) { dialog, _ -> + adapter.notifyItemChanged(viewHolder.adapterPosition) + dialog.dismiss() + } + val dialog = builder.create() + dialog.show() + } else { + adapter.editItem(position) + } + } + + override fun onChildDraw( + c: Canvas, + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + dX: Float, + dY: Float, + actionState: Int, + isCurrentlyActive: Boolean + ) { + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + + val itemView = viewHolder.itemView + val backgroundCornerOffset = 20 + val icon: Drawable? + val background: ColorDrawable + + if (dX > 0) { // Swiping to the right + icon = ContextCompat.getDrawable(adapter.getContext(), R.drawable.ic_baseline_edit) + background = ColorDrawable(ContextCompat.getColor(adapter.getContext(), R.color.colorPrimaryDark)) + icon?.let { + val iconMargin = (itemView.height - it.intrinsicHeight) / 2 + val iconTop = itemView.top + (itemView.height - it.intrinsicHeight) / 2 + val iconBottom = iconTop + it.intrinsicHeight + val iconLeft = itemView.left + iconMargin + val iconRight = itemView.left + iconMargin + it.intrinsicWidth + it.setBounds(iconLeft, iconTop, iconRight, iconBottom) + } + background.setBounds(itemView.left, itemView.top, itemView.left + dX.toInt() + backgroundCornerOffset, itemView.bottom) + } else { // Swiping to the left + icon = ContextCompat.getDrawable(adapter.getContext(), R.drawable.ic_baseline_delete) + background = ColorDrawable(Color.RED) + icon?.let { + val iconMargin = (itemView.height - it.intrinsicHeight) / 2 + val iconTop = itemView.top + (itemView.height - it.intrinsicHeight) / 2 + val iconBottom = iconTop + it.intrinsicHeight + val iconLeft = itemView.right - iconMargin - it.intrinsicWidth + val iconRight = itemView.right - iconMargin + it.setBounds(iconLeft, iconTop, iconRight, iconBottom) + } + background.setBounds(itemView.right + dX.toInt() - backgroundCornerOffset, itemView.top, itemView.right, itemView.bottom) + } + + background.draw(c) + icon?.draw(c) + } +} diff --git a/src/main/java/com/bignerdranch/android/pomodo/SplashActivity.kt b/src/main/java/com/bignerdranch/android/pomodo/SplashActivity.kt new file mode 100644 index 0000000..68117a2 --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/SplashActivity.kt @@ -0,0 +1,23 @@ +package com.bignerdranch.android.pomodo + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import androidx.appcompat.app.AppCompatActivity + + +class SplashActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_splash) + supportActionBar?.hide() + + val intent = Intent(this, MainActivity::class.java) + Handler(Looper.getMainLooper()).postDelayed({ + startActivity(intent) + finish() + }, 2000) + } +} diff --git a/src/main/java/com/bignerdranch/android/pomodo/Utils/DatabaseHandler.kt b/src/main/java/com/bignerdranch/android/pomodo/Utils/DatabaseHandler.kt new file mode 100644 index 0000000..b9a9579 --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/Utils/DatabaseHandler.kt @@ -0,0 +1,87 @@ +package com.bignerdranch.android.pomodo + +import android.content.ContentValues +import android.content.Context +import android.database.Cursor +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteOpenHelper +import com.bignerdranch.android.pomodo.Model.ToDoModel + +open class DatabaseHandler(context: Context?) : SQLiteOpenHelper(context, NAME, null, VERSION) { + + private var db: SQLiteDatabase? = null + + override fun onCreate(db: SQLiteDatabase) { + db.execSQL(CREATE_TODO_TABLE) + } + + override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + db.execSQL("DROP TABLE IF EXISTS $TODO_TABLE") + onCreate(db) + } + + open fun openDatabase() { + db = writableDatabase + } + + open fun insertTask(task: ToDoModel) { + val cv = ContentValues().apply { + put(TASK, task.task) + put(STATUS, task.status) + } + db?.insert(TODO_TABLE, null, cv) + } + + open fun getAllTasks(): List { + val taskList = mutableListOf() + var cursor: Cursor? = null + db?.beginTransaction() + try { + cursor = db?.query(TODO_TABLE, null, null, null, null, null, null) + if (cursor != null && cursor.moveToFirst()) { + do { + val task = ToDoModel().apply { + // Use getInt to properly fetch the integer id + id = cursor.getInt(cursor.getColumnIndexOrThrow(ID)) // id as Int + task = cursor.getString(cursor.getColumnIndexOrThrow(TASK)) + status = cursor.getInt(cursor.getColumnIndexOrThrow(STATUS)) + } + taskList.add(task) + } while (cursor.moveToNext()) + } + db?.setTransactionSuccessful() + } finally { + db?.endTransaction() + cursor?.close() + } + return taskList + } + + fun updateStatus(id: Int, status: Int) { + val cv = ContentValues().apply { + put(STATUS, status) + } + db?.update(TODO_TABLE, cv, "$ID=?", arrayOf(id.toString())) + } + + fun updateTask(id: Int, task: String) { + val cv = ContentValues().apply { + put(TASK, task) + } + db?.update(TODO_TABLE, cv, "$ID=?", arrayOf(id.toString())) + } + + fun deleteTask(id: Int) { + db?.delete(TODO_TABLE, "$ID=?", arrayOf(id.toString())) + } + + companion object { + private const val VERSION = 1 + private const val NAME = "toDoListDatabase" + private const val TODO_TABLE = "todo" + private const val ID = "id" + private const val TASK = "task" + private const val STATUS = "status" + private const val CREATE_TODO_TABLE = "CREATE TABLE $TODO_TABLE ($ID INTEGER PRIMARY KEY AUTOINCREMENT, $TASK TEXT, $STATUS INTEGER)" + } +} diff --git a/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Color.kt b/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Color.kt new file mode 100644 index 0000000..5f0a952 --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.bignerdranch.android.pomodo.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Theme.kt b/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Theme.kt new file mode 100644 index 0000000..3cc8d5e --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Theme.kt @@ -0,0 +1,70 @@ +package com.bignerdranch.android.pomodo.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 + + /* 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), + */ +) + +@Composable +fun PomoDoTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Type.kt b/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Type.kt new file mode 100644 index 0000000..085c0b4 --- /dev/null +++ b/src/main/java/com/bignerdranch/android/pomodo/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.bignerdranch.android.pomodo.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 + ) + */ +) \ No newline at end of file diff --git a/src/main/res/drawable-v24/ic_launcher_foreground.xml b/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..7de5a29 --- /dev/null +++ b/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/src/main/res/drawable/gradient_ic_launcher_foreground.xml b/src/main/res/drawable/gradient_ic_launcher_foreground.xml new file mode 100644 index 0000000..9278fe5 --- /dev/null +++ b/src/main/res/drawable/gradient_ic_launcher_foreground.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/src/main/res/drawable/ic_baseline_add_24.xml b/src/main/res/drawable/ic_baseline_add_24.xml new file mode 100644 index 0000000..c60b4f8 --- /dev/null +++ b/src/main/res/drawable/ic_baseline_add_24.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/src/main/res/drawable/ic_baseline_delete.xml b/src/main/res/drawable/ic_baseline_delete.xml new file mode 100644 index 0000000..3b74ec2 --- /dev/null +++ b/src/main/res/drawable/ic_baseline_delete.xml @@ -0,0 +1,6 @@ + + + + diff --git a/src/main/res/drawable/ic_baseline_edit.xml b/src/main/res/drawable/ic_baseline_edit.xml new file mode 100644 index 0000000..2e9cf19 --- /dev/null +++ b/src/main/res/drawable/ic_baseline_edit.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/src/main/res/drawable/ic_launcher_background.xml b/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..e93e11a --- /dev/null +++ b/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/drawable/logo.png b/src/main/res/drawable/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..95a24a4fb4f9419512c13e32cb5e05c1340f4997 GIT binary patch literal 4465 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 DcxU&K literal 0 HcmV?d00001 diff --git a/src/main/res/layout/activity_main.xml b/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..24148c2 --- /dev/null +++ b/src/main/res/layout/activity_main.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/layout/activity_splash.xml b/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000..320373a --- /dev/null +++ b/src/main/res/layout/activity_splash.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/src/main/res/layout/new_task.xml b/src/main/res/layout/new_task.xml new file mode 100644 index 0000000..4d3aabf --- /dev/null +++ b/src/main/res/layout/new_task.xml @@ -0,0 +1,26 @@ + + + + +