diff --git a/CHANGELOG.md b/CHANGELOG.md index e98a9e609..e30699b10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +### 1.5.4 (May 29, 2016) + +* Fix crash upon opening settings screen in some phones +* Fix missing folders in CSV archive +* Add Serbian translation + ### 1.5.3 (May 22, 2016) * Complete Arabic and Czech translations diff --git a/app/src/androidTest/java/org/isoron/uhabits/unit/models/HabitTest.java b/app/src/androidTest/java/org/isoron/uhabits/unit/models/HabitTest.java index 007ccd060..265cd80f1 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/unit/models/HabitTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/unit/models/HabitTest.java @@ -366,9 +366,9 @@ public class HabitTest extends BaseAndroidTest HabitFixtures.createShortHabit(); String expectedCSV = - "Name,Description,NumRepetitions,Interval,Color\n" + - "Meditate,Did you meditate this morning?,1,1,#AFB42B\n" + - "Wake up early,Did you wake up before 6am?,2,3,#00897B\n"; + "Position,Name,Description,NumRepetitions,Interval,Color\n" + + "001,Meditate,Did you meditate this morning?,1,1,#AFB42B\n" + + "002,Wake up early,Did you wake up before 6am?,2,3,#00897B\n"; StringWriter writer = new StringWriter(); Habit.writeCSV(Habit.getAll(true), writer); diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 055cae918..940b19bde 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,8 +21,8 @@ + android:versionCode="20" + android:versionName="1.5.4"> diff --git a/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java b/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java index 6ae20f8fc..0a3a80e26 100644 --- a/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/HabitsCSVExporter.java @@ -19,10 +19,12 @@ package org.isoron.uhabits.io; -import org.isoron.uhabits.utils.DateUtils; +import android.support.annotation.NonNull; + import org.isoron.uhabits.models.CheckmarkList; import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.models.ScoreList; +import org.isoron.uhabits.utils.DateUtils; import java.io.File; import java.io.FileInputStream; @@ -64,7 +66,10 @@ public class HabitsCSVExporter for(Habit h : habits) { - String habitDirName = String.format("%03d %s/", h.position + 1, h.name); + String sane = sanitizeFilename(h.name); + String habitDirName = String.format("%03d %s", h.position + 1, sane); + habitDirName = habitDirName.trim() + "/"; + new File(exportDirName + habitDirName).mkdirs(); generateDirs.add(habitDirName); @@ -73,6 +78,13 @@ public class HabitsCSVExporter } } + @NonNull + private String sanitizeFilename(String name) + { + String s = name.replaceAll("[^ a-zA-Z0-9\\._-]+", ""); + return s.substring(0, Math.min(s.length(), 100)); + } + private void writeScores(String habitDirName, ScoreList scores) throws IOException { String path = habitDirName + "Scores.csv"; diff --git a/app/src/main/java/org/isoron/uhabits/models/Habit.java b/app/src/main/java/org/isoron/uhabits/models/Habit.java index 8752fbb1f..3d4066823 100644 --- a/app/src/main/java/org/isoron/uhabits/models/Habit.java +++ b/app/src/main/java/org/isoron/uhabits/models/Habit.java @@ -498,7 +498,7 @@ public class Habit extends Model */ public static void writeCSV(List habits, Writer out) throws IOException { - String header[] = { "Name", "Description", "NumRepetitions", "Interval", "Color" }; + String header[] = { "Position", "Name", "Description", "NumRepetitions", "Interval", "Color" }; CSVWriter csv = new CSVWriter(out); csv.writeNext(header, false); @@ -507,6 +507,7 @@ public class Habit extends Model { String[] cols = { + String.format("%03d", habit.position + 1), habit.name, habit.description, Integer.toString(habit.freqNum), diff --git a/app/src/main/java/org/isoron/uhabits/ui/settings/SettingsFragment.java b/app/src/main/java/org/isoron/uhabits/ui/settings/SettingsFragment.java index 93aa9af80..b5f9e0d72 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/settings/SettingsFragment.java +++ b/app/src/main/java/org/isoron/uhabits/ui/settings/SettingsFragment.java @@ -142,6 +142,7 @@ public class SettingsFragment extends PreferenceFragmentCompat private void updateRingtoneDescription() { String ringtoneName = ReminderUtils.getRingtoneName(getContext()); + if(ringtoneName == null) return; Preference ringtonePreference = findPreference("reminderSound"); ringtonePreference.setSummary(ringtoneName); } diff --git a/app/src/main/java/org/isoron/uhabits/utils/ReminderUtils.java b/app/src/main/java/org/isoron/uhabits/utils/ReminderUtils.java index 22abd0859..43d07c3f0 100644 --- a/app/src/main/java/org/isoron/uhabits/utils/ReminderUtils.java +++ b/app/src/main/java/org/isoron/uhabits/utils/ReminderUtils.java @@ -144,21 +144,30 @@ public abstract class ReminderUtils fragment.startActivityForResult(intent, requestCode); } + @Nullable public static String getRingtoneName(Context context) { - Uri ringtoneUri = getRingtoneUri(context); - String ringtoneName = context.getResources().getString(R.string.none); - - if(ringtoneUri != null) + try { - Ringtone ringtone = RingtoneManager.getRingtone(context, ringtoneUri); - if(ringtone != null) + Uri ringtoneUri = getRingtoneUri(context); + String ringtoneName = context.getResources().getString(R.string.none); + + if (ringtoneUri != null) { - ringtoneName = ringtone.getTitle(context); - ringtone.stop(); + Ringtone ringtone = RingtoneManager.getRingtone(context, ringtoneUri); + if (ringtone != null) + { + ringtoneName = ringtone.getTitle(context); + ringtone.stop(); + } } - } - return ringtoneName; + return ringtoneName; + } + catch (RuntimeException e) + { + e.printStackTrace(); + return null; + } } } diff --git a/app/src/main/res/layout/about.xml b/app/src/main/res/layout/about.xml index 47fd5ea92..0308cd4c6 100644 --- a/app/src/main/res/layout/about.xml +++ b/app/src/main/res/layout/about.xml @@ -180,6 +180,10 @@ style="@style/About.Item" android:text="Robin (Svenska)"/> + + diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml new file mode 100644 index 000000000..ad03fd5f2 --- /dev/null +++ b/app/src/main/res/values-sr/strings.xml @@ -0,0 +1,180 @@ + + + "Loop – праћење навика" + "Навике" + "Поставке" + "Уреди" + "Обриши" + "Архивирај" + "Врати из архива" + "Додај навику" + "Промена боје" + "Навика је створена." + "Навике су обрисане." + "Навике су враћене." + "Нема шта да се опозове." + "Нема шта да се понови." + "Навика је промењена." + + + "Навика је враћена." + "Навике су архивиране." + "Навике су враћене из архива." + "Преглед" + "Снага навике" + "Историја" + "Очисти" + "Питање (нпр. „Да ли сте трчали данас?)" + + + "Понови" + "пута у" + "дана" + "Подсетник" + "Одбаци" + "Сачувај" + + + "Низови" + "Немате активних навика." + "Притисните и држите да бисте маркирали или демаркирали." + "искључен" + "Име не може бити празно." + "Број мора бити позитиван." + "Можете имати највише једно понављање на дан." + "Стварање навике" + "Уређивање навике" + "Маркирај" + "Касније" + + + "Добро дошли" + "Loop вам помаже да створите и одржавате здраве навике." + "Створите нове навике" + "Сваког дана, након што обавите навику, означите поље у апликацији." + "Будите истрајни" + "Навике којих се доследно придржавате дужи период биће означене пуном звездом." + "Пратите свој напредак" + "Детаљни графикони показују вам колико су се ваше навике временом побољшале." + "15 минута" + "30 минута" + "1 сат" + "2 сата" + "4 сата" + "8 сати" + "Маркирај кратким додиром" + "Практичније, али може доћи до случајног маркирања." + "Одлагање подсетника" + "Оцени апликацију" + "Повратне информације" + "Изворни кôд на GitHub-у" + "Увод апликације" + "Везе" + "Понашање" + "Име" + "Прикажи архивиране" + "Поставке" + "Време одлагања" + "Да ли сте знали?" + "Притисните и држите име навике да бисте је прераспоредили." + "Положите уређај да бисте видели више дана." + "Брисање навика" + "Навике ће бити трајно обрисане. Ова радња је неповратна." + "викендом" + "понедељак–петак" + "сваког дана" + "Избор дана" + "Извези као CSV" + "Готово" + "Очисти" + "Избор часова" + "Избор минута" + + + "Створите здраве навике и пратите напредак (без огласа)." + "Loop вам помаже да створите и одржавате здраве навике, самим тим и да достигнете дугорочне циљеве. Детаљна статистика и графикони показују вам колико су се ваше навике временом побољшале. Апликација је отвореног кода и не садржи огласе." +"<b>Једноставан, леп и модеран дизајн</b> +Loop има минималистички интерфејс који је једноставан за коришћење и прати смернице за материјални дизајн." +"<b>Оцена навике</b> +Поред приказа тренутног низа, Loop поседује напредни алгоритам за израчунавање снаге ваших навика. Ваша навика са сваким понављањем постаје јача, а са сваким пропуштеним даном слабија. Неколико пропуштених дана након дугог низа, пак, неће у потпуности упропастити ваш резултат." +"<b>Детаљни графикони и статистика</b> +Пратите свој напредак уз лепе и детаљне графиконе. Вратите се уназад да бисте видели целу историју навика." +"<b>Флексибилни распоред</b> +Подржава како дневне навике, тако и оне са сложенијим понављањем (трипут недељно, једанпут сваке друге недеље, сваки други дан и сл.)." +"<b>Подсетници</b> +Направите појединачни подсетник за сваку навику у жељено доба дана. С лакоћом маркирајте, одложите или откажите навику директно из обавештења, без отварања апликације." +"<b>У потпуности отвореног кода и без огласа</b> +Апликација не садржи никакве огласе, досадна обавештења или наметљиве дозволе; никада и неће. Изворни кôд је у целости доступан под лиценцом GPLv3." +"<b>Оптимизовано за паметне сатове</b> +Навике можете маркирати, одложити или отказати директно помоћу Android Wear сата." + "О апликацији" + "Преводиоци" + "Програмери" + + + "Верзија %s" + "Учесталост" + "Штрикла" + + + "Снага" + "Најбољи низови" + "Тренутни низ" + "Број понављања" + "посл. %d дана" + "посл. %d нед." + "посл. %d мес." + "посл. %d год." + + + "одувек" + "сваког дана" + "сваке недеље" + "2 пута недељно" + "5 пута недељно" + "прилагоди…" + "Помоћ" + "Не могу да извезем податке." + "Не могу да увезем податке." + + + "Датотека није препозната." + "Резервна копија је враћена." + "Направљена је резервна копија." + "Врати резервну копију" + "Направи резервну копију" + "Поред матичног формата, апликација подржава и увоз датотека које је направио Tickmate, HabitBull и Rewire. Детаљније у ЧПП." + "Направите датотеку коју можете отворити у програму за рад са табелама (нпр. Microsoft Excel или OpenOffice Calc). Њу не можете да увезете назад у апликацију." + "Направите датотеку са свим подацима апликације. Њу касније можете да увезете." + "Не могу да направим извештај о грешци." + "Направи извештај о грешци" + "Решавање проблема" + "Помоћ у преводу" + "Ноћни режим" + "Чиста црна у ноћном режиму" + "Замењује сиву позадину са чистом црном у ноћном режиму. Смањује потрошњу батерије код телефона са AMOLED екраном." + "Интерфејс" + "Обрнути редослед дана" + "Прикажите дане у обрнутом редоследу на главном екрану." + "дан" + "недеља" + "месец" + + + "тромесечје" + "година" + + + + "пут у" + "Сваких %d дана" + "Сваких %d недеља" + "Сваких %d месеци" + + + "снага" + "Звук подсетника" + + + "Без звука" + \ No newline at end of file