Commit 60706230 authored by Lukas Bersinger's avatar Lukas Bersinger
Browse files

add TimeTrackingActivity

parent f11d7c28
......@@ -3,14 +3,17 @@
package="ch.ost.rj.mge.miniproject.tasktracker">
<application
android:name=".TaskTrackerApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:name=".TaskTrackerApplication">
<activity android:name=".activities.EditTaskActivity"/>
android:theme="@style/AppTheme">
<activity android:name=".activities.TimeTrackingActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.EditTaskActivity" />
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
......
......@@ -78,6 +78,6 @@ class EditTaskActivity : AppCompatActivity(), TaskFormFragment.OnTaskChangeListe
}
companion object {
val KEY_TASK_ID = "KEY_TASK_ID"
const val KEY_TASK_ID = "KEY_TASK_ID"
}
}
\ No newline at end of file
......@@ -34,8 +34,8 @@ class MainActivity : AppCompatActivity(), TaskListFragment.OnItemClickListener {
}
override fun onItemClick(task: Task) {
val intent = Intent(this, EditTaskActivity::class.java)
intent.putExtra(EditTaskActivity.KEY_TASK_ID, task.id)
val intent = Intent(this, TimeTrackingActivity::class.java)
intent.putExtra(TimeTrackingActivity.KEY_TASK_ID, task.id)
startActivity(intent)
}
......
package ch.ost.rj.mge.miniproject.tasktracker.activities
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import ch.ost.rj.mge.miniproject.tasktracker.R
import ch.ost.rj.mge.miniproject.tasktracker.models.Task
import ch.ost.rj.mge.miniproject.tasktracker.repositories.TaskRepository
import java.text.DateFormat
import java.util.*
import kotlin.math.floor
import kotlin.math.roundToInt
class TimeTrackingActivity : AppCompatActivity() {
private val mainHandler = Handler(Looper.getMainLooper())
private val updateActualTimeTask = object : Runnable {
override fun run() {
updateActualTime()
mainHandler.postDelayed(this, 1000)
}
}
private var timerRunning = false
private lateinit var task: Task
private lateinit var txtTaskTitle: TextView
private lateinit var txtActualTime: TextView
private lateinit var btnStart: Button
private lateinit var btnStop: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_time_tracking)
val taskId = intent.extras!!.getInt(KEY_TASK_ID)
task = TaskRepository.getTaskById(taskId)!!
txtTaskTitle = findViewById(R.id.txtToolbarTitle)
txtActualTime = findViewById(R.id.txtActualTime)
btnStart = findViewById(R.id.btnStart)
btnStart.setOnClickListener {
task.timerStartDate = Calendar.getInstance()
TaskRepository.updateTask(task)
updateButtonState()
startTimer()
}
btnStop = findViewById(R.id.btnStop)
btnStop.setOnClickListener {
val timeNow = Calendar.getInstance().timeInMillis / 1000
val timeStart = task.timerStartDate!!.timeInMillis / 1000
val diffSeconds = timeNow - timeStart
task.timerStartDate = null
task.actualTimeSeconds += diffSeconds
TaskRepository.updateTask(task)
updateButtonState()
stopTimer()
}
}
override fun onResume() {
super.onResume()
val taskId = intent.extras!!.getInt(KEY_TASK_ID)
task = TaskRepository.getTaskById(taskId)!!
txtTaskTitle.text = task.name
val txtDueDate: TextView = findViewById(R.id.txtDueDate)
txtDueDate.text = DateFormat.getDateInstance().format(task.dueDate!!.time)
setEstimatedTime()
updateActualTime()
updateButtonState()
if (task.isTimerRunning()) {
startTimer()
}
}
override fun onPause() {
super.onPause()
stopTimer()
}
private fun updateActualTime() {
var timeSeconds: Long = task.actualTimeSeconds
val timerStart = task.timerStartDate
if (timerStart != null) {
val nowSeconds = Calendar.getInstance().timeInMillis / 1000
val timerStartSeconds = timerStart.timeInMillis / 1000
val sinceTimerStart = nowSeconds - timerStartSeconds
timeSeconds += sinceTimerStart
}
val hours: Int = floor(timeSeconds / (60.0 * 60.0)).roundToInt()
val minutes: Int = floor((timeSeconds - (hours * 60.0 * 60.0)) / 60.0).roundToInt()
val seconds: Int = floor(timeSeconds - (minutes * 60.0) - (hours * 60.0 * 60.0)).roundToInt()
txtActualTime.text = String.format("%02d:%02d:%02d", hours, minutes, seconds)
}
private fun setEstimatedTime() {
val txtEstimatedTime: TextView = findViewById(R.id.txtEstimatedTime)
val hours: Int = floor(task.estimatedTimeMinutes / 60.0).roundToInt()
val minutes: Int = (task.estimatedTimeMinutes - (hours * 60.0)).roundToInt()
txtEstimatedTime.text = String.format("%02d:%02d:00", hours, minutes)
}
private fun updateButtonState() {
val timerRunning = task.isTimerRunning()
btnStart.isEnabled = !timerRunning
btnStop.isEnabled = timerRunning
}
private fun startTimer() {
if (!timerRunning) {
mainHandler.post(updateActualTimeTask)
timerRunning = true
}
}
private fun stopTimer() {
if (timerRunning) {
mainHandler.removeCallbacks(updateActualTimeTask)
timerRunning = false
}
}
companion object {
const val KEY_TASK_ID = "KEY_TASK_ID"
}
}
\ No newline at end of file
......@@ -5,7 +5,7 @@ import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import ch.ost.rj.mge.miniproject.tasktracker.models.Task
@Database(entities = arrayOf(Task::class), version = 1, exportSchema = false)
@Database(entities = arrayOf(Task::class), version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun taskDao(): TaskDao
......
......@@ -19,9 +19,15 @@ class Task {
@ColumnInfo(name = "completed")
var isCompleted: Boolean = false
@ColumnInfo(name = "estimated_time_minutes")
var estimatedTimeMinutes: Long = 0
@ColumnInfo(name = "actual_time_seconds")
var actualTimeSeconds: Long = 0
@ColumnInfo
var timerStartDate: Calendar? = null
fun differenceMinutes(): Long {
return Math.round(this.actualTimeSeconds / 60.0) - this.estimatedTimeMinutes
}
......@@ -45,4 +51,8 @@ class Task {
fun isNew(): Boolean {
return id == 0;
}
fun isTimerRunning(): Boolean {
return timerStartDate != null
}
}
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.TimeTrackingActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@color/colorPrimary"
android:elevation="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/txtToolbarTitle"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="clip_vertical|start|center_vertical"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:fontFamily="sans-serif-medium"
android:gravity="clip_vertical|center_vertical"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title"
android:textColor="@android:color/primary_text_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btnEdit"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/btnEdit"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="end"
android:layout_marginEnd="8dp"
android:backgroundTint="@color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_baseline_edit_24" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
<TextView
android:id="@+id/txtActualTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="TextView"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat.Display2"
android:textColor="@android:color/primary_text_light"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lblActualTime" />
<TextView
android:id="@+id/lblDueDate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/lblDueDate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
<TextView
android:id="@+id/txtDueDate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="TextView"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lblDueDate" />
<TextView
android:id="@+id/lblEstimatedTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/lblEstimateTime"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtDueDate" />
<TextView
android:id="@+id/txtEstimatedTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="TextView"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lblEstimatedTime" />
<TextView
android:id="@+id/lblActualTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:text="@string/lblActualTime"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtEstimatedTime" />
<Button
android:id="@+id/btnStop"
style="@style/AppTheme.Widget.ButtonError"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:text="@string/btnStop"
app:layout_constraintEnd_toStartOf="@+id/btnStart"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtActualTime" />
<Button
android:id="@+id/btnStart"
style="@style/AppTheme.Widget.ButtonSuccess"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:text="@string/btnStart"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btnStop"
app:layout_constraintTop_toBottomOf="@+id/txtActualTime" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -3,4 +3,6 @@
<color name="colorPrimary">#2196F3</color>
<color name="colorPrimaryDark">#1565C0</color>
<color name="colorSecondary">#F9A825</color>
<color name="colorSuccess">#4CAF50</color>
<color name="colorError">#F44336</color>
</resources>
\ No newline at end of file
......@@ -10,4 +10,7 @@
<string name="btnCancelCreateTask">Abbrechen</string>
<string name="lblEstimateHours">h</string>
<string name="lblEstimateMinutes">m</string>
<string name="lblActualTime">Gemessene Zeit</string>
<string name="btnStart">Start</string>
<string name="btnStop">Stop</string>
</resources>
\ No newline at end of file
......@@ -7,4 +7,18 @@
<item name="colorSecondary">@color/colorSecondary</item>
</style>
<style name="AppTheme.NoActionBar" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorSecondary">@color/colorSecondary</item>
</style>
<style name="AppTheme.Widget.ButtonSuccess" parent="Widget.AppCompat.Button">
<item name="backgroundTint">@color/colorSuccess</item>
</style>
<style name="AppTheme.Widget.ButtonError" parent="Widget.AppCompat.Button">
<item name="backgroundTint">@color/colorError</item>
</style>
</resources>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment