Allow user to change first day of the week

Closes #421
This commit is contained in:
2019-12-31 13:40:56 -06:00
parent 5cdb9eb9d5
commit 7801c933f0
31 changed files with 283 additions and 108 deletions

View File

@@ -30,6 +30,7 @@ import android.util.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.common.views.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.tasks.*;
import org.isoron.uhabits.utils.*;
@@ -51,6 +52,8 @@ public class HistoryEditorDialog extends AppCompatDialogFragment
private TaskRunner taskRunner;
private Preferences prefs;
public HistoryEditorDialog()
{
this.controller = new Controller() {};
@@ -72,9 +75,11 @@ public class HistoryEditorDialog extends AppCompatDialogFragment
(HabitsApplication) getActivity().getApplicationContext();
habitList = app.getComponent().getHabitList();
taskRunner = app.getComponent().getTaskRunner();
prefs = app.getComponent().getPreferences();
historyChart = new HistoryChart(context);
historyChart.setController(controller);
historyChart.setFirstWeekday(prefs.getFirstWeekday());
if (savedInstanceState != null)
{

View File

@@ -29,6 +29,8 @@ import org.isoron.uhabits.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import java.util.*;
/**
* Dialog that allows the user to pick one or more days of the week.
*/
@@ -59,8 +61,9 @@ public class WeekdayPickerDialog extends AppCompatDialogFragment implements
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder
.setTitle(R.string.select_weekdays)
.setMultiChoiceItems(DateUtils.getLongDayNames(), selectedDays,
this)
.setMultiChoiceItems(DateUtils.getLongWeekdayNames(Calendar.SATURDAY),
selectedDays,
this)
.setPositiveButton(android.R.string.yes, this)
.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
dismiss();

View File

@@ -69,8 +69,11 @@ public class FrequencyChart extends ScrollableChart
@NonNull
private HashMap<Timestamp, Integer[]> frequency;
private int maxFreq;
private int firstWeekday = Calendar.SUNDAY;
public FrequencyChart(Context context)
{
super(context);
@@ -98,6 +101,12 @@ public class FrequencyChart extends ScrollableChart
postInvalidate();
}
public void setFirstWeekday(int firstWeekday)
{
this.firstWeekday = firstWeekday;
postInvalidate();
}
private int getMaxFreq(HashMap<Timestamp, Integer[]> frequency)
{
int maxValue = 1;
@@ -144,7 +153,6 @@ public class FrequencyChart extends ScrollableChart
prevRect.setEmpty();
GregorianCalendar currentDate = DateUtils.getStartOfTodayCalendar();
currentDate.set(Calendar.DAY_OF_MONTH, 1);
currentDate.add(Calendar.MONTH, -nColumns + 2 - getDataOffset());
@@ -193,11 +201,11 @@ public class FrequencyChart extends ScrollableChart
private void drawColumn(Canvas canvas, RectF rect, GregorianCalendar date)
{
Integer values[] = frequency.get(new Timestamp(date));
Integer[] values = frequency.get(new Timestamp(date));
float rowHeight = rect.height() / 8.0f;
prevRect.set(rect);
Integer[] localeWeekdayList = DateUtils.getLocaleWeekdayList();
int[] localeWeekdayList = DateUtils.getWeekdaySequence(firstWeekday);
for (int j = 0; j < localeWeekdayList.length; j++)
{
rect.set(0, 0, baseSize, baseSize);
@@ -233,7 +241,7 @@ public class FrequencyChart extends ScrollableChart
pText.setColor(textColor);
pGrid.setColor(gridColor);
for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT))
for (String day : DateUtils.getShortWeekdayNames(firstWeekday))
{
canvas.drawText(day, rGrid.right - columnWidth,
rGrid.top + rowHeight / 2 + 0.25f * em, pText);

View File

@@ -93,6 +93,8 @@ public class HistoryChart extends ScrollableChart
private boolean isNumerical = false;
private int firstWeekday = Calendar.SUNDAY;
@NonNull
private Controller controller;
@@ -210,6 +212,12 @@ public class HistoryChart extends ScrollableChart
postInvalidate();
}
public void setFirstWeekday(int firstWeekday)
{
this.firstWeekday = firstWeekday;
postInvalidate();
}
protected void initPaints()
{
pTextHeader = new Paint();
@@ -293,7 +301,7 @@ public class HistoryChart extends ScrollableChart
{
float verticalOffset = pTextHeader.getFontSpacing() * 0.4f;
for (String day : DateUtils.getLocaleDayNames(Calendar.SHORT))
for (String day : DateUtils.getShortWeekdayNames(firstWeekday))
{
location.offset(0, columnWidth);
canvas.drawText(day, location.left + headerTextOffset,
@@ -375,7 +383,7 @@ public class HistoryChart extends ScrollableChart
{
float width = 0;
for (String w : DateUtils.getLocaleDayNames(Calendar.SHORT))
for (String w : DateUtils.getShortWeekdayNames(firstWeekday))
width = Math.max(width, pSquareFg.measureText(w));
return width;
@@ -473,7 +481,7 @@ public class HistoryChart extends ScrollableChart
int realWeekday =
DateUtils.getStartOfTodayCalendar().get(Calendar.DAY_OF_WEEK);
todayPositionInColumn =
(7 + realWeekday - baseDate.getFirstDayOfWeek()) % 7;
(7 + realWeekday - firstWeekday) % 7;
baseDate.add(Calendar.DAY_OF_YEAR, -nDays);
baseDate.add(Calendar.DAY_OF_YEAR, -todayPositionInColumn);

View File

@@ -28,6 +28,7 @@ import org.isoron.uhabits.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.common.views.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.tasks.*;
import org.isoron.uhabits.utils.*;
@@ -56,6 +57,9 @@ public class BarCard extends HabitCard
private int bucketSize;
@Nullable
private Preferences prefs;
public BarCard(Context context)
{
super(context);
@@ -84,6 +88,12 @@ public class BarCard extends HabitCard
private void init()
{
Context appContext = getContext().getApplicationContext();
if (appContext instanceof HabitsApplication)
{
HabitsApplication app = (HabitsApplication) appContext;
prefs = app.getComponent().getPreferences();
}
inflate(getContext(), R.layout.show_habit_bar, this);
ButterKnife.bind(this);
boolSpinner.setSelection(1);
@@ -120,8 +130,11 @@ public class BarCard extends HabitCard
{
if (isCanceled()) return;
List<Checkmark> checkmarks;
int firstWeekday = Calendar.SATURDAY;
if (prefs != null) firstWeekday = prefs.getFirstWeekday();
if (bucketSize == 1) checkmarks = habit.getCheckmarks().getAll();
else checkmarks = habit.getCheckmarks().groupBy(getTruncateField(bucketSize));
else checkmarks = habit.getCheckmarks().groupBy(getTruncateField(bucketSize),
firstWeekday);
chart.setCheckmarks(checkmarks);
chart.setBucketSize(bucketSize);
}

View File

@@ -28,6 +28,7 @@ import org.isoron.uhabits.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.common.views.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.tasks.*;
import org.isoron.uhabits.utils.*;
@@ -43,6 +44,9 @@ public class FrequencyCard extends HabitCard
@BindView(R.id.frequencyChart)
FrequencyChart chart;
@Nullable
private Preferences prefs;
public FrequencyCard(Context context)
{
super(context);
@@ -63,6 +67,12 @@ public class FrequencyCard extends HabitCard
private void init()
{
Context appContext = getContext().getApplicationContext();
if (appContext instanceof HabitsApplication)
{
HabitsApplication app = (HabitsApplication) appContext;
prefs = app.getComponent().getPreferences();
}
inflate(getContext(), R.layout.show_habit_frequency, this);
ButterKnife.bind(this);
if (isInEditMode()) initEditMode();
@@ -84,6 +94,7 @@ public class FrequencyCard extends HabitCard
if (isCanceled()) return;
RepetitionList reps = getHabit().getRepetitions();
HashMap<Timestamp, Integer[]> frequency = reps.getWeekdayFrequency();
if(prefs != null) chart.setFirstWeekday(prefs.getFirstWeekday());
chart.setFrequency(frequency);
}

View File

@@ -28,6 +28,7 @@ import org.isoron.uhabits.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.common.views.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.tasks.*;
import org.isoron.uhabits.utils.*;
@@ -41,9 +42,12 @@ public class HistoryCard extends HabitCard
@BindView(R.id.title)
TextView title;
@NonNull
@Nullable
private Controller controller;
@Nullable
private Preferences prefs;
public HistoryCard(Context context)
{
super(context);
@@ -59,16 +63,23 @@ public class HistoryCard extends HabitCard
@OnClick(R.id.edit)
public void onClickEditButton()
{
controller.onEditHistoryButtonClick();
if(controller != null) controller.onEditHistoryButtonClick();
}
public void setController(@NonNull Controller controller)
public void setController(@Nullable Controller controller)
{
this.controller = controller;
}
private void init()
{
Context appContext = getContext().getApplicationContext();
if (appContext instanceof HabitsApplication)
{
HabitsApplication app = (HabitsApplication) appContext;
prefs = app.getComponent().getPreferences();
}
inflate(getContext(), R.layout.show_habit_history, this);
ButterKnife.bind(this);
controller = new Controller() {};
@@ -107,7 +118,8 @@ public class HistoryCard extends HabitCard
public void doInBackground()
{
if (isCanceled()) return;
int checkmarks[] = habit.getCheckmarks().getAllValues();
int[] checkmarks = habit.getCheckmarks().getAllValues();
if(prefs != null) chart.setFirstWeekday(prefs.getFirstWeekday());
chart.setCheckmarks(checkmarks);
}

View File

@@ -143,9 +143,12 @@ public class ScoreCard extends HabitCard
if (isCanceled()) return;
List<Score> scores;
ScoreList scoreList = getHabit().getScores();
int firstWeekday = Calendar.SATURDAY;
if (prefs != null) firstWeekday = prefs.getFirstWeekday();
Log.d("ScoreCard", "firstWeekday="+firstWeekday);
if (bucketSize == 1) scores = scoreList.toList();
else scores = scoreList.groupBy(getTruncateField(bucketSize));
else scores = scoreList.groupBy(getTruncateField(bucketSize), firstWeekday);
chart.setScores(scores);
chart.setBucketSize(bucketSize);

View File

@@ -32,9 +32,12 @@ import org.isoron.uhabits.R;
import org.isoron.uhabits.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.ui.*;
import org.isoron.uhabits.core.utils.*;
import org.isoron.uhabits.notifications.*;
import org.isoron.uhabits.widgets.*;
import java.util.*;
import static android.media.RingtoneManager.*;
import static android.os.Build.VERSION.*;
import static org.isoron.uhabits.activities.habits.list.ListHabitsScreenKt.*;
@@ -143,6 +146,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
devCategory.setVisible(false);
}
updateWeekdayPreference();
if (SDK_INT < Build.VERSION_CODES.O)
findPreference("reminderCustomize").setVisible(false);
else
@@ -154,6 +159,19 @@ public class SettingsFragment extends PreferenceFragmentCompat
updateSync();
}
private void updateWeekdayPreference()
{
if (prefs == null) return;
ListPreference weekdayPref = (ListPreference) findPreference("pref_first_weekday");
int currentFirstWeekday = prefs.getFirstWeekday();
String[] dayNames = DateUtils.getLongWeekdayNames(Calendar.SATURDAY);
String[] dayValues = {"7", "1", "2", "3", "4", "5", "6"};
weekdayPref.setEntries(dayNames);
weekdayPref.setEntryValues(dayValues);
weekdayPref.setDefaultValue(Integer.toString(currentFirstWeekday));
weekdayPref.setSummary(dayNames[currentFirstWeekday % 7]);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key)
@@ -163,6 +181,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
Log.d("SettingsFragment", "updating widgets");
widgetUpdater.updateWidgets();
}
if (key.equals("pref_first_weekday")) updateWeekdayPreference();
BackupManager.dataChanged("org.isoron.uhabits");
updateSync();
}

View File

@@ -41,8 +41,8 @@ public class AndroidDateUtils
public static String formatWeekdayList(Context context, boolean weekday[])
{
String shortDayNames[] = org.isoron.uhabits.core.utils.DateUtils.getShortDayNames();
String longDayNames[] = org.isoron.uhabits.core.utils.DateUtils.getLongDayNames();
String shortDayNames[] = org.isoron.uhabits.core.utils.DateUtils.getShortWeekdayNames(Calendar.SATURDAY);
String longDayNames[] = org.isoron.uhabits.core.utils.DateUtils.getLongWeekdayNames(Calendar.SATURDAY);
StringBuilder buffer = new StringBuilder();
int count = 0;

View File

@@ -40,6 +40,7 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
private HabitList habits;
private Preferences preferences;
private WidgetPreferences widgetPrefs;
public static void updateAppWidget(@NonNull AppWidgetManager manager,
@@ -195,4 +196,9 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider
preferences = app.getComponent().getPreferences();
widgetPrefs = app.getComponent().getWidgetPreferences();
}
public Preferences getPreferences()
{
return preferences;
}
}

View File

@@ -29,7 +29,8 @@ import org.isoron.uhabits.widgets.views.*
class FrequencyWidget(
context: Context,
widgetId: Int,
private val habit: Habit
private val habit: Habit,
private val firstWeekday: Int
) : BaseWidget(context, widgetId) {
override fun getOnClickPendingIntent(context: Context) =
@@ -40,6 +41,7 @@ class FrequencyWidget(
widgetView.setTitle(habit.name)
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
(widgetView.dataView as FrequencyChart).apply {
setFirstWeekday(firstWeekday)
setColor(PaletteUtils.getColor(context, habit.color))
setFrequency(habit.repetitions.weekdayFrequency)
}

View File

@@ -24,7 +24,10 @@ import android.content.*
class FrequencyWidgetProvider : BaseWidgetProvider() {
override fun getWidgetFromId(context: Context, id: Int): BaseWidget {
val habits = getHabitsFromWidgetId(id)
if (habits.size == 1) return FrequencyWidget(context, id, habits[0])
if (habits.size == 1) return FrequencyWidget(context,
id,
habits[0],
preferences.firstWeekday)
else return StackWidget(context, id, StackWidgetType.FREQUENCY, habits)
}
}

View File

@@ -30,7 +30,8 @@ import org.isoron.uhabits.widgets.views.*
class HistoryWidget(
context: Context,
id: Int,
private val habit: Habit
private val habit: Habit,
private val firstWeekday: Int
) : BaseWidget(context, id) {
override fun getOnClickPendingIntent(context: Context): PendingIntent {
@@ -41,6 +42,7 @@ class HistoryWidget(
val widgetView = view as GraphWidgetView
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
(widgetView.dataView as HistoryChart).apply {
setFirstWeekday(firstWeekday)
setColor(PaletteUtils.getColor(context, habit.color))
setCheckmarks(habit.checkmarks.allValues)
}

View File

@@ -23,7 +23,10 @@ import android.content.*
class HistoryWidgetProvider : BaseWidgetProvider() {
override fun getWidgetFromId(context: Context, id: Int): BaseWidget {
val habits = getHabitsFromWidgetId(id)
if (habits.size == 1) return HistoryWidget(context, id, habits[0])
if (habits.size == 1) return HistoryWidget(context,
id,
habits[0],
preferences.firstWeekday)
else return StackWidget(context, id, StackWidgetType.HISTORY, habits)
}
}

View File

@@ -40,7 +40,8 @@ class ScoreWidget(
val size = ScoreCard.BUCKET_SIZES[prefs.defaultScoreSpinnerPosition]
val scores = when(size) {
1 -> habit.scores.toList()
else -> habit.scores.groupBy(ScoreCard.getTruncateField(size))
else -> habit.scores.groupBy(ScoreCard.getTruncateField(size),
prefs.firstWeekday)
}
val widgetView = view as GraphWidgetView

View File

@@ -9,6 +9,7 @@ import android.widget.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.utils.*;
import java.util.*;
@@ -87,18 +88,19 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory
}
@NonNull
private BaseWidget constructWidget(@NonNull Habit habit)
private BaseWidget constructWidget(@NonNull Habit habit,
@NonNull Preferences prefs)
{
switch (widgetType)
{
case CHECKMARK:
return new CheckmarkWidget(context, widgetId, habit);
case FREQUENCY:
return new FrequencyWidget(context, widgetId, habit);
return new FrequencyWidget(context, widgetId, habit, prefs.getFirstWeekday());
case SCORE:
return new ScoreWidget(context, widgetId, habit);
case HISTORY:
return new HistoryWidget(context, widgetId, habit);
return new HistoryWidget(context, widgetId, habit, prefs.getFirstWeekday());
case STREAKS:
return new StreakWidget(context, widgetId, habit);
}
@@ -136,6 +138,7 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory
Log.i("StackRemoteViewsFactory", "onDataSetChanged started");
HabitsApplication app = (HabitsApplication) context.getApplicationContext();
Preferences prefs = app.getComponent().getPreferences();
HabitList habitList = app.getComponent().getHabitList();
Bundle options = AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId);
ArrayList<RemoteViews> newRemoteViews = new ArrayList<>();
@@ -147,7 +150,7 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory
Habit h = habitList.getById(id);
if (h == null) throw new HabitNotFoundException();
BaseWidget widget = constructWidget(h);
BaseWidget widget = constructWidget(h, prefs);
widget.setDimensions(getDimensionsFromOptions(context, options));
RemoteViews landscapeViews = widget.getLandscapeRemoteViews();

View File

@@ -242,5 +242,6 @@
<string name="database">Database</string>
<string name="widget_opacity_title">Widget opacity</string>
<string name="widget_opacity_description">Makes widgets more transparent or more opaque in your home screen.</string>
<string name="first_day_of_the_week">First day of the week</string>
</resources>

View File

@@ -55,6 +55,11 @@
android:title="@string/widget_opacity_title"
app:iconSpaceReserved="false" />
<ListPreference
android:key="pref_first_weekday"
android:title="@string/first_day_of_the_week"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory