mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 11:39:42 +01:00
Merge pull request #4552 from nextcloud/issue-4274-migrate-javautil-date-time-1
Migrating away from java.util.Date to java.time - DateTimePickerFragment
This commit is contained in:
commit
a34e0c6e7f
@ -40,6 +40,7 @@
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
|
@ -54,11 +54,13 @@ import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.content.PermissionChecker
|
||||
import androidx.core.content.PermissionChecker.PERMISSION_GRANTED
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.text.bold
|
||||
import androidx.emoji2.text.EmojiCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
@ -147,7 +149,7 @@ import com.nextcloud.talk.ui.PlaybackSpeed
|
||||
import com.nextcloud.talk.ui.PlaybackSpeedControl
|
||||
import com.nextcloud.talk.ui.StatusDrawable
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||
import com.nextcloud.talk.ui.dialog.DateTimePickerFragment
|
||||
import com.nextcloud.talk.ui.dialog.DateTimeCompose
|
||||
import com.nextcloud.talk.ui.dialog.FileAttachmentPreviewFragment
|
||||
import com.nextcloud.talk.ui.dialog.MessageActionsDialog
|
||||
import com.nextcloud.talk.ui.dialog.SaveToStorageDialogFragment
|
||||
@ -3502,8 +3504,17 @@ class ChatActivity :
|
||||
|
||||
val chatApiVersion = ApiUtils.getChatApiVersion(spreedCapabilities, intArrayOf(ApiUtils.API_V1, 1))
|
||||
|
||||
val newFragment: DialogFragment = DateTimePickerFragment.newInstance(roomToken, message!!.id, chatApiVersion)
|
||||
newFragment.show(supportFragmentManager, DateTimePickerFragment.TAG)
|
||||
val bundle = bundleOf()
|
||||
bundle.putString(KEY_ROOM_TOKEN, roomToken)
|
||||
bundle.putString(BundleKeys.KEY_MESSAGE_ID, message!!.id)
|
||||
bundle.putInt(BundleKeys.KEY_CHAT_API_VERSION, chatApiVersion)
|
||||
|
||||
binding.genericComposeView.apply {
|
||||
val shouldDismiss = mutableStateOf(false)
|
||||
setContent {
|
||||
DateTimeCompose(bundle).GetDateTimeDialog(shouldDismiss, this@ChatActivity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun markAsUnread(message: IMessage?) {
|
||||
|
@ -150,6 +150,7 @@ class ChatViewModel @Inject constructor(
|
||||
|
||||
object GetReminderStartState : ViewState
|
||||
open class GetReminderExistState(val reminder: Reminder) : ViewState
|
||||
object GetReminderStateSet : ViewState
|
||||
|
||||
private val _getReminderExistState: MutableLiveData<ViewState> = MutableLiveData(GetReminderStartState)
|
||||
|
||||
@ -310,6 +311,10 @@ class ChatViewModel @Inject constructor(
|
||||
?.subscribe(GetReminderObserver())
|
||||
}
|
||||
|
||||
fun overrideReminderState() {
|
||||
_getReminderExistState.value = GetReminderStateSet
|
||||
}
|
||||
|
||||
fun deleteReminder(user: User, roomToken: String, messageId: String, chatApiVersion: Int) {
|
||||
chatNetworkDataSource.deleteReminder(user, roomToken, messageId, chatApiVersion)
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -754,7 +759,7 @@ class ChatViewModel @Inject constructor(
|
||||
val model = ConversationModel.mapToConversationModel(it, userProvider.currentUser.blockingGet())
|
||||
ConversationUtils.isNoteToSelfConversation(model)
|
||||
}
|
||||
_getNoteToSelfAvailability.value = NoteToSelfAvailableState(noteToSelf.token!!)
|
||||
_getNoteToSelfAvailability.value = NoteToSelfAvailableState(noteToSelf.token)
|
||||
} catch (e: NoSuchElementException) {
|
||||
_getNoteToSelfAvailability.value = NoteToSelfNotAvailableState
|
||||
Log.e(TAG, "Note to self not found $e")
|
||||
|
@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Nextcloud Talk - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2025 Julius Linus <juliuslinus1@gmail.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.ui.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.DateRange
|
||||
import androidx.compose.material3.DatePicker
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TimePicker
|
||||
import androidx.compose.material3.rememberDatePickerState
|
||||
import androidx.compose.material3.rememberTimePickerState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.collectAsState
|
||||
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.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.asFlow
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.chat.viewmodels.ChatViewModel
|
||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
import java.time.DayOfWeek
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.temporal.TemporalAdjusters.nextOrSame
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class DateTimeCompose(val bundle: Bundle) {
|
||||
private var timeState = mutableStateOf(LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.MIN))
|
||||
|
||||
init {
|
||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
val user = userManager.currentUser.blockingGet()
|
||||
val roomToken = bundle.getString(BundleKeys.KEY_ROOM_TOKEN)!!
|
||||
val messageId = bundle.getString(BundleKeys.KEY_MESSAGE_ID)!!
|
||||
val apiVersion = bundle.getInt(BundleKeys.KEY_CHAT_API_VERSION)
|
||||
chatViewModel.getReminder(user, roomToken, messageId, apiVersion)
|
||||
}
|
||||
|
||||
@Inject
|
||||
lateinit var chatViewModel: ChatViewModel
|
||||
|
||||
@Inject
|
||||
lateinit var userManager: UserManager
|
||||
|
||||
@Inject
|
||||
lateinit var viewThemeUtils: ViewThemeUtils
|
||||
|
||||
@Composable
|
||||
fun GetDateTimeDialog(shouldDismiss: MutableState<Boolean>, context: Context) {
|
||||
if (shouldDismiss.value) {
|
||||
return
|
||||
}
|
||||
|
||||
val colorScheme = viewThemeUtils.getColorScheme(context)
|
||||
val isCollapsed = remember { mutableStateOf(true) }
|
||||
|
||||
MaterialTheme(colorScheme = colorScheme) {
|
||||
Dialog(
|
||||
onDismissRequest = {
|
||||
shouldDismiss.value = true
|
||||
},
|
||||
properties = DialogProperties(
|
||||
dismissOnBackPress = true,
|
||||
dismissOnClickOutside = true,
|
||||
usePlatformDefaultWidth = isCollapsed.value
|
||||
)
|
||||
) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(INT_8.dp),
|
||||
modifier = Modifier.animateContentSize()
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(INT_16.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Header()
|
||||
Body()
|
||||
CollapsableDateTime(shouldDismiss, isCollapsed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Submission(shouldDismiss: MutableState<Boolean>) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
TextButton(
|
||||
onClick = {
|
||||
val user = userManager.currentUser.blockingGet()
|
||||
val roomToken = bundle.getString(BundleKeys.KEY_ROOM_TOKEN)!!
|
||||
val messageId = bundle.getString(BundleKeys.KEY_MESSAGE_ID)!!
|
||||
val apiVersion = bundle.getInt(BundleKeys.KEY_CHAT_API_VERSION)
|
||||
chatViewModel.deleteReminder(user, roomToken, messageId, apiVersion)
|
||||
shouldDismiss.value = true
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(CUBED_PADDING)
|
||||
) {
|
||||
Text(
|
||||
stringResource(R.string.nc_delete),
|
||||
color = Color.Red
|
||||
)
|
||||
}
|
||||
|
||||
TextButton(
|
||||
onClick = {
|
||||
val user = userManager.currentUser.blockingGet()
|
||||
val roomToken = bundle.getString(BundleKeys.KEY_ROOM_TOKEN)!!
|
||||
val messageId = bundle.getString(BundleKeys.KEY_MESSAGE_ID)!!
|
||||
val apiVersion = bundle.getInt(BundleKeys.KEY_CHAT_API_VERSION)
|
||||
val offset = timeState.value.atZone(ZoneOffset.systemDefault()).offset
|
||||
val timeVal = timeState.value.toEpochSecond(offset)
|
||||
chatViewModel.setReminder(user, roomToken, messageId, timeVal.toInt(), apiVersion)
|
||||
shouldDismiss.value = true
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(CUBED_PADDING)
|
||||
) {
|
||||
Text(stringResource(R.string.set))
|
||||
}
|
||||
|
||||
TextButton(
|
||||
onClick = {
|
||||
shouldDismiss.value = true
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(CUBED_PADDING)
|
||||
) {
|
||||
Text(stringResource(R.string.close))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Body() {
|
||||
val currTime = LocalDateTime.now()
|
||||
|
||||
val laterToday = LocalDateTime.now()
|
||||
.withHour(INT_18)
|
||||
.withMinute(0)
|
||||
.withSecond(0)
|
||||
val laterTodayStr = laterToday.format(DateTimeFormatter.ofPattern(PATTERN))
|
||||
|
||||
val tomorrow = LocalDateTime.now()
|
||||
.plusDays(1)
|
||||
.withHour(INT_8)
|
||||
.withMinute(0)
|
||||
.withSecond(0)
|
||||
val tomorrowStr = tomorrow.format(DateTimeFormatter.ofPattern(PATTERN))
|
||||
|
||||
val thisWeekend = LocalDateTime.now()
|
||||
.with(nextOrSame(DayOfWeek.SATURDAY))
|
||||
.withHour(INT_8)
|
||||
.withMinute(0)
|
||||
.withSecond(0)
|
||||
val thisWeekendStr = thisWeekend.format(DateTimeFormatter.ofPattern(PATTERN))
|
||||
|
||||
val nextWeek = LocalDateTime.now()
|
||||
.plusWeeks(1)
|
||||
.with(DayOfWeek.MONDAY)
|
||||
.withHour(INT_8)
|
||||
.withMinute(0)
|
||||
.withSecond(0)
|
||||
val nextWeekStr = nextWeek.format(DateTimeFormatter.ofPattern(PATTERN))
|
||||
|
||||
if (currTime < laterToday) {
|
||||
TimeOption(
|
||||
label = stringResource(R.string.later_today),
|
||||
timeString = laterTodayStr
|
||||
) {
|
||||
setTime(laterToday)
|
||||
}
|
||||
}
|
||||
|
||||
if (tomorrow.dayOfWeek < DayOfWeek.SATURDAY) {
|
||||
TimeOption(
|
||||
label = stringResource(R.string.tomorrow),
|
||||
timeString = tomorrowStr
|
||||
) {
|
||||
setTime(tomorrow)
|
||||
}
|
||||
}
|
||||
|
||||
if (currTime.dayOfWeek < DayOfWeek.SATURDAY) {
|
||||
TimeOption(
|
||||
label = stringResource(R.string.this_weekend),
|
||||
timeString = thisWeekendStr
|
||||
) {
|
||||
setTime(thisWeekend)
|
||||
}
|
||||
}
|
||||
|
||||
TimeOption(
|
||||
label = stringResource(R.string.next_week),
|
||||
timeString = nextWeekStr
|
||||
) {
|
||||
setTime(nextWeek)
|
||||
}
|
||||
|
||||
HorizontalDivider()
|
||||
}
|
||||
|
||||
private fun setTime(localDateTime: LocalDateTime) {
|
||||
timeState.value = localDateTime
|
||||
chatViewModel.overrideReminderState()
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Header() {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(INT_8.dp)
|
||||
) {
|
||||
Text(stringResource(R.string.nc_remind), modifier = Modifier.weight(1f))
|
||||
|
||||
val reminderState = chatViewModel.getReminderExistState
|
||||
.asFlow()
|
||||
.collectAsState(ChatViewModel.GetReminderStartState)
|
||||
|
||||
when (reminderState.value) {
|
||||
is ChatViewModel.GetReminderExistState -> {
|
||||
val timeL =
|
||||
(reminderState.value as ChatViewModel.GetReminderExistState).reminder.timestamp!!.toLong()
|
||||
timeState.value = LocalDateTime.ofInstant(Instant.ofEpochSecond(timeL), ZoneId.systemDefault())
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
if (timeState.value != LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.MIN)) {
|
||||
Text(timeState.value.format(DateTimeFormatter.ofPattern(PATTERN)))
|
||||
}
|
||||
}
|
||||
HorizontalDivider()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun CollapsableDateTime(shouldDismiss: MutableState<Boolean>, isCollapsed: MutableState<Boolean>) {
|
||||
GeneralIconButton(icon = Icons.Filled.DateRange, label = "Custom") { isCollapsed.value = !isCollapsed.value }
|
||||
val scrollState = rememberScrollState()
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.verticalScroll(scrollState)
|
||||
) {
|
||||
if (!isCollapsed.value) {
|
||||
val datePickerState = rememberDatePickerState()
|
||||
val timePickerState = rememberTimePickerState()
|
||||
|
||||
DatePicker(
|
||||
state = datePickerState
|
||||
)
|
||||
|
||||
TimePicker(
|
||||
state = timePickerState
|
||||
)
|
||||
|
||||
val date = datePickerState.selectedDateMillis?.let {
|
||||
val instant = Instant.ofEpochMilli(it)
|
||||
LocalDateTime.ofInstant(instant, ZoneOffset.UTC) // Google sends time in UTC
|
||||
}
|
||||
if (date != null) {
|
||||
val year = date.year
|
||||
val month = date.month
|
||||
val day = date.dayOfMonth
|
||||
val hour = timePickerState.hour
|
||||
val minute = timePickerState.minute
|
||||
val newTime = LocalDateTime.of(year, month, day, hour, minute)
|
||||
setTime(newTime)
|
||||
} else {
|
||||
val newTime = LocalDate.now().atTime(timePickerState.hour, timePickerState.minute)
|
||||
setTime(newTime)
|
||||
}
|
||||
}
|
||||
Submission(shouldDismiss)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun GeneralIconButton(icon: ImageVector, label: String, onClick: () -> Unit) {
|
||||
TextButton(
|
||||
onClick = onClick
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Start
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(INT_24.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(INT_8.dp))
|
||||
Text(text = label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TimeOption(label: String, timeString: String, onClick: () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(INT_8.dp)
|
||||
.clickable { onClick() }
|
||||
) {
|
||||
Text(label, modifier = Modifier.weight(HALF_WEIGHT))
|
||||
Text(timeString, modifier = Modifier.weight(HALF_WEIGHT))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PATTERN = "dd MMM, HH:mm a"
|
||||
private const val HALF_WEIGHT = 0.5f
|
||||
private const val INT_8 = 8
|
||||
private const val INT_16 = 16
|
||||
private const val INT_18 = 18
|
||||
private const val INT_24 = 24
|
||||
private const val CUBED_PADDING = 0.33f
|
||||
}
|
||||
}
|
@ -1,315 +0,0 @@
|
||||
/*
|
||||
* Nextcloud Talk - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Julius Linus <julius.linus@nextcloud.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package com.nextcloud.talk.ui.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.text.format.DateFormat
|
||||
import android.text.format.DateUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import autodagger.AutoInjector
|
||||
import com.google.android.material.datepicker.CalendarConstraints
|
||||
import com.google.android.material.datepicker.DateValidatorPointForward
|
||||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.timepicker.MaterialTimePicker
|
||||
import com.google.android.material.timepicker.TimeFormat
|
||||
import com.nextcloud.android.common.ui.theme.utils.ColorRole
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.chat.ChatActivity
|
||||
import com.nextcloud.talk.chat.viewmodels.ChatViewModel
|
||||
import com.nextcloud.talk.databinding.DialogDateTimePickerBinding
|
||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import java.util.Calendar
|
||||
import java.util.TimeZone
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class DateTimePickerFragment : DialogFragment() {
|
||||
|
||||
lateinit var binding: DialogDateTimePickerBinding
|
||||
private var dialogView: View? = null
|
||||
private lateinit var viewModel: ChatViewModel
|
||||
private var currentTimeStamp: Long? = null
|
||||
private lateinit var roomToken: String
|
||||
private lateinit var messageId: String
|
||||
private var chatApiVersion: Int = -1
|
||||
private var laterTodayTimeStamp = 0L
|
||||
private var tomorrowTimeStamp = 0L
|
||||
private var weekendTimeStamp = 0L
|
||||
private var nextWeekTimeStamp = 0L
|
||||
|
||||
@Inject
|
||||
lateinit var userManager: UserManager
|
||||
|
||||
@Inject
|
||||
lateinit var viewThemeUtils: ViewThemeUtils
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
binding = DialogDateTimePickerBinding.inflate(layoutInflater)
|
||||
dialogView = binding.root
|
||||
viewModel = (requireActivity() as ChatActivity).chatViewModel
|
||||
arguments?.let {
|
||||
roomToken = it.getString(TOKEN_ARG, "")
|
||||
messageId = it.getString(ID_ARG, "")
|
||||
chatApiVersion = it.getInt(CHAT_API_VERSION_ARG)
|
||||
}
|
||||
return MaterialAlertDialogBuilder(requireContext()).setView(dialogView).create()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
setUpDefaults()
|
||||
setUpColors()
|
||||
setListeners()
|
||||
getReminder()
|
||||
viewModel.getReminderExistState.observe(this) { state ->
|
||||
when (state) {
|
||||
is ChatViewModel.GetReminderExistState -> {
|
||||
val timeStamp = state.reminder.timestamp?.toLong()?.times(ONE_SEC)
|
||||
showDelete(true)
|
||||
setTimeStamp(getTimeFromTimeStamp(timeStamp!!))
|
||||
}
|
||||
|
||||
else -> {
|
||||
showDelete(false)
|
||||
binding.dateTimePickerTimestamp.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inflater.inflate(R.layout.dialog_date_time_picker, container, false)
|
||||
}
|
||||
|
||||
private fun setUpDefaults() {
|
||||
val currTime = getTimeFromCalendar()
|
||||
val currentWeekInYear = Calendar.getInstance().get(Calendar.WEEK_OF_YEAR)
|
||||
|
||||
laterTodayTimeStamp = getTimeFromCalendar(hour = HOUR_SIX_PM, minute = 0)
|
||||
binding.dateTimePickerLaterTodayTextview.text = getTimeFromTimeStamp(laterTodayTimeStamp)
|
||||
|
||||
if (Calendar.getInstance().get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
|
||||
tomorrowTimeStamp = getTimeFromCalendar(
|
||||
hour = HOUR_EIGHT_AM,
|
||||
minute = 0,
|
||||
daysToAdd = 1
|
||||
)
|
||||
|
||||
binding.dateTimePickerWeekend.visibility = View.GONE // because today is the weekend
|
||||
} else {
|
||||
tomorrowTimeStamp = getTimeFromCalendar(hour = HOUR_EIGHT_AM, minute = 0, daysToAdd = 1)
|
||||
weekendTimeStamp = getTimeFromCalendar(hour = HOUR_EIGHT_AM, weekDay = Calendar.SATURDAY, minute = 0)
|
||||
}
|
||||
binding.dateTimePickerTomorrowTextview.text = getTimeFromTimeStamp(tomorrowTimeStamp)
|
||||
binding.dateTimePickerWeekendTextview.text = getTimeFromTimeStamp(weekendTimeStamp)
|
||||
|
||||
nextWeekTimeStamp = getTimeFromCalendar(
|
||||
hour = HOUR_EIGHT_AM,
|
||||
weekDay = Calendar.MONDAY,
|
||||
minute = 0,
|
||||
weekInYear =
|
||||
currentWeekInYear + 1
|
||||
) // this should only pick mondays from next week only
|
||||
binding.dateTimePickerNextWeekTextview.text = getTimeFromTimeStamp(nextWeekTimeStamp)
|
||||
|
||||
// This is to hide the later today option, if it's past 6pm
|
||||
if (currTime > laterTodayTimeStamp) {
|
||||
binding.dateTimePickerLaterToday.visibility = View.GONE
|
||||
}
|
||||
|
||||
// This is to hide the tomorrow option, if that's also the weekend
|
||||
if (binding.dateTimePickerTomorrowTextview.text == binding.dateTimePickerWeekendTextview.text) {
|
||||
binding.dateTimePickerTomorrow.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun getReminder() {
|
||||
viewModel.getReminder(userManager.currentUser.blockingGet(), roomToken, messageId, chatApiVersion)
|
||||
}
|
||||
|
||||
private fun showDelete(value: Boolean) {
|
||||
if (value) {
|
||||
binding.buttonDelete.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.buttonDelete.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpColors() {
|
||||
binding.root.let {
|
||||
viewThemeUtils.platform.colorViewBackground(it)
|
||||
}
|
||||
|
||||
binding.dateTimePickerCustomIcon.let {
|
||||
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
|
||||
}
|
||||
|
||||
binding.dateTimePickerTimestamp.let {
|
||||
viewThemeUtils.material.themeSearchBarText(it)
|
||||
}
|
||||
|
||||
binding.run {
|
||||
listOf(
|
||||
binding.buttonClose,
|
||||
binding.buttonSet
|
||||
)
|
||||
}.forEach(viewThemeUtils.material::colorMaterialButtonPrimaryBorderless)
|
||||
}
|
||||
|
||||
private fun setListeners() {
|
||||
binding.dateTimePickerLaterToday.setOnClickListener {
|
||||
currentTimeStamp = laterTodayTimeStamp / ONE_SEC
|
||||
setTimeStamp(getTimeFromTimeStamp(laterTodayTimeStamp))
|
||||
}
|
||||
binding.dateTimePickerTomorrow.setOnClickListener {
|
||||
currentTimeStamp = tomorrowTimeStamp / ONE_SEC
|
||||
setTimeStamp(getTimeFromTimeStamp(tomorrowTimeStamp))
|
||||
}
|
||||
binding.dateTimePickerWeekend.setOnClickListener {
|
||||
currentTimeStamp = weekendTimeStamp / ONE_SEC
|
||||
setTimeStamp(getTimeFromTimeStamp(weekendTimeStamp))
|
||||
}
|
||||
binding.dateTimePickerNextWeek.setOnClickListener {
|
||||
currentTimeStamp = nextWeekTimeStamp / ONE_SEC
|
||||
setTimeStamp(getTimeFromTimeStamp(nextWeekTimeStamp))
|
||||
}
|
||||
binding.dateTimePickerCustom.setOnClickListener {
|
||||
val constraintsBuilder = CalendarConstraints.Builder()
|
||||
.setValidator(DateValidatorPointForward.now())
|
||||
.build()
|
||||
val time = System.currentTimeMillis()
|
||||
val datePicker = MaterialDatePicker.Builder.datePicker()
|
||||
.setTitleText(R.string.nc_remind)
|
||||
.setSelection(time + TimeZone.getDefault().getOffset(time))
|
||||
.setCalendarConstraints(constraintsBuilder).build()
|
||||
|
||||
datePicker.addOnPositiveButtonClickListener { selection ->
|
||||
val localTimeInMillis = selection - TimeZone.getDefault().getOffset(selection)
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = localTimeInMillis
|
||||
|
||||
val year = calendar.get(Calendar.YEAR)
|
||||
val month = calendar.get(Calendar.MONTH)
|
||||
val day = calendar.get(Calendar.DAY_OF_YEAR)
|
||||
|
||||
setUpTimePicker(year, month, day)
|
||||
}
|
||||
datePicker.show(this.parentFragmentManager, TAG)
|
||||
}
|
||||
|
||||
binding.buttonClose.setOnClickListener { dismiss() }
|
||||
binding.buttonSet.setOnClickListener {
|
||||
currentTimeStamp?.let { time ->
|
||||
viewModel.setReminder(
|
||||
userManager.currentUser.blockingGet(),
|
||||
roomToken,
|
||||
messageId,
|
||||
time.toInt(),
|
||||
chatApiVersion
|
||||
)
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
binding.buttonDelete.setOnClickListener {
|
||||
viewModel.deleteReminder(userManager.currentUser.blockingGet(), roomToken, messageId, chatApiVersion)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpTimePicker(year: Int, month: Int, day: Int) {
|
||||
val locale = if (DateFormat.is24HourFormat(requireContext())) TimeFormat.CLOCK_24H else TimeFormat.CLOCK_12H
|
||||
val timePicker = MaterialTimePicker.Builder()
|
||||
.setTitleText(R.string.nc_remind)
|
||||
.setTimeFormat(locale)
|
||||
.build()
|
||||
|
||||
timePicker.addOnPositiveButtonClickListener {
|
||||
val timestamp = getTimeFromCalendar(
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
timePicker.hour,
|
||||
timePicker.minute
|
||||
)
|
||||
setTimeStamp(getTimeFromTimeStamp(timestamp))
|
||||
currentTimeStamp = timestamp / ONE_SEC
|
||||
}
|
||||
|
||||
timePicker.show(this.parentFragmentManager, TAG)
|
||||
}
|
||||
|
||||
/**
|
||||
* You can use `weekDay` or `daysToAdd` or neither but don't use both b/c it messes up the calendar
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
private fun getTimeFromCalendar(
|
||||
year: Int = Calendar.getInstance().get(Calendar.YEAR),
|
||||
month: Int = Calendar.getInstance().get(Calendar.MONTH),
|
||||
day: Int = Calendar.getInstance().get(Calendar.DAY_OF_YEAR),
|
||||
hour: Int = Calendar.getInstance().get(Calendar.HOUR_OF_DAY),
|
||||
minute: Int = Calendar.getInstance().get(Calendar.MINUTE),
|
||||
daysToAdd: Int = 0,
|
||||
weekInYear: Int = -1,
|
||||
weekDay: Int = -1
|
||||
): Long {
|
||||
val calendar: Calendar = Calendar.getInstance().apply {
|
||||
set(Calendar.YEAR, year)
|
||||
set(Calendar.MONTH, month)
|
||||
set(Calendar.DAY_OF_YEAR, day)
|
||||
if (weekDay > -1) set(Calendar.DAY_OF_WEEK, weekDay)
|
||||
if (daysToAdd > 0) add(Calendar.DAY_OF_YEAR, daysToAdd)
|
||||
if (weekInYear != -1) set(Calendar.WEEK_OF_YEAR, weekInYear)
|
||||
set(Calendar.HOUR_OF_DAY, hour)
|
||||
set(Calendar.MINUTE, minute)
|
||||
set(Calendar.SECOND, 0)
|
||||
}
|
||||
return calendar.timeInMillis
|
||||
}
|
||||
|
||||
private fun setTimeStamp(date: String) {
|
||||
binding.dateTimePickerTimestamp.text = date
|
||||
}
|
||||
|
||||
private fun getTimeFromTimeStamp(time: Long): String {
|
||||
return DateUtils.formatDateTime(
|
||||
requireContext(),
|
||||
time,
|
||||
DateUtils.FORMAT_SHOW_DATE
|
||||
) + ", " + DateUtils.formatDateTime(
|
||||
requireContext(),
|
||||
time,
|
||||
DateUtils.FORMAT_SHOW_TIME
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG = DateTimePickerFragment::class.simpleName
|
||||
private const val ONE_SEC = 1000
|
||||
private const val HOUR_EIGHT_AM = 8
|
||||
private const val HOUR_SIX_PM = 18
|
||||
private const val TOKEN_ARG = "TOKEN_ARG"
|
||||
private const val ID_ARG = "ID_ARG"
|
||||
private const val CHAT_API_VERSION_ARG = "CHAT_API_VERSION_ARG"
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance(token: String, id: String, chatApiVersion: Int): DateTimePickerFragment {
|
||||
val args = Bundle()
|
||||
args.putString(TOKEN_ARG, token)
|
||||
args.putString(ID_ARG, id)
|
||||
args.putInt(CHAT_API_VERSION_ARG, chatApiVersion)
|
||||
|
||||
val dateTimePickerFragment = DateTimePickerFragment()
|
||||
dateTimePickerFragment.arguments = args
|
||||
return dateTimePickerFragment
|
||||
}
|
||||
}
|
||||
}
|
@ -269,4 +269,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="0dp"
|
||||
/>
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/generic_compose_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
@ -1,212 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk - Android Client
|
||||
~
|
||||
~ SPDX-FileCopyrightText: 2023 Julius Linus <julius.linus@nextcloud.com>
|
||||
~ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:background="@color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/standard_margin"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/nc_remind"
|
||||
android:textSize="@dimen/md_title_textsize" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/date_time_picker_timestamp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/supporting_text_text_size"
|
||||
android:textStyle="bold"
|
||||
tools:text="Apr 15th, 8:00 AM" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/date_time_picker_later_today"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/standard_padding">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/later_today"
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/date_time_picker_later_today_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/date_time_picker_tomorrow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/standard_padding">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/tomorrow"
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/date_time_picker_tomorrow_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/date_time_picker_weekend"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/standard_padding">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/this_weekend"
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/date_time_picker_weekend_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/date_time_picker_next_week"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/standard_padding">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/next_week"
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/date_time_picker_next_week_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/date_time_picker_custom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/standard_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/date_time_picker_custom_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/calendar"
|
||||
android:paddingEnd="@dimen/standard_double_padding"
|
||||
android:src="@drawable/baseline_calendar_month_24"
|
||||
tools:ignore="RtlSymmetry" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/custom"
|
||||
android:textSize="@dimen/headline_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_delete"
|
||||
style="@style/Button.Borderless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="@dimen/min_size_clickable_area"
|
||||
android:text="@string/nc_delete"
|
||||
android:textColor="@color/design_default_color_error" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_set"
|
||||
style="@style/Button.Borderless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="@dimen/min_size_clickable_area"
|
||||
android:text="@string/set" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_close"
|
||||
style="@style/Button.Borderless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:minHeight="@dimen/min_size_clickable_area"
|
||||
android:text="@string/close" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
@ -1,2 +1,2 @@
|
||||
DO NOT TOUCH; GENERATED BY DRONE
|
||||
<span class="mdl-layout-title">Lint Report: 66 errors and 158 warnings</span>
|
||||
<span class="mdl-layout-title">Lint Report: 36 errors and 106 warnings</span>
|
||||
|
Loading…
Reference in New Issue
Block a user