From 55da0759d45405956764c1f81628bfd97459d50c Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 11 Apr 2017 16:58:35 -0400 Subject: [PATCH 1/7] Bump version --- app/src/main/AndroidManifest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 33ab12704..2a9260417 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,8 +21,8 @@ + android:versionCode="28" + android:versionName="1.7.1"> From 5c8e52264686ac34829984a054259ba1cb217398 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 11 Apr 2017 17:14:25 -0400 Subject: [PATCH 2/7] Fix header labels for RTL languages such as Arabic --- .../habits/list/views/HeaderView.java | 19 +++++++++++++++---- .../isoron/uhabits/utils/InterfaceUtils.java | 8 ++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java index e4863cd54..4eb1f4317 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HeaderView.java @@ -50,8 +50,6 @@ public class HeaderView extends ScrollableChart private RectF rect; - private int maxDataOffset; - public HeaderView(Context context, AttributeSet attrs) { super(context, attrs); @@ -76,7 +74,6 @@ public class HeaderView extends ScrollableChart Resources res = context.getResources(); setScrollerBucketSize((int) res.getDimension(R.dimen.checkmarkWidth)); - setDirection(shouldReverseCheckmarks() ? 1 : -1); StyledResources sr = new StyledResources(context); paint = new TextPaint(); @@ -99,7 +96,7 @@ public class HeaderView extends ScrollableChart @Override public void onCheckmarkOrderChanged() { - setDirection(shouldReverseCheckmarks() ? 1 : -1); + updateDirection(); postInvalidate(); } @@ -112,11 +109,20 @@ public class HeaderView extends ScrollableChart @Override protected void onAttachedToWindow() { + updateDirection(); super.onAttachedToWindow(); if (prefs != null) prefs.addListener(this); if (midnightTimer != null) midnightTimer.addListener(this); } + private void updateDirection() + { + int direction = -1; + if (shouldReverseCheckmarks()) direction *= -1; + if (InterfaceUtils.isLayoutRtl(this)) direction *= -1; + setDirection(direction); + } + @Override protected void onDetachedFromWindow() { @@ -145,6 +151,7 @@ public class HeaderView extends ScrollableChart float width = res.getDimension(R.dimen.checkmarkWidth); float height = res.getDimension(R.dimen.checkmarkHeight); boolean reverse = shouldReverseCheckmarks(); + boolean isRtl = InterfaceUtils.isLayoutRtl(this); day.add(GregorianCalendar.DAY_OF_MONTH, -getDataOffset()); float em = paint.measureText("m"); @@ -153,9 +160,13 @@ public class HeaderView extends ScrollableChart { rect.set(0, 0, width, height); rect.offset(canvas.getWidth(), 0); + if(reverse) rect.offset(- (i + 1) * width, 0); else rect.offset((i - buttonCount) * width, 0); + if (isRtl) rect.set(canvas.getWidth() - rect.right, rect.top, + canvas.getWidth() - rect.left, rect.bottom); + String text = DateUtils.formatHeaderDate(day).toUpperCase(); String[] lines = text.split("\n"); diff --git a/app/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.java b/app/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.java index e22118b2b..8fdc5fc9f 100644 --- a/app/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.java +++ b/app/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.java @@ -22,7 +22,9 @@ package org.isoron.uhabits.utils; import android.content.*; import android.content.res.*; import android.graphics.*; +import android.support.v4.view.*; import android.util.*; +import android.view.*; public abstract class InterfaceUtils { @@ -49,4 +51,10 @@ public abstract class InterfaceUtils DisplayMetrics metrics = resources.getDisplayMetrics(); return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, metrics); } + + public static boolean isLayoutRtl(View view) + { + return ViewCompat.getLayoutDirection(view) == + ViewCompat.LAYOUT_DIRECTION_RTL; + } } From 4c58b084c63f1680efb7962a8a21971ff3487536 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 11 Apr 2017 17:19:18 -0400 Subject: [PATCH 3/7] Fix missing dialog title --- .../isoron/uhabits/activities/habits/edit/BaseDialog.java | 6 ++++++ app/src/main/res/values/styles.xml | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/BaseDialog.java b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/BaseDialog.java index b4c228876..5d2db5a55 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/BaseDialog.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/BaseDialog.java @@ -62,6 +62,12 @@ public abstract class BaseDialog extends AppCompatDialogFragment private ColorPickerDialogFactory colorPickerDialogFactory; + @Override + public int getTheme() + { + return R.style.DialogWithTitle; + } + @Override public void onActivityCreated(Bundle savedInstanceState) { diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index a456262a8..86435f56f 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -256,4 +256,8 @@ + + From 6855ef9d5e23090bd3ac3e518d68c468edae24be Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 11 Apr 2017 17:26:06 -0400 Subject: [PATCH 4/7] Update translations --- app/src/main/res/layout/about.xml | 4 ++++ app/src/main/res/values-hi/strings.xml | 18 +++++++++++++++--- app/src/main/res/values-id/strings.xml | 2 ++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/about.xml b/app/src/main/res/layout/about.xml index 5fe1b1a2f..2869631df 100644 --- a/app/src/main/res/layout/about.xml +++ b/app/src/main/res/layout/about.xml @@ -317,6 +317,10 @@ + + diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 45158aac6..c37f603f3 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -91,6 +91,7 @@ 2 घंटा 4 घंटा 8 घंटा + 24 घंटे टॉगल पुनरावृत्ति हल्का दबाने से \" अधिक सुविधाजनक है, लेकिन आकस्मिक टॉगल हो सकता है ।\" @@ -179,7 +180,7 @@ repetitions की संख्या\" इस फ़ाइल में वापस आयात नहीं किया जा सकता है।\" ऐसी फाइल्स उत्पन्न करता है जिसमे आपका सारा डेटा रहता है इस फ़ाइल को वापस आयात किया जा सकता है। बग रिपोर्ट जनरेट करने मे असफल - बग रिपोर्ट जनरेट करने मे सफल + बग रिपोर्ट जनरेट करें \" समस्या निवारण\" \" @@ -198,15 +199,26 @@ repetitions की संख्या\" तिमाही साल - समय शुरू + समय में \" हर %d दिन\" \" हर %d हफ्ते\" \" -हर %d साल\" +हर %d महीने\" स्कोर अनुस्मारक ध्वनि \" कोई आवाज नहीं\" + फिल्टर + डेटाबेस को रिपेयर करें + डेटाबेस रिपेयर सफल + आदत + सॉर्ट करें + मैन्यूअली + नाम द्वारा + रंग द्वारा + स्कोर से + डाउनलोड + एक्सपोर्ट करे diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index cc808293f..4602cbfd6 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -19,6 +19,7 @@ ~ with this program. If not, see . --> + Loop Habit Tracker Kebiasaan Pengaturan Ubah @@ -73,6 +74,7 @@ 2 jam 4 jam 8 jam + 24 jam Tandai dengan cepat. Lebih nyaman namun memungkinkan kesalahan. Durasi tunda sejenak pada pengingat From 65cc99dbf7bf53d8a292482c60122cc84ef7cce1 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 11 Apr 2017 17:49:55 -0400 Subject: [PATCH 5/7] Switch from View.BaseSavedState to Support Library's AbsSavedState See https://code.google.com/p/android/issues/detail?id=196430 --- .../uhabits/activities/common/views/BundleSavedState.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/isoron/uhabits/activities/common/views/BundleSavedState.java b/app/src/main/java/org/isoron/uhabits/activities/common/views/BundleSavedState.java index 9f61d88f0..fe33993d1 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/common/views/BundleSavedState.java +++ b/app/src/main/java/org/isoron/uhabits/activities/common/views/BundleSavedState.java @@ -20,9 +20,8 @@ package org.isoron.uhabits.activities.common.views; import android.os.*; -import android.view.*; -public class BundleSavedState extends View.BaseSavedState +public class BundleSavedState extends android.support.v4.view.AbsSavedState { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() @@ -51,7 +50,7 @@ public class BundleSavedState extends View.BaseSavedState public BundleSavedState(Parcel source) { super(source); - this.bundle = source.readBundle(); + this.bundle = source.readBundle(getClass().getClassLoader()); } @Override From 0d6ad265054dcf668407acc1ba3211e07c34cda9 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 11 Apr 2017 21:19:03 -0400 Subject: [PATCH 6/7] Ignore exception when habit is not found --- .../uhabits/preferences/WidgetPreferences.java | 3 ++- .../isoron/uhabits/widgets/BaseWidgetProvider.java | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/isoron/uhabits/preferences/WidgetPreferences.java b/app/src/main/java/org/isoron/uhabits/preferences/WidgetPreferences.java index f7830e2ba..56566f639 100644 --- a/app/src/main/java/org/isoron/uhabits/preferences/WidgetPreferences.java +++ b/app/src/main/java/org/isoron/uhabits/preferences/WidgetPreferences.java @@ -23,6 +23,7 @@ import android.content.*; import android.preference.*; import org.isoron.uhabits.*; +import org.isoron.uhabits.models.*; import javax.inject.*; @@ -48,7 +49,7 @@ public class WidgetPreferences public long getHabitIdFromWidgetId(int widgetId) { Long habitId = prefs.getLong(getHabitIdKey(widgetId), -1); - if (habitId < 0) throw new RuntimeException("widget not found"); + if (habitId < 0) throw new HabitNotFoundException(); return habitId; } diff --git a/app/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java b/app/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java index 6c6008d36..e0a188851 100644 --- a/app/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java +++ b/app/src/main/java/org/isoron/uhabits/widgets/BaseWidgetProvider.java @@ -25,6 +25,8 @@ import android.os.*; import android.support.annotation.*; import android.widget.*; +import com.activeandroid.util.*; + import org.isoron.uhabits.*; import org.isoron.uhabits.models.*; import org.isoron.uhabits.preferences.*; @@ -76,8 +78,15 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider for (int id : ids) { - BaseWidget widget = getWidgetFromId(context, id); - widget.delete(); + try + { + BaseWidget widget = getWidgetFromId(context, id); + widget.delete(); + } + catch (HabitNotFoundException e) + { + Log.e("BaseWidgetProvider", e); + } } } From 140ab34a76f7fb8d467c9ada000a1bbab6ea3a13 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Tue, 11 Apr 2017 22:03:16 -0400 Subject: [PATCH 7/7] Verify database version before importing --- .../org/isoron/uhabits/HabitsApplication.java | 13 +++++- .../org/isoron/uhabits/io/LoopDBImporter.java | 41 +++++++++++++------ .../InvalidDatabaseVersionException.java | 24 +++++++++++ .../isoron/uhabits/utils/DatabaseUtils.java | 12 +++++- 4 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/org/isoron/uhabits/models/sqlite/InvalidDatabaseVersionException.java diff --git a/app/src/main/java/org/isoron/uhabits/HabitsApplication.java b/app/src/main/java/org/isoron/uhabits/HabitsApplication.java index bad1c4ee5..8e2e1e8ad 100644 --- a/app/src/main/java/org/isoron/uhabits/HabitsApplication.java +++ b/app/src/main/java/org/isoron/uhabits/HabitsApplication.java @@ -21,10 +21,10 @@ package org.isoron.uhabits; import android.app.*; import android.content.*; -import android.support.annotation.*; import com.activeandroid.*; +import org.isoron.uhabits.models.sqlite.*; import org.isoron.uhabits.notifications.*; import org.isoron.uhabits.preferences.*; import org.isoron.uhabits.tasks.*; @@ -88,7 +88,16 @@ public class HabitsApplication extends Application if (db.exists()) db.delete(); } - DatabaseUtils.initializeActiveAndroid(context); + try + { + DatabaseUtils.initializeActiveAndroid(context); + } + catch (InvalidDatabaseVersionException e) + { + File db = DatabaseUtils.getDatabaseFile(context); + db.renameTo(new File(db.getAbsolutePath() + ".invalid")); + DatabaseUtils.initializeActiveAndroid(context); + } widgetUpdater = component.getWidgetUpdater(); widgetUpdater.startListening(); diff --git a/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java b/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java index a3ebcf882..bfcf5886f 100644 --- a/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/LoopDBImporter.java @@ -19,20 +19,20 @@ package org.isoron.uhabits.io; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.support.annotation.NonNull; +import android.content.*; +import android.database.*; +import android.database.sqlite.*; +import android.support.annotation.*; +import android.util.*; -import com.activeandroid.ActiveAndroid; +import com.activeandroid.*; -import org.isoron.uhabits.AppContext; +import org.isoron.uhabits.*; import org.isoron.uhabits.models.*; import org.isoron.uhabits.utils.DatabaseUtils; -import org.isoron.uhabits.utils.FileUtils; +import org.isoron.uhabits.utils.*; -import java.io.File; -import java.io.IOException; +import java.io.*; import javax.inject.*; @@ -45,7 +45,8 @@ public class LoopDBImporter extends AbstractImporter private Context context; @Inject - public LoopDBImporter(@NonNull @AppContext Context context, @NonNull HabitList habits) + public LoopDBImporter(@NonNull @AppContext Context context, + @NonNull HabitList habits) { super(habits); this.context = context; @@ -59,15 +60,29 @@ public class LoopDBImporter extends AbstractImporter SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getPath(), null, SQLiteDatabase.OPEN_READONLY); + boolean canHandle = true; + Cursor c = db.rawQuery( "select count(*) from SQLITE_MASTER where name=? or name=?", - new String[]{"Checkmarks", "Repetitions"}); + new String[]{ "Checkmarks", "Repetitions" }); + + if (!c.moveToFirst() || c.getInt(0) != 2) + { + Log.w("LoopDBImporter", "Cannot handle file: tables not found"); + canHandle = false; + } - boolean result = (c.moveToFirst() && c.getInt(0) == 2); + if (db.getVersion() > BuildConfig.databaseVersion) + { + Log.w("LoopDBImporter", String.format( + "Cannot handle file: incompatible version: %d > %d", + db.getVersion(), BuildConfig.databaseVersion)); + canHandle = false; + } c.close(); db.close(); - return result; + return canHandle; } @Override diff --git a/app/src/main/java/org/isoron/uhabits/models/sqlite/InvalidDatabaseVersionException.java b/app/src/main/java/org/isoron/uhabits/models/sqlite/InvalidDatabaseVersionException.java new file mode 100644 index 000000000..6fb417cc4 --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/models/sqlite/InvalidDatabaseVersionException.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.models.sqlite; + +public class InvalidDatabaseVersionException extends RuntimeException +{ +} diff --git a/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java b/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java index 5e6d9e97a..4db87a8db 100644 --- a/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java +++ b/app/src/main/java/org/isoron/uhabits/utils/DatabaseUtils.java @@ -25,6 +25,7 @@ import android.support.annotation.*; import com.activeandroid.*; import org.isoron.uhabits.*; +import org.isoron.uhabits.models.sqlite.*; import org.isoron.uhabits.models.sqlite.records.*; import java.io.*; @@ -76,7 +77,16 @@ public abstract class DatabaseUtils RepetitionRecord.class, ScoreRecord.class, StreakRecord.class) .create(); - ActiveAndroid.initialize(dbConfig); + try + { + ActiveAndroid.initialize(dbConfig); + } + catch (RuntimeException e) + { + if(e.getMessage().contains("downgrade")) + throw new InvalidDatabaseVersionException(); + else throw e; + } } @SuppressWarnings("ResultOfMethodCallIgnored")