Add the option to quickly add a calendar event from the exam details (#1802)

* Extract intent utils to separate file

* Add add to calendar button in exam details dialog

* Set 8:00-8:45 start/end time
This commit is contained in:
Mikołaj Pich 2022-03-14 00:38:40 +01:00 committed by GitHub
parent 15537586c4
commit 08c1bedca1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 144 additions and 94 deletions

View File

@ -9,7 +9,9 @@ import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.databinding.DialogExamBinding
import io.github.wulkanowy.utils.lifecycleAwareVariable
import io.github.wulkanowy.utils.openCalendarEventAdd
import io.github.wulkanowy.utils.toFormattedString
import java.time.LocalTime
class ExamDialog : DialogFragment() {
@ -54,6 +56,14 @@ class ExamDialog : DialogFragment() {
}
examDialogClose.setOnClickListener { dismiss() }
examDialogAddToCalendar.setOnClickListener {
requireContext().openCalendarEventAdd(
title = "${exam.subject} - ${exam.type}",
description = exam.description,
start = exam.date.atTime(LocalTime.of(8, 0)),
end = exam.date.atTime(LocalTime.of(8, 45)),
)
}
}
}
}

View File

@ -1,31 +1,17 @@
package io.github.wulkanowy.utils
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.Rect
import android.graphics.Typeface
import android.net.Uri
import android.graphics.*
import android.text.TextPaint
import android.util.DisplayMetrics.DENSITY_DEFAULT
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.PluralsRes
import androidx.annotation.*
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
import androidx.core.graphics.applyCanvas
import androidx.core.graphics.drawable.RoundedBitmapDrawable
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import androidx.core.graphics.drawable.toBitmap
import io.github.wulkanowy.BuildConfig.APPLICATION_ID
@ColorInt
fun Context.getThemeAttrColor(@AttrRes colorAttr: Int): Int {
@ -61,69 +47,6 @@ fun Context.getCompatBitmap(@DrawableRes drawableRes: Int, @ColorRes colorRes: I
fun Context.getPlural(@PluralsRes pluralRes: Int, quantity: Int, vararg arguments: Any) =
resources.getQuantityString(pluralRes, quantity, *arguments)
fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) -> Unit = {}) {
Intent.parseUri(uri, 0).let {
try {
startActivity(it)
} catch (e: ActivityNotFoundException) {
onActivityNotFound(uri)
}
}
}
fun Context.openAppInMarket(onActivityNotFound: (uri: String) -> Unit) {
openInternetBrowser("market://details?id=${APPLICATION_ID}") {
openInternetBrowser("https://github.com/wulkanowy/wulkanowy/releases", onActivityNotFound)
}
}
fun Context.openEmailClient(
chooserTitle: String,
email: String,
subject: String,
body: String,
onActivityNotFound: () -> Unit = {}
) {
val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:")).apply {
putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
putExtra(Intent.EXTRA_SUBJECT, subject)
putExtra(Intent.EXTRA_TEXT, body)
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(Intent.createChooser(intent, chooserTitle))
} else onActivityNotFound()
}
fun Context.openNavigation(location: String) {
val intentUri = Uri.parse("geo:0,0?q=${Uri.encode(location)}")
val intent = Intent(Intent.ACTION_VIEW, intentUri)
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
}
fun Context.openDialer(phone: String) {
val intentUri = Uri.parse("tel:$phone")
val intent = Intent(Intent.ACTION_DIAL, intentUri)
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
}
fun Context.shareText(text: String, subject: String?) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, text)
if (subject != null) {
putExtra(Intent.EXTRA_SUBJECT, subject)
}
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
startActivity(shareIntent)
}
fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT
@SuppressLint("DefaultLocale")

View File

@ -0,0 +1,100 @@
package io.github.wulkanowy.utils
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.CalendarContract
import io.github.wulkanowy.BuildConfig
import java.time.LocalDateTime
import java.time.ZoneId
fun Context.openInternetBrowser(uri: String, onActivityNotFound: (uri: String) -> Unit = {}) {
Intent.parseUri(uri, 0).let {
try {
startActivity(it)
} catch (e: ActivityNotFoundException) {
onActivityNotFound(uri)
}
}
}
fun Context.openAppInMarket(onActivityNotFound: (uri: String) -> Unit) {
openInternetBrowser("market://details?id=${BuildConfig.APPLICATION_ID}") {
openInternetBrowser("https://github.com/wulkanowy/wulkanowy/releases", onActivityNotFound)
}
}
fun Context.openEmailClient(
chooserTitle: String,
email: String,
subject: String,
body: String,
onActivityNotFound: () -> Unit = {}
) {
val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:")).apply {
putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
putExtra(Intent.EXTRA_SUBJECT, subject)
putExtra(Intent.EXTRA_TEXT, body)
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(Intent.createChooser(intent, chooserTitle))
} else onActivityNotFound()
}
fun Context.openCalendarEventAdd(
title: String,
description: String,
start: LocalDateTime,
end: LocalDateTime? = null,
isAllDay: Boolean = false,
onActivityNotFound: (uri: String?) -> Unit = {},
) {
val beginTime = start.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
val endTime = end?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
val intent = Intent(Intent.ACTION_INSERT)
.setData(CalendarContract.Events.CONTENT_URI)
.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime)
.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime)
.putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, isAllDay)
.putExtra(CalendarContract.Events.TITLE, title)
.putExtra(CalendarContract.Events.DESCRIPTION, description)
.putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY)
try {
startActivity(intent)
} catch (e: ActivityNotFoundException) {
onActivityNotFound(intent.dataString)
}
}
fun Context.openNavigation(location: String) {
val intentUri = Uri.parse("geo:0,0?q=${Uri.encode(location)}")
val intent = Intent(Intent.ACTION_VIEW, intentUri)
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
}
fun Context.openDialer(phone: String) {
val intentUri = Uri.parse("tel:$phone")
val intent = Intent(Intent.ACTION_DIAL, intentUri)
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
}
fun Context.shareText(text: String, subject: String?) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, text)
if (subject != null) {
putExtra(Intent.EXTRA_SUBJECT, subject)
}
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
startActivity(shareIntent)
}

View File

@ -33,7 +33,7 @@
android:layout_marginHorizontal="16dp"
android:layout_marginTop="28dp"
android:hint="@string/all_date"
app:startIconDrawable="@drawable/ic_calendat_all">
app:startIconDrawable="@drawable/ic_calendar_all">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/additionalLessonDialogDateEdit"

View File

@ -9,7 +9,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="24dp"
android:paddingStart="8dp"
android:paddingEnd="8dp">
<View
@ -23,7 +23,7 @@
android:id="@+id/allDetailsHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:text="@string/all_details"
@ -38,7 +38,7 @@
android:id="@+id/examDialogSubjectTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="28dp"
android:layout_marginEnd="24dp"
android:text="@string/all_subject"
@ -53,7 +53,7 @@
android:id="@+id/examDialogSubjectValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="24dp"
android:paddingStart="0dp"
android:paddingEnd="16dp"
@ -69,7 +69,7 @@
android:id="@+id/examDialogTypeTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:text="@string/exam_type"
@ -84,7 +84,7 @@
android:id="@+id/examDialogTypeValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="24dp"
android:paddingStart="0dp"
android:paddingEnd="16dp"
@ -100,7 +100,7 @@
android:id="@+id/examDialogTeacherTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:text="@string/all_teacher"
@ -115,7 +115,7 @@
android:id="@+id/examDialogTeacherValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="24dp"
android:paddingStart="0dp"
android:paddingEnd="16dp"
@ -131,7 +131,7 @@
android:id="@+id/examDialogDeadlineDateTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:text="@string/all_date"
@ -177,7 +177,7 @@
android:id="@+id/examDialogEntryDateValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="24dp"
android:paddingStart="0dp"
android:paddingEnd="16dp"
@ -193,7 +193,7 @@
android:id="@+id/examDialogDescriptionTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:text="@string/all_description"
@ -208,7 +208,7 @@
android:id="@+id/examDialogDescriptionValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="24dp"
android:paddingStart="0dp"
android:paddingEnd="16dp"
@ -220,6 +220,22 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/examDialogDescriptionTitle" />
<com.google.android.material.button.MaterialButton
android:id="@+id/examDialogAddToCalendar"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/all_add_to_calendar"
android:insetLeft="0dp"
android:insetTop="0dp"
android:insetRight="0dp"
android:insetBottom="0dp"
android:text="@string/all_add"
app:icon="@drawable/ic_calendar_all"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/examDialogClose"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"

View File

@ -33,7 +33,7 @@
android:layout_marginHorizontal="16dp"
android:layout_marginTop="28dp"
android:hint="@string/all_date"
app:startIconDrawable="@drawable/ic_calendat_all">
app:startIconDrawable="@drawable/ic_calendar_all">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/homeworkDialogDateEdit"

View File

@ -637,6 +637,7 @@
<string name="all_copied">Copied</string>
<string name="all_undo">Undo</string>
<string name="all_change">Change</string>
<string name="all_add_to_calendar">Add to calendar</string>
<!--Timetable Widget-->