/* Copyright (C) 2015-2024 Andreas Shimokawa, Carsten Pfeiffer, Daniel Dakhno, Daniele Gobbetti, Dmitry Markin, Lem Dulfo, Taavi Eomäe, Martin.JM This file is part of Gadgetbridge. Gadgetbridge is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Gadgetbridge is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.activities; import android.os.Bundle; import android.text.InputFilter; import android.text.Spanned; import android.text.format.DateFormat; import android.view.MenuItem; import android.view.View; import android.widget.CheckedTextView; import android.widget.EditText; import android.widget.TimePicker; import java.text.NumberFormat; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.entities.Alarm; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; public class AlarmDetails extends AbstractGBActivity { private Alarm alarm; private TimePicker timePicker; private CheckedTextView cbSmartWakeup; private CheckedTextView cbSnooze; private CheckedTextView cbMonday; private CheckedTextView cbTuesday; private CheckedTextView cbWednesday; private CheckedTextView cbThursday; private CheckedTextView cbFriday; private CheckedTextView cbSaturday; private CheckedTextView cbSunday; private EditText title; private EditText description; private EditText smartWakeupInterval; private GBDevice device; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_alarm_details); alarm = (Alarm) getIntent().getSerializableExtra(nodomain.freeyourgadget.gadgetbridge.model.Alarm.EXTRA_ALARM); device = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE); title = findViewById(R.id.alarm_title); description = findViewById(R.id.alarm_description); timePicker = findViewById(R.id.alarm_time_picker); cbSmartWakeup = findViewById(R.id.alarm_cb_smart_wakeup); smartWakeupInterval = findViewById(R.id.alarm_cb_smart_wakeup_interval); cbSnooze = findViewById(R.id.alarm_cb_snooze); cbMonday = findViewById(R.id.alarm_cb_monday); cbTuesday = findViewById(R.id.alarm_cb_tuesday); cbWednesday = findViewById(R.id.alarm_cb_wednesday); cbThursday = findViewById(R.id.alarm_cb_thursday); cbFriday = findViewById(R.id.alarm_cb_friday); cbSaturday = findViewById(R.id.alarm_cb_saturday); cbSunday = findViewById(R.id.alarm_cb_sunday); cbSmartWakeup.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); smartWakeupInterval.setEnabled(((CheckedTextView) v).isChecked()); } }); cbSnooze.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); } }); cbMonday.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); } }); cbTuesday.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); } }); cbWednesday.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); } }); cbThursday.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); } }); cbFriday.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); } }); cbSaturday.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); } }); cbSunday.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { ((CheckedTextView) v).toggle(); } }); timePicker.setIs24HourView(DateFormat.is24HourFormat(GBApplication.getContext())); timePicker.setCurrentHour(alarm.getHour()); timePicker.setCurrentMinute(alarm.getMinute()); boolean smartAlarmSupported = supportsSmartWakeup(alarm.getPosition()); boolean smartAlarmForced = forcedSmartWakeup(alarm.getPosition()); boolean smartAlarmIntervalSupported = supportsSmartWakeupInterval(alarm.getPosition()); cbSmartWakeup.setChecked(alarm.getSmartWakeup() || smartAlarmForced); cbSmartWakeup.setVisibility(smartAlarmSupported ? View.VISIBLE : View.GONE); if (smartAlarmForced) { cbSmartWakeup.setEnabled(false); // Force the text to be visible for the "interval" part // Enabled or not can still be seen in the checkmark // TODO: I'd like feedback on this if (GBApplication.isDarkThemeEnabled()) cbSmartWakeup.setTextColor(getResources().getColor(android.R.color.secondary_text_dark)); else cbSmartWakeup.setTextColor(getResources().getColor(android.R.color.secondary_text_light)); } if (smartAlarmIntervalSupported) cbSmartWakeup.setText(R.string.alarm_smart_wakeup_interval); smartWakeupInterval.setVisibility(smartAlarmSupported && smartAlarmIntervalSupported ? View.VISIBLE : View.GONE); smartWakeupInterval.setEnabled(alarm.getSmartWakeup() || smartAlarmForced); if (alarm.getSmartWakeupInterval() != null) smartWakeupInterval.setText(NumberFormat.getInstance().format(alarm.getSmartWakeupInterval())); smartWakeupInterval.setFilters(new InputFilter[] { new InputFilter() { @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { if (dend >= 3) // Limit length return ""; String strValue = dest.subSequence(0, dstart) + source.subSequence(start, end).toString() + dest.subSequence(dend, dest.length()); try { int value = Integer.parseInt(strValue); if (value > 255) { smartWakeupInterval.setText("255"); smartWakeupInterval.setSelection(3); // Move cursor to end } } catch (NumberFormatException e) { return ""; } return null; } } }); cbSnooze.setChecked(alarm.getSnooze()); int snoozeVisibility = supportsSnoozing() ? View.VISIBLE : View.GONE; cbSnooze.setVisibility(snoozeVisibility); title.setVisibility(supportsTitle() ? View.VISIBLE : View.GONE); title.setText(alarm.getTitle()); final int titleLimit = getAlarmTitleLimit(); if (titleLimit > 0) { title.setFilters(new InputFilter[]{new InputFilter.LengthFilter(titleLimit)}); } description.setVisibility(supportsDescription() ? View.VISIBLE : View.GONE); description.setText(alarm.getDescription()); cbMonday.setChecked(alarm.getRepetition(Alarm.ALARM_MON)); cbTuesday.setChecked(alarm.getRepetition(Alarm.ALARM_TUE)); cbWednesday.setChecked(alarm.getRepetition(Alarm.ALARM_WED)); cbThursday.setChecked(alarm.getRepetition(Alarm.ALARM_THU)); cbFriday.setChecked(alarm.getRepetition(Alarm.ALARM_FRI)); cbSaturday.setChecked(alarm.getRepetition(Alarm.ALARM_SAT)); cbSunday.setChecked(alarm.getRepetition(Alarm.ALARM_SUN)); } private boolean supportsSmartWakeup(int position) { if (device != null) { DeviceCoordinator coordinator = device.getDeviceCoordinator(); return coordinator.supportsSmartWakeup(device, position); } return false; } private boolean supportsSmartWakeupInterval(int position) { if (device != null) { DeviceCoordinator coordinator = device.getDeviceCoordinator(); return coordinator.supportsSmartWakeupInterval(device, position); } return false; } /** * The alarm at this position *must* be a smart alarm */ private boolean forcedSmartWakeup(int position) { if (device != null) { DeviceCoordinator coordinator = device.getDeviceCoordinator(); return coordinator.forcedSmartWakeup(device, position); } return false; } private boolean supportsTitle() { if (device != null) { DeviceCoordinator coordinator = device.getDeviceCoordinator(); return coordinator.supportsAlarmTitle(device); } return false; } private int getAlarmTitleLimit() { if (device != null) { DeviceCoordinator coordinator = device.getDeviceCoordinator(); return coordinator.getAlarmTitleLimit(device); } return -1; } private boolean supportsDescription() { if (device != null) { DeviceCoordinator coordinator = device.getDeviceCoordinator(); return coordinator.supportsAlarmDescription(device); } return false; } private boolean supportsSnoozing() { if (device != null) { DeviceCoordinator coordinator = device.getDeviceCoordinator(); return coordinator.supportsAlarmSnoozing(); } return false; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: // back button finish(); return true; } return super.onOptionsItemSelected(item); } private void updateAlarm() { // Set alarm as used and enabled if time has changed if (alarm.getUnused() && alarm.getHour() != timePicker.getCurrentHour() || alarm.getMinute() != timePicker.getCurrentMinute()) { alarm.setUnused(false); alarm.setEnabled(true); } alarm.setSmartWakeup(supportsSmartWakeup(alarm.getPosition()) && cbSmartWakeup.isChecked()); String interval = smartWakeupInterval.getText().toString(); alarm.setSmartWakeupInterval(interval.equals("") ? null : Integer.parseInt(interval)); alarm.setSnooze(supportsSnoozing() && cbSnooze.isChecked()); int repetitionMask = AlarmUtils.createRepetitionMask(cbMonday.isChecked(), cbTuesday.isChecked(), cbWednesday.isChecked(), cbThursday.isChecked(), cbFriday.isChecked(), cbSaturday.isChecked(), cbSunday.isChecked()); alarm.setRepetition(repetitionMask); alarm.setHour(timePicker.getCurrentHour()); alarm.setMinute(timePicker.getCurrentMinute()); alarm.setTitle(title.getText().toString()); alarm.setDescription(description.getText().toString()); DBHelper.store(alarm); } @Override protected void onPause() { updateAlarm(); super.onPause(); } }