diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 654b8e968..50c71f0a3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,6 +22,7 @@ + diff --git a/app/src/main/java/com/best/deskclock/provider/Alarm.java b/app/src/main/java/com/best/deskclock/provider/Alarm.java index 64852bda7..d834cf861 100644 --- a/app/src/main/java/com/best/deskclock/provider/Alarm.java +++ b/app/src/main/java/com/best/deskclock/provider/Alarm.java @@ -130,7 +130,8 @@ public Alarm[] newArray(int size) { SNOOZE_DURATION, MISSED_ALARM_REPEAT_LIMIT, CRESCENDO_DURATION, - ALARM_VOLUME + ALARM_VOLUME, + HOLIDAY_OPTION }; private static final String[] QUERY_ALARMS_WITH_INSTANCES_COLUMNS = { ClockDatabaseHelper.ALARMS_TABLE_NAME + "." + _ID, @@ -152,6 +153,7 @@ public Alarm[] newArray(int size) { ClockDatabaseHelper.ALARMS_TABLE_NAME + "." + MISSED_ALARM_REPEAT_LIMIT, ClockDatabaseHelper.ALARMS_TABLE_NAME + "." + CRESCENDO_DURATION, ClockDatabaseHelper.ALARMS_TABLE_NAME + "." + ALARM_VOLUME, + ClockDatabaseHelper.ALARMS_TABLE_NAME + "." + HOLIDAY_OPTION, ClockDatabaseHelper.INSTANCES_TABLE_NAME + "." + ClockContract.InstancesColumns.ALARM_STATE, ClockDatabaseHelper.INSTANCES_TABLE_NAME + "." + ClockContract.InstancesColumns._ID, ClockDatabaseHelper.INSTANCES_TABLE_NAME + "." + ClockContract.InstancesColumns.YEAR, @@ -168,7 +170,8 @@ public Alarm[] newArray(int size) { ClockDatabaseHelper.INSTANCES_TABLE_NAME + "." + ClockContract.InstancesColumns.MISSED_ALARM_REPEAT_COUNT, ClockDatabaseHelper.INSTANCES_TABLE_NAME + "." + ClockContract.InstancesColumns.MISSED_ALARM_REPEAT_LIMIT, ClockDatabaseHelper.INSTANCES_TABLE_NAME + "." + ClockContract.InstancesColumns.CRESCENDO_DURATION, - ClockDatabaseHelper.INSTANCES_TABLE_NAME + "." + ClockContract.InstancesColumns.ALARM_VOLUME + ClockDatabaseHelper.INSTANCES_TABLE_NAME + "." + ClockContract.InstancesColumns.ALARM_VOLUME, + HOLIDAY_OPTION }; /** * These save calls to cursor.getColumnIndexOrThrow() @@ -193,27 +196,29 @@ public Alarm[] newArray(int size) { private static final int MISSED_ALARM_REPEAT_LIMIT_INDEX = 16; private static final int CRESCENDO_DURATION_INDEX = 17; private static final int ALARM_VOLUME_INDEX = 18; - - private static final int INSTANCE_STATE_INDEX = 19; - public static final int INSTANCE_ID_INDEX = 20; - public static final int INSTANCE_YEAR_INDEX = 21; - public static final int INSTANCE_MONTH_INDEX = 22; - public static final int INSTANCE_DAY_INDEX = 23; - public static final int INSTANCE_HOUR_INDEX = 24; - public static final int INSTANCE_MINUTE_INDEX = 25; - public static final int INSTANCE_LABEL_INDEX = 26; - public static final int INSTANCE_VIBRATE_INDEX = 27; - public static final int INSTANCE_VIBRATION_PATTERN_INDEX = 28; - public static final int INSTANCE_FLASH_INDEX = 29; - public static final int INSTANCE_AUTO_SILENCE_DURATION_INDEX = 30; - public static final int INSTANCE_SNOOZE_DURATION_INDEX = 31; - public static final int INSTANCE_MISSED_ALARM_REPEAT_COUNT_INDEX = 32; - public static final int INSTANCE_MISSED_ALARM_REPEAT_LIMIT_INDEX = 33; - public static final int INSTANCE_CRESCENDO_DURATION_INDEX = 34; - public static final int INSTANCE_ALARM_VOLUME_INDEX = 35; - - private static final int COLUMN_COUNT = ALARM_VOLUME_INDEX + 1; - private static final int ALARM_JOIN_INSTANCE_COLUMN_COUNT = INSTANCE_ALARM_VOLUME_INDEX + 1; + private static final int HOLIDAY_OPTION_INDEX = 19; + + private static final int INSTANCE_STATE_INDEX = 20; + public static final int INSTANCE_ID_INDEX = 21; + public static final int INSTANCE_YEAR_INDEX = 22; + public static final int INSTANCE_MONTH_INDEX = 23; + public static final int INSTANCE_DAY_INDEX = 24; + public static final int INSTANCE_HOUR_INDEX = 25; + public static final int INSTANCE_MINUTE_INDEX = 26; + public static final int INSTANCE_LABEL_INDEX = 27; + public static final int INSTANCE_VIBRATE_INDEX = 28; + public static final int INSTANCE_VIBRATION_PATTERN_INDEX = 29; + public static final int INSTANCE_FLASH_INDEX = 30; + public static final int INSTANCE_AUTO_SILENCE_DURATION_INDEX = 31; + public static final int INSTANCE_SNOOZE_DURATION_INDEX = 32; + public static final int INSTANCE_MISSED_ALARM_REPEAT_COUNT_INDEX = 33; + public static final int INSTANCE_MISSED_ALARM_REPEAT_LIMIT_INDEX = 34; + public static final int INSTANCE_CRESCENDO_DURATION_INDEX = 35; + public static final int INSTANCE_ALARM_VOLUME_INDEX = 36; + public static final int INSTANCE_HOLIDAY_OPTION_INDEX = 37; + + private static final int COLUMN_COUNT = HOLIDAY_OPTION_INDEX + 1; + private static final int ALARM_JOIN_INSTANCE_COLUMN_COUNT = INSTANCE_HOLIDAY_OPTION_INDEX + 1; // Public fields public long id; public boolean enabled; @@ -314,6 +319,7 @@ public Alarm(Cursor c) { missedAlarmRepeatLimit = c.getInt(MISSED_ALARM_REPEAT_LIMIT_INDEX); crescendoDuration = c.getInt(CRESCENDO_DURATION_INDEX); alarmVolume = c.getInt(ALARM_VOLUME_INDEX); + holidayOption = c.getInt(HOLIDAY_OPTION_INDEX); if (c.getColumnCount() == ALARM_JOIN_INSTANCE_COLUMN_COUNT) { instanceState = c.getInt(INSTANCE_STATE_INDEX); @@ -350,6 +356,7 @@ public Alarm(Cursor c) { missedAlarmRepeatLimit = p.readInt(); crescendoDuration = p.readInt(); alarmVolume = p.readInt(); + holidayOption = p.readInt(); } public ContentValues createContentValues() { @@ -375,6 +382,7 @@ public ContentValues createContentValues() { values.put(MISSED_ALARM_REPEAT_LIMIT, missedAlarmRepeatLimit); values.put(CRESCENDO_DURATION, crescendoDuration); values.put(ALARM_VOLUME, alarmVolume); + values.put(HOLIDAY_OPTION, holidayOption); if (alert == null) { // We want to put null, so default alarm changes values.putNull(RINGTONE); @@ -405,6 +413,7 @@ public void writeToParcel(Parcel p, int flags) { p.writeInt(missedAlarmRepeatLimit); p.writeInt(crescendoDuration); p.writeInt(alarmVolume); + p.writeInt(holidayOption); } public int describeContents() { @@ -665,6 +674,7 @@ public AlarmInstance createInstanceAfter(Calendar time) { result.mMissedAlarmRepeatLimit = missedAlarmRepeatLimit; result.mCrescendoDuration = crescendoDuration; result.mAlarmVolume = alarmVolume; + result.mHolidayOption = holidayOption; return result; } diff --git a/app/src/main/java/com/best/deskclock/provider/AlarmInstance.java b/app/src/main/java/com/best/deskclock/provider/AlarmInstance.java index 064cb1641..5b2103d4f 100644 --- a/app/src/main/java/com/best/deskclock/provider/AlarmInstance.java +++ b/app/src/main/java/com/best/deskclock/provider/AlarmInstance.java @@ -68,7 +68,8 @@ public final class AlarmInstance implements ClockContract.InstancesColumns { MISSED_ALARM_REPEAT_COUNT, MISSED_ALARM_REPEAT_LIMIT, CRESCENDO_DURATION, - ALARM_VOLUME + ALARM_VOLUME, + HOLIDAY_OPTION }; /** @@ -94,8 +95,9 @@ public final class AlarmInstance implements ClockContract.InstancesColumns { private static final int MISSED_ALARM_MAX_COUNT_INDEX = 16; private static final int CRESCENDO_DURATION_INDEX = 17; private static final int ALARM_VOLUME_INDEX = 18; + private static final int HOLIDAY_OPTION_INDEX = 19; - private static final int COLUMN_COUNT = ALARM_VOLUME_INDEX + 1; + private static final int COLUMN_COUNT = HOLIDAY_OPTION_INDEX + 1; // Public fields public long mId; public int mYear; @@ -117,6 +119,7 @@ public final class AlarmInstance implements ClockContract.InstancesColumns { public int mCrescendoDuration; // Alarm volume level in steps; not a percentage public int mAlarmVolume; + public int mHolidayOption; public AlarmInstance(Calendar calendar, Long alarmId) { this(calendar); @@ -138,6 +141,7 @@ public AlarmInstance(Calendar calendar) { mMissedAlarmRepeatLimit = Integer.parseInt(DEFAULT_MISSED_ALARM_REPEAT_LIMIT); mCrescendoDuration = DEFAULT_VOLUME_CRESCENDO_DURATION; mAlarmVolume = DEFAULT_ALARM_VOLUME; + mHolidayOption = 0; } public AlarmInstance(AlarmInstance instance) { @@ -160,6 +164,7 @@ public AlarmInstance(AlarmInstance instance) { this.mMissedAlarmRepeatLimit = instance.mMissedAlarmRepeatLimit; this.mCrescendoDuration = instance.mCrescendoDuration; this.mAlarmVolume = instance.mAlarmVolume; + this.mHolidayOption = instance.mHolidayOption; } public AlarmInstance(Cursor c, boolean joinedTable) { @@ -180,6 +185,7 @@ public AlarmInstance(Cursor c, boolean joinedTable) { mMissedAlarmRepeatLimit = c.getInt(Alarm.INSTANCE_MISSED_ALARM_REPEAT_LIMIT_INDEX); mCrescendoDuration = c.getInt(Alarm.INSTANCE_CRESCENDO_DURATION_INDEX); mAlarmVolume = c.getInt(Alarm.INSTANCE_ALARM_VOLUME_INDEX); + mHolidayOption = c.getInt(Alarm.INSTANCE_HOLIDAY_OPTION_INDEX); } else { mId = c.getLong(ID_INDEX); mYear = c.getInt(YEAR_INDEX); @@ -197,6 +203,7 @@ public AlarmInstance(Cursor c, boolean joinedTable) { mMissedAlarmRepeatLimit = c.getInt(MISSED_ALARM_MAX_COUNT_INDEX); mCrescendoDuration = c.getInt(CRESCENDO_DURATION_INDEX); mAlarmVolume = c.getInt(ALARM_VOLUME_INDEX); + mHolidayOption = c.getInt(HOLIDAY_OPTION_INDEX); } if (c.isNull(RINGTONE_INDEX)) { // Should we be saving this with the current ringtone or leave it null @@ -242,6 +249,7 @@ public ContentValues createContentValues() { values.put(MISSED_ALARM_REPEAT_LIMIT, mMissedAlarmRepeatLimit); values.put(CRESCENDO_DURATION, mCrescendoDuration); values.put(ALARM_VOLUME, mAlarmVolume); + values.put(HOLIDAY_OPTION, mHolidayOption); return values; } diff --git a/app/src/main/java/com/best/deskclock/provider/ClockContract.java b/app/src/main/java/com/best/deskclock/provider/ClockContract.java index b1a229d59..8e2532831 100644 --- a/app/src/main/java/com/best/deskclock/provider/ClockContract.java +++ b/app/src/main/java/com/best/deskclock/provider/ClockContract.java @@ -60,6 +60,13 @@ private interface AlarmSettingColumns extends BaseColumns { */ String VIBRATION_PATTERN = "vibrationPattern"; + /** + * Alarm holiday option. + * + *

Type: INTEGER

+ */ + String HOLIDAY_OPTION = "holidayOption"; + /** * True if flash should turn on *

Type: BOOLEAN

diff --git a/app/src/main/java/com/best/deskclock/provider/ClockDatabaseHelper.java b/app/src/main/java/com/best/deskclock/provider/ClockDatabaseHelper.java index 556acfa60..e4c5e0729 100644 --- a/app/src/main/java/com/best/deskclock/provider/ClockDatabaseHelper.java +++ b/app/src/main/java/com/best/deskclock/provider/ClockDatabaseHelper.java @@ -27,7 +27,7 @@ class ClockDatabaseHelper extends SQLiteOpenHelper { static final String ALARMS_TABLE_NAME = "alarm_templates"; static final String INSTANCES_TABLE_NAME = "alarm_instances"; - private static final int DATABASE_VERSION = 21; + private static final int DATABASE_VERSION = 22; private static final int MINIMUM_SUPPORTED_VERSION = 15; private final Context mContext; @@ -47,6 +47,8 @@ private static void createAlarmsTable(SQLiteDatabase db, String alarmsTableName) ClockContract.AlarmsColumns.DAYS_OF_WEEK + " INTEGER NOT NULL, " + ClockContract.AlarmsColumns.ENABLED + " INTEGER NOT NULL, " + ClockContract.AlarmsColumns.VIBRATE + " INTEGER NOT NULL, " + + ClockContract.AlarmsColumns.VIBRATION_PATTERN + " TEXT DEFAULT 'default', " + + ClockContract.AlarmsColumns.HOLIDAY_OPTION + " INTEGER NOT NULL DEFAULT 0, " + ClockContract.AlarmsColumns.FLASH + " INTEGER NOT NULL, " + ClockContract.AlarmsColumns.LABEL + " TEXT NOT NULL, " + ClockContract.AlarmsColumns.RINGTONE + " TEXT, " + @@ -68,6 +70,8 @@ private static void createInstanceTable(SQLiteDatabase db, String instanceTableN ClockContract.InstancesColumns.HOUR + " INTEGER NOT NULL, " + ClockContract.InstancesColumns.MINUTES + " INTEGER NOT NULL, " + ClockContract.InstancesColumns.VIBRATE + " INTEGER NOT NULL, " + + ClockContract.InstancesColumns.VIBRATION_PATTERN + " TEXT DEFAULT 'default', " + + ClockContract.InstancesColumns.HOLIDAY_OPTION + " INTEGER NOT NULL DEFAULT 0, " + ClockContract.InstancesColumns.FLASH + " INTEGER NOT NULL, " + ClockContract.InstancesColumns.LABEL + " TEXT NOT NULL, " + ClockContract.InstancesColumns.RINGTONE + " TEXT, " + @@ -195,6 +199,16 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { LogUtils.i("dismissAlarmWhenRingtoneEnds, alarmSnoozeActions and increasingVolume" + " columns removed for version 21 upgrade."); + + // Add vibrationPattern and holidayOption columns + if (oldVersion < 22) { + db.execSQL("ALTER TABLE " + ALARMS_TABLE_NAME + " ADD COLUMN vibrationPattern TEXT DEFAULT 'default';"); + db.execSQL("ALTER TABLE " + ALARMS_TABLE_NAME + " ADD COLUMN holidayOption INTEGER NOT NULL DEFAULT 0;"); + db.execSQL("ALTER TABLE " + INSTANCES_TABLE_NAME + " ADD COLUMN vibrationPattern TEXT DEFAULT 'default';"); + db.execSQL("ALTER TABLE " + INSTANCES_TABLE_NAME + " ADD COLUMN holidayOption INTEGER NOT NULL DEFAULT 0;"); + + LogUtils.i("Added vibrationPattern and holidayOption columns for version 22 upgrade."); + } } } diff --git a/app/src/main/java/com/best/deskclock/provider/ClockProvider.java b/app/src/main/java/com/best/deskclock/provider/ClockProvider.java index 9d71a8845..d2a981e4f 100644 --- a/app/src/main/java/com/best/deskclock/provider/ClockProvider.java +++ b/app/src/main/java/com/best/deskclock/provider/ClockProvider.java @@ -77,6 +77,10 @@ public class ClockProvider extends ContentProvider { ALARMS_TABLE_NAME + "." + AlarmsColumns.ENABLED); sAlarmsWithInstancesProjection.put(ALARMS_TABLE_NAME + "." + AlarmsColumns.VIBRATE, ALARMS_TABLE_NAME + "." + AlarmsColumns.VIBRATE); + sAlarmsWithInstancesProjection.put(ALARMS_TABLE_NAME + "." + AlarmsColumns.VIBRATION_PATTERN, + ALARMS_TABLE_NAME + "." + AlarmsColumns.VIBRATION_PATTERN); + sAlarmsWithInstancesProjection.put(ALARMS_TABLE_NAME + "." + AlarmsColumns.HOLIDAY_OPTION, + ALARMS_TABLE_NAME + "." + AlarmsColumns.HOLIDAY_OPTION); sAlarmsWithInstancesProjection.put(ALARMS_TABLE_NAME + "." + AlarmsColumns.FLASH, ALARMS_TABLE_NAME + "." + AlarmsColumns.FLASH); sAlarmsWithInstancesProjection.put(ALARMS_TABLE_NAME + "." + AlarmsColumns.LABEL, @@ -112,6 +116,10 @@ public class ClockProvider extends ContentProvider { INSTANCES_TABLE_NAME + "." + InstancesColumns.LABEL); sAlarmsWithInstancesProjection.put(INSTANCES_TABLE_NAME + "." + InstancesColumns.VIBRATE, INSTANCES_TABLE_NAME + "." + InstancesColumns.VIBRATE); + sAlarmsWithInstancesProjection.put(INSTANCES_TABLE_NAME + "." + InstancesColumns.VIBRATION_PATTERN, + INSTANCES_TABLE_NAME + "." + InstancesColumns.VIBRATION_PATTERN); + sAlarmsWithInstancesProjection.put(INSTANCES_TABLE_NAME + "." + InstancesColumns.HOLIDAY_OPTION, + INSTANCES_TABLE_NAME + "." + InstancesColumns.HOLIDAY_OPTION); sAlarmsWithInstancesProjection.put(INSTANCES_TABLE_NAME + "." + InstancesColumns.FLASH, INSTANCES_TABLE_NAME + "." + InstancesColumns.FLASH); sAlarmsWithInstancesProjection.put(INSTANCES_TABLE_NAME + "." + InstancesColumns.AUTO_SILENCE_DURATION, diff --git a/duplicates.txt b/duplicates.txt deleted file mode 100644 index 32a365364..000000000 --- a/duplicates.txt +++ /dev/null @@ -1,9 +0,0 @@ -connect_external_audio_device_title -disconnect_external_audio_device_title -external_audio_device_volume_title -vibration_pattern_default_title -vibration_pattern_escalating_title -vibration_pattern_heartbeat_title -vibration_pattern_soft_title -vibration_pattern_strong_title -vibration_pattern_tick_tock_title diff --git a/restore_strings.py b/restore_strings.py deleted file mode 100644 index 15f23a79a..000000000 --- a/restore_strings.py +++ /dev/null @@ -1,58 +0,0 @@ -import xml.etree.ElementTree as ET -import sys -import os - -def restore_strings(old_file, new_file): - if not os.path.exists(old_file) or not os.path.exists(new_file): - print(f"File not found: {old_file} or {new_file}") - return - - # Use a simpler parser that handles comments and preserves some structure - def get_strings(file_path): - try: - tree = ET.parse(file_path) - root = tree.getroot() - return {child.get('name'): child for child in root if child.tag == 'string'} - except Exception as e: - print(f"Error parsing {file_path}: {e}") - return {} - - old_strings = get_strings(old_file) - new_strings = get_strings(new_file) - - missing_names = set(old_strings.keys()) - set(new_strings.keys()) - - if not missing_names: - print(f"No strings missing in {new_file}") - return - - # Read the current file to append at the end correctly - with open(new_file, 'r', encoding='utf-8') as f: - lines = f.readlines() - - # Find the closing resources tag - closing_tag_index = -1 - for i in range(len(lines) - 1, -1, -1): - if '' in lines[i]: - closing_tag_index = i - break - - if closing_tag_index == -1: - print(f"Could not find closing tag in {new_file}") - return - - new_content = [] - for name in sorted(missing_names): - element = old_strings[name] - xml_str = ET.tostring(element, encoding='unicode').strip() - new_content.append(f" {xml_str}\n") - - lines.insert(closing_tag_index, "".join(new_content)) - - with open(new_file, 'w', encoding='utf-8') as f: - f.writelines(lines) - - print(f"Restored {len(missing_names)} strings to {new_file}") - -restore_strings('strings_old.xml', 'app/src/main/res/values/strings.xml') -restore_strings('strings_zh_old.xml', 'app/src/main/res/values-zh-rCN/strings.xml') diff --git a/update_alarm_settings.py b/update_alarm_settings.py deleted file mode 100644 index 5c45d1e9c..000000000 --- a/update_alarm_settings.py +++ /dev/null @@ -1,49 +0,0 @@ -import sys - -path = 'app/src/main/java/com/best/deskclock/settings/AlarmSettingsFragment.java' -with open(path, 'r') as f: - lines = f.readlines() - -new_lines = [] -for line in lines: - if line.strip() == 'import com.best.deskclock.holiday.HolidayRepository;': - continue - if line.startswith('package com.best.deskclock.settings;'): - new_lines.append(line) - new_lines.append('import com.best.deskclock.holiday.HolidayRepository;\n') - else: - new_lines.append(line) - -# Add holiday preference logic -end_of_on_create = -1 -for i, line in enumerate(new_lines): - if 'mDeleteOccasionalAlarmByDefaultPref.setOnPreferenceChangeListener(this);' in line: - end_of_on_create = i + 1 - break - -if end_of_on_create != -1: - holiday_logic = ''' - Preference updateHolidayDataPref = findPreference(KEY_UPDATE_HOLIDAY_DATA); - if (updateHolidayDataPref != null) { - updateHolidayDataPref.setOnPreferenceClickListener(preference -> { - HolidayRepository.getInstance(requireContext()).updateWorkdayData(); - return true; - }); - } - - mHolidayDataUrlPref = findPreference(KEY_HOLIDAY_DATA_URL); - if (mHolidayDataUrlPref != null) { - mHolidayDataUrlPref.setSummary(SettingsDAO.getHolidayDataUrl(mPrefs)); - mHolidayDataUrlPref.setOnPreferenceChangeListener(this); - } -''' - new_lines.insert(end_of_on_create, holiday_logic) - -# Add field declaration -for i, line in enumerate(new_lines): - if 'private CustomSwitchPreference mDeleteOccasionalAlarmByDefaultPref;' in line: - new_lines.insert(i + 1, ' private androidx.preference.EditTextPreference mHolidayDataUrlPref;\n') - break - -with open(path, 'w') as f: - f.writelines(new_lines)