diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7aeea75..0000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -language: android - -jdk: - - oraclejdk8 - -env: - - TERM=dumb - -android: - components: - - tools - - build-tools-25.0.0 - - android-25 - -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ -script: - - ./gradlew build -deploy: - provider: releases - api_key: $GITHUB_ACCESS_TOKEN - file: - - build/outputs/apk/talalarmo-debug.apk - skip_cleanup: true - on: - tags: true diff --git a/README.md b/README.md index 4842f61..ffbcf26 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,9 @@ Crafted by a team with over 25 years of sleeping experience - it just has to be


-It does only one function but does it well. Only one alarm time is supported and it's recurring daily. Setting the new alarm time takes less than a second. To dismiss the alarm you can touch the screen anywhere which is handy if you are still sleepy and have barely opened your eyes. There is no snooze mode because you should be honest to yourself: if it's time to wake up - go ahead! +It does only one function but does it well. Only one alarm time is supported and it can be set to recur daily. +Setting the new alarm time takes less than a second. To dismiss the alarm simply hold down anywhere on the screen. +There is no snooze mode because you should be honest to yourself: if it's time to wake up - go ahead!

@@ -23,10 +25,10 @@ It does only one function but does it well. Only one alarm time is supported and ## Features -* Clean, minimal and easy-to-use design with modern material UI. -* Set alarm with only two taps - the easiest way to set alarm time. -* Only one alarm time is supported and it's recurring daily. You will never miss it or be disturbed by a wrong alarm. -* Choose alarm music, optionally turn on the vibration +* Clean, minimal and easy-to-use design with modern material UI +* Set alarm with only two taps - the easiest way to set alarm time +* Only one alarm time is supported and can be set to recur daily - you will never miss it or be disturbed by a wrong alarm +* Ability to choose alarm music and enable vibration * Wake up easily with gentle alarm (gradually increasing alarm volume) * Dark and light themes @@ -44,4 +46,3 @@ It does only one function but does it well. Only one alarm time is supported and ## License Code is distributed under MIT license, feel free to use it. Just please, don't upload Talalarmo clones to Google Play (they are likely to be rejected anyway). - diff --git a/build.gradle b/build.gradle index 1f519ce..df9b24e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,22 +1,23 @@ buildscript { repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.2' - classpath 'me.tatarka:gradle-retrolambda:3.2.5' + classpath 'com.android.tools.build:gradle:3.6.2' + classpath 'me.tatarka:gradle-retrolambda:3.7.1' } } apply plugin: 'com.android.application' apply plugin: 'me.tatarka.retrolambda' android { - compileSdkVersion 'android-25' - buildToolsVersion '25.0.0' + compileSdkVersion 'android-26' + buildToolsVersion '25.0.3' defaultConfig { minSdkVersion 15 - targetSdkVersion 25 + targetSdkVersion 26 versionCode 19 versionName '3.9' } @@ -45,16 +46,17 @@ android { repositories { jcenter() + google() maven { url 'https://jitpack.io/' } } dependencies { - compile 'com.github.trikita:jedux:-SNAPSHOT' - compile 'com.github.trikita:promote:-SNAPSHOT' - compile 'co.trikita:anvil-sdk15:0.3.1' - compile 'org.immutables:gson:2.1.14' - annotationProcessor 'org.immutables:value:2.1.14' - provided 'org.immutables:value:2.1.14' + implementation 'com.github.trikita:jedux:-SNAPSHOT' + implementation 'com.github.trikita:promote:-SNAPSHOT' + implementation 'co.trikita:anvil-sdk15:0.3.1' + implementation 'org.immutables:gson:2.8.3' + annotationProcessor 'org.immutables:value:2.8.3' + compileOnly 'org.immutables:value:2.8.3' } apply from: 'https://raw.github.com/trikita/gradle-android-signing/master/gradle-android-signing.gradle' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 04e285f..eaba979 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/src/main/java/trikita/talalarmo/Actions.java b/src/main/java/trikita/talalarmo/Actions.java index e3605c5..658cd01 100644 --- a/src/main/java/trikita/talalarmo/Actions.java +++ b/src/main/java/trikita/talalarmo/Actions.java @@ -3,5 +3,5 @@ public final class Actions { public enum Alarm {ON, OFF, SET_MINUTE, SET_HOUR, SET_AM_PM, WAKEUP, DISMISS, RESTART_ALARM} - public enum Settings {SET_VIBRATE, SET_RAMPING, SET_RINGTONE, SET_SNAP, SET_THEME} + public enum Settings {SET_VIBRATE, SET_RAMPING, SET_RINGTONE, SET_SNAP, SET_THEME, SET_REPEAT, SET_OFFSET} } diff --git a/src/main/java/trikita/talalarmo/App.java b/src/main/java/trikita/talalarmo/App.java index f2e60a7..b4e4920 100644 --- a/src/main/java/trikita/talalarmo/App.java +++ b/src/main/java/trikita/talalarmo/App.java @@ -1,6 +1,7 @@ package trikita.talalarmo; import android.app.Application; +import android.util.Log; import trikita.anvil.Anvil; import trikita.jedux.Action; @@ -29,7 +30,13 @@ public void onCreate() { App.instance = this; PersistanceController persistanceController = new PersistanceController(this); - State initialState = persistanceController.getSavedState(); + State initialState = null; + try { + initialState = persistanceController.getSavedState(); + } catch (Throwable ex) { + if(!(ex.getCause() instanceof IllegalStateException)) + Log.w("Talalarmo", ex); + } if (initialState == null) { initialState = State.Default.build(); } diff --git a/src/main/java/trikita/talalarmo/MainActivity.java b/src/main/java/trikita/talalarmo/MainActivity.java index 7aae3c2..49594e3 100644 --- a/src/main/java/trikita/talalarmo/MainActivity.java +++ b/src/main/java/trikita/talalarmo/MainActivity.java @@ -32,11 +32,6 @@ public void onResume() { super.onResume(); updateTheme(); Anvil.render(); - Promote.after(7).days().every(7).days().rate(this); - Promote.after(3).days().every(14).days().share(this, - Promote.FACEBOOK_TWITTER, - "https://github.com/trikita/talalarmo", - "Talalarmo: elegant open-source alarm clock"); } public void openSettings() { diff --git a/src/main/java/trikita/talalarmo/SettingsActivity.java b/src/main/java/trikita/talalarmo/SettingsActivity.java index ae14242..6c01c73 100644 --- a/src/main/java/trikita/talalarmo/SettingsActivity.java +++ b/src/main/java/trikita/talalarmo/SettingsActivity.java @@ -9,6 +9,7 @@ import android.os.Bundle; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; +import android.util.Log; import trikita.jedux.Action; @@ -43,15 +44,21 @@ protected void onCreate(Bundle savedInstanceState) { @Override public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { switch (key) { + case "repeat_setting": + App.dispatch(new Action<>(Actions.Settings.SET_REPEAT, prefs.getBoolean(key, true))); + break; + case "snap_setting": + App.dispatch(new Action<>(Actions.Settings.SET_SNAP, prefs.getBoolean(key, true))); + break; + case "offset_setting": + App.dispatch(new Action<>(Actions.Settings.SET_OFFSET, getIntSetting(prefs, key, 30))); + break; case "vibration_setting": App.dispatch(new Action<>(Actions.Settings.SET_VIBRATE, prefs.getBoolean(key, false))); break; case "ramping_setting": App.dispatch(new Action<>(Actions.Settings.SET_RAMPING, prefs.getBoolean(key, true))); break; - case "snap_setting": - App.dispatch(new Action<>(Actions.Settings.SET_SNAP, prefs.getBoolean(key, true))); - break; case "ringtone_setting": String s = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM).toString(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M @@ -62,17 +69,22 @@ && checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageMana App.dispatch(new Action<>(Actions.Settings.SET_RINGTONE, prefs.getString(key, s))); break; case "theme_setting": - int themeIndex = 0; - try { - themeIndex = Integer.valueOf(prefs.getString("theme_setting", "0")); - } catch (NumberFormatException e) { - e.printStackTrace(); - } - App.dispatch(new Action<>(Actions.Settings.SET_THEME, themeIndex)); + App.dispatch(new Action<>(Actions.Settings.SET_THEME, getIntSetting(prefs, key, 0))); + recreate(); break; } } + private int getIntSetting(SharedPreferences prefs, String key, int def) { + int value = def; + try { + value = Integer.parseInt(prefs.getString(key, String.valueOf(def))); + } catch (NumberFormatException e) { + Log.w("Talalarmo", e.toString()); + } + return value; + } + public static class SettingsFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { diff --git a/src/main/java/trikita/talalarmo/State.java b/src/main/java/trikita/talalarmo/State.java index f10ac28..a04bac8 100644 --- a/src/main/java/trikita/talalarmo/State.java +++ b/src/main/java/trikita/talalarmo/State.java @@ -24,8 +24,12 @@ interface Settings { boolean snap(); + int offset(); + boolean ramping(); + boolean repeat(); + String ringtone(); int theme(); @@ -69,6 +73,8 @@ public static State build() { .ramping(true) .snap(true) .vibrate(true) + .repeat(false) + .offset(30) .theme(0) .build()) .build(); @@ -87,8 +93,12 @@ State.Settings reduceSettings(Action action, State.Settings settings) { if (action.type instanceof Actions.Settings) { Actions.Settings type = (Actions.Settings) action.type; switch (type) { + case SET_REPEAT: + return ImmutableSettings.copyOf(settings).withRepeat((Boolean) action.value); case SET_RAMPING: return ImmutableSettings.copyOf(settings).withRamping((Boolean) action.value); + case SET_OFFSET: + return ImmutableSettings.copyOf(settings).withOffset((Integer) action.value); case SET_VIBRATE: return ImmutableSettings.copyOf(settings).withVibrate((Boolean) action.value); case SET_SNAP: diff --git a/src/main/java/trikita/talalarmo/alarm/AlarmActivity.java b/src/main/java/trikita/talalarmo/alarm/AlarmActivity.java index 820775a..030c587 100644 --- a/src/main/java/trikita/talalarmo/alarm/AlarmActivity.java +++ b/src/main/java/trikita/talalarmo/alarm/AlarmActivity.java @@ -1,14 +1,20 @@ package trikita.talalarmo.alarm; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.os.PowerManager; +import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; import trikita.anvil.RenderableView; +import trikita.anvil.Anvil; import static trikita.anvil.DSL.*; import trikita.jedux.Action; @@ -19,6 +25,10 @@ public class AlarmActivity extends Activity { private PowerManager.WakeLock mWakeLock; + private ValueAnimator mAnimator; + private int bgColor; + private String txt; + private boolean canceled; @Override protected void onCreate(Bundle b) { @@ -37,15 +47,59 @@ protected void onCreate(Bundle b) { window.setStatusBarColor(Theme.get(App.getState().settings().theme()).primaryDarkColor); } + txt = "\ue857"; // alarm_off icon + int colorFrom = Theme.get(App.getState().settings().theme()).backgroundColor; + int colorTo = Theme.get(App.getState().settings().theme()).accentColor; + bgColor = colorFrom; + mAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); + mAnimator.setDuration(2000); // millis + mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animator) { + bgColor = (int) animator.getAnimatedValue(); + Anvil.render(); + } + }); + mAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + canceled = false; + txt = "\ue913"; // touch_app icon + } + @Override + public void onAnimationCancel(Animator animator) { + canceled = true; + txt = "\ue857"; // alarm_off icon + bgColor = colorFrom; + Anvil.render(); + } + @Override + public void onAnimationEnd(Animator animator) { + if (!canceled) { + stopAlarm(); + } + } + }); + setContentView(new RenderableView(this) { public void view() { Theme.materialIcon(() -> { size(FILL, FILL); - text("\ue857"); // "alarm off" + text(txt); textColor(Theme.get(App.getState().settings().theme()).accentColor); textSize(dip(128)); - backgroundColor(Theme.get(App.getState().settings().theme()).backgroundColor); - onClick(v -> stopAlarm()); + backgroundColor(bgColor); + onTouch((v, e) -> { + if(e.getAction() == MotionEvent.ACTION_DOWN){ + mAnimator.start(); + return true; + } + if(e.getAction() == MotionEvent.ACTION_UP){ + mAnimator.cancel(); + return true; + } + return false; + }); }); } }); @@ -71,6 +125,8 @@ protected void onDestroy() { private void stopAlarm() { App.dispatch(new Action<>(Actions.Alarm.DISMISS)); + if(!App.getState().settings().repeat()) + App.dispatch(new Action<>(Actions.Alarm.OFF)); finish(); } } diff --git a/src/main/java/trikita/talalarmo/alarm/AlarmController.java b/src/main/java/trikita/talalarmo/alarm/AlarmController.java index 2af60fa..3814fe3 100644 --- a/src/main/java/trikita/talalarmo/alarm/AlarmController.java +++ b/src/main/java/trikita/talalarmo/alarm/AlarmController.java @@ -14,6 +14,7 @@ import trikita.jedux.Action; import trikita.jedux.Store; import trikita.talalarmo.Actions; +import trikita.talalarmo.App; import trikita.talalarmo.MainActivity; import trikita.talalarmo.State; @@ -29,7 +30,7 @@ public AlarmController(Context c) { public void dispatch(Store store, Action action, Store.NextDispatcher next) { if (action.type == Actions.Alarm.ON) { Calendar c = Calendar.getInstance(); - c.add(Calendar.MINUTE, 1); + c.add(Calendar.MINUTE, App.getState().settings().offset()); store.dispatch(new Action<>(Actions.Alarm.SET_HOUR, c.get(Calendar.HOUR))); store.dispatch(new Action<>(Actions.Alarm.SET_MINUTE, c.get(Calendar.MINUTE))); store.dispatch(new Action<>(Actions.Alarm.SET_AM_PM, c.get(Calendar.AM_PM) == 0)); @@ -49,7 +50,8 @@ public void dispatch(Store store, Action action, Store.NextDispat break; case DISMISS: dismissAlarm(); - restartAlarm(store.getState()); + if(App.getState().settings().repeat()) + restartAlarm(store.getState()); break; case OFF: cancelAlarm(); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 789ddf4..caf48cc 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -5,6 +5,8 @@ Settings Ringtone Snap to 5 min + Default Alarm Offset + Repeat Alarm Daily Theme Vibrate Fade-in sound diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index 70ecf52..1aab358 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -1,32 +1,36 @@ - + android:defaultValue="false" + android:key="repeat_setting" + android:title="@string/settings_repeat_option" /> + /> + + + android:key="vibration_setting" + android:title="@string/settings_vibration_option" /> + android:defaultValue="true" /> + + android:entryValues="@array/settings_themes_values" />