commit bbb5a19d3243cdf69eaedb12e56a6452378a46b8 Author: Lucàs <86352901+LucasVbr@users.noreply.github.com> Date: Thu Oct 24 12:58:00 2024 +0200 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..aa89f68 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..7b3006b --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..74dd639 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..f3d4a2e --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.readme/Screenshot_20241024_122802.png b/.readme/Screenshot_20241024_122802.png new file mode 100644 index 0000000..2c78703 Binary files /dev/null and b/.readme/Screenshot_20241024_122802.png differ diff --git a/.readme/Screenshot_20241024_122832.png b/.readme/Screenshot_20241024_122832.png new file mode 100644 index 0000000..8e26f8a Binary files /dev/null and b/.readme/Screenshot_20241024_122832.png differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5422d37 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 LucasVbr + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8bec958 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +

Welcome to TodoList Android App 👋

+

+ Version + + License: MIT + +

+ +> A simple Android App to manage your Todos + + + +App Interface +App Menu + + + +## Author + +👤 **LucasVbr** + +* Website: https://lucasvbr.dev +* Github: [@LucasVbr](https://github.com/LucasVbr) +* LinkedIn: [@lucasvbr](https://linkedin.com/in/lucasvbr) + +## Show your support + +Give a ⭐️ if this project helped you! + +## 📝 License + +Copyright © 2024 [LucasVbr](https://github.com/LucasVbr).
+This project is [MIT](./LICENSE) licensed. \ No newline at end of file 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..7e3aec4 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,43 @@ +plugins { + alias(libs.plugins.android.application) +} + +android { + namespace = "fr.univpau.todolist" + compileSdk = 34 + + defaultConfig { + applicationId = "fr.univpau.todolist" + minSdk = 29 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } +} + +dependencies { + + implementation(libs.appcompat) + implementation(libs.material) + implementation(libs.activity) + implementation(libs.constraintlayout) + testImplementation(libs.junit) + androidTestImplementation(libs.ext.junit) + androidTestImplementation(libs.espresso.core) +} \ 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/fr/univpau/todolist/ExampleInstrumentedTest.java b/app/src/androidTest/java/fr/univpau/todolist/ExampleInstrumentedTest.java new file mode 100644 index 0000000..0dc380c --- /dev/null +++ b/app/src/androidTest/java/fr/univpau/todolist/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package fr.univpau.todolist; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("fr.univpau.todolist", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f813944 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/fr/univpau/todolist/MainActivity.java b/app/src/main/java/fr/univpau/todolist/MainActivity.java new file mode 100644 index 0000000..514d4ce --- /dev/null +++ b/app/src/main/java/fr/univpau/todolist/MainActivity.java @@ -0,0 +1,81 @@ +/* + * MainActivity.java, 24/10/2024 + * UPPA M2TI 2024-2025 + * MIT License (MIT) + */ + +package fr.univpau.todolist; + +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import java.util.ArrayList; + +/** + * The main activity of the application. + * + * @author LucasVbr + */ +public class MainActivity extends AppCompatActivity { + + /** + * The adapter for the list of todos. + */ + private TodoAdapter todoAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EdgeToEdge.enable(this); + setContentView(R.layout.activity_main); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + EditText inputTask = findViewById(R.id.input_task); + Button buttonAdd = findViewById(R.id.button_add); + ListView todoListView = findViewById(R.id.todo_list); + + this.todoAdapter = new TodoAdapter(this, new ArrayList<>()); + todoListView.setAdapter(todoAdapter); + + buttonAdd.setOnClickListener(new OnAddTodoListener(inputTask, todoAdapter)); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + + if (id == R.id.clear_list) { + todoAdapter.clear(); + return true; + } + + if (id == R.id.remove_checked) { + this.todoAdapter.removeChecked(); + return true; + } + + return super.onOptionsItemSelected(item); + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/univpau/todolist/OnAddTodoListener.java b/app/src/main/java/fr/univpau/todolist/OnAddTodoListener.java new file mode 100644 index 0000000..d904501 --- /dev/null +++ b/app/src/main/java/fr/univpau/todolist/OnAddTodoListener.java @@ -0,0 +1,41 @@ +/* + * OnAddTodoListener.java, 24/10/2024 + * UPPA M2TI 2024-2025 + * MIT License (MIT) + */ + +package fr.univpau.todolist; + +import android.view.View; +import android.widget.EditText; + + +/** + * Listener for the add button + * + * @author LucasVbr + */ +public class OnAddTodoListener implements View.OnClickListener { + private final EditText inputTask; + private final TodoAdapter todoAdapter; + + /** + * Create a new listener for the add button. + * @param inputTask The input field for the task. + * @param todoAdapter The adapter for the list of todos. + */ + public OnAddTodoListener(EditText inputTask, TodoAdapter todoAdapter) { + this.inputTask = inputTask; + this.todoAdapter = todoAdapter; + } + + @Override + public void onClick(View view) { + String task = inputTask.getText().toString(); + if (task.trim().isEmpty()) return; + + todoAdapter.add(new Todo(task)); + inputTask.setText(""); + + } +} diff --git a/app/src/main/java/fr/univpau/todolist/OnCheckedTodoListener.java b/app/src/main/java/fr/univpau/todolist/OnCheckedTodoListener.java new file mode 100644 index 0000000..1efb3d1 --- /dev/null +++ b/app/src/main/java/fr/univpau/todolist/OnCheckedTodoListener.java @@ -0,0 +1,33 @@ +/* + * OnCheckedTodoListener.java, 24/10/2024 + * UPPA M2TI 2024-2025 + * MIT License (MIT) + */ + +package fr.univpau.todolist; + +import android.widget.CompoundButton; + +/** + * Listener for the checkbox. + * + * @author LucasVbr + */ +public class OnCheckedTodoListener implements CompoundButton.OnCheckedChangeListener { + + /** The task to update */ + private final Todo todo; + + /** + * Create a new listener for the checkbox. + * @param todo The task to update. + */ + public OnCheckedTodoListener(Todo todo) { + this.todo = todo; + } + + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + todo.setDone(b); + } +} diff --git a/app/src/main/java/fr/univpau/todolist/Todo.java b/app/src/main/java/fr/univpau/todolist/Todo.java new file mode 100644 index 0000000..a7ebcfc --- /dev/null +++ b/app/src/main/java/fr/univpau/todolist/Todo.java @@ -0,0 +1,69 @@ +/* + * Todo.java, 24/10/2024 + * UPPA M2TI 2024-2025 + * MIT License (MIT) + */ + +package fr.univpau.todolist; + +import android.util.Log; + +import java.util.Date; + +/** + * Represents a task to do. + * + * @author LucasVbr + */ +public class Todo { + + /** The task name */ + private final String task; + + /** The creation date */ + private final Date date; + + /** Whether the task is done */ + private boolean done; + + /** + * Create a new task. + * @param task The task name + */ + public Todo(String task) { + this.task = task; + this.date = new Date(); + this.done = false; + } + + /** @return The task name */ + public String getTask() { + return task; + } + + /** @return The creation date */ + public Date getDate() { + return date; + } + + /** @return Whether the task is done */ + public boolean isDone() { + return done; + } + + /** + * Set whether the task is done. + * @param done Whether the task is done + */ + public void setDone(boolean done) { + this.done = done; + Log.i("Checkbox", this.toString()); + } + + @Override + public String toString() { + return "Task: " + task + + ", Date: " + date + + ", Done: " + (done ? "Yes" : "No"); + } +} diff --git a/app/src/main/java/fr/univpau/todolist/TodoAdapter.java b/app/src/main/java/fr/univpau/todolist/TodoAdapter.java new file mode 100644 index 0000000..8e59197 --- /dev/null +++ b/app/src/main/java/fr/univpau/todolist/TodoAdapter.java @@ -0,0 +1,74 @@ +/* + * TodoAdapter.java, 24/10/2024 + * UPPA M2TI 2024-2025 + * MIT License (MIT) + */ + +package fr.univpau.todolist; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.TextView; + +import java.util.ArrayList; + +/** + * Adapter for the list of todos. + * + * @author LucasVbr + */ +public class TodoAdapter extends ArrayAdapter { + + /** The context of the adapter */ + private final Context context; + + /** The list of todos */ + private ArrayList todoList; + + /** + * Create a new adapter for the list of todos. + * @param context The context of the adapter. + * @param todoList The list of todos. + */ + public TodoAdapter(Context context, ArrayList todoList) { + super(context, 0, todoList); + + this.context = context; + this.todoList = todoList; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + Todo todoItem = getItem(position); + + if (convertView == null) { + convertView = LayoutInflater.from(context).inflate(R.layout.todo_item, parent, false); + } + + TextView todoTask = convertView.findViewById(R.id.task); + TextView todoDate = convertView.findViewById(R.id.date); + CheckBox todoCheckBox = convertView.findViewById(R.id.check); + + assert todoItem != null; + todoCheckBox.setOnCheckedChangeListener(null); + + todoTask.setText(todoItem.getTask()); + todoDate.setText(todoItem.getDate().toString()); + todoCheckBox.setChecked(todoItem.isDone()); + + todoCheckBox.setOnCheckedChangeListener(new OnCheckedTodoListener(todoItem)); + + return convertView; + } + + /** Remove all checked todos */ + public void removeChecked() { + todoList.removeIf(Todo::isDone); + notifyDataSetChanged(); + } + +} 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..f601032 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,38 @@ + + + + + + + + +