mirror of
https://github.com/BlackyHawky/Clock.git
synced 2025-07-02 07:01:13 +00:00
Ability to set a new duration to an existing timer - Fix #76
- Doable by long-pressing time; - Only possible when the timer is stopped;
This commit is contained in:
parent
34846c73ef
commit
fc8d5c6dcb
25 changed files with 651 additions and 50 deletions
|
@ -478,6 +478,15 @@ public final class DataModel {
|
|||
mTimerModel.updateTimer(timer.setLabel(label));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timer the timer to which the new {@code newLength} belongs
|
||||
* @param newLength the new duration to store for the {@code timer}
|
||||
*/
|
||||
public void setNewTimerDuration(Timer timer, long newLength) {
|
||||
enforceMainLooper();
|
||||
mTimerModel.updateTimer(timer.setNewDuration(newLength));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timer the timer to which the new {@code buttonTime} belongs
|
||||
* @param buttonTime the new add button text to store for the {@code timer}
|
||||
|
|
|
@ -178,6 +178,23 @@ public final class Timer {
|
|||
mLastStartWallClockTime, mRemainingTime, label, mButtonTime, mDeleteAfterUse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a copy of this timer with the given {@code newLength}
|
||||
*/
|
||||
Timer setNewDuration(long newLength) {
|
||||
if (mState != State.RESET) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (mLength == newLength) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return new Timer(mId, mState, newLength, newLength, mLastStartTime, mLastStartWallClockTime,
|
||||
newLength, mLabel, mButtonTime, mDeleteAfterUse
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a copy of this timer with the given button time
|
||||
*/
|
||||
|
|
|
@ -95,7 +95,7 @@ public class TimerAddTimeButtonDialogFragment extends DialogFragment {
|
|||
|
||||
final FragmentTransaction tx = manager.beginTransaction();
|
||||
|
||||
// Remove existing instance of LabelDialogFragment if necessary.
|
||||
// Remove existing instance of this DialogFragment if necessary.
|
||||
final Fragment existing = manager.findFragmentByTag(TAG);
|
||||
if (existing != null) {
|
||||
tx.remove(existing);
|
||||
|
@ -108,7 +108,7 @@ public class TimerAddTimeButtonDialogFragment extends DialogFragment {
|
|||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
// As long as the add time button box exists, save its state.
|
||||
// As long as this dialog exists, save its state.
|
||||
if (mEditMinutes != null && mEditSeconds != null) {
|
||||
outState.putString(ARG_EDIT_MINUTES, Objects.requireNonNull(mEditMinutes.getText()).toString());
|
||||
outState.putString(ARG_EDIT_SECONDS, Objects.requireNonNull(mEditSeconds.getText()).toString());
|
||||
|
@ -186,7 +186,7 @@ public class TimerAddTimeButtonDialogFragment extends DialogFragment {
|
|||
new MaterialAlertDialogBuilder(requireContext())
|
||||
.setIcon(drawable)
|
||||
.setTitle(isInvalidInput(inputMinutesText, inputSecondsText)
|
||||
? getString(R.string.timer_button_time_warning_box_title)
|
||||
? getString(R.string.timer_time_warning_box_title)
|
||||
: getString(R.string.timer_button_time_box_title))
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
|
@ -285,7 +285,7 @@ public class TimerAddTimeButtonDialogFragment extends DialogFragment {
|
|||
|
||||
AlertDialog alertDialog = (AlertDialog) requireDialog();
|
||||
alertDialog.setIcon(drawable);
|
||||
alertDialog.setTitle(getString(R.string.timer_button_time_warning_box_title));
|
||||
alertDialog.setTitle(getString(R.string.timer_time_warning_box_title));
|
||||
|
||||
String minutesText = Objects.requireNonNull(mEditMinutes.getText()).toString();
|
||||
String secondsText = Objects.requireNonNull(mEditSeconds.getText()).toString();
|
||||
|
|
|
@ -32,9 +32,15 @@ public final class TimerClickHandler {
|
|||
}
|
||||
|
||||
public void onEditAddTimeButtonLongClicked(Timer timer) {
|
||||
Events.sendAlarmEvent(R.string.action_add_custom_time_to_timer, R.string.label_deskclock);
|
||||
Events.sendTimerEvent(R.string.action_add_custom_time_to_timer, R.string.label_deskclock);
|
||||
final TimerAddTimeButtonDialogFragment fragment = TimerAddTimeButtonDialogFragment.newInstance(timer);
|
||||
TimerAddTimeButtonDialogFragment.show(mFragment.getParentFragmentManager(), fragment);
|
||||
}
|
||||
|
||||
public void onDurationClicked(Timer timer) {
|
||||
Events.sendTimerEvent(R.string.action_set_new_timer_duration, R.string.label_deskclock);
|
||||
final TimerSetNewDurationDialogFragment fragment = TimerSetNewDurationDialogFragment.newInstance(timer);
|
||||
TimerSetNewDurationDialogFragment.show(mFragment.getParentFragmentManager(), fragment);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,461 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
package com.best.deskclock.timer;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.best.deskclock.R;
|
||||
import com.best.deskclock.data.DataModel;
|
||||
import com.best.deskclock.data.Timer;
|
||||
import com.google.android.material.color.MaterialColors;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* DialogFragment to set a new duration to the timer.
|
||||
*/
|
||||
public class TimerSetNewDurationDialogFragment extends DialogFragment {
|
||||
|
||||
/**
|
||||
* The tag that identifies instances of TimerSetNewDurationDialogFragment in the fragment manager.
|
||||
*/
|
||||
private static final String TAG = "set_new_duration_dialog";
|
||||
|
||||
private static final String ARG_EDIT_HOURS = "arg_edit_hours";
|
||||
private static final String ARG_EDIT_MINUTES = "arg_edit_minutes";
|
||||
private static final String ARG_EDIT_SECONDS = "arg_edit_seconds";
|
||||
private static final String ARG_TIMER_ID = "arg_timer_id";
|
||||
|
||||
private TextInputLayout mHoursInputLayout;
|
||||
private TextInputLayout mMinutesInputLayout;
|
||||
private TextInputLayout mSecondsInputLayout;
|
||||
private EditText mEditHours;
|
||||
private EditText mEditMinutes;
|
||||
private EditText mEditSeconds;
|
||||
private int mTimerId;
|
||||
private InputMethodManager mInput;
|
||||
|
||||
public static TimerSetNewDurationDialogFragment newInstance(Timer timer) {
|
||||
final Bundle args = new Bundle();
|
||||
|
||||
long remainingTime = timer.getRemainingTime();
|
||||
long hours = TimeUnit.MILLISECONDS.toHours(remainingTime);
|
||||
long minutes = TimeUnit.MILLISECONDS.toMinutes(remainingTime) % 60;
|
||||
long seconds = TimeUnit.MILLISECONDS.toSeconds(remainingTime) % 60;
|
||||
|
||||
args.putLong(ARG_EDIT_HOURS, hours);
|
||||
args.putLong(ARG_EDIT_MINUTES, minutes);
|
||||
args.putLong(ARG_EDIT_SECONDS, seconds);
|
||||
args.putInt(ARG_TIMER_ID, timer.getId());
|
||||
|
||||
final TimerSetNewDurationDialogFragment frag = new TimerSetNewDurationDialogFragment();
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces any existing TimerSetNewDurationDialogFragment with the given {@code fragment}.
|
||||
*/
|
||||
public static void show(FragmentManager manager, TimerSetNewDurationDialogFragment fragment) {
|
||||
if (manager == null || manager.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Finish any outstanding fragment work.
|
||||
manager.executePendingTransactions();
|
||||
|
||||
final FragmentTransaction tx = manager.beginTransaction();
|
||||
|
||||
// Remove existing instance of this DialogFragment if necessary.
|
||||
final Fragment existing = manager.findFragmentByTag(TAG);
|
||||
if (existing != null) {
|
||||
tx.remove(existing);
|
||||
}
|
||||
tx.addToBackStack(null);
|
||||
|
||||
fragment.show(tx, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
// As long as this dialog exists, save its state.
|
||||
if (mEditHours != null && mEditMinutes != null && mEditSeconds != null) {
|
||||
outState.putString(ARG_EDIT_HOURS, Objects.requireNonNull(mEditHours.getText()).toString());
|
||||
outState.putString(ARG_EDIT_MINUTES, Objects.requireNonNull(mEditMinutes.getText()).toString());
|
||||
outState.putString(ARG_EDIT_SECONDS, Objects.requireNonNull(mEditSeconds.getText()).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Bundle args = getArguments() == null ? Bundle.EMPTY : getArguments();
|
||||
mTimerId = args.getInt(ARG_TIMER_ID, -1);
|
||||
|
||||
long editHours = args.getLong(ARG_EDIT_HOURS, 0);
|
||||
long editMinutes = args.getLong(ARG_EDIT_MINUTES, 0);
|
||||
long editSeconds = args.getLong(ARG_EDIT_SECONDS, 0);
|
||||
if (savedInstanceState != null) {
|
||||
editHours = savedInstanceState.getLong(ARG_EDIT_HOURS, editHours);
|
||||
editMinutes = savedInstanceState.getLong(ARG_EDIT_MINUTES, editMinutes);
|
||||
editSeconds = savedInstanceState.getLong(ARG_EDIT_SECONDS, editSeconds);
|
||||
}
|
||||
|
||||
View view = LayoutInflater.from(requireContext()).inflate(R.layout.timer_dialog_edit_new_time, null);
|
||||
|
||||
mHoursInputLayout = view.findViewById(R.id.dialog_input_layout_hours);
|
||||
mHoursInputLayout.setHelperText(getString(R.string.timer_hours_warning_box_text));
|
||||
|
||||
mMinutesInputLayout = view.findViewById(R.id.dialog_input_layout_minutes);
|
||||
mMinutesInputLayout.setHelperText(getString(R.string.timer_minutes_warning_box_text));
|
||||
|
||||
mSecondsInputLayout = view.findViewById(R.id.dialog_input_layout_seconds);
|
||||
mSecondsInputLayout.setHelperText(getString(R.string.timer_seconds_warning_box_text));
|
||||
|
||||
mEditHours = view.findViewById(R.id.edit_hours);
|
||||
mEditMinutes = view.findViewById(R.id.edit_minutes);
|
||||
mEditSeconds = view.findViewById(R.id.edit_seconds);
|
||||
|
||||
mEditHours.setText(String.valueOf(editHours));
|
||||
if (editHours == 24) {
|
||||
mEditHours.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
mEditHours.setOnEditorActionListener(new ImeDoneListener());
|
||||
mEditMinutes.setEnabled(false);
|
||||
mEditSeconds.setEnabled(false);
|
||||
} else {
|
||||
mEditHours.setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
mEditMinutes.setEnabled(true);
|
||||
mEditMinutes.setImeOptions(EditorInfo.IME_ACTION_NEXT & EditorInfo.IME_ACTION_PREVIOUS);
|
||||
mEditSeconds.setEnabled(true);
|
||||
}
|
||||
mEditHours.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
mEditHours.selectAll();
|
||||
mEditHours.requestFocus();
|
||||
mEditHours.addTextChangedListener(new TextChangeListener());
|
||||
mEditHours.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (hasFocus) {
|
||||
mEditHours.selectAll();
|
||||
}
|
||||
});
|
||||
|
||||
mEditMinutes.setText(String.valueOf(editMinutes));
|
||||
mEditMinutes.selectAll();
|
||||
mEditMinutes.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
mEditMinutes.addTextChangedListener(new TextChangeListener());
|
||||
mEditMinutes.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (hasFocus) {
|
||||
mEditMinutes.selectAll();
|
||||
}
|
||||
});
|
||||
|
||||
mEditSeconds.setText(String.valueOf(editSeconds));
|
||||
mEditSeconds.selectAll();
|
||||
mEditSeconds.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
mEditSeconds.setOnEditorActionListener(new ImeDoneListener());
|
||||
mEditSeconds.addTextChangedListener(new TextChangeListener());
|
||||
mEditSeconds.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (hasFocus) {
|
||||
mEditSeconds.selectAll();
|
||||
}
|
||||
});
|
||||
|
||||
String inputHoursText = mEditHours.getText().toString();
|
||||
String inputMinutesText = mEditMinutes.getText().toString();
|
||||
String inputSecondsText = mEditSeconds.getText().toString();
|
||||
|
||||
mInput = (InputMethodManager) requireContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
|
||||
final Drawable drawable = AppCompatResources.getDrawable(requireContext(),
|
||||
isInvalidInput(inputHoursText, inputMinutesText, inputSecondsText)
|
||||
? R.drawable.ic_error
|
||||
: R.drawable.ic_hourglass_top);
|
||||
if (drawable != null) {
|
||||
drawable.setTint(MaterialColors.getColor(
|
||||
requireContext(), com.google.android.material.R.attr.colorOnSurface, Color.BLACK));
|
||||
}
|
||||
|
||||
final MaterialAlertDialogBuilder dialogBuilder =
|
||||
new MaterialAlertDialogBuilder(requireContext())
|
||||
.setIcon(drawable)
|
||||
.setTitle(isInvalidInput(inputHoursText, inputMinutesText, inputSecondsText)
|
||||
? getString(R.string.timer_time_warning_box_title)
|
||||
: getString(R.string.timer_time_box_title))
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
if (isInvalidInput(inputHoursText, inputMinutesText, inputSecondsText)) {
|
||||
updateDialogForInvalidInput();
|
||||
} else {
|
||||
setNewDuration();
|
||||
dismiss();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null);
|
||||
|
||||
final AlertDialog dialog = dialogBuilder.create();
|
||||
|
||||
final Window alertDialogWindow = dialog.getWindow();
|
||||
if (alertDialogWindow != null) {
|
||||
alertDialogWindow.setSoftInputMode(SOFT_INPUT_ADJUST_PAN | SOFT_INPUT_STATE_VISIBLE);
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
// Stop callbacks from the IME since there is no view to process them.
|
||||
mEditHours.setOnEditorActionListener(null);
|
||||
mEditMinutes.setOnEditorActionListener(null);
|
||||
mEditSeconds.setOnEditorActionListener(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new duration to the timer.
|
||||
*/
|
||||
private void setNewDuration() {
|
||||
String hoursText = Objects.requireNonNull(mEditHours.getText()).toString();
|
||||
String minutesText = Objects.requireNonNull(mEditMinutes.getText()).toString();
|
||||
String secondsText = Objects.requireNonNull(mEditSeconds.getText()).toString();
|
||||
|
||||
int hours = 0;
|
||||
int minutes = 0;
|
||||
int seconds = 0;
|
||||
|
||||
if (!hoursText.isEmpty()) {
|
||||
hours = Integer.parseInt(hoursText);
|
||||
}
|
||||
|
||||
if (!minutesText.isEmpty()) {
|
||||
minutes = Integer.parseInt(minutesText);
|
||||
}
|
||||
|
||||
if (!secondsText.isEmpty()) {
|
||||
seconds = Integer.parseInt(secondsText);
|
||||
}
|
||||
|
||||
if ((hoursText.isEmpty() && minutesText.isEmpty() && secondsText.isEmpty())
|
||||
|| (hours == 0 && minutes == 0 && seconds == 0)) {
|
||||
seconds = 1;
|
||||
}
|
||||
|
||||
if (hours == 24) {
|
||||
minutes = 0;
|
||||
seconds = 0;
|
||||
}
|
||||
|
||||
if (mTimerId >= 0) {
|
||||
final Timer timer = DataModel.getDataModel().getTimer(mTimerId);
|
||||
if (timer != null) {
|
||||
int totalSeconds = hours * 3600 + minutes * 60 + seconds;
|
||||
long newLengthMillis = totalSeconds * 1000L;
|
||||
DataModel.getDataModel().setNewTimerDuration(timer, newLengthMillis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if:
|
||||
* <ul>
|
||||
* <li>hours are less than 0 or greater than 24</li>
|
||||
* <li>minutes are less than 0 or greater than 59</li>
|
||||
* <li>seconds are less than 0 or greater than 59</li>
|
||||
* </ul>
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
private boolean isInvalidInput(String hoursText, String minutesText, String secondsText) {
|
||||
int hours = 0;
|
||||
int minutes = 0;
|
||||
int seconds = 0;
|
||||
|
||||
if (!hoursText.isEmpty()) {
|
||||
hours = Integer.parseInt(hoursText);
|
||||
}
|
||||
|
||||
if (!minutesText.isEmpty()) {
|
||||
minutes = Integer.parseInt(minutesText);
|
||||
}
|
||||
|
||||
if (!secondsText.isEmpty()) {
|
||||
seconds = Integer.parseInt(secondsText);
|
||||
}
|
||||
|
||||
return hours < 0 || hours > 24 || minutes < 0 || minutes > 59 || seconds < 0 || seconds > 59;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the dialog icon and title for invalid entries.
|
||||
* The outline color of the edit box and the hint color are also changed.
|
||||
*/
|
||||
private void updateDialogForInvalidInput() {
|
||||
final Drawable drawable = AppCompatResources.getDrawable(requireContext(), R.drawable.ic_error);
|
||||
if (drawable != null) {
|
||||
drawable.setTint(MaterialColors.getColor(
|
||||
requireContext(), com.google.android.material.R.attr.colorOnSurface, Color.BLACK));
|
||||
}
|
||||
|
||||
AlertDialog alertDialog = (AlertDialog) requireDialog();
|
||||
alertDialog.setIcon(drawable);
|
||||
alertDialog.setTitle(getString(R.string.timer_time_warning_box_title));
|
||||
|
||||
String hoursText = Objects.requireNonNull(mEditHours.getText()).toString();
|
||||
String minutesText = Objects.requireNonNull(mEditMinutes.getText()).toString();
|
||||
String secondsText = Objects.requireNonNull(mEditSeconds.getText()).toString();
|
||||
boolean hoursInvalid = (!hoursText.isEmpty() && Integer.parseInt(hoursText) < 0)
|
||||
|| (!hoursText.isEmpty() && Integer.parseInt(hoursText) > 24);
|
||||
boolean minutesInvalid = (!minutesText.isEmpty() && Integer.parseInt(minutesText) < 0)
|
||||
|| (!minutesText.isEmpty() && Integer.parseInt(minutesText) > 59);
|
||||
boolean secondsInvalid = (!secondsText.isEmpty() && Integer.parseInt(secondsText) < 0)
|
||||
|| (!secondsText.isEmpty() && Integer.parseInt(secondsText) > 59);
|
||||
int invalidColor = ContextCompat.getColor(requireContext(), R.color.md_theme_error);
|
||||
int validColor = MaterialColors.getColor(requireContext(), com.google.android.material.R.attr.colorPrimary, Color.BLACK);
|
||||
|
||||
mHoursInputLayout.setBoxStrokeColor(hoursInvalid ? invalidColor : validColor);
|
||||
mHoursInputLayout.setHintTextColor(hoursInvalid
|
||||
? ColorStateList.valueOf(invalidColor)
|
||||
: ColorStateList.valueOf(validColor));
|
||||
|
||||
mMinutesInputLayout.setBoxStrokeColor(minutesInvalid ? invalidColor : validColor);
|
||||
mMinutesInputLayout.setHintTextColor(minutesInvalid
|
||||
? ColorStateList.valueOf(invalidColor)
|
||||
: ColorStateList.valueOf(validColor));
|
||||
|
||||
mSecondsInputLayout.setBoxStrokeColor(secondsInvalid ? invalidColor : validColor);
|
||||
mSecondsInputLayout.setHintTextColor(secondsInvalid
|
||||
? ColorStateList.valueOf(invalidColor)
|
||||
: ColorStateList.valueOf(validColor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the dialog icon and title for valid entries.
|
||||
* The outline color of the edit box and the hint color are also changed.
|
||||
*/
|
||||
private void updateDialogForValidInput() {
|
||||
final Drawable drawable = AppCompatResources.getDrawable(requireContext(), R.drawable.ic_hourglass_top);
|
||||
if (drawable != null) {
|
||||
drawable.setTint(MaterialColors.getColor(
|
||||
requireContext(), com.google.android.material.R.attr.colorOnSurface, Color.BLACK));
|
||||
}
|
||||
|
||||
AlertDialog alertDialog = (AlertDialog) requireDialog();
|
||||
alertDialog.setIcon(drawable);
|
||||
alertDialog.setTitle(getString(R.string.timer_button_time_box_title));
|
||||
|
||||
int validColor = MaterialColors.getColor(requireContext(), com.google.android.material.R.attr.colorPrimary, Color.BLACK);
|
||||
mHoursInputLayout.setBoxStrokeColor(validColor);
|
||||
mHoursInputLayout.setHintTextColor(ColorStateList.valueOf(validColor));
|
||||
mMinutesInputLayout.setBoxStrokeColor(validColor);
|
||||
mMinutesInputLayout.setHintTextColor(ColorStateList.valueOf(validColor));
|
||||
mSecondsInputLayout.setBoxStrokeColor(validColor);
|
||||
mSecondsInputLayout.setHintTextColor(ColorStateList.valueOf(validColor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Alters the UI to indicate when input is valid or invalid.
|
||||
* Note: In the hours field, if the hours are equal to 24, the entry can be validated with
|
||||
* the enter key, otherwise the enter key will switch to the seconds field.
|
||||
*/
|
||||
private class TextChangeListener implements TextWatcher {
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
|
||||
String hoursText = mEditHours.getText() != null ? mEditHours.getText().toString() : "";
|
||||
String minutesText = mEditMinutes.getText() != null ? mEditMinutes.getText().toString() : "";
|
||||
String secondsText = mEditSeconds.getText() != null ? mEditSeconds.getText().toString() : "";
|
||||
|
||||
if (isInvalidInput(hoursText, minutesText, secondsText)) {
|
||||
updateDialogForInvalidInput();
|
||||
return;
|
||||
}
|
||||
|
||||
updateDialogForValidInput();
|
||||
|
||||
int hours = 0;
|
||||
|
||||
if (!hoursText.isEmpty()) {
|
||||
hours = Integer.parseInt(hoursText);
|
||||
}
|
||||
|
||||
if (hours == 24) {
|
||||
mEditHours.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
mEditHours.setOnEditorActionListener(new ImeDoneListener());
|
||||
mEditMinutes.setEnabled(false);
|
||||
mEditSeconds.setEnabled(false);
|
||||
} else {
|
||||
mEditHours.setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
mEditMinutes.setEnabled(true);
|
||||
mEditMinutes.setImeOptions(EditorInfo.IME_ACTION_NEXT & EditorInfo.IME_ACTION_PREVIOUS);
|
||||
mEditSeconds.setEnabled(true);
|
||||
}
|
||||
|
||||
mEditHours.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
mInput.restartInput(mEditHours);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles completing the new duration from the IME keyboard.
|
||||
*/
|
||||
private class ImeDoneListener implements TextView.OnEditorActionListener {
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
String inputHoursText = Objects.requireNonNull(mEditHours.getText()).toString();
|
||||
String inputMinutesText = Objects.requireNonNull(mEditMinutes.getText()).toString();
|
||||
String inputSecondsText = Objects.requireNonNull(mEditSeconds.getText()).toString();
|
||||
if (isInvalidInput(inputHoursText, inputMinutesText, inputSecondsText)) {
|
||||
updateDialogForInvalidInput();
|
||||
} else {
|
||||
setNewDuration();
|
||||
dismiss();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -41,14 +41,44 @@ public class TimerViewHolder extends RecyclerView.ViewHolder {
|
|||
mTimerItem = (TimerItem) view;
|
||||
mTimerClickHandler = timerClickHandler;
|
||||
|
||||
view.findViewById(R.id.reset).setOnClickListener(v -> {
|
||||
View timerLabel = view.findViewById(R.id.timer_label);
|
||||
View resetButton = view.findViewById(R.id.reset);
|
||||
View timerTotalDuration = view.findViewById(R.id.timer_total_duration);
|
||||
View addTimeButton = view.findViewById(R.id.timer_add_time_button);
|
||||
View circleContainer = view.findViewById(R.id.circle_container);
|
||||
View timerTimeText = view.findViewById(R.id.timer_time_text);
|
||||
View playPauseButton = view.findViewById(R.id.play_pause);
|
||||
View deleteButton = view.findViewById(R.id.delete_timer);
|
||||
|
||||
View.OnClickListener playPauseListener = v -> {
|
||||
Utils.setVibrationTime(context, 50);
|
||||
if (getTimer().isPaused() || getTimer().isReset()) {
|
||||
DataModel.getDataModel().startTimer(getTimer());
|
||||
} else if (getTimer().isRunning()) {
|
||||
DataModel.getDataModel().pauseTimer(getTimer());
|
||||
} else if (getTimer().isExpired() || getTimer().isMissed()) {
|
||||
DataModel.getDataModel().resetOrDeleteExpiredTimers(R.string.label_deskclock);
|
||||
}
|
||||
};
|
||||
|
||||
View.OnLongClickListener setNewDurationListener = v -> {
|
||||
if (!getTimer().isReset()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mTimerClickHandler.onDurationClicked(getTimer());
|
||||
return true;
|
||||
};
|
||||
|
||||
timerLabel.setOnClickListener(v -> mTimerClickHandler.onEditLabelClicked(getTimer()));
|
||||
|
||||
resetButton.setOnClickListener(v -> {
|
||||
DataModel.getDataModel().resetOrDeleteTimer(getTimer(), R.string.label_deskclock);
|
||||
Utils.setVibrationTime(context, 10);
|
||||
});
|
||||
|
||||
view.findViewById(R.id.timer_add_time_button).setOnClickListener(v -> {
|
||||
final Timer timer = getTimer();
|
||||
DataModel.getDataModel().addCustomTimeToTimer(timer);
|
||||
addTimeButton.setOnClickListener(v -> {
|
||||
DataModel.getDataModel().addCustomTimeToTimer(getTimer());
|
||||
Utils.setVibrationTime(context, 10);
|
||||
Events.sendTimerEvent(R.string.action_add_custom_time_to_timer, R.string.label_deskclock);
|
||||
|
||||
|
@ -61,37 +91,31 @@ public class TimerViewHolder extends RecyclerView.ViewHolder {
|
|||
}
|
||||
});
|
||||
|
||||
view.findViewById(R.id.timer_add_time_button).setOnLongClickListener(v -> {
|
||||
addTimeButton.setOnLongClickListener(v -> {
|
||||
mTimerClickHandler.onEditAddTimeButtonLongClicked(getTimer());
|
||||
return true;
|
||||
});
|
||||
|
||||
view.findViewById(R.id.timer_label).setOnClickListener(v -> mTimerClickHandler.onEditLabelClicked(getTimer()));
|
||||
|
||||
View.OnClickListener mPlayPauseListener = v -> {
|
||||
Utils.setVibrationTime(context, 50);
|
||||
final Timer clickedTimer = getTimer();
|
||||
if (clickedTimer.isPaused() || clickedTimer.isReset()) {
|
||||
DataModel.getDataModel().startTimer(clickedTimer);
|
||||
} else if (clickedTimer.isRunning()) {
|
||||
DataModel.getDataModel().pauseTimer(clickedTimer);
|
||||
} else if (clickedTimer.isExpired() || clickedTimer.isMissed()) {
|
||||
DataModel.getDataModel().resetOrDeleteExpiredTimers(R.string.label_deskclock);
|
||||
}
|
||||
};
|
||||
|
||||
// If we click on the circular container when the phones (only) are in landscape mode,
|
||||
// indicating a title for the timers is not possible so in this case we click on the time text.
|
||||
if (!ThemeUtils.isTablet() && ThemeUtils.isLandscape()) {
|
||||
view.findViewById(R.id.timer_time_text).setOnClickListener(mPlayPauseListener);
|
||||
} else {
|
||||
view.findViewById(R.id.circle_container).setOnClickListener(mPlayPauseListener);
|
||||
view.findViewById(R.id.circle_container).setOnTouchListener(new Utils.CircleTouchListener());
|
||||
if (timerTotalDuration != null) {
|
||||
timerTotalDuration.setOnLongClickListener(setNewDurationListener);
|
||||
}
|
||||
|
||||
view.findViewById(R.id.play_pause).setOnClickListener(mPlayPauseListener);
|
||||
// If we click on the circular container when the phones (only) are in landscape mode,
|
||||
// indicating a title for the timers is not possible so in this case we click on the
|
||||
// time to start the timer.
|
||||
// Long press on the time displays the dialog to set a new timer duration.
|
||||
if (!ThemeUtils.isTablet() && ThemeUtils.isLandscape()) {
|
||||
timerTimeText.setOnLongClickListener(setNewDurationListener);
|
||||
timerTimeText.setOnClickListener(playPauseListener);
|
||||
} else {
|
||||
circleContainer.setOnLongClickListener(setNewDurationListener);
|
||||
circleContainer.setOnClickListener(playPauseListener);
|
||||
circleContainer.setOnTouchListener(new Utils.CircleTouchListener());
|
||||
}
|
||||
|
||||
view.findViewById(R.id.delete_timer).setOnClickListener(v -> {
|
||||
playPauseButton.setOnClickListener(playPauseListener);
|
||||
|
||||
deleteButton.setOnClickListener(v -> {
|
||||
Utils.setVibrationTime(context, 10);
|
||||
|
||||
if (SettingsDAO.isWarningDisplayedBeforeDeletingTimer(getDefaultSharedPreferences(context))) {
|
||||
|
|
69
app/src/main/res/layout/timer_dialog_edit_new_time.xml
Normal file
69
app/src/main/res/layout/timer_dialog_edit_new_time.xml
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-License-Identifier: GPL-3.0-only
|
||||
-->
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="?attr/dialogPreferredPadding"
|
||||
android:paddingEnd="?attr/dialogPreferredPadding"
|
||||
android:paddingTop="20dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/dialog_input_layout_hours"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_hours"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:hint="@string/label_hours"
|
||||
android:inputType="number"
|
||||
android:maxLength="2" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/dialog_input_layout_minutes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_minutes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:hint="@string/label_minutes"
|
||||
android:inputType="number"
|
||||
android:maxLength="2" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/dialog_input_layout_seconds"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_seconds"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/label_seconds"
|
||||
android:inputType="number"
|
||||
android:maxLength="2" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
|
@ -86,6 +86,10 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:paddingStart="@null"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingVertical="8dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:textStyle="bold"
|
||||
android:textSize="24sp"
|
||||
|
|
|
@ -445,7 +445,7 @@
|
|||
<string name="first_launch_important_info_message_for_SDK34">• <b>OZNÁMENÍ NA CELÉ OBRAZOVCE;</b> <br> <br></string>
|
||||
<string name="widgets_settings">Widgety</string>
|
||||
<string name="settings_language_turkish">Turečtina</string>
|
||||
<string name="timer_button_time_warning_box_title">Zadána neplatná hodnota</string>
|
||||
<string name="timer_time_warning_box_title">Zadána neplatná hodnota</string>
|
||||
<string name="contributors">Přispěvatelé</string>
|
||||
<string name="about_github_link">Zobrazit na GitHubu</string>
|
||||
<string name="license">Licence open source</string>
|
||||
|
|
|
@ -645,7 +645,7 @@
|
|||
<string name="settings_tab_to_display">Tab, der beim Öffnen der App angezeigt wird</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">Geben Sie einen Wert zwischen 0 und 60 Minuten ein</string>
|
||||
<string name="last_tab_used_title">Zuletzt verwendeter Tab</string>
|
||||
<string name="timer_button_time_warning_box_title">Falscher Wert eingegeben</string>
|
||||
<string name="timer_time_warning_box_title">Falscher Wert eingegeben</string>
|
||||
<string name="settings_language_turkish">Türkisch</string>
|
||||
<string name="reset_settings_title">Einstellungen zurücksetzen</string>
|
||||
<string name="contributors_dialog_title">Profil ansehen</string>
|
||||
|
|
|
@ -658,5 +658,5 @@
|
|||
<string name="toast_message_for_reset">Reinicio completo</string>
|
||||
<string name="shake_intensity_title">Intensidad de sacudida</string>
|
||||
<string name="clock_style_spinner">Spinner</string>
|
||||
<string name="timer_button_time_warning_box_title">Valor incorrecto ingresado</string>
|
||||
<string name="timer_time_warning_box_title">Valor incorrecto ingresado</string>
|
||||
</resources>
|
||||
|
|
|
@ -652,7 +652,7 @@
|
|||
<string name="analog_widget_configuration_warning">Vidin on seadistatav vaid alates Androidi versioonist 12</string>
|
||||
<string name="last_tab_used_title">Viimatikasutatud vahekaart</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">Sisesta väärtus 0 ja 60 minuti vahemikust</string>
|
||||
<string name="timer_button_time_warning_box_title">Sisestasid vigase väärtuse</string>
|
||||
<string name="timer_time_warning_box_title">Sisestasid vigase väärtuse</string>
|
||||
<string name="settings_tab_to_display">Rakenduse avamisel kuvatav vahekaart</string>
|
||||
<string name="settings_language_turkish">türgi keel</string>
|
||||
<string name="reset_settings_title">Lähtesta seadistused</string>
|
||||
|
|
|
@ -657,7 +657,7 @@
|
|||
<string name="analog_widget_configuration_warning">Ce widget n\'est configurable qu\'à partir d\'Android 12</string>
|
||||
<string name="analog_widget_choice_title">Choisissez votre style</string>
|
||||
<string name="last_tab_used_title">Dernier onglet utilisé</string>
|
||||
<string name="timer_button_time_warning_box_title">Valeur saisie incorrecte</string>
|
||||
<string name="timer_time_warning_box_title">Valeur saisie incorrecte</string>
|
||||
<string name="settings_tab_to_display">Onglet à afficher lors de l\'ouverture de l\'application</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">Saisir une valeur comprise entre 0 et 60 minutes</string>
|
||||
<string name="settings_language_turkish">Turc</string>
|
||||
|
|
|
@ -655,7 +655,7 @@
|
|||
<string name="blue_accent_color">Blu</string>
|
||||
<string name="settings_language_korean">Coreano</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">Inserisci un valore tra 0 e 60 minuti</string>
|
||||
<string name="timer_button_time_warning_box_title">Valore inserito non valido</string>
|
||||
<string name="timer_time_warning_box_title">Valore inserito non valido</string>
|
||||
<string name="toast_message_for_reset">Ripristino completato</string>
|
||||
<string name="settings_tab_to_display">Scheda da visualizzare all\'apertura dell\'applicazione</string>
|
||||
<string name="last_tab_used_title">Ultima scheda utilizzata</string>
|
||||
|
|
|
@ -615,7 +615,7 @@
|
|||
<string name="blue_accent_color">파란색</string>
|
||||
<string name="toast_message_for_reset">초기화를 완료했습니다.</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">0분에서 60분 사이의 시간을 입력할 수 있습니다.</string>
|
||||
<string name="timer_button_time_warning_box_title">잘못된 값 입력됨</string>
|
||||
<string name="timer_time_warning_box_title">잘못된 값 입력됨</string>
|
||||
<string name="sw_long_press_volume_up_action_title">볼륨 위(길게 눌렀을 때)</string>
|
||||
<string name="analog_widget_configuration_warning">이 위젯은 Android 12 이상에서만 설정할 수 있습니다.</string>
|
||||
<string name="actions_category_title">동작</string>
|
||||
|
|
|
@ -645,7 +645,7 @@
|
|||
<string name="settings_tab_to_display">Tabblad openen bij start</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">Voer een waarde in tussen 0 en 60 minuten</string>
|
||||
<string name="last_tab_used_title">Laatst gebruikt</string>
|
||||
<string name="timer_button_time_warning_box_title">Onjuiste waarde ingevoerd</string>
|
||||
<string name="timer_time_warning_box_title">Onjuiste waarde ingevoerd</string>
|
||||
<string name="settings_language_turkish">Turks</string>
|
||||
<string name="contributors_dialog_title">Profiel bekijken</string>
|
||||
<string name="reset_settings_title">Instellingen opnieuw instellen</string>
|
||||
|
|
|
@ -661,7 +661,7 @@
|
|||
<string name="settings_tab_to_display">Karta wyświetlana podczas otwierania aplikacji</string>
|
||||
<string name="last_tab_used_title">Ostatnio używana karta</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">Wprowadź wartość od 0 do 60 minut</string>
|
||||
<string name="timer_button_time_warning_box_title">Wprowadzono nieprawidłową wartość</string>
|
||||
<string name="timer_time_warning_box_title">Wprowadzono nieprawidłową wartość</string>
|
||||
<string name="settings_language_turkish">Turecki</string>
|
||||
<string name="reset_settings_title">Zresetuj ustawienia</string>
|
||||
<string name="reset_settings_message">Czy na pewno chcesz zresetować wszystkie ustawienia aplikacji?\n\nUwaga: dzwonki niestandardowe nie zostaną zresetowane.</string>
|
||||
|
|
|
@ -672,7 +672,7 @@
|
|||
<string name="toast_message_for_reset">Сброс выполнен</string>
|
||||
<string name="settings_language_korean">Корейский</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">Введите значение между 0 и 60 минутами</string>
|
||||
<string name="timer_button_time_warning_box_title">Неверное значение введено</string>
|
||||
<string name="timer_time_warning_box_title">Неверное значение введено</string>
|
||||
<string name="settings_language_russian">Русский</string>
|
||||
<string name="display_date_title">Показывать дату на виджете</string>
|
||||
<string name="analog_widget_choice_title">Выберите ваш стиль</string>
|
||||
|
|
|
@ -617,7 +617,7 @@
|
|||
<string name="display_warning_before_deleting_timer_title">Прикажи упозорење пре брисања тајмера</string>
|
||||
<string name="warning_dialog_title">Обриши тајмер</string>
|
||||
<string name="settings_language_turkish">Турски</string>
|
||||
<string name="timer_button_time_warning_box_title">Унета је некоректна вредност</string>
|
||||
<string name="timer_time_warning_box_title">Унета је некоректна вредност</string>
|
||||
<string name="about_translate_link">Преведите на Codeberg-у</string>
|
||||
<string name="translate_dialog_message">Посетите страницу Codeberg:\n\n%s</string>
|
||||
<string name="clock_style_analog_material">Аналогни (Материјал)</string>
|
||||
|
|
|
@ -398,7 +398,7 @@
|
|||
<string name="sw_start_pause_action">Başlat / Duraklat</string>
|
||||
<string name="timer_label_box_title">Zamanlayıcı etiketi</string>
|
||||
<string name="timer_button_time_box_title">Zamanlayıcıya eklenecek dakika</string>
|
||||
<string name="timer_button_time_warning_box_title">Geçersiz değer girildi</string>
|
||||
<string name="timer_time_warning_box_title">Geçersiz değer girildi</string>
|
||||
<string name="purple_accent_color">Mor</string>
|
||||
<string name="auto_silence_20_seconds">20 saniye</string>
|
||||
<string name="black_accent_color">Siyah</string>
|
||||
|
|
|
@ -672,7 +672,7 @@
|
|||
<string name="analog_widget_without_second_hand_title">Без секундної стрілки</string>
|
||||
<string name="last_tab_used_title">Остання використана вкладка</string>
|
||||
<string name="settings_tab_to_display">Вкладка, на якій відкриватиметься додаток</string>
|
||||
<string name="timer_button_time_warning_box_title">Введено неправильне значення</string>
|
||||
<string name="timer_time_warning_box_title">Введено неправильне значення</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">Введіть значення від 0 до 60 хвилин</string>
|
||||
<string name="settings_language_turkish">Турецька</string>
|
||||
<string name="reset_settings_message">Ви дійсно хочете скинути всі налаштування додатка?\n\nЗауважте, що користувацькі мелодії не скидаються.</string>
|
||||
|
|
|
@ -633,7 +633,7 @@
|
|||
<string name="analog_widget_configuration_warning">此微件仅可从 Android 12 配置</string>
|
||||
<string name="analog_widget_choice_title">选择样式</string>
|
||||
<string name="last_tab_used_title">上次使用的标签页</string>
|
||||
<string name="timer_button_time_warning_box_title">输入的值不正确</string>
|
||||
<string name="timer_time_warning_box_title">输入的值不正确</string>
|
||||
<string name="settings_tab_to_display">打开应用时显示的标签页</string>
|
||||
<string name="timer_button_time_minutes_warning_box_text">请输入介于 0 和 60 分钟之间的值</string>
|
||||
<string name="settings_language_turkish">土耳其语</string>
|
||||
|
|
|
@ -465,7 +465,7 @@
|
|||
<string name="alarm_settings_general_summary">您可展開鬧鐘面板並各別設定</string>
|
||||
<string name="alarm_display_customization_title">自訂鬧鐘顯示</string>
|
||||
<string name="timer_label_box_title">計時器名稱</string>
|
||||
<string name="timer_button_time_warning_box_title">數值無效</string>
|
||||
<string name="timer_time_warning_box_title">數值無效</string>
|
||||
<string name="warning_dialog_title">刪除計時器</string>
|
||||
<string name="occasional_alarm_deleted">已刪除臨時鬧鐘「<xliff:g example="14:20" id="alarm_time">%s</xliff:g>」</string>
|
||||
<string name="first_launch_main_feature_title">主要功能</string>
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
<string name="action_reset">Reset</string>
|
||||
<string name="action_show">Show</string>
|
||||
<string name="action_add_custom_time_to_timer">Add Custom Time To Timer</string>
|
||||
<string name="action_set_new_timer_duration">Set New Timer Duration</string>
|
||||
<string name="action_lap">Lap</string>
|
||||
<string name="action_enable">Enable</string>
|
||||
<string name="action_disable">Disable</string>
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
<string name="duplicate">Duplicate</string>
|
||||
<!-- Label "Warning" -->
|
||||
<string name="warning">Warning</string>
|
||||
<!-- Label "Hours" -->
|
||||
<string name="label_hours">Hours</string>
|
||||
<!-- Label "Minutes" -->
|
||||
<string name="label_minutes">Minutes</string>
|
||||
<!-- Label "Seconds" -->
|
||||
|
@ -679,14 +681,22 @@
|
|||
<!-- timer strings -->
|
||||
<!-- Title of dialog box for editing timer label -->
|
||||
<string name="timer_label_box_title">Timer label</string>
|
||||
<!-- Title of dialog box to set a new duration to an existing timer. -->
|
||||
<string name="timer_time_box_title">New timer duration</string>
|
||||
<!-- Text of dialog box to edit hours to set a new duration to an existing timer. -->
|
||||
<string name="timer_hours_warning_box_text">Enter a value between 0 and 24 hours</string>
|
||||
<!-- Text of dialog box to edit minutes to set a new duration to an existing timer. -->
|
||||
<string name="timer_minutes_warning_box_text">Enter a value between 0 and 59 minutes</string>
|
||||
<!-- Text of dialog box to edit seconds to set a new duration to an existing timer. -->
|
||||
<string name="timer_seconds_warning_box_text">Enter a value between 0 and 59 seconds</string>
|
||||
<!-- Title of dialog box to edit button for adding time to timer. -->
|
||||
<string name="timer_button_time_box_title">Minutes to add to the timer</string>
|
||||
<!-- Text of dialog box to edit minutes for adding time to timer. -->
|
||||
<string name="timer_button_time_minutes_warning_box_text">Enter a value between 0 and 60 minutes</string>
|
||||
<!-- Text of dialog box to edit seconds for adding time to timer. -->
|
||||
<string name="timer_button_time_seconds_warning_box_text">Enter a value between 0 and 59 seconds</string>
|
||||
<!-- Title of dialog box to edit button for adding time to timer if the entered value is incorrect. -->
|
||||
<string name="timer_button_time_warning_box_title">Incorrect value entered</string>
|
||||
<!-- Title of dialog box to edit timers if an entered value is incorrect. -->
|
||||
<string name="timer_time_warning_box_title">Incorrect value entered</string>
|
||||
<!-- Describes the purpose of the button to add a new timer -->
|
||||
<string name="timer_add_timer">Add Timer</string>
|
||||
<!-- Describes the purpose of the button to begin or continue running a timer -->
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue