diff --git a/app/src/main/java/org/dhis2/usescases/settings/bindings/SyncManagerBindings.kt b/app/src/main/java/org/dhis2/usescases/settings/bindings/SyncManagerBindings.kt index 4c1aafd7f3..b72fa3e2ba 100644 --- a/app/src/main/java/org/dhis2/usescases/settings/bindings/SyncManagerBindings.kt +++ b/app/src/main/java/org/dhis2/usescases/settings/bindings/SyncManagerBindings.kt @@ -1,11 +1,17 @@ package org.dhis2.usescases.settings.bindings +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Text +import androidx.compose.ui.Alignment import androidx.compose.ui.platform.ComposeView import androidx.databinding.BindingAdapter -import org.dhis2.ui.Dhis2ProgressIndicator import org.dhis2.ui.model.ButtonUiModel import org.dhis2.ui.theme.Dhis2Theme +import org.dhis2.ui.theme.textSecondary import org.hisp.dhis.mobile.ui.designsystem.component.Button +import org.hisp.dhis.mobile.ui.designsystem.component.ProgressIndicator +import org.hisp.dhis.mobile.ui.designsystem.component.ProgressIndicatorType +import org.hisp.dhis.mobile.ui.designsystem.theme.DHIS2Theme @BindingAdapter("addTextButton") fun ComposeView.addTextButton(model: ButtonUiModel?) { @@ -25,8 +31,13 @@ fun ComposeView.addTextButton(model: ButtonUiModel?) { @BindingAdapter("progressIndicator") fun ComposeView.progressIndicator(message: String?) { setContent { - Dhis2Theme { - Dhis2ProgressIndicator(message) + DHIS2Theme { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + ProgressIndicator( + type = ProgressIndicatorType.CIRCULAR, + ) + message?.let { Text(it, color = textSecondary) } + } } } } diff --git a/dhis_android_analytics/src/main/java/dhis2/org/analytics/charts/mappers/GraphToTable.kt b/dhis_android_analytics/src/main/java/dhis2/org/analytics/charts/mappers/GraphToTable.kt index efdf436adc..3923766790 100644 --- a/dhis_android_analytics/src/main/java/dhis2/org/analytics/charts/mappers/GraphToTable.kt +++ b/dhis_android_analytics/src/main/java/dhis2/org/analytics/charts/mappers/GraphToTable.kt @@ -13,11 +13,18 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import com.google.android.material.composethemeadapter.MdcTheme import dhis2.org.R import dhis2.org.analytics.charts.data.ChartType @@ -41,7 +48,6 @@ import org.dhis2.composetable.ui.TableDimensions import org.dhis2.composetable.ui.TableSelection import org.dhis2.composetable.ui.TableTheme import org.dhis2.composetable.ui.compositions.LocalInteraction -import org.dhis2.ui.theme.descriptionTextStyle import org.hisp.dhis.android.core.arch.helpers.DateUtils import kotlin.math.roundToInt @@ -169,7 +175,15 @@ class GraphToTable { R.string.line_listing_max_results, LINE_LISTING_MAX_ROWS, ), - style = descriptionTextStyle, + style = TextStyle( + color = Color(0xFF667685), + fontSize = 10.sp, + fontWeight = FontWeight.Normal, + fontFamily = FontFamily(Font(org.dhis2.ui.R.font.roboto_regular)), + lineHeight = 16.sp, + letterSpacing = (0.4).sp, + textAlign = TextAlign.End, + ), ) } } diff --git a/form/src/main/java/org/dhis2/form/model/FieldUiModelImpl.kt b/form/src/main/java/org/dhis2/form/model/FieldUiModelImpl.kt index 46fa01a3e0..c01908c685 100644 --- a/form/src/main/java/org/dhis2/form/model/FieldUiModelImpl.kt +++ b/form/src/main/java/org/dhis2/form/model/FieldUiModelImpl.kt @@ -61,11 +61,7 @@ data class FieldUiModelImpl( override fun invokeUiEvent(uiEventType: UiEventType) { callback?.intent(FormIntent.OnRequestCoordinates(uid)) - if (uiEventType != UiEventType.QR_CODE && - uiEventType != UiEventType.EMAIL && - uiEventType != UiEventType.PHONE_NUMBER && - !focused - ) { + if (!focused) { onItemClick() } uiEventFactory?.generateEvent(value, uiEventType, renderingType, this)?.let { diff --git a/form/src/main/java/org/dhis2/form/model/UiEventType.kt b/form/src/main/java/org/dhis2/form/model/UiEventType.kt index 5e7a85142e..81eb03f23b 100644 --- a/form/src/main/java/org/dhis2/form/model/UiEventType.kt +++ b/form/src/main/java/org/dhis2/form/model/UiEventType.kt @@ -1,21 +1,9 @@ package org.dhis2.form.model enum class UiEventType { - DATE_TIME, - AGE_CALENDAR, - ORG_UNIT, - REQUEST_CURRENT_LOCATION, REQUEST_LOCATION_BY_MAP, ADD_PICTURE, - SHOW_PICTURE, - SHOW_DESCRIPTION, - COPY_TO_CLIPBOARD, - QR_CODE, - OPTION_SET, - ADD_SIGNATURE, ADD_FILE, OPEN_FILE, - EMAIL, - PHONE_NUMBER, SHARE_IMAGE, } diff --git a/form/src/main/java/org/dhis2/form/ui/FormView.kt b/form/src/main/java/org/dhis2/form/ui/FormView.kt index bb1d1e70f1..f5997abe9e 100644 --- a/form/src/main/java/org/dhis2/form/ui/FormView.kt +++ b/form/src/main/java/org/dhis2/form/ui/FormView.kt @@ -9,16 +9,13 @@ import android.content.Context import android.content.DialogInterface import android.content.Intent import android.content.pm.PackageManager -import android.graphics.Bitmap import android.net.Uri import android.os.Build import android.os.Bundle -import android.text.format.DateFormat import android.view.ContextThemeWrapper import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.DatePicker import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.RequiresApi @@ -32,9 +29,6 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.timepicker.MaterialTimePicker -import com.google.android.material.timepicker.TimeFormat.CLOCK_12H -import com.google.android.material.timepicker.TimeFormat.CLOCK_24H import com.journeyapps.barcodescanner.ScanOptions import org.dhis2.commons.ActivityResultObservable import org.dhis2.commons.ActivityResultObserver @@ -48,9 +42,6 @@ import org.dhis2.commons.date.DateUtils import org.dhis2.commons.dialogs.AlertBottomDialog import org.dhis2.commons.dialogs.CustomDialog import org.dhis2.commons.dialogs.PeriodDialog -import org.dhis2.commons.dialogs.calendarpicker.CalendarPicker -import org.dhis2.commons.dialogs.calendarpicker.OnDatePickerListener -import org.dhis2.commons.dialogs.imagedetail.ImageDetailActivity import org.dhis2.commons.extensions.closeKeyboard import org.dhis2.commons.extensions.serializable import org.dhis2.commons.extensions.truncate @@ -75,9 +66,7 @@ import org.dhis2.form.model.InfoUiModel import org.dhis2.form.model.RowAction import org.dhis2.form.model.UiRenderType import org.dhis2.form.model.exception.RepositoryRecordsException -import org.dhis2.form.ui.dialog.OptionSetDialog import org.dhis2.form.ui.dialog.QRDetailBottomDialog -import org.dhis2.form.ui.event.DialogDelegate import org.dhis2.form.ui.event.RecyclerViewUiEvents import org.dhis2.form.ui.idling.FormCountingIdlingResource import org.dhis2.form.ui.intent.FormIntent @@ -92,7 +81,6 @@ import org.dhis2.ui.dialogs.bottomsheet.BottomSheetDialog import org.dhis2.ui.dialogs.bottomsheet.BottomSheetDialogUiModel import org.dhis2.ui.dialogs.bottomsheet.FieldWithIssue import org.dhis2.ui.dialogs.bottomsheet.IssueType -import org.dhis2.ui.dialogs.signature.SignatureDialog import org.hisp.dhis.android.core.arch.helpers.FileResourceDirectoryHelper import org.hisp.dhis.android.core.arch.helpers.GeometryHelper import org.hisp.dhis.android.core.common.FeatureType @@ -101,7 +89,6 @@ import org.hisp.dhis.android.core.common.ValueTypeRenderingType import org.hisp.dhis.android.core.event.EventStatus import timber.log.Timber import java.io.File -import java.util.Calendar import java.util.Date class FormView : Fragment() { @@ -306,7 +293,6 @@ class FormView : Fragment() { ) } - private lateinit var dialogDelegate: DialogDelegate private lateinit var formSectionMapper: FormSectionMapper var scrollCallback: ((Boolean) -> Unit)? = null private var displayConfErrors = true @@ -334,7 +320,6 @@ class FormView : Fragment() { savedInstanceState: Bundle?, ): View { val contextWrapper = ContextThemeWrapper(context, R.style.searchFormInputText) - dialogDelegate = DialogDelegate() formSectionMapper = FormSectionMapper() FormFileProvider.init(contextWrapper.applicationContext) @@ -462,7 +447,10 @@ class FormView : Fragment() { } @Composable - private fun DialogContent(fieldsWithIssues: List, bottomSheetDialog: BottomSheetDialog): Unit? { + private fun DialogContent( + fieldsWithIssues: List, + bottomSheetDialog: BottomSheetDialog, + ): Unit? { return if (fieldsWithIssues.isEmpty()) { null } else { @@ -509,12 +497,14 @@ class FormView : Fragment() { } else { showBottomSheetDialog() } + EventStatus.SKIPPED -> { if (fieldsWithIssues.isEmpty()) { viewModel.activateEvent() } showBottomSheetDialog() } + else -> onFinishDataEntry?.invoke() } if (result.eventResultDetails.eventStatus == null && result is NotSavedResult) { @@ -528,7 +518,8 @@ class FormView : Fragment() { isEventCompleted: Boolean, bottomSheetDialog: BottomSheetDialog, ) { - val errorsInField = fieldsWithIssues.isNotEmpty() || fieldsWithIssues.any { it.issueType == IssueType.ERROR } + val errorsInField = + fieldsWithIssues.isNotEmpty() || fieldsWithIssues.any { it.issueType == IssueType.ERROR } if (errorsInField) { bottomSheetDialog.dismiss() } else if (isEventCompleted) { @@ -563,6 +554,7 @@ class FormView : Fragment() { result = result, ) } + is FieldsWithWarningResult -> formResultDialogUiProvider?.invoke( canComplete = result.canComplete, onCompleteMessage = result.onCompleteMessage, @@ -629,22 +621,12 @@ class FormView : Fragment() { private fun uiEventHandler(uiEvent: RecyclerViewUiEvents) { when (uiEvent) { - is RecyclerViewUiEvents.OpenCustomCalendar -> showCustomCalendar(uiEvent) - is RecyclerViewUiEvents.OpenTimePicker -> showTimePicker(uiEvent) - is RecyclerViewUiEvents.ShowDescriptionLabelDialog -> showDescriptionLabelDialog( - uiEvent, - ) - is RecyclerViewUiEvents.RequestCurrentLocation -> requestCurrentLocation(uiEvent) is RecyclerViewUiEvents.RequestLocationByMap -> requestLocationByMap(uiEvent) is RecyclerViewUiEvents.DisplayQRCode -> displayQRImage(uiEvent) is RecyclerViewUiEvents.ScanQRCode -> requestQRScan(uiEvent) is RecyclerViewUiEvents.OpenOrgUnitDialog -> showOrgUnitDialog(uiEvent) is RecyclerViewUiEvents.AddImage -> requestAddImage(uiEvent) - is RecyclerViewUiEvents.ShowImage -> showFullPicture(uiEvent) - is RecyclerViewUiEvents.CopyToClipboard -> copyToClipboard(uiEvent.value) - is RecyclerViewUiEvents.OpenOptionSetDialog -> showOptionSetDialog(uiEvent) - is RecyclerViewUiEvents.AddSignature -> showSignatureDialog(uiEvent) is RecyclerViewUiEvents.OpenFile -> openFile(uiEvent) is RecyclerViewUiEvents.OpenFileSelector -> openFileSelector(uiEvent) is RecyclerViewUiEvents.OpenChooserIntent -> openChooserIntent(uiEvent) @@ -762,83 +744,6 @@ class FormView : Fragment() { viewModel.submitIntent(intent) } - private fun showCustomCalendar(intent: RecyclerViewUiEvents.OpenCustomCalendar) { - val dialog = CalendarPicker(requireContext()).apply { - setTitle(intent.label) - setInitialDate(intent.date) - isFutureDatesAllowed(intent.allowFutureDates) - setListener(object : OnDatePickerListener { - override fun onNegativeClick() { - intentHandler(FormIntent.ClearValue(intent.uid)) - } - - override fun onPositiveClick(datePicker: DatePicker) { - when (intent.isDateTime) { - true -> uiEventHandler( - dialogDelegate.handleDateTimeInput( - intent.uid, - intent.label, - intent.date, - datePicker.year, - datePicker.month, - datePicker.dayOfMonth, - ), - ) - - else -> intentHandler( - dialogDelegate.handleDateInput( - intent.uid, - datePicker.year, - datePicker.month, - datePicker.dayOfMonth, - ), - ) - } - } - }) - } - dialog.show() - } - - private fun showTimePicker(intent: RecyclerViewUiEvents.OpenTimePicker) { - val calendar = Calendar.getInstance() - intent.date?.let { calendar.time = it } - val is24HourFormat = DateFormat.is24HourFormat(requireContext()) - MaterialTimePicker.Builder() - .setTheme(R.style.TimePicker) - .setTimeFormat(CLOCK_24H.takeIf { is24HourFormat } ?: CLOCK_12H) - .setHour(calendar[Calendar.HOUR_OF_DAY]) - .setMinute(calendar[Calendar.MINUTE]) - .setTitleText(intent.label) - .build().apply { - addOnPositiveButtonClickListener { - intentHandler( - dialogDelegate.handleTimeInput( - intent.uid, - if (intent.isDateTime == true) intent.date else null, - hour, - minute, - ), - ) - } - } - .show(childFragmentManager, "timePicker") - } - - private fun showDescriptionLabelDialog( - intent: RecyclerViewUiEvents.ShowDescriptionLabelDialog, - ) { - CustomDialog( - requireContext(), - intent.title, - intent.message ?: requireContext().getString(R.string.empty_description), - requireContext().getString(R.string.action_close), - null, - Constants.DESCRIPTION_DIALOG, - null, - ).show() - } - private fun requestCurrentLocation(event: RecyclerViewUiEvents.RequestCurrentLocation) { locationProvider?.getLastKnownLocation( { location -> @@ -972,16 +877,6 @@ class FormView : Fragment() { .show() } - private fun showFullPicture(event: RecyclerViewUiEvents.ShowImage) { - val intent = ImageDetailActivity.intent( - title = event.label, - imagePath = event.value, - context = requireActivity(), - ) - - startActivity(intent) - } - private fun openFileSelector(event: RecyclerViewUiEvents.OpenFileSelector) { onSavePicture = { file -> intentHandler( @@ -1077,43 +972,6 @@ class FormView : Fragment() { } } - private fun showOptionSetDialog(uiEvent: RecyclerViewUiEvents.OpenOptionSetDialog) { - OptionSetDialog( - field = uiEvent.field, - onClearValue = { - intentHandler(FormIntent.ClearValue(uiEvent.field.uid)) - }, - ) { code -> - intentHandler( - FormIntent.OnSave( - uiEvent.field.uid, - code, - uiEvent.field.valueType, - ), - ) - }.show(this@FormView.childFragmentManager) - } - - private fun showSignatureDialog(uiEvent: RecyclerViewUiEvents.AddSignature) { - SignatureDialog(uiEvent.label) { - val file = File( - FileResourceDirectoryHelper.getFileResourceDirectory(requireContext()), - TEMP_FILE, - ) - file.outputStream().use { out -> - it.compress(Bitmap.CompressFormat.PNG, 85, out) - out.flush() - } - intentHandler( - FormIntent.OnStoreFile( - uiEvent.uid, - file.path, - ValueType.IMAGE, - ), - ) - }.show(this@FormView.childFragmentManager) - } - fun onBackPressed() { viewModel.runDataIntegrityCheck(backButtonPressed = true) } diff --git a/form/src/main/java/org/dhis2/form/ui/event/DialogDelegate.kt b/form/src/main/java/org/dhis2/form/ui/event/DialogDelegate.kt deleted file mode 100644 index ff848a54e0..0000000000 --- a/form/src/main/java/org/dhis2/form/ui/event/DialogDelegate.kt +++ /dev/null @@ -1,92 +0,0 @@ -package org.dhis2.form.ui.event - -import org.dhis2.commons.date.DateUtils -import org.dhis2.form.ui.intent.FormIntent -import org.hisp.dhis.android.core.common.ValueType -import java.util.Calendar -import java.util.Date - -class DialogDelegate { - - fun handleDateInput(uid: String, year: Int, month: Int, day: Int): FormIntent { - val currentCalendar = Calendar.getInstance() - val ageDate = with(currentCalendar) { - set(Calendar.YEAR, year) - set(Calendar.MONTH, month) - set(Calendar.DAY_OF_MONTH, day) - set(Calendar.HOUR_OF_DAY, 0) - set(Calendar.MINUTE, 0) - set(Calendar.SECOND, 0) - set(Calendar.MILLISECOND, 0) - return@with time - } - val date = DateUtils.oldUiDateFormat().format(ageDate) - - return FormIntent.OnSave( - uid = uid, - value = date, - valueType = ValueType.DATE, - ) - } - - fun handleYearMonthDayInput(uid: String, year: Int, month: Int, day: Int): FormIntent { - val currentCalendar = Calendar.getInstance() - val ageDate = with(currentCalendar) { - add(Calendar.YEAR, year) - add(Calendar.MONTH, month) - add(Calendar.DAY_OF_MONTH, day) - set(Calendar.HOUR_OF_DAY, 0) - set(Calendar.MINUTE, 0) - set(Calendar.SECOND, 0) - set(Calendar.MILLISECOND, 0) - return@with time - } - val date = DateUtils.oldUiDateFormat().format(ageDate) - - return FormIntent.OnSave( - uid = uid, - value = date, - valueType = ValueType.DATE, - ) - } - - fun handleTimeInput(uid: String, date: Date?, hourOfDay: Int, minutes: Int): FormIntent { - val currentCalendar = Calendar.getInstance() - val dateTime = with(currentCalendar) { - date?.let { time = it } - set(Calendar.HOUR_OF_DAY, hourOfDay) - set(Calendar.MINUTE, minutes) - set(Calendar.SECOND, 0) - set(Calendar.MILLISECOND, 0) - return@with time - } - val dateValue = when (date) { - null -> DateUtils.timeFormat().format(dateTime) - else -> DateUtils.databaseDateFormatNoSeconds().format(dateTime) - } - return FormIntent.OnSave( - uid = uid, - value = dateValue, - valueType = date?.let { ValueType.DATETIME } ?: ValueType.TIME, - ) - } - - fun handleDateTimeInput( - uid: String, - label: String, - date: Date?, - year: Int, - month: Int, - day: Int, - ): RecyclerViewUiEvents { - val currentCalendar = Calendar.getInstance() - val dateTime = with(currentCalendar) { - date?.let { time = it } - set(Calendar.YEAR, year) - set(Calendar.MONTH, month) - set(Calendar.DAY_OF_MONTH, day) - return@with time - } - return RecyclerViewUiEvents.OpenTimePicker(uid, label, dateTime, isDateTime = true) - } -} diff --git a/form/src/main/java/org/dhis2/form/ui/event/RecyclerViewUiEvents.kt b/form/src/main/java/org/dhis2/form/ui/event/RecyclerViewUiEvents.kt index 017b751638..945f95ccdd 100644 --- a/form/src/main/java/org/dhis2/form/ui/event/RecyclerViewUiEvents.kt +++ b/form/src/main/java/org/dhis2/form/ui/event/RecyclerViewUiEvents.kt @@ -9,26 +9,6 @@ import java.util.Date sealed class RecyclerViewUiEvents { - data class OpenCustomCalendar( - val uid: String, - val label: String, - val date: Date?, - val allowFutureDates: Boolean, - val isDateTime: Boolean? = false, - ) : RecyclerViewUiEvents() - - data class OpenTimePicker( - val uid: String, - val label: String, - val date: Date?, - val isDateTime: Boolean? = false, - ) : RecyclerViewUiEvents() - - data class ShowDescriptionLabelDialog( - val title: String, - val message: String?, - ) : RecyclerViewUiEvents() - data class RequestCurrentLocation( val uid: String, ) : RecyclerViewUiEvents() @@ -65,24 +45,6 @@ sealed class RecyclerViewUiEvents { val uid: String, ) : RecyclerViewUiEvents() - data class AddSignature( - val uid: String, - val label: String, - ) : RecyclerViewUiEvents() - - data class ShowImage( - val label: String, - val value: String, - ) : RecyclerViewUiEvents() - - data class CopyToClipboard( - val value: String?, - ) : RecyclerViewUiEvents() - - data class OpenOptionSetDialog( - val field: FieldUiModel, - ) : RecyclerViewUiEvents() - data class OpenFileSelector( val field: FieldUiModel, ) : RecyclerViewUiEvents() diff --git a/form/src/main/java/org/dhis2/form/ui/event/UiEventFactoryImpl.kt b/form/src/main/java/org/dhis2/form/ui/event/UiEventFactoryImpl.kt index ee52d3439f..f05f27c5aa 100644 --- a/form/src/main/java/org/dhis2/form/ui/event/UiEventFactoryImpl.kt +++ b/form/src/main/java/org/dhis2/form/ui/event/UiEventFactoryImpl.kt @@ -1,27 +1,13 @@ package org.dhis2.form.ui.event import android.content.Intent -import org.dhis2.commons.date.DateUtils -import org.dhis2.commons.extensions.toDate import org.dhis2.form.model.FieldUiModel import org.dhis2.form.model.UiEventType import org.dhis2.form.model.UiEventType.ADD_FILE import org.dhis2.form.model.UiEventType.ADD_PICTURE -import org.dhis2.form.model.UiEventType.ADD_SIGNATURE -import org.dhis2.form.model.UiEventType.AGE_CALENDAR -import org.dhis2.form.model.UiEventType.COPY_TO_CLIPBOARD -import org.dhis2.form.model.UiEventType.DATE_TIME -import org.dhis2.form.model.UiEventType.EMAIL import org.dhis2.form.model.UiEventType.OPEN_FILE -import org.dhis2.form.model.UiEventType.OPTION_SET -import org.dhis2.form.model.UiEventType.ORG_UNIT -import org.dhis2.form.model.UiEventType.PHONE_NUMBER -import org.dhis2.form.model.UiEventType.QR_CODE -import org.dhis2.form.model.UiEventType.REQUEST_CURRENT_LOCATION import org.dhis2.form.model.UiEventType.REQUEST_LOCATION_BY_MAP import org.dhis2.form.model.UiEventType.SHARE_IMAGE -import org.dhis2.form.model.UiEventType.SHOW_DESCRIPTION -import org.dhis2.form.model.UiEventType.SHOW_PICTURE import org.dhis2.form.model.UiRenderType import org.hisp.dhis.android.core.common.FeatureType import org.hisp.dhis.android.core.common.ValueType @@ -44,104 +30,15 @@ class UiEventFactoryImpl( var uiEvent: RecyclerViewUiEvents? = null try { uiEvent = when (uiEventType) { - DATE_TIME -> { - when (valueType) { - ValueType.DATE -> RecyclerViewUiEvents.OpenCustomCalendar( - uid, - label, - value?.let { DateUtils.oldUiDateFormat().parse(it) }, - allowFutureDates ?: true, - ) - - ValueType.DATETIME -> RecyclerViewUiEvents.OpenCustomCalendar( - uid, - label, - value?.let { DateUtils.databaseDateFormatNoSeconds().parse(it) }, - allowFutureDates ?: true, - isDateTime = true, - ) - - ValueType.TIME -> RecyclerViewUiEvents.OpenTimePicker( - uid, - label, - value?.let { DateUtils.timeFormat().parse(it) }, - ) - - else -> null - } - } - - AGE_CALENDAR -> RecyclerViewUiEvents.OpenCustomCalendar( - uid = uid, - label = label, - date = value?.toDate(), - allowFutureDates = allowFutureDates ?: false, - ) - - ORG_UNIT -> RecyclerViewUiEvents.OpenOrgUnitDialog( - uid, - label, - value, - fieldUiModel.orgUnitSelectorScope, - ) - - REQUEST_CURRENT_LOCATION -> RecyclerViewUiEvents.RequestCurrentLocation( - uid = uid, - ) - REQUEST_LOCATION_BY_MAP -> RecyclerViewUiEvents.RequestLocationByMap( uid = uid, featureType = getFeatureType(renderingType), value = value, ) - SHOW_DESCRIPTION -> RecyclerViewUiEvents.ShowDescriptionLabelDialog( - title = label, - message = description, - ) - ADD_PICTURE -> RecyclerViewUiEvents.AddImage(uid) - SHOW_PICTURE -> RecyclerViewUiEvents.ShowImage( - label, - value ?: "", - ) - - COPY_TO_CLIPBOARD -> RecyclerViewUiEvents.CopyToClipboard( - value = value, - ) - - QR_CODE -> { - if (value.isNullOrEmpty() && fieldUiModel.editable) { - RecyclerViewUiEvents.ScanQRCode( - uid = uid, - optionSet = optionSet, - renderingType = renderingType, - ) - } else if (value != null) { - RecyclerViewUiEvents.DisplayQRCode( - uid = uid, - optionSet = optionSet, - value = value, - renderingType = renderingType, - editable = fieldUiModel.editable, - label = label, - ) - } else { - null - } - } - - OPTION_SET -> RecyclerViewUiEvents.OpenOptionSetDialog(fieldUiModel) - ADD_SIGNATURE -> RecyclerViewUiEvents.AddSignature(uid, label) ADD_FILE -> RecyclerViewUiEvents.OpenFileSelector(fieldUiModel) OPEN_FILE -> RecyclerViewUiEvents.OpenFile(fieldUiModel) - EMAIL -> RecyclerViewUiEvents.OpenChooserIntent(Intent.ACTION_SENDTO, value, uid) - PHONE_NUMBER -> RecyclerViewUiEvents.OpenChooserIntent( - Intent.ACTION_DIAL, - value, - uid, - ) - SHARE_IMAGE -> RecyclerViewUiEvents.OpenChooserIntent( Intent.ACTION_SEND, fieldUiModel.displayName, diff --git a/form/src/main/java/org/dhis2/form/ui/provider/inputfield/InputFileProvider.kt b/form/src/main/java/org/dhis2/form/ui/provider/inputfield/InputFileProvider.kt index 41d9f3e396..f6f03c16c3 100644 --- a/form/src/main/java/org/dhis2/form/ui/provider/inputfield/InputFileProvider.kt +++ b/form/src/main/java/org/dhis2/form/ui/provider/inputfield/InputFileProvider.kt @@ -15,10 +15,10 @@ import org.dhis2.form.extensions.supportingText import org.dhis2.form.model.FieldUiModel import org.dhis2.form.model.UiEventType import org.dhis2.form.ui.event.RecyclerViewUiEvents -import org.dhis2.ui.model.InputData import org.hisp.dhis.mobile.ui.designsystem.component.InputFileResource import org.hisp.dhis.mobile.ui.designsystem.component.UploadFileState import java.io.File +import java.text.DecimalFormat @Composable internal fun ProvideInputFileResource( @@ -27,17 +27,15 @@ internal fun ProvideInputFileResource( resources: ResourceManager, uiEventHandler: (RecyclerViewUiEvents) -> Unit, ) { - var uploadState by remember(fieldUiModel) { mutableStateOf(getFileUploadState(fieldUiModel.displayName, fieldUiModel.isLoadingData)) } - - val fileInputData = - fieldUiModel.displayName?.let { - val file = File(it) - InputData.FileInputData( - fileName = file.name, - fileSize = file.length(), - filePath = file.path, - ) - } + var uploadState by remember(fieldUiModel) { + mutableStateOf( + getFileUploadState( + fieldUiModel.displayName, + fieldUiModel.isLoadingData, + ), + ) + } + val file = fieldUiModel.displayName?.let { File(it) } InputFileResource( modifier = modifier.fillMaxWidth(), @@ -46,8 +44,8 @@ internal fun ProvideInputFileResource( supportingText = fieldUiModel.supportingText(), buttonText = resources.getString(R.string.add_file), uploadFileState = uploadState, - fileName = fileInputData?.fileName, - fileWeight = fileInputData?.fileSizeLabel, + fileName = file?.name, + fileWeight = file?.length()?.let { fileSizeLabel(it) }, onSelectFile = { uploadState = getFileUploadState(fieldUiModel.displayName, true) fieldUiModel.invokeUiEvent(UiEventType.ADD_FILE) @@ -62,6 +60,16 @@ internal fun ProvideInputFileResource( ) } +private fun fileSizeLabel(fileSize: Long) = run { + val kb = fileSize / 1024f + val mb = kb / 1024f + if (kb < 1024f) { + "${DecimalFormat("*0").format(kb)}KB" + } else { + "${DecimalFormat("*0.##").format(mb)}MB" + } +} + private fun getFileUploadState(value: String?, isLoading: Boolean): UploadFileState { return if (isLoading && value.isNullOrEmpty()) { UploadFileState.UPLOADING diff --git a/form/src/test/java/org/dhis2/form/ui/event/UiEventFactoryImplTest.kt b/form/src/test/java/org/dhis2/form/ui/event/UiEventFactoryImplTest.kt deleted file mode 100644 index c30f4db510..0000000000 --- a/form/src/test/java/org/dhis2/form/ui/event/UiEventFactoryImplTest.kt +++ /dev/null @@ -1,74 +0,0 @@ -package org.dhis2.form.ui.event - -import org.dhis2.form.model.FieldUiModelImpl -import org.dhis2.form.model.UiEventType -import org.hamcrest.MatcherAssert.assertThat -import org.hisp.dhis.android.core.common.ValueType -import org.junit.Test - -class UiEventFactoryImplTest { - - private var uiEventFactory: UiEventFactory? = null - - @Test - fun `Should return UiEvent OpenCustomCalendar for ValueType DATE`() { - uiEventFactory = provideEventForType(ValueType.DATE) - - val event = uiEventFactory?.generateEvent( - value = "2021-09-27", - uiEventType = UiEventType.DATE_TIME, - fieldUiModel = provideFieldUiModel(), - ) - assertThat( - "Event is OpenCustomCalendar", - event is RecyclerViewUiEvents.OpenCustomCalendar, - ) - } - - @Test - fun `Should return UiEvent OpenCustomCalendar for ValueType DATETIME`() { - uiEventFactory = provideEventForType(ValueType.DATETIME) - - val event = uiEventFactory?.generateEvent( - value = "2021-09-27T10:20", - uiEventType = UiEventType.DATE_TIME, - fieldUiModel = provideFieldUiModel(), - ) - assertThat( - "Event is OpenCustomCalendar", - event is RecyclerViewUiEvents.OpenCustomCalendar, - ) - } - - @Test - fun `Should return UiEvent OpenCustomCalendar for ValueType TIME`() { - uiEventFactory = provideEventForType(ValueType.TIME) - - val event = uiEventFactory?.generateEvent( - value = "10:20", - uiEventType = UiEventType.DATE_TIME, - fieldUiModel = provideFieldUiModel(), - ) - assertThat( - "Event is OpenTimePicker", - event is RecyclerViewUiEvents.OpenTimePicker, - ) - } - - private fun provideEventForType(valueType: ValueType) = UiEventFactoryImpl( - uid = "uid", - label = "label", - description = "description", - valueType = valueType, - true, - null, - ) - - private fun provideFieldUiModel() = FieldUiModelImpl( - uid = "uid", - label = "label", - valueType = ValueType.TEXT, - optionSetConfiguration = null, - autocompleteList = null, - ) -} diff --git a/stock-usecase/src/main/java/org/dhis2/android/rtsm/ui/home/screens/HomeScreen.kt b/stock-usecase/src/main/java/org/dhis2/android/rtsm/ui/home/screens/HomeScreen.kt index 8761707717..a551e0b902 100644 --- a/stock-usecase/src/main/java/org/dhis2/android/rtsm/ui/home/screens/HomeScreen.kt +++ b/stock-usecase/src/main/java/org/dhis2/android/rtsm/ui/home/screens/HomeScreen.kt @@ -32,7 +32,7 @@ import org.dhis2.android.rtsm.ui.home.HomeViewModel import org.dhis2.android.rtsm.ui.home.screens.components.Backdrop import org.dhis2.android.rtsm.ui.home.screens.components.CompletionDialog import org.dhis2.android.rtsm.ui.managestock.ManageStockViewModel -import org.dhis2.ui.buttons.FAButton +import org.hisp.dhis.mobile.ui.designsystem.component.ExtendedFAB import org.hisp.dhis.mobile.ui.designsystem.component.navigationBar.NavigationBar import org.hisp.dhis.mobile.ui.designsystem.component.navigationBar.NavigationBarItem import org.hisp.dhis.mobile.ui.designsystem.theme.DHIS2Theme @@ -73,10 +73,8 @@ fun HomeScreen( enter = fadeIn(), exit = fadeOut(), ) { - FAButton( - text = dataEntryUiState.button.text, - contentColor = dataEntryUiState.button.contentColor, - containerColor = dataEntryUiState.button.containerColor, + ExtendedFAB( + text = stringResource(dataEntryUiState.button.text), icon = { Icon( painter = painterResource(id = dataEntryUiState.button.icon), @@ -84,9 +82,10 @@ fun HomeScreen( tint = dataEntryUiState.button.contentColor, ) }, - ) { - proceedAction(scope, scaffoldState) - } + onClick = { + proceedAction(scope, scaffoldState) + }, + ) } }, snackbarHost = { @@ -111,18 +110,18 @@ fun HomeScreen( label = "HomeScreenContent", ) { targetIndex -> when (targetIndex) { - BottomNavigation.ANALYTICS.id -> - { - DHIS2Theme() {} - AnalyticsScreen( - viewModel = viewModel, - backAction = { manageStockViewModel.onHandleBackNavigation() }, - themeColor = themeColor, - modifier = Modifier.padding(paddingValues), - scaffoldState = scaffoldState, - supportFragmentManager = supportFragmentManager, - ) - } + BottomNavigation.ANALYTICS.id -> { + DHIS2Theme() {} + AnalyticsScreen( + viewModel = viewModel, + backAction = { manageStockViewModel.onHandleBackNavigation() }, + themeColor = themeColor, + modifier = Modifier.padding(paddingValues), + scaffoldState = scaffoldState, + supportFragmentManager = supportFragmentManager, + ) + } + BottomNavigation.DATA_ENTRY.id -> { Backdrop( activity = activity, diff --git a/ui-components/src/androidTest/java/org/dhis2/ui/ExampleInstrumentedTest.kt b/ui-components/src/androidTest/java/org/dhis2/ui/ExampleInstrumentedTest.kt deleted file mode 100644 index 70e81dc505..0000000000 --- a/ui-components/src/androidTest/java/org/dhis2/ui/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.dhis2.ui - -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("org.dhis2.ui.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/ui-components/src/main/java/org/dhis2/ui/Progress.kt b/ui-components/src/main/java/org/dhis2/ui/Progress.kt deleted file mode 100644 index 00bc559b87..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/Progress.kt +++ /dev/null @@ -1,23 +0,0 @@ -package org.dhis2.ui - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import org.dhis2.ui.theme.textSecondary - -@Composable -fun Dhis2ProgressIndicator(message: String? = null) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - CircularProgressIndicator( - modifier = Modifier.padding(16.dp), - color = MaterialTheme.colorScheme.primary, - ) - message?.let { Text(it, color = textSecondary) } - } -} diff --git a/ui-components/src/main/java/org/dhis2/ui/buttons/FAButton.kt b/ui-components/src/main/java/org/dhis2/ui/buttons/FAButton.kt deleted file mode 100644 index f2d40a1fa6..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/buttons/FAButton.kt +++ /dev/null @@ -1,54 +0,0 @@ -package org.dhis2.ui.buttons - -import androidx.annotation.StringRes -import androidx.compose.material3.ExtendedFloatingActionButton -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import org.dhis2.ui.R - -@Composable -fun FAButton( - modifier: Modifier = Modifier, - @StringRes text: Int, - contentColor: Color, - containerColor: Color, - expanded: Boolean = true, - icon: @Composable - () -> Unit, - onClick: () -> Unit, -) { - ExtendedFloatingActionButton( - onClick = onClick, - modifier = modifier, - expanded = expanded, - icon = icon, - text = { Text(text = stringResource(text)) }, - contentColor = contentColor, - containerColor = containerColor, - ) -} - -@Preview -@Composable -fun ExtendedFAButtonPreview() { - FAButton( - modifier = Modifier, - text = R.string.button_extended, - contentColor = Color.DarkGray, - containerColor = Color.LightGray, - expanded = true, - icon = { - Icon( - painter = painterResource(id = R.drawable.ic_home_positive), - contentDescription = null, - ) - }, - ) { - } -} diff --git a/ui-components/src/main/java/org/dhis2/ui/dialogs/alert/DescriptionDialog.kt b/ui-components/src/main/java/org/dhis2/ui/dialogs/alert/DescriptionDialog.kt deleted file mode 100644 index fbbeab2d67..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/dialogs/alert/DescriptionDialog.kt +++ /dev/null @@ -1,23 +0,0 @@ -package org.dhis2.ui.dialogs.alert - -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import org.dhis2.ui.R -import org.hisp.dhis.mobile.ui.designsystem.component.Button - -@Composable -fun DescriptionDialog(labelText: String, descriptionText: String, onDismiss: () -> Unit) { - AlertDialog( - onDismissRequest = onDismiss, - title = { Text(text = labelText) }, - text = { Text(text = descriptionText) }, - confirmButton = { - Button( - text = stringResource(id = R.string.action_close), - onClick = onDismiss, - ) - }, - ) -} diff --git a/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureCanvas.kt b/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureCanvas.kt deleted file mode 100644 index 0bc187e22c..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureCanvas.kt +++ /dev/null @@ -1,50 +0,0 @@ -package org.dhis2.ui.dialogs.signature - -import android.view.MotionEvent -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Path -import androidx.compose.ui.graphics.drawscope.Stroke -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.input.pointer.pointerInteropFilter - -@OptIn(ExperimentalComposeUiApi::class) -@Composable -fun SignatureCanvas(modifier: Modifier = Modifier, drawing: MutableState) { - val path by remember { mutableStateOf(Path()) } - Canvas( - modifier = modifier - .fillMaxSize() - .pointerInteropFilter { - when (it.action) { - MotionEvent.ACTION_DOWN -> { - drawing.value = Offset(it.x, it.y) - path.moveTo(it.x, it.y) - } - MotionEvent.ACTION_MOVE -> { - drawing.value = Offset(it.x, it.y) - path.lineTo(it.x, it.y) - } - } - true - }.graphicsLayer { clip = true }, - ) { - drawing.value?.let { - drawPath( - path = path, - color = Color.Black, - alpha = 1f, - style = Stroke(7f), - ) - } ?: path.reset() - } -} diff --git a/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureDialog.kt b/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureDialog.kt deleted file mode 100644 index 354e6888fd..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureDialog.kt +++ /dev/null @@ -1,59 +0,0 @@ -package org.dhis2.ui.dialogs.signature - -import android.app.Dialog -import android.graphics.Bitmap -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.Window -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.ViewCompositionStrategy -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.FragmentManager -import org.dhis2.ui.theme.Dhis2Theme - -const val TAG = "SignatureDialog" - -class SignatureDialog( - private val title: String, - private val onSaveSignature: ((Bitmap) -> Unit)? = null, -) : DialogFragment() { - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val dialog = super.onCreateDialog(savedInstanceState) - dialog.window!!.requestFeature(Window.FEATURE_NO_TITLE) - dialog.window!!.setBackgroundDrawableResource(android.R.color.transparent) - return dialog - } - - @OptIn(ExperimentalComposeUiApi::class) - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - return ComposeView(requireContext()).apply { - setViewCompositionStrategy( - ViewCompositionStrategy.DisposeOnDetachedFromWindow, - ) - setContent { - Dhis2Theme { - SignatureDialogUi( - title = title, - onSave = { - onSaveSignature?.invoke(it) - dismiss() - }, - onCancel = { dismiss() }, - ) - } - } - } - } - - fun show(manager: FragmentManager) { - super.show(manager, TAG) - } -} diff --git a/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureDialogUi.kt b/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureDialogUi.kt deleted file mode 100644 index 28f85f256b..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/dialogs/signature/SignatureDialogUi.kt +++ /dev/null @@ -1,163 +0,0 @@ -package org.dhis2.ui.dialogs.signature - -import android.graphics.Bitmap -import android.graphics.Canvas -import android.view.View -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Clear -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.boundsInRoot -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import org.dhis2.ui.R -import org.dhis2.ui.theme.textSecondary -import org.dhis2.ui.utils.dashedBorder -import org.hisp.dhis.mobile.ui.designsystem.component.Button -import org.hisp.dhis.mobile.ui.designsystem.component.IconButton -import kotlin.math.roundToInt - -@ExperimentalComposeUiApi -@Composable -fun SignatureDialogUi(title: String, onSave: (Bitmap) -> Unit, onCancel: () -> Unit) { - var capturingViewBounds: Rect? = null - val view = LocalView.current - - var capturing by remember { mutableStateOf(false) } - val drawing = remember { mutableStateOf(null) } - val isSigned by remember { derivedStateOf { drawing.value != null } } - - Column( - modifier = Modifier - .background(Color.White, RoundedCornerShape(16.dp)) - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - ) { - Text( - text = title, - style = TextStyle( - fontSize = 10.sp, - color = textSecondary, - ), - ) - Box { - SignatureCanvas( - modifier = Modifier - .height(200.dp) - .dashedBorder( - strokeWidth = 1.dp, - color = textSecondary.copy(alpha = 0.3f), - cornerRadiusDp = 8.dp, - ) - .onGloballyPositioned { - capturingViewBounds = it.boundsInRoot() - }, - drawing = drawing, - ) - if (!capturing) { - Text( - modifier = Modifier - .padding(8.dp) - .align(Alignment.TopEnd) - .background( - MaterialTheme.colorScheme.primary, - RoundedCornerShape(6.dp, 6.dp, 6.dp, 0.dp), - ) - .padding(8.dp, 4.dp), - text = stringResource(R.string.draw_here), - style = TextStyle( - fontSize = 10.sp, - color = MaterialTheme.colorScheme.onPrimary, - ), - ) - if (isSigned) { - IconButton( - modifier = Modifier.align(Alignment.BottomEnd), - onClick = { - drawing.value = null - }, - icon = { - Icon( - imageVector = Icons.Default.Clear, - contentDescription = stringResource(R.string.clear), - ) - }, - ) - } - } - } - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End), - ) { - Button( - text = stringResource(R.string.cancel), - onClick = onCancel, - ) - Button( - text = stringResource(R.string.save), - onClick = { - capturing = true - }, - enabled = isSigned, - ) - } - } - - LaunchedEffect(capturing) { - capturingViewBounds - ?.takeIf { capturing } - ?.captureBitmap(view) - ?.let { onSave(it) } - } -} - -fun Rect.captureBitmap(view: View): Bitmap? { - val rect = deflate(2f) - val imageBitmap = Bitmap.createBitmap( - rect.width.roundToInt(), - rect.height.roundToInt(), - Bitmap.Config.ARGB_8888, - ) - val canvas = Canvas(imageBitmap) - .apply { - translate(-rect.left, -rect.top) - } - view.draw(canvas) - return imageBitmap -} - -@OptIn(ExperimentalComposeUiApi::class) -@Preview -@Composable -fun PreviewSignatureUI() { - SignatureDialogUi(title = "Form name", onSave = {}, onCancel = {}) -} diff --git a/ui-components/src/main/java/org/dhis2/ui/extensions/Extensions.kt b/ui-components/src/main/java/org/dhis2/ui/extensions/Extensions.kt deleted file mode 100644 index 14ee1ce20f..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/extensions/Extensions.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.dhis2.ui.extensions - -import java.text.DecimalFormat - -fun Float.decimalFormat(pattern: String = "*0.##"): String { - return DecimalFormat(pattern).format(this) -} diff --git a/ui-components/src/main/java/org/dhis2/ui/inputs/FileInput.kt b/ui-components/src/main/java/org/dhis2/ui/inputs/FileInput.kt deleted file mode 100644 index 2d4b0d2659..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/inputs/FileInput.kt +++ /dev/null @@ -1,278 +0,0 @@ -package org.dhis2.ui.inputs - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -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.platform.LocalViewConfiguration -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.vectorResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.constraintlayout.compose.ConstraintLayout -import androidx.constraintlayout.compose.Dimension -import androidx.core.graphics.toColorInt -import org.dhis2.ui.R -import org.dhis2.ui.model.InputData -import org.dhis2.ui.theme.defaultFontFamily -import org.hisp.dhis.mobile.ui.designsystem.component.Button -import org.hisp.dhis.mobile.ui.designsystem.component.ButtonStyle -import org.hisp.dhis.mobile.ui.designsystem.component.IconButton - -@Composable -fun BoxedInput( - leadingIcon: @Composable - (modifier: Modifier) -> Unit, - trailingIcons: @Composable - RowScope.() -> Unit, - content: @Composable - (modifier: Modifier) -> Unit, -) { - Surface( - modifier = Modifier - .wrapContentSize(), - shape = RoundedCornerShape(6.dp), - color = Color.White, - shadowElevation = 4.dp, - ) { - ConstraintLayout( - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - .padding(8.dp), - ) { - val (leadingIconRef, contentRef, trailingIconsRef) = createRefs() - leadingIcon( - Modifier.constrainAs(leadingIconRef) { - start.linkTo(parent.start) - top.linkTo(parent.top) - bottom.linkTo(parent.bottom) - height = Dimension.wrapContent - }, - ) - content( - Modifier.constrainAs(contentRef) { - start.linkTo(leadingIconRef.end, 8.dp) - top.linkTo(parent.top) - bottom.linkTo(parent.bottom) - end.linkTo(trailingIconsRef.start, 8.dp) - height = Dimension.fillToConstraints - width = Dimension.fillToConstraints - }, - ) - Row( - modifier = Modifier.constrainAs(trailingIconsRef) { - top.linkTo(parent.top) - bottom.linkTo(parent.bottom) - end.linkTo(parent.end) - height = Dimension.wrapContent - }, - ) { - trailingIcons() - } - } - } -} - -@Composable -fun FileDescription(modifier: Modifier, fileInputData: InputData.FileInputData) { - Column( - modifier = modifier, - verticalArrangement = Arrangement.Center, - ) { - Text( - text = fileInputData.fileName, - style = TextStyle( - color = Color.Black.copy(alpha = 0.87f), - fontSize = 12.sp, - fontFamily = defaultFontFamily, - fontWeight = FontWeight(400), - lineHeight = 20.sp, - ), - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - Text( - text = fileInputData.fileSizeLabel, - style = TextStyle( - color = Color.Black.copy(alpha = 0.38f), - fontSize = 10.sp, - fontWeight = FontWeight(400), - fontFamily = defaultFontFamily, - lineHeight = 12.sp, - ), - ) - } -} - -@Composable -fun FileInput( - fileInputData: InputData.FileInputData?, - addFileLabel: String, - enabled: Boolean = true, - onAddFile: () -> Unit = {}, - onDownloadClick: () -> Unit = {}, - onDeleteFile: () -> Unit = {}, -) { - if (fileInputData != null) { - FileInputWithValue( - fileInputData = fileInputData, - enabled = enabled, - onDownloadClick = onDownloadClick, - onDeleteFile = onDeleteFile, - - ) - } else { - FileInputWithoutValue( - modifier = Modifier.fillMaxWidth(), - label = addFileLabel, - enabled = enabled, - onAddFile = onAddFile, - ) - } -} - -@Composable -fun FileInputWithoutValue( - modifier: Modifier, - label: String, - enabled: Boolean, - onAddFile: () -> Unit, -) { - Button( - modifier = modifier, - enabled = enabled, - style = ButtonStyle.OUTLINED, - onClick = onAddFile, - icon = { - Icon( - painter = painterResource(id = R.drawable.ic_file), - contentDescription = "", - ) - }, - text = label, - ) -} - -@Composable -fun FileInputWithValue( - fileInputData: InputData.FileInputData, - enabled: Boolean, - onDownloadClick: () -> Unit, - onDeleteFile: () -> Unit, -) { - BoxedInput( - leadingIcon = { modifier -> - Box( - modifier = modifier - .size(LocalViewConfiguration.current.minimumTouchTargetSize), - contentAlignment = Alignment.Center, - ) { - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.ic_file), - contentDescription = "", - tint = MaterialTheme.colorScheme.primary, - ) - } - }, - trailingIcons = { - IconButton( - enabled = enabled, - onClick = onDownloadClick, - icon = { - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.ic_file_download), - contentDescription = "", - tint = MaterialTheme.colorScheme.primary, - ) - }, - ) - - IconButton( - enabled = enabled, - onClick = { onDeleteFile() }, - icon = { - Icon( - imageVector = ImageVector.vectorResource(id = R.drawable.ic_delete), - contentDescription = "", - tint = MaterialTheme.colorScheme.primary, - ) - }, - ) - }, - ) { modifier -> - FileDescription(modifier = modifier, fileInputData = fileInputData) - } -} - -@Composable -@Preview -fun FileWithoutValueInputTest() { - FileInput(fileInputData = null, addFileLabel = "addFile") -} - -@Composable -@Preview -fun FileWithValueInputTest() { - FileInput(fileInputData = null, addFileLabel = "addFile") -} - -@Composable -@Preview -fun FileInputWithMessageTest() { - FormInputBox( - labelText = "This is the label", - helperText = "This is a messsage", - descriptionText = "This is a description", - selected = true, - labelTextColor = Color.Black.copy(alpha = 0.54f), - helperTextColor = Color("#E91E63".toColorInt()), - ) { - FileInput( - fileInputData = InputData.FileInputData( - fileName = "file.txt", - fileSize = 1234, - filePath = "/file.txt", - ), - addFileLabel = "addFile", - ) - } -} - -@Composable -@Preview -fun FileInputNoValueWithMessageTest() { - FormInputBox( - labelText = "This is the label", - helperText = "This is a messsage", - descriptionText = "This is a description", - selected = true, - labelTextColor = Color.Black.copy(alpha = 0.54f), - helperTextColor = Color("#E91E63".toColorInt()), - ) { - FileInput( - fileInputData = null, - addFileLabel = "addFile", - ) - } -} diff --git a/ui-components/src/main/java/org/dhis2/ui/inputs/FormInputBox.kt b/ui-components/src/main/java/org/dhis2/ui/inputs/FormInputBox.kt deleted file mode 100644 index ff3f4ebb9d..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/inputs/FormInputBox.kt +++ /dev/null @@ -1,151 +0,0 @@ -package org.dhis2.ui.inputs - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.draw.drawBehind -import androidx.compose.ui.geometry.CornerRadius -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.geometry.RoundRect -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Path -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.vectorResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import org.dhis2.ui.R -import org.dhis2.ui.dialogs.alert.DescriptionDialog - -@Composable -fun FormInputBox( - labelText: String?, - helperText: String? = null, - descriptionText: String? = null, - selected: Boolean = false, - enabled: Boolean = true, - labelTextColor: Color, - helperTextColor: Color = Color.Black.copy(alpha = 0.38f), - content: @Composable - () -> Unit, -) { - val openDescriptionDialog = remember { mutableStateOf(false) } - Box( - modifier = Modifier - .wrapContentHeight() - .alpha(1.0f.takeIf { enabled } ?: 0.5f), - ) { - Column( - modifier = Modifier - .wrapContentHeight() - .padding( - top = 9.dp, - bottom = 16.dp, - ) - .drawInputSelector( - selected = selected, - color = MaterialTheme.colorScheme.primary, - ) - .padding( - start = 16.dp, - end = 16.dp, - ) - .graphicsLayer { clip = false }, - verticalArrangement = spacedBy(9.dp), - ) { - labelText?.let { - Row( - modifier = Modifier, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = spacedBy(8.dp), - ) { - HelperText( - helperText = labelText, - textStyle = TextStyle( - color = labelTextColor, - fontSize = 10.sp, - lineHeight = 10.sp, - ), - ) - descriptionText?.let { - Icon( - modifier = Modifier - .size(10.dp) - .clickable { openDescriptionDialog.value = true }, - imageVector = ImageVector.vectorResource(id = R.drawable.ic_input_info), - contentDescription = "", - tint = MaterialTheme.colorScheme.primary, - ) - } - } - } - content() - helperText?.let { - HelperText( - helperText = helperText, - textStyle = TextStyle( - color = helperTextColor, - fontSize = 10.sp, - lineHeight = 12.sp, - ), - ) - } - } - - if (openDescriptionDialog.value) { - DescriptionDialog(labelText!!, descriptionText!!) { - openDescriptionDialog.value = false - } - } - } -} - -@Composable -fun HelperText(helperText: String, textStyle: TextStyle) { - Text( - text = helperText, - style = textStyle, - ) -} - -fun Modifier.drawInputSelector(selected: Boolean, color: Color) = when (selected) { - true -> this.then( - drawBehind { - drawPath( - Path().apply { - addRoundRect( - RoundRect( - rect = Rect( - offset = Offset(8.dp.toPx(), 0f), - size = Size(2.dp.toPx(), size.height), - ), - topLeft = CornerRadius(10f, 10f), - topRight = CornerRadius(10f, 10f), - bottomLeft = CornerRadius(10f, 10f), - bottomRight = CornerRadius(10f, 10f), - ), - ) - }, - color = color, - ) - }, - ) - else -> this -} diff --git a/ui-components/src/main/java/org/dhis2/ui/inputs/PictureInput.kt b/ui-components/src/main/java/org/dhis2/ui/inputs/PictureInput.kt deleted file mode 100644 index 8ba56d8ffc..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/inputs/PictureInput.kt +++ /dev/null @@ -1,122 +0,0 @@ -package org.dhis2.ui.inputs - -import android.graphics.Bitmap -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Clear -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.asImageBitmap -import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import org.dhis2.ui.theme.errorColor -import org.hisp.dhis.mobile.ui.designsystem.component.Button -import org.hisp.dhis.mobile.ui.designsystem.component.IconButton -import org.hisp.dhis.mobile.ui.designsystem.resource.provideDHIS2Icon - -@Composable -fun PictureInput( - imageValue: Bitmap?, - enabled: Boolean = true, - addButtonData: AddButtonData, - onClick: () -> Unit, - onClear: () -> Unit, -) { - if (imageValue != null) { - Picture(imageValue.asImageBitmap(), enabled, onClick, onClear) - } else { - Button( - modifier = Modifier.fillMaxWidth(), - enabled = enabled, - text = addButtonData.label, - icon = { - Icon( - painter = addButtonData.icon, - contentDescription = "", - ) - }, - onClick = addButtonData.onClick, - ) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun Picture(image: ImageBitmap, enabled: Boolean, onClick: () -> Unit, onClear: () -> Unit) { - Box { - Surface( - onClick = onClick, - shadowElevation = 4.dp, - shape = RoundedCornerShape(6.dp), - ) { - Image( - modifier = Modifier.defaultMinSize( - minWidth = if (image.width >= image.height) 200.dp else 0.dp, - minHeight = if (image.width < image.height) 200.dp else 0.dp, - ), - bitmap = image, - contentScale = ContentScale.Crop, - contentDescription = "picture", - ) - } - if (enabled) { - IconButton( - modifier = Modifier - .padding(8.dp) - .background(Color.White, CircleShape) - .size(40.dp) - .align(Alignment.TopEnd), - onClick = onClear, - icon = { - Icon( - imageVector = Icons.Default.Clear, - contentDescription = "clear", - tint = errorColor, - ) - }, - ) - } - } -} - -@Preview -@Composable -fun IconClear() { - Icon( - imageVector = Icons.Default.Clear, - contentDescription = "clear", - tint = errorColor, - ) -} - -@Preview -@Composable -fun IconClearUI() { - Icon( - painter = provideDHIS2Icon(resourceName = "dhis2_microscope_outline"), - contentDescription = "clear", - tint = errorColor, - ) -} - -data class AddButtonData( - val icon: Painter, - val label: String, - val onClick: () -> Unit, -) diff --git a/ui-components/src/main/java/org/dhis2/ui/model/InputData.kt b/ui-components/src/main/java/org/dhis2/ui/model/InputData.kt deleted file mode 100644 index 806ea176af..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/model/InputData.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.dhis2.ui.model - -import org.dhis2.ui.extensions.decimalFormat - -sealed class InputData { - data class FileInputData( - val fileName: String, - private val fileSize: Long, - val filePath: String, - ) { - val fileSizeLabel - get() = run { - val kb = fileSize / 1024f - val mb = kb / 1024f - if (kb < 1024f) { - "${kb.decimalFormat("*0")}KB" - } else { - "${mb.decimalFormat()}MB" - } - } - } -} diff --git a/ui-components/src/main/java/org/dhis2/ui/sync/SyncButtonProvider.kt b/ui-components/src/main/java/org/dhis2/ui/sync/SyncButtonProvider.kt deleted file mode 100644 index bec020aa45..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/sync/SyncButtonProvider.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.dhis2.ui.sync - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Sync -import androidx.compose.material3.Icon -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import org.hisp.dhis.mobile.ui.designsystem.component.Button -import org.hisp.dhis.mobile.ui.designsystem.component.ButtonStyle -import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor - -@Composable -private fun ProvideSyncButton(text: String?, onSyncIconClick: () -> Unit) { - text?.let { - Button( - style = ButtonStyle.TONAL, - text = it, - icon = { - Icon( - imageVector = Icons.Outlined.Sync, - contentDescription = it, - tint = TextColor.OnPrimaryContainer, - ) - }, - onClick = onSyncIconClick, - modifier = Modifier.fillMaxWidth(), - ) - } -} diff --git a/ui-components/src/main/java/org/dhis2/ui/theme/Color.kt b/ui-components/src/main/java/org/dhis2/ui/theme/Color.kt index 319a999a50..8b58a1c740 100644 --- a/ui-components/src/main/java/org/dhis2/ui/theme/Color.kt +++ b/ui-components/src/main/java/org/dhis2/ui/theme/Color.kt @@ -2,9 +2,6 @@ package org.dhis2.ui.theme import androidx.compose.ui.graphics.Color -val contrastDark = Color(0xB3000000) -val contrastLight = Color(0xE6FFFFFF) - val programColorDark = Color(0xFF00BCD4) val programColorLight = Color(0xFF84FFFF) @@ -12,67 +9,4 @@ val textPrimary = Color(0xDE000000) val textSecondary = Color(0x8A000000) val textSubtitle = Color(0x61000000) val warningColor = Color(0xFFFF9800) -val errorColor = Color(0xFFE91E63) val colorPrimary = Color(0xFF2C98F0) - -val md_theme_light_primary = Color(0xFF2C98F0) -val md_theme_light_onPrimary = Color(0xFFFFFFFF) -val md_theme_light_primaryContainer = Color(0xFFD1E4FF) -val md_theme_light_onPrimaryContainer = Color(0xFF001D35) -val md_theme_light_secondary = Color(0xFF4CAF50) -val md_theme_light_onSecondary = Color(0xFFFFFFFF) -val md_theme_light_secondaryContainer = Color(0xFF94F990) -val md_theme_light_onSecondaryContainer = Color(0xFF002204) -val md_theme_light_tertiary = Color(0xFFFF9800) -val md_theme_light_onTertiary = Color(0xFFFFFFFF) -val md_theme_light_tertiaryContainer = Color(0xFFFFDCBE) -val md_theme_light_onTertiaryContainer = Color(0xFF2C1600) -val md_theme_light_error = Color(0xFF2C98F0) -val md_theme_light_errorContainer = Color(0xFFFFFFFF) -val md_theme_light_onError = Color(0xFFFFD9DE) -val md_theme_light_onErrorContainer = Color(0xFF400014) -val md_theme_light_background = Color(0xFFFDFCFF) -val md_theme_light_onBackground = Color(0xFF1A1C1E) -val md_theme_light_surface = Color(0xFFFDFCFF) -val md_theme_light_onSurface = Color(0xFF1A1C1E) -val md_theme_light_surfaceVariant = Color(0xFFDFE2EB) -val md_theme_light_onSurfaceVariant = Color(0xFF42474E) -val md_theme_light_outline = Color(0xFF73777F) -val md_theme_light_inverseOnSurface = Color(0xFFF1F0F4) -val md_theme_light_inverseSurface = Color(0xFF2F3033) -val md_theme_light_inversePrimary = Color(0xFF9DCAFF) -val md_theme_light_shadow = Color(0xFF000000) -val md_theme_light_surfaceTint = Color(0xFF0062A2) -val md_theme_light_outlineVariant = Color(0xFFC3C7CF) -val md_theme_light_scrim = Color(0xFF000000) - -val md_theme_dark_primary = Color(0xFF9DCAFF) -val md_theme_dark_onPrimary = Color(0xFF003257) -val md_theme_dark_primaryContainer = Color(0xFF00497C) -val md_theme_dark_onPrimaryContainer = Color(0xFFD1E4FF) -val md_theme_dark_secondary = Color(0xFF78DC77) -val md_theme_dark_onSecondary = Color(0xFF00390A) -val md_theme_dark_secondaryContainer = Color(0xFF005313) -val md_theme_dark_onSecondaryContainer = Color(0xFF94F990) -val md_theme_dark_tertiary = Color(0xFFFFB870) -val md_theme_dark_onTertiary = Color(0xFF4A2800) -val md_theme_dark_tertiaryContainer = Color(0xFF693C00) -val md_theme_dark_onTertiaryContainer = Color(0xFFFFDCBE) -val md_theme_dark_error = Color(0xFFFFB2BE) -val md_theme_dark_errorContainer = Color(0xFF660025) -val md_theme_dark_onError = Color(0xFF900038) -val md_theme_dark_onErrorContainer = Color(0xFFFFD9DE) -val md_theme_dark_background = Color(0xFF1A1C1E) -val md_theme_dark_onBackground = Color(0xFFE2E2E6) -val md_theme_dark_surface = Color(0xFF1A1C1E) -val md_theme_dark_onSurface = Color(0xFFE2E2E6) -val md_theme_dark_surfaceVariant = Color(0xFF42474E) -val md_theme_dark_onSurfaceVariant = Color(0xFFC3C7CF) -val md_theme_dark_outline = Color(0xFF8D9199) -val md_theme_dark_inverseOnSurface = Color(0xFF1A1C1E) -val md_theme_dark_inverseSurface = Color(0xFFE2E2E6) -val md_theme_dark_inversePrimary = Color(0xFF0062A2) -val md_theme_dark_shadow = Color(0xFF000000) -val md_theme_dark_surfaceTint = Color(0xFF9DCAFF) -val md_theme_dark_outlineVariant = Color(0xFF42474E) -val md_theme_dark_scrim = Color(0xFF000000) diff --git a/ui-components/src/main/java/org/dhis2/ui/theme/Theme.kt b/ui-components/src/main/java/org/dhis2/ui/theme/Theme.kt index d1173d3ad1..9026e316b0 100644 --- a/ui-components/src/main/java/org/dhis2/ui/theme/Theme.kt +++ b/ui-components/src/main/java/org/dhis2/ui/theme/Theme.kt @@ -1,74 +1,8 @@ package org.dhis2.ui.theme -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import com.google.accompanist.themeadapter.material3.Mdc3Theme -private val LightColors = lightColorScheme( - primary = md_theme_light_primary, - onPrimary = md_theme_light_onPrimary, - primaryContainer = md_theme_light_primaryContainer, - onPrimaryContainer = md_theme_light_onPrimaryContainer, - secondary = md_theme_light_secondary, - onSecondary = md_theme_light_onSecondary, - secondaryContainer = md_theme_light_secondaryContainer, - onSecondaryContainer = md_theme_light_onSecondaryContainer, - tertiary = md_theme_light_tertiary, - onTertiary = md_theme_light_onTertiary, - tertiaryContainer = md_theme_light_tertiaryContainer, - onTertiaryContainer = md_theme_light_onTertiaryContainer, - error = md_theme_light_error, - errorContainer = md_theme_light_errorContainer, - onError = md_theme_light_onError, - onErrorContainer = md_theme_light_onErrorContainer, - background = md_theme_light_background, - onBackground = md_theme_light_onBackground, - surface = md_theme_light_surface, - onSurface = md_theme_light_onSurface, - surfaceVariant = md_theme_light_surfaceVariant, - onSurfaceVariant = md_theme_light_onSurfaceVariant, - outline = md_theme_light_outline, - inverseOnSurface = md_theme_light_inverseOnSurface, - inverseSurface = md_theme_light_inverseSurface, - inversePrimary = md_theme_light_inversePrimary, - surfaceTint = md_theme_light_surfaceTint, - outlineVariant = md_theme_light_outlineVariant, - scrim = md_theme_light_scrim, -) - -private val DarkColors = darkColorScheme( - primary = md_theme_dark_primary, - onPrimary = md_theme_dark_onPrimary, - primaryContainer = md_theme_dark_primaryContainer, - onPrimaryContainer = md_theme_dark_onPrimaryContainer, - secondary = md_theme_dark_secondary, - onSecondary = md_theme_dark_onSecondary, - secondaryContainer = md_theme_dark_secondaryContainer, - onSecondaryContainer = md_theme_dark_onSecondaryContainer, - tertiary = md_theme_dark_tertiary, - onTertiary = md_theme_dark_onTertiary, - tertiaryContainer = md_theme_dark_tertiaryContainer, - onTertiaryContainer = md_theme_dark_onTertiaryContainer, - error = md_theme_dark_error, - errorContainer = md_theme_dark_errorContainer, - onError = md_theme_dark_onError, - onErrorContainer = md_theme_dark_onErrorContainer, - background = md_theme_dark_background, - onBackground = md_theme_dark_onBackground, - surface = md_theme_dark_surface, - onSurface = md_theme_dark_onSurface, - surfaceVariant = md_theme_dark_surfaceVariant, - onSurfaceVariant = md_theme_dark_onSurfaceVariant, - outline = md_theme_dark_outline, - inverseOnSurface = md_theme_dark_inverseOnSurface, - inverseSurface = md_theme_dark_inverseSurface, - inversePrimary = md_theme_dark_inversePrimary, - surfaceTint = md_theme_dark_surfaceTint, - outlineVariant = md_theme_dark_outlineVariant, - scrim = md_theme_dark_scrim, -) - @Composable fun Dhis2Theme(content: @Composable () -> Unit) { Mdc3Theme(content = content) diff --git a/ui-components/src/main/java/org/dhis2/ui/theme/Type.kt b/ui-components/src/main/java/org/dhis2/ui/theme/Type.kt deleted file mode 100644 index 6501bfce54..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/theme/Type.kt +++ /dev/null @@ -1,26 +0,0 @@ -package org.dhis2.ui.theme - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.sp -import org.dhis2.ui.R - -val defaultFontFamily = FontFamily( - Font(R.font.rubik_regular), - Font(R.font.rubik_bold, FontWeight.Bold), - Font(R.font.rubik_light, FontWeight.Light), -) - -val descriptionTextStyle = TextStyle( - color = Color(0xFF667685), - fontSize = 10.sp, - fontWeight = FontWeight.Normal, - fontFamily = FontFamily(Font(R.font.roboto_regular)), - lineHeight = 16.sp, - letterSpacing = (0.4).sp, - textAlign = TextAlign.End, -) diff --git a/ui-components/src/main/java/org/dhis2/ui/utils/ColorUtils.kt b/ui-components/src/main/java/org/dhis2/ui/utils/ColorUtils.kt deleted file mode 100644 index c605eb09a3..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/utils/ColorUtils.kt +++ /dev/null @@ -1,27 +0,0 @@ -package org.dhis2.ui.utils - -import androidx.compose.ui.graphics.Color -import androidx.core.graphics.blue -import androidx.core.graphics.green -import androidx.core.graphics.red -import org.dhis2.ui.theme.contrastDark -import org.dhis2.ui.theme.contrastLight -import kotlin.math.pow - -fun Int.getAlphaContrastColor(): Color { - val rgb = listOf( - red / 255.0, - green / 255.0, - blue / 255.0, - ).map { - when { - it <= 0.03928 -> it / 12.92 - else -> ((it + 0.055) / 1.055).pow(2.4) - } - } - val l = 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2] - return when { - l > 0.500 -> contrastDark - else -> contrastLight - } -} diff --git a/ui-components/src/main/java/org/dhis2/ui/utils/Modifiers.kt b/ui-components/src/main/java/org/dhis2/ui/utils/Modifiers.kt deleted file mode 100644 index 4893285ef7..0000000000 --- a/ui-components/src/main/java/org/dhis2/ui/utils/Modifiers.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.dhis2.ui.utils - -import androidx.compose.ui.Modifier -import androidx.compose.ui.composed -import androidx.compose.ui.draw.drawWithCache -import androidx.compose.ui.geometry.CornerRadius -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PathEffect -import androidx.compose.ui.graphics.drawscope.Stroke -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.Dp - -fun Modifier.dashedBorder(strokeWidth: Dp, color: Color, cornerRadiusDp: Dp) = composed( - factory = { - val density = LocalDensity.current - val strokeWidthPx = density.run { strokeWidth.toPx() } - val cornerRadiusPx = density.run { cornerRadiusDp.toPx() } - - this.then( - Modifier.drawWithCache { - onDrawBehind { - val stroke = Stroke( - width = strokeWidthPx, - pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f), - ) - - drawRoundRect( - color = color, - style = stroke, - cornerRadius = CornerRadius(cornerRadiusPx), - ) - } - }, - ) - }, -)