├── settings.gradle ├── app ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── dimensions.xml │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── drawable │ │ │ │ ├── ic_add_white_18dp.xml │ │ │ │ ├── ic_done_white_24dp.xml │ │ │ │ ├── ic_navigate_before_white_24dp.xml │ │ │ │ ├── ic_break.xml │ │ │ │ ├── ic_study.xml │ │ │ │ ├── hour_block_grey_rounded_bg.xml │ │ │ │ ├── green.xml │ │ │ │ ├── ic_list_white_24dp.xml │ │ │ │ ├── circle_lime.xml │ │ │ │ ├── circle_red.xml │ │ │ │ ├── circle_teal.xml │ │ │ │ ├── ic_rest.xml │ │ │ │ ├── circle_brown.xml │ │ │ │ ├── circle_green.xml │ │ │ │ ├── circle_mauve.xml │ │ │ │ ├── circle_dark_blue.xml │ │ │ │ ├── circle_burnt_orange.xml │ │ │ │ ├── circle_light_blue.xml │ │ │ │ ├── input_box_style.xml │ │ │ │ ├── ic_free_time.xml │ │ │ │ ├── ic_work.xml │ │ │ │ ├── ic_exercise.xml │ │ │ │ ├── ic_eat.xml │ │ │ │ ├── ic_shop.xml │ │ │ │ ├── ic_bhavana.xml │ │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ │ ├── activity_day.xml │ │ │ │ ├── activity_tasks.xml │ │ │ │ ├── activity_manage_hour.xml │ │ │ │ ├── activity_manage_task.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── fragment_day_view.xml │ │ │ │ ├── view_hour_block.xml │ │ │ │ ├── spinner_icon_item.xml │ │ │ │ ├── spinner_icon_dropdown_item.xml │ │ │ │ ├── toolbar_tasks.xml │ │ │ │ ├── toolbar_hour_view.xml │ │ │ │ ├── toolbar_manage_task.xml │ │ │ │ ├── toolbar_day_view.xml │ │ │ │ ├── fragment_tasks.xml │ │ │ │ ├── view_half_hour_task.xml │ │ │ │ ├── view_full_hour_task.xml │ │ │ │ ├── view_quarter_hour_task.xml │ │ │ │ ├── view_quarter_hour_toggle.xml │ │ │ │ ├── list_item_task.xml │ │ │ │ ├── fragment_hour_view.xml │ │ │ │ ├── list_item_day_view_full_hour.xml │ │ │ │ ├── fragment_manage_task.xml │ │ │ │ ├── view_color_picker_sheet.xml │ │ │ │ ├── list_item_day_view_quarter_three_quarter.xml │ │ │ │ ├── list_item_day_view_half_and_half.xml │ │ │ │ └── list_item_day_view_three_quarter_quarter.xml │ │ │ └── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── wiseassblog │ │ │ │ └── samsaradayplanner │ │ │ │ ├── ui │ │ │ │ ├── dayview │ │ │ │ │ ├── DayViewUpdate.java │ │ │ │ │ ├── LIST_ITEM_TYPE.java │ │ │ │ │ ├── IDayViewContract.java │ │ │ │ │ ├── DayViewEvent.java │ │ │ │ │ ├── buildlogic │ │ │ │ │ │ └── DayViewInjector.java │ │ │ │ │ ├── DayActivity.java │ │ │ │ │ ├── DayViewModel.java │ │ │ │ │ ├── DayListItemView.java │ │ │ │ │ ├── DayViewLogic.java │ │ │ │ │ └── DayView.java │ │ │ │ ├── managehourview │ │ │ │ │ ├── ToggleHourView.java │ │ │ │ │ ├── HourViewModel.java │ │ │ │ │ ├── IHourContract.java │ │ │ │ │ ├── buildlogic │ │ │ │ │ │ └── HourViewInjector.java │ │ │ │ │ ├── HourActivity.java │ │ │ │ │ ├── HourViewEvent.java │ │ │ │ │ ├── HourToggleView.java │ │ │ │ │ └── HourView.java │ │ │ │ ├── tasklistview │ │ │ │ │ ├── TaskListViewModel.java │ │ │ │ │ ├── ITaskListViewContract.java │ │ │ │ │ ├── TasksListViewEvent.java │ │ │ │ │ ├── buildlogic │ │ │ │ │ │ └── TaskListViewInjector.java │ │ │ │ │ ├── TaskGridItemView.java │ │ │ │ │ ├── TaskGridItemViewMaker.java │ │ │ │ │ ├── TaskListActivity.java │ │ │ │ │ ├── TaskListViewLogic.java │ │ │ │ │ ├── TaskGridItemViewAdapter.java │ │ │ │ │ └── TaskListView.java │ │ │ │ └── managetaskview │ │ │ │ │ ├── TaskViewModel.java │ │ │ │ │ ├── ITaskViewContract.java │ │ │ │ │ ├── TaskViewEvent.java │ │ │ │ │ ├── buildlogic │ │ │ │ │ └── TaskViewInjector.java │ │ │ │ │ ├── IconSpinnerItem.java │ │ │ │ │ ├── IconSpinnerAdapter.java │ │ │ │ │ ├── TaskActivity.java │ │ │ │ │ ├── ColorPickerView.java │ │ │ │ │ └── TaskViewLogic.java │ │ │ │ ├── domain │ │ │ │ ├── constants │ │ │ │ │ ├── HOUR_MODE.java │ │ │ │ │ ├── QUARTER.java │ │ │ │ │ ├── Extras.java │ │ │ │ │ ├── BASIC_TASKS.java │ │ │ │ │ ├── COLOR.java │ │ │ │ │ └── ICON.java │ │ │ │ ├── ITaskStorage.java │ │ │ │ ├── Tasks.java │ │ │ │ ├── IDayStorage.java │ │ │ │ ├── Hour.java │ │ │ │ ├── QuarterHour.java │ │ │ │ ├── Task.java │ │ │ │ └── Day.java │ │ │ │ ├── common │ │ │ │ ├── Continuation.java │ │ │ │ ├── Messages.java │ │ │ │ ├── Subscriber.java │ │ │ │ ├── BaseViewLogic.java │ │ │ │ ├── Publisher.java │ │ │ │ ├── IconUtility.java │ │ │ │ ├── ColorUtility.java │ │ │ │ └── TimeFormatUtility.java │ │ │ │ ├── SamsaraApp.java │ │ │ │ ├── ApplicationExecutors.java │ │ │ │ └── StorageServiceLocator.java │ │ └── AndroidManifest.xml │ └── test │ │ └── java │ │ └── com │ │ └── wiseassblog │ │ └── samsaradayplanner │ │ ├── FakeTaskStorage.java │ │ ├── FakeDayStorage.java │ │ ├── TestData.java │ │ ├── TaskListTests.java │ │ └── DayViewTests.java ├── proguard-rules.pro └── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew.bat └── gradlew /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name='SamsaraDayPlanner' 2 | include ':app' 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BracketCove/SamsaraDayPlanner/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/DayViewUpdate.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview; 2 | 3 | enum DayViewUpdate { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/constants/HOUR_MODE.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain.constants; 2 | 3 | 4 | public enum HOUR_MODE { 5 | TWELVE_HOUR, 6 | TWENTY_FOUR_HOUR 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/constants/QUARTER.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain.constants; 2 | 3 | public enum QUARTER { 4 | ZERO, 5 | FIFTEEN, 6 | THIRTY, 7 | FOURTY_FIVE 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/common/Continuation.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.common; 2 | 3 | public interface Continuation { 4 | public void onSuccess(T result); 5 | 6 | public void onException(Exception e); 7 | } 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Oct 13 06:30:35 PDT 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/constants/Extras.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain.constants; 2 | 3 | public class Extras { 4 | public static final String EXTRA_HOUR_INTEGER = "EXTRA_HOUR"; 5 | public static final String EXTRA_TASK_ID = "EXTRA_TASK_ID"; 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/constants/BASIC_TASKS.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain.constants; 2 | 3 | enum BASIC_TASKS { 4 | FREE_TIME, 5 | BREAK, 6 | STUDY, 7 | WORK, 8 | EXERCISE, 9 | MEDITATE, 10 | EAT, 11 | SLEEP, 12 | SHOP 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SamsaraDayPlanner 3 | Manage Task 4 | Tasks 5 | Manage Hour 6 | Day View 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/common/Messages.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.common; 2 | 3 | 4 | public class Messages { 5 | //static data is data associated with a class instead of an object 6 | public static final String GENERIC_ERROR_MESSAGE = "An error has occurred!"; 7 | 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/constants/COLOR.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain.constants; 2 | 3 | import java.io.Serializable; 4 | 5 | public enum COLOR { 6 | DARK_BLUE, 7 | BURNT_ORANGE, 8 | GREEN, 9 | DARK_RED, 10 | DARK_LIME, 11 | LIGHT_BLUE, 12 | MAUVE, 13 | BROWN, 14 | TEAL 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_white_18dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_day.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_done_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_navigate_before_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_tasks.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_break.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_study.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_manage_hour.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/hour_block_grey_rounded_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/green.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_list_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_lime.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_red.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_teal.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_rest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/common/Subscriber.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.common; 2 | 3 | public interface Subscriber { 4 | 5 | public void onUpdateString(EVENT e, String s); 6 | 7 | public void onUpdateInt(EVENT e, int i); 8 | 9 | public void onUpdateBool(EVENT e, boolean b); 10 | 11 | /** 12 | * Use with caution. 13 | */ 14 | public void onUpdateObject(EVENT e, Object o); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_brown.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_green.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_mauve.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/ITaskStorage.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain; 2 | 3 | import com.wiseassblog.samsaradayplanner.common.Continuation; 4 | 5 | public interface ITaskStorage { 6 | public void getTasks(Continuation continuation); 7 | 8 | public void getTask(int taskId, Continuation continuation); 9 | 10 | public void updateTask(Task task, Continuation continuation); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_dark_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_burnt_orange.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle_light_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_manage_task.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managehourview/ToggleHourView.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managehourview; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | 7 | import androidx.annotation.Nullable; 8 | 9 | class ToggleHourView extends View { 10 | public ToggleHourView(Context context, @Nullable AttributeSet attrs) { 11 | super(context, attrs); 12 | 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/constants/ICON.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain.constants; 2 | 3 | /** 4 | * Represent all icons the user can select from. 5 | * 6 | * NOTE: IF YOU UPDATE THIS ENUM, YOU MUST ALSO UPDATE THE STATIC FINAL CONSTANT IconSpinnerItem!!! 7 | */ 8 | public enum ICON { 9 | FREE_TIME, 10 | BREAK, 11 | STUDY, 12 | WORK, 13 | EXERCISE, 14 | MENTAL_CULTIVATION, 15 | EAT, 16 | SLEEP, 17 | SHOP 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/input_box_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_free_time.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/SamsaraApp.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner; 2 | 3 | import android.app.Application; 4 | 5 | public class SamsaraApp extends Application { 6 | 7 | private StorageServiceLocator locator; 8 | 9 | @Override 10 | public void onCreate() { 11 | super.onCreate(); 12 | 13 | locator = new StorageServiceLocator(this); 14 | } 15 | 16 | public StorageServiceLocator getServiceLocator() { 17 | return locator; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/TaskListViewModel.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 4 | 5 | public class TaskListViewModel implements ITaskListViewContract.ViewModel { 6 | 7 | private Tasks tasks; 8 | 9 | @Override 10 | public void setTasks(Tasks tasks) { 11 | this.tasks = tasks; 12 | } 13 | 14 | @Override 15 | public Tasks getTasks() { 16 | return this.tasks; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_work.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managetaskview/TaskViewModel.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managetaskview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Task; 4 | 5 | /** 6 | * A data store (cache) for front end session data 7 | */ 8 | public class TaskViewModel implements ITaskViewContract.ViewModel { 9 | private Task task; 10 | 11 | @Override 12 | public void setTask(Task task) { 13 | this.task = task; 14 | } 15 | 16 | @Override 17 | public Task getTask() { 18 | return this.task; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/ITaskListViewContract.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 4 | 5 | public interface ITaskListViewContract { 6 | interface View { 7 | void setTasks(Tasks tasks); 8 | void showMessage(String message); 9 | void navigateToDayView(); 10 | void navigateToTaskView(int taskId); 11 | } 12 | 13 | interface ViewModel { 14 | void setTasks(Tasks tasks); 15 | Tasks getTasks(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_exercise.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_eat.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/LIST_ITEM_TYPE.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview; 2 | 3 | /** 4 | * 0 - Full Hour 5 | * 1 - Half Half 6 | * 2 - Quarter Quarter Half 7 | * 3 - Quarter Half Quarter 8 | * 4 - Half Quarter Quarter 9 | * 5 - Quarter Quarter Quarter Quarter 10 | */ 11 | public enum LIST_ITEM_TYPE { 12 | FULL_HOUR, 13 | HALF_HALF, 14 | QUARTER_QUARTER_HALF, 15 | QUARTER_HALF_QUARTER, 16 | HALF_QUARTER_QUARTER, 17 | QUARTER_THREE_QUARTER, 18 | THREE_QUARTER_QUARTER, 19 | QUARTER_QUARTER_QUARTER_QUARTER 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #333333 4 | #121212 5 | #BB86FC 6 | 7 | 8 | #1A237E 9 | #D84315 10 | #388E3C 11 | #B71C1C 12 | #827717 13 | #0288D1 14 | #BA68C8 15 | #795548 16 | #00897B 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shop.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/IDayViewContract.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Day; 4 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 5 | 6 | public interface IDayViewContract { 7 | interface View { 8 | void setData(Day day, Tasks tasks); 9 | void navigateToHourView(int hourInteger); 10 | void navigateToTasksView(); 11 | void showMessage(String message); 12 | void restartFeature(); 13 | } 14 | 15 | interface ViewModel { 16 | void setDay(Day day); 17 | Day getDay(); 18 | void setTasks(Tasks tasks); 19 | Tasks getTasks(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/TasksListViewEvent.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview; 2 | 3 | public class TasksListViewEvent { 4 | private final TasksListViewEvent.Event event; 5 | private final Object value; 6 | 7 | public TasksListViewEvent(TasksListViewEvent.Event event, Object value){ 8 | this.event = event; 9 | this.value = value; 10 | } 11 | 12 | public TasksListViewEvent.Event getEvent() { 13 | return event; 14 | } 15 | 16 | public Object getValue() { 17 | return value; 18 | } 19 | 20 | public enum Event { 21 | ON_LIST_ITEM_SELECTED, 22 | ON_START, 23 | ON_BACK_PRESSED 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/DayViewEvent.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview; 2 | 3 | /** 4 | * It models interactions between the View and the Logic class 5 | */ 6 | public class DayViewEvent { 7 | 8 | private final Event event; 9 | private final Object value; 10 | 11 | public DayViewEvent(Event event, Object value){ 12 | this.event = event; 13 | this.value = value; 14 | } 15 | 16 | public Event getEvent() { 17 | return event; 18 | } 19 | 20 | public Object getValue() { 21 | return value; 22 | } 23 | 24 | public enum Event { 25 | ON_START, 26 | ON_HOUR_SELECTED, 27 | ON_MANAGE_TASKS_SELECTED 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/Tasks.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Collections of tasks to make reads/writes easier 7 | * 8 | * See JavaDoc comments in "Day.java" for an explanation of why I am using 9 | * Serializable instead of Parcelable. 10 | */ 11 | public class Tasks implements Serializable { 12 | private final Task[] tasks; 13 | 14 | public Tasks(Task[] tasks) { 15 | this.tasks = tasks; 16 | } 17 | 18 | public Task[] get() { 19 | return tasks; 20 | } 21 | 22 | public Task getTaskById(int taskId) { 23 | for (Task task : tasks) { 24 | if (task.getTaskId() == taskId) return task; 25 | } 26 | 27 | return null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managehourview/HourViewModel.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managehourview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Hour; 4 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 5 | 6 | public class HourViewModel implements IHourContract.ViewModel { 7 | private Hour hour; 8 | private Tasks tasks; 9 | 10 | @Override 11 | public void setHour(Hour hour) { 12 | this.hour = hour; 13 | } 14 | 15 | @Override 16 | public Hour getHour() { 17 | return this.hour; 18 | } 19 | 20 | @Override 21 | public void setTaskList(Tasks tasks) { 22 | this.tasks = tasks; 23 | } 24 | 25 | @Override 26 | public Tasks getTasks() { 27 | return this.tasks; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bhavana.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managetaskview/ITaskViewContract.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managetaskview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Task; 4 | import com.wiseassblog.samsaradayplanner.domain.constants.COLOR; 5 | import com.wiseassblog.samsaradayplanner.domain.constants.ICON; 6 | 7 | public interface ITaskViewContract { 8 | interface View { 9 | void showColorPickerSheet(); 10 | void hideColorPickerSheet(); 11 | void setName(String name); 12 | String getName(); 13 | void setIconSelection(ICON icon); 14 | void setSelectedSpinnerItem(int position); 15 | void setButtonColor(COLOR c); 16 | void goToTaskListActivity(); 17 | void showMessage(String message); 18 | } 19 | 20 | interface ViewModel { 21 | void setTask(Task task); 22 | Task getTask(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managetaskview/TaskViewEvent.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managetaskview; 2 | 3 | /** 4 | * It models interactions between the View and the Logic class 5 | */ 6 | public class TaskViewEvent { 7 | 8 | private final Event event; 9 | private final Object value; 10 | 11 | public TaskViewEvent(Event event, Object value){ 12 | this.event = event; 13 | this.value = value; 14 | } 15 | 16 | public Event getEvent() { 17 | return event; 18 | } 19 | 20 | public Object getValue() { 21 | return value; 22 | } 23 | 24 | /** 25 | * NOTE: ON_START expects a taskID to be sent in as the value 26 | */ 27 | public enum Event { 28 | ON_COLOR_BUTTON_CLICK, 29 | ON_COLOR_SELECTED, 30 | ON_DONE_CLICK, 31 | ON_ICON_SELECTED, 32 | ON_START 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/common/BaseViewLogic.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.common; 2 | 3 | /** 4 | * Base class for ViewLogic classes, which are similar in nature to Presenters or Controllers. 5 | * 6 | * 7 | * 8 | * @param Expected to be a ViewEvent class for a given feature. This pattern helps to organize 9 | * communication between the View and the ViewLogic, and gives the ViewLogic class a 10 | * single primary entry point to test most of its methods. 11 | * 12 | */ 13 | public abstract class BaseViewLogic { 14 | 15 | private boolean isCancelled = false; 16 | 17 | /** 18 | * If the View indicates that it is to be destroyed, we want to inform the Logic class 19 | * so that it can avoid calling back to a null fragment/activity. 20 | */ 21 | public void onCancel(){ 22 | isCancelled = true; 23 | } 24 | 25 | public abstract void onViewEvent(T event); 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managehourview/IHourContract.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managehourview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Hour; 4 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 5 | import com.wiseassblog.samsaradayplanner.domain.constants.QUARTER; 6 | 7 | public interface IHourContract { 8 | interface View { 9 | void setQuarterHourText(QUARTER quarter, String hour); 10 | void setQuarterHourAdapterData(QUARTER quarter, String[] taskNames, int startingPosition); 11 | void setQuarterHourActive(QUARTER quarter, boolean isActive); 12 | void setListeners(); 13 | void navigateToDayView(); 14 | void showMessage(String message); 15 | void setQuarterHour(QUARTER q); 16 | } 17 | 18 | interface ViewModel { 19 | void setHour(Hour hour); 20 | Hour getHour(); 21 | void setTaskList(Tasks tasks); 22 | Tasks getTasks(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/buildlogic/DayViewInjector.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview.buildlogic; 2 | 3 | import com.wiseassblog.samsaradayplanner.StorageServiceLocator; 4 | import com.wiseassblog.samsaradayplanner.ui.dayview.DayView; 5 | import com.wiseassblog.samsaradayplanner.ui.dayview.DayViewLogic; 6 | import com.wiseassblog.samsaradayplanner.ui.dayview.DayViewModel; 7 | import com.wiseassblog.samsaradayplanner.ui.dayview.IDayViewContract; 8 | 9 | public class DayViewInjector { 10 | public static void build( 11 | DayView view, 12 | StorageServiceLocator locator 13 | ) { 14 | IDayViewContract.ViewModel vm = new DayViewModel(); 15 | 16 | view.setLogic( 17 | new DayViewLogic( 18 | view, 19 | vm, 20 | locator.getDayStorageImpl(), 21 | locator.getTaskStorageImpl() 22 | ) 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/IDayStorage.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain; 2 | 3 | import com.wiseassblog.samsaradayplanner.common.Continuation; 4 | 5 | /** 6 | * The facade pattern uses an abstraction (interface or abstract class) to hide the implementation 7 | * details of a sub-system, from the client (class) that use the sub-system 8 | * 9 | * We hide the implementation details of the back end, from the front end (client) 10 | */ 11 | public interface IDayStorage { 12 | 13 | public void getDay(Continuation continuation); 14 | 15 | public void updateDay(Day day, Continuation continuation); 16 | 17 | /** 18 | * Expect for onSuccess: 19 | * result[0] to be an Hour Type 20 | * result[1] to be an HOUR_MODE enum 21 | * @param hour 22 | * @param continuation 23 | */ 24 | public void getHourWithMode(int hour, Continuation continuation); 25 | 26 | public void updateHour(Hour hour, Continuation continuation); 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/Hour.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Represents an hour of a given day. An hour is divided into four quarters (15 minute intervals) 7 | */ 8 | public class Hour implements Serializable { 9 | /** 10 | * NOTE: the first QuarterHour in quarters may never be inactive! 11 | * This is enforced in the UI but must be respected elsewhere 12 | */ 13 | private final QuarterHour[] quarters; 14 | 15 | /** 16 | * One of: 17 | * Integers 0-23 where 0 is 12:00AM or 0:00, 23 is 11:00pm or 23:00hrs 18 | */ 19 | private final int hourInteger; 20 | 21 | public Hour(QuarterHour[] quarters, int hourInteger) { 22 | this.quarters = quarters; 23 | this.hourInteger = hourInteger; 24 | } 25 | 26 | public QuarterHour[] getQuarters() { 27 | return quarters; 28 | } 29 | 30 | public int getHourInteger() { 31 | return hourInteger; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/buildlogic/TaskListViewInjector.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview.buildlogic; 2 | 3 | import com.wiseassblog.samsaradayplanner.StorageServiceLocator; 4 | import com.wiseassblog.samsaradayplanner.ui.tasklistview.ITaskListViewContract; 5 | import com.wiseassblog.samsaradayplanner.ui.tasklistview.TaskListView; 6 | import com.wiseassblog.samsaradayplanner.ui.tasklistview.TaskListViewLogic; 7 | import com.wiseassblog.samsaradayplanner.ui.tasklistview.TaskListViewModel; 8 | 9 | public class TaskListViewInjector { 10 | public static void build( 11 | TaskListView view, 12 | StorageServiceLocator locator 13 | ) { 14 | 15 | ITaskListViewContract.ViewModel vm = new TaskListViewModel(); 16 | 17 | view.setLogic( 18 | new TaskListViewLogic( 19 | view, 20 | vm, 21 | locator.getTaskStorageImpl() 22 | ) 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ApplicationExecutors.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import java.util.concurrent.Executor; 7 | import java.util.concurrent.Executors; 8 | 9 | public class ApplicationExecutors { 10 | 11 | private final Executor background; 12 | private final Executor mainThread; 13 | 14 | public Executor getBackground() { 15 | return background; 16 | } 17 | 18 | public Executor getMainThread() { 19 | return mainThread; 20 | } 21 | 22 | public ApplicationExecutors() { 23 | this.background = Executors.newSingleThreadExecutor(); 24 | this.mainThread = new MainThreadExecutor(); 25 | } 26 | 27 | private static class MainThreadExecutor implements Executor { 28 | private Handler mainThreadHandler = new Handler(Looper.getMainLooper()); 29 | 30 | @Override 31 | public void execute(Runnable command) { 32 | mainThreadHandler.post(command); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/QuarterHour.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.constants.COLOR; 4 | import com.wiseassblog.samsaradayplanner.domain.constants.ICON; 5 | import com.wiseassblog.samsaradayplanner.domain.constants.QUARTER; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * A virtual representation of a quarter of an hour; i.e. a 15 minute interval. 11 | * 12 | * 13 | * 14 | */ 15 | public class QuarterHour implements Serializable { 16 | private final int taskId; 17 | private final QUARTER quarter; 18 | private final boolean isActive; 19 | 20 | public QuarterHour(int taskId, QUARTER quarter, boolean isActive) { 21 | this.taskId = taskId; 22 | this.quarter = quarter; 23 | this.isActive = isActive; 24 | } 25 | 26 | public boolean getIsActive() { 27 | return isActive; 28 | } 29 | 30 | public int getTaskId() { 31 | return taskId; 32 | } 33 | 34 | public QUARTER getQuarter() { 35 | return quarter; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 17 | 18 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_day_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_hour_block.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/common/Publisher.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.common; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * That which produces events and/or data for any subscriber. 8 | * 9 | * Why the Event Class? 10 | * I wanted a way that I could introduce a rudimentary form of Domain 11 | */ 12 | public abstract class Publisher { 13 | List> subscribers = new ArrayList<>(); 14 | 15 | protected void updateString(EVENT e, String s){ 16 | for (Subscriber sub: subscribers) { 17 | sub.onUpdateString(e, s); 18 | } 19 | } 20 | 21 | protected void updateInt(EVENT e, int i){ 22 | for (Subscriber sub: subscribers) { 23 | sub.onUpdateInt(e, i); 24 | } 25 | } 26 | 27 | protected void updateBool(EVENT e, boolean b){ 28 | for (Subscriber sub: subscribers) { 29 | sub.onUpdateBool(e, b); 30 | } 31 | } 32 | 33 | //USE WITH CAUTION 34 | protected void updateObject(EVENT e, Object o){ 35 | for (Subscriber sub: subscribers) { 36 | sub.onUpdateObject(e, o); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/Task.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.constants.COLOR; 4 | import com.wiseassblog.samsaradayplanner.domain.constants.ICON; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Domain Model is a pure language class 10 | * Data Model as being basically the same thing, but we can include libraries 11 | */ 12 | public class Task implements Serializable { 13 | private final int taskId; 14 | private final String taskName; 15 | 16 | //these things need to be translated into Resource Ids 17 | private final ICON taskIcon; 18 | private final COLOR taskColor; 19 | 20 | public Task(int taskId, String taskName, ICON taskIcon, COLOR taskColor) { 21 | this.taskId = taskId; 22 | this.taskName = taskName; 23 | this.taskIcon = taskIcon; 24 | this.taskColor = taskColor; 25 | } 26 | 27 | public int getTaskId() { 28 | return taskId; 29 | } 30 | 31 | public String getTaskName() { 32 | return taskName; 33 | } 34 | 35 | public ICON getTaskIcon() { 36 | return taskIcon; 37 | } 38 | 39 | public COLOR getTaskColor() { 40 | return taskColor; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/DayActivity.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | import com.wiseassblog.samsaradayplanner.R; 8 | import com.wiseassblog.samsaradayplanner.SamsaraApp; 9 | import com.wiseassblog.samsaradayplanner.ui.dayview.buildlogic.DayViewInjector; 10 | 11 | //Feature level container 12 | public class DayActivity extends AppCompatActivity { 13 | 14 | private static final String DAY_VIEW = "DAY_VIEW"; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_day); 20 | 21 | DayView fragment = (DayView) this.getSupportFragmentManager().findFragmentByTag( 22 | DAY_VIEW 23 | ); 24 | 25 | if (fragment == null) { 26 | fragment = DayView.newInstance(); 27 | } 28 | 29 | this.getSupportFragmentManager().beginTransaction().replace( 30 | R.id.root_day_view, 31 | fragment, 32 | DAY_VIEW 33 | ).commit(); 34 | 35 | DayViewInjector.build(fragment, ((SamsaraApp) getApplication()).getServiceLocator()); 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/test/java/com/wiseassblog/samsaradayplanner/FakeTaskStorage.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner; 2 | 3 | import com.wiseassblog.samsaradayplanner.common.Continuation; 4 | import com.wiseassblog.samsaradayplanner.domain.ITaskStorage; 5 | import com.wiseassblog.samsaradayplanner.domain.Task; 6 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 7 | 8 | import java.io.IOException; 9 | 10 | class FakeTaskStorage implements ITaskStorage { 11 | 12 | private Boolean willFail = false; 13 | 14 | public void setWillFail(Boolean willFail) { 15 | this.willFail = willFail; 16 | } 17 | 18 | @Override 19 | public void getTasks(Continuation continuation) { 20 | if (willFail) continuation.onException(new IOException()); 21 | else continuation.onSuccess(TestData.getTestTasks()); 22 | } 23 | 24 | @Override 25 | public void getTask(int taskId, Continuation continuation) { 26 | if (willFail) continuation.onException(new IOException()); 27 | else continuation.onSuccess(TestData.getTestTask()); 28 | } 29 | 30 | @Override 31 | public void updateTask(Task task, Continuation continuation) { 32 | if (willFail) continuation.onException(new IOException()); 33 | else continuation.onSuccess(null); 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/TaskGridItemView.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview; 2 | 3 | import android.content.Context; 4 | import android.widget.ImageView; 5 | import android.widget.TextView; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.constraintlayout.widget.ConstraintLayout; 9 | 10 | import com.wiseassblog.samsaradayplanner.R; 11 | 12 | class TaskGridItemView extends ConstraintLayout { 13 | private ImageView background, icon; 14 | private TextView taskName; 15 | 16 | public TaskGridItemView(@NonNull Context context) { 17 | super(context); 18 | 19 | build(); 20 | } 21 | 22 | private void build() { 23 | inflate(getContext(), R.layout.list_item_task, this); 24 | 25 | background = findViewById(R.id.imv_background_color); 26 | icon = findViewById(R.id.imv_list_item_task); 27 | taskName = findViewById(R.id.lbl_task_name); 28 | } 29 | 30 | public void setListItemText(String text) { 31 | taskName.setText(text); 32 | } 33 | 34 | public void setListItemIcon(int resId) { 35 | icon.setImageResource(resId); 36 | } 37 | 38 | public void setListItemBackground(int resId) { 39 | background.setBackgroundColor(resId); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managehourview/buildlogic/HourViewInjector.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managehourview.buildlogic; 2 | 3 | import com.wiseassblog.samsaradayplanner.StorageServiceLocator; 4 | import com.wiseassblog.samsaradayplanner.domain.Hour; 5 | import com.wiseassblog.samsaradayplanner.ui.managehourview.HourView; 6 | import com.wiseassblog.samsaradayplanner.ui.managehourview.HourViewLogic; 7 | import com.wiseassblog.samsaradayplanner.ui.managehourview.HourViewModel; 8 | import com.wiseassblog.samsaradayplanner.ui.managehourview.IHourContract; 9 | 10 | public class HourViewInjector { 11 | public static void build( 12 | int hourInt, 13 | HourView view, 14 | StorageServiceLocator locator 15 | ) { 16 | IHourContract.ViewModel vm = new HourViewModel(); 17 | vm.setHour( 18 | new Hour( 19 | null, 20 | hourInt 21 | ) 22 | ); 23 | 24 | view.setLogic( 25 | new HourViewLogic( 26 | view, 27 | vm, 28 | locator.getDayStorageImpl(), 29 | locator.getTaskStorageImpl() 30 | ) 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/DayViewModel.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Day; 4 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 5 | 6 | import java.util.Observable; 7 | import java.util.Optional; 8 | 9 | /** 10 | * This class exists solely for the purpose of storing "front end session state". I could also have 11 | * the Fragment or the Logic class store this state, but I prefer to keep it separate. 12 | * 13 | * According to AAC and Android docs, A ViewModel is a hybrid between a logic class and a front end 14 | * model (caching front end session state). 15 | * 16 | * I use ViewModels like the name implies: it stores models necessary to render the View, so that 17 | * I do not need to reload them every time. 18 | */ 19 | public class DayViewModel implements IDayViewContract.ViewModel { 20 | 21 | private Day day; 22 | private Tasks tasks; 23 | 24 | @Override 25 | public void setTasks(Tasks tasks) { 26 | this.tasks = tasks; 27 | } 28 | 29 | @Override 30 | public Tasks getTasks() { 31 | return this.tasks; 32 | } 33 | 34 | public void setDay(Day day) { 35 | this.day = day; 36 | } 37 | 38 | @Override 39 | public Day getDay() { 40 | return this.day; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/TaskGridItemViewMaker.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview; 2 | 3 | import android.content.Context; 4 | 5 | import com.wiseassblog.samsaradayplanner.common.ColorUtility; 6 | import com.wiseassblog.samsaradayplanner.common.IconUtility; 7 | import com.wiseassblog.samsaradayplanner.domain.Task; 8 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class TaskGridItemViewMaker { 14 | public static List getTaskGridItems(Context context, Tasks tasks) { 15 | List taskItems = new ArrayList<>(); 16 | for (Task t : tasks.get()) { 17 | TaskGridItemView newItem = new TaskGridItemView(context); 18 | newItem.setListItemBackground( 19 | ColorUtility.getColorResId( 20 | context, 21 | t.getTaskColor() 22 | ) 23 | ); 24 | 25 | newItem.setListItemIcon( 26 | IconUtility.getResIdFromEnum(context, t.getTaskIcon()) 27 | ); 28 | 29 | newItem.setListItemText(t.getTaskName()); 30 | 31 | taskItems.add( 32 | newItem 33 | ); 34 | } 35 | 36 | return taskItems; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/spinner_icon_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/spinner_icon_dropdown_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/TaskListActivity.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | import com.wiseassblog.samsaradayplanner.R; 8 | import com.wiseassblog.samsaradayplanner.SamsaraApp; 9 | import com.wiseassblog.samsaradayplanner.ui.tasklistview.buildlogic.TaskListViewInjector; 10 | 11 | public class TaskListActivity extends AppCompatActivity { 12 | 13 | private static final String TASK_LIST_VIEW = "TASK_LIST_VIEW"; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_tasks); 19 | 20 | TaskListView fragment = (TaskListView) this.getSupportFragmentManager().findFragmentByTag( 21 | TASK_LIST_VIEW 22 | ); 23 | 24 | if (fragment == null) { 25 | fragment = TaskListView.newInstance(); 26 | } 27 | 28 | this.getSupportFragmentManager() 29 | .beginTransaction() 30 | .replace( 31 | R.id.root_task_list_view, 32 | fragment, 33 | TASK_LIST_VIEW 34 | ).commit(); 35 | 36 | 37 | TaskListViewInjector.build( 38 | fragment, 39 | ((SamsaraApp) getApplication()).getServiceLocator() 40 | ); 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managetaskview/buildlogic/TaskViewInjector.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managetaskview.buildlogic; 2 | 3 | import com.wiseassblog.samsaradayplanner.StorageServiceLocator; 4 | import com.wiseassblog.samsaradayplanner.domain.Task; 5 | import com.wiseassblog.samsaradayplanner.domain.constants.COLOR; 6 | import com.wiseassblog.samsaradayplanner.domain.constants.ICON; 7 | import com.wiseassblog.samsaradayplanner.ui.managetaskview.ITaskViewContract; 8 | import com.wiseassblog.samsaradayplanner.ui.managetaskview.TaskView; 9 | import com.wiseassblog.samsaradayplanner.ui.managetaskview.TaskViewLogic; 10 | import com.wiseassblog.samsaradayplanner.ui.managetaskview.TaskViewModel; 11 | 12 | public class TaskViewInjector { 13 | public static void build( 14 | TaskView view, 15 | StorageServiceLocator locator, 16 | int taskId 17 | ) { 18 | 19 | ITaskViewContract.ViewModel vm = new TaskViewModel(); 20 | 21 | vm.setTask( 22 | new Task( 23 | taskId, 24 | "", 25 | ICON.BREAK, 26 | COLOR.DARK_BLUE 27 | ) 28 | ); 29 | 30 | view.setLogic( 31 | new TaskViewLogic( 32 | (ITaskViewContract.View) view, 33 | vm, 34 | locator.getTaskStorageImpl() 35 | ) 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/StorageServiceLocator.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner; 2 | 3 | import android.content.Context; 4 | 5 | import com.wiseassblog.samsaradayplanner.domain.IDayStorage; 6 | import com.wiseassblog.samsaradayplanner.domain.ITaskStorage; 7 | import com.wiseassblog.samsaradayplanner.persistence.LocalDayStorageImpl; 8 | import com.wiseassblog.samsaradayplanner.persistence.LocalTaskStorageImpl; 9 | 10 | public class StorageServiceLocator { 11 | 12 | private final IDayStorage dayStorageImpl; 13 | private final ITaskStorage taskStorageImpl; 14 | 15 | /** 16 | * Why toString? By passing the String instead of context, I can keep the Android code out of 17 | * my backend components. This class inevitably must interact with Context, so I can work with 18 | * it here. 19 | * @param context 20 | */ 21 | public StorageServiceLocator(Context context) { 22 | ApplicationExecutors exec = new ApplicationExecutors(); 23 | 24 | dayStorageImpl = new LocalDayStorageImpl( 25 | context.getFilesDir().getPath(), 26 | exec 27 | ); 28 | taskStorageImpl = new LocalTaskStorageImpl( 29 | context.getFilesDir().getPath(), 30 | exec 31 | ); 32 | } 33 | 34 | public IDayStorage getDayStorageImpl() { 35 | return dayStorageImpl; 36 | } 37 | 38 | public ITaskStorage getTaskStorageImpl() { 39 | return taskStorageImpl; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managetaskview/IconSpinnerItem.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managetaskview; 2 | 3 | import android.content.Context; 4 | 5 | import com.wiseassblog.samsaradayplanner.common.IconUtility; 6 | import com.wiseassblog.samsaradayplanner.domain.constants.ICON; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | class IconSpinnerItem { 12 | 13 | public static final int NUMBER_OF_ICONS = 9; 14 | 15 | public static List getItems(Context context) { 16 | List list = new ArrayList<>(); 17 | 18 | for (int index = 0; index < NUMBER_OF_ICONS; index++) { 19 | list.add( 20 | new IconSpinnerItem( 21 | IconUtility.iconNames[index], 22 | IconUtility.getResIdFromEnum( 23 | context, 24 | ICON.values()[index] 25 | ) 26 | ) 27 | ); 28 | } 29 | 30 | return list; 31 | } 32 | 33 | private final String itemText; 34 | private final int itemIconResId; 35 | 36 | public IconSpinnerItem(String itemText, int itemIconResId) { 37 | this.itemText = itemText; 38 | this.itemIconResId = itemIconResId; 39 | } 40 | 41 | public String getItemText() { 42 | return itemText; 43 | } 44 | 45 | public int getItemIconResId() { 46 | return itemIconResId; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar_tasks.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar_hour_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar_manage_task.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/test/java/com/wiseassblog/samsaradayplanner/FakeDayStorage.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner; 2 | 3 | import com.wiseassblog.samsaradayplanner.common.Continuation; 4 | import com.wiseassblog.samsaradayplanner.domain.Day; 5 | import com.wiseassblog.samsaradayplanner.domain.Hour; 6 | import com.wiseassblog.samsaradayplanner.domain.IDayStorage; 7 | 8 | import java.io.IOException; 9 | 10 | class FakeDayStorage implements IDayStorage { 11 | 12 | private Boolean willFail = false; 13 | 14 | public void setWillFail(Boolean willFail) { 15 | this.willFail = willFail; 16 | } 17 | 18 | @Override 19 | public void getDay(Continuation continuation) { 20 | 21 | if (willFail) continuation.onException(new IOException()); 22 | else continuation.onSuccess(TestData.getTestDay()); 23 | } 24 | 25 | @Override 26 | public void updateDay(Day day, Continuation continuation) { 27 | if (willFail) continuation.onException(new IOException()); 28 | else continuation.onSuccess(null); 29 | } 30 | 31 | @Override 32 | public void getHourWithMode(int hour, Continuation continuation) { 33 | Object[] results = new Object[2]; 34 | results[0] = TestData.getTestHour(); 35 | results[1] = TestData.MODE; 36 | continuation.onSuccess( 37 | results 38 | ); 39 | } 40 | 41 | @Override 42 | public void updateHour(Hour hour, Continuation continuation) { 43 | if (willFail) continuation.onException(new IOException()); 44 | else continuation.onSuccess(null); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar_day_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 23 | 24 | 34 | 35 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 29 7 | buildToolsVersion "29.0.3" 8 | 9 | defaultConfig { 10 | applicationId "com.wiseassblog.samsaradayplanner" 11 | minSdkVersion 21 12 | targetSdkVersion 29 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | 19 | compileOptions { 20 | //Allows usage of Java Optional type on lower API levels 21 | coreLibraryDesugaringEnabled true 22 | 23 | sourceCompatibility JavaVersion.VERSION_1_8 24 | targetCompatibility JavaVersion.VERSION_1_8 25 | } 26 | 27 | testOptions { 28 | unitTests { 29 | includeAndroidResources = true 30 | } 31 | } 32 | 33 | buildTypes { 34 | release { 35 | minifyEnabled false 36 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 37 | } 38 | } 39 | 40 | } 41 | 42 | dependencies { 43 | 44 | testImplementation 'junit:junit:4.12' 45 | coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' 46 | 47 | testImplementation 'androidx.test:core:1.3.0' 48 | testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2' 49 | 50 | implementation 'androidx.appcompat:appcompat:1.2.0' 51 | implementation 'com.google.android.material:material:1.2.1' 52 | implementation 'androidx.constraintlayout:constraintlayout:2.0.1' 53 | 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/domain/Day.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.domain; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.constants.HOUR_MODE; 4 | 5 | import java.io.Serializable; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * Question: Why Serializable instead of Parcelable; isn't that less efficient? 11 | * Answer: Parcelable is designed for IPC (inter-process communication), not for persistent file 12 | * storage. Since I am storing the object in a file instead for transferring it, and the docs 13 | * do not recommend Parcelable for persistent storage, I use Serializable instead. 14 | * 15 | * https://developer.android.com/reference/android/os/Parcel 16 | * "This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable." 17 | */ 18 | public class Day implements Serializable { 19 | //We hide the data itself for security and protection 20 | private final HOUR_MODE mode; 21 | private final Hour[] hours; 22 | 23 | public Day(HOUR_MODE mode, Hour[] hours) { 24 | this.mode = mode; 25 | this.hours = hours; 26 | 27 | List list = new ArrayList(); 28 | } 29 | 30 | //we provide a way of accessing the data which is secure 31 | public HOUR_MODE getMode() { 32 | return mode; 33 | } 34 | 35 | public Hour[] getHours() { 36 | return hours; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/DayListItemView.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview; 2 | 3 | import androidx.annotation.IntegerRes; 4 | import androidx.annotation.VisibleForTesting; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * In order to isolate the logic of generating appropriate data for the view and the adapter, 10 | * I will create a special kind of ViewModel which will contain the data in a form which simplifies 11 | * the View binding for the Adapter. 12 | *

13 | *

14 | *

15 | *

16 | * See the DayListViewItemMaker class for more details 17 | */ 18 | public 19 | class DayListItemView { 20 | private final String hourBlockText; 21 | 22 | @IntegerRes 23 | private final int[] iconResId; 24 | 25 | @IntegerRes 26 | private final int[] backgroundResId; 27 | 28 | private final String[] taskNames; 29 | 30 | private final LIST_ITEM_TYPE type; 31 | 32 | public String getHourBlockText() { 33 | return hourBlockText; 34 | } 35 | 36 | public int[] getIconResId() { 37 | return iconResId; 38 | } 39 | 40 | public int[] getBackgroundResId() { 41 | return backgroundResId; 42 | } 43 | 44 | public String[] getTaskNames() { 45 | return taskNames; 46 | } 47 | 48 | public LIST_ITEM_TYPE getType() { 49 | return type; 50 | } 51 | 52 | public DayListItemView(String hourBlockText, int[] iconResId, int[] backgroundResId, String[] taskNames, LIST_ITEM_TYPE type) { 53 | this.hourBlockText = hourBlockText; 54 | this.backgroundResId = backgroundResId; 55 | this.iconResId = iconResId; 56 | this.taskNames = taskNames; 57 | this.type = type; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/common/IconUtility.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.common; 2 | 3 | import android.content.Context; 4 | 5 | import com.wiseassblog.samsaradayplanner.domain.constants.ICON; 6 | 7 | /** 8 | * Helps to map to and from the ICON enum and dynamically generated resource ids 9 | */ 10 | public class IconUtility { 11 | 12 | public static final String[] iconNames = { 13 | "Free Time", 14 | "Break", 15 | "Study", 16 | "Work", 17 | "Exercise", 18 | "Mental Cultivation", 19 | "Eat", 20 | "Rest", 21 | "Shop" 22 | }; 23 | 24 | public static int getResIdFromEnum(Context context, ICON icon) { 25 | switch (icon) { 26 | case FREE_TIME: return getId("ic_free_time", context); 27 | case BREAK: return getId("ic_break", context); 28 | case STUDY: return getId("ic_study", context); 29 | case WORK: return getId("ic_work", context); 30 | case EXERCISE: return getId("ic_exercise", context); 31 | case MENTAL_CULTIVATION: return getId("ic_bhavana", context); 32 | case EAT: return getId("ic_eat", context); 33 | case SLEEP: return getId("ic_rest", context); 34 | case SHOP: return getId("ic_shopping", context); 35 | default: FREE_TIME: return getId("ic_free_time", context); 36 | } 37 | } 38 | 39 | private static int getId(String s, Context context) { 40 | return context.getResources() 41 | .getIdentifier( 42 | s, 43 | "drawable", 44 | context.getPackageName() 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_tasks.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 26 | 27 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managetaskview/IconSpinnerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managetaskview; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ArrayAdapter; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import androidx.annotation.NonNull; 12 | import androidx.annotation.Nullable; 13 | 14 | import com.wiseassblog.samsaradayplanner.R; 15 | 16 | import java.util.List; 17 | 18 | class IconSpinnerAdapter extends ArrayAdapter { 19 | 20 | public IconSpinnerAdapter(Context context, List items) { 21 | super(context, 0, items); 22 | } 23 | 24 | @NonNull 25 | @Override 26 | public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { 27 | if (convertView == null) convertView = LayoutInflater.from(getContext()) 28 | .inflate(android.R.layout.simple_spinner_item, parent, false); 29 | 30 | IconSpinnerItem item = getItem(position); 31 | TextView itemText = convertView.findViewById(android.R.id.text1); 32 | 33 | if (item != null) { 34 | itemText.setText(item.getItemText()); 35 | } 36 | 37 | return convertView; 38 | } 39 | 40 | @NonNull 41 | @Override 42 | public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { 43 | if (convertView == null) convertView = LayoutInflater.from(getContext()) 44 | .inflate(R.layout.spinner_icon_dropdown_item, parent, false); 45 | 46 | IconSpinnerItem item = getItem(position); 47 | 48 | ImageView itemIcon = convertView.findViewById(R.id.imv_spinner_item_icon); 49 | TextView itemText = convertView.findViewById(R.id.lbl_spinner_item); 50 | 51 | if (item != null) { 52 | itemIcon.setImageResource(item.getItemIconResId()); 53 | itemText.setText(item.getItemText()); 54 | } 55 | 56 | return convertView; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_half_hour_task.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 33 | 34 | 44 | 45 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_full_hour_task.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 33 | 34 | 44 | 45 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_quarter_hour_task.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 33 | 34 | 44 | 45 | 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/TaskListViewLogic.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview; 2 | 3 | import com.wiseassblog.samsaradayplanner.common.BaseViewLogic; 4 | import com.wiseassblog.samsaradayplanner.common.Continuation; 5 | import com.wiseassblog.samsaradayplanner.domain.ITaskStorage; 6 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 7 | 8 | public class TaskListViewLogic extends BaseViewLogic { 9 | private final ITaskListViewContract.View view; 10 | private final ITaskListViewContract.ViewModel vm; 11 | private final ITaskStorage storage; 12 | 13 | public TaskListViewLogic(ITaskListViewContract.View view, ITaskListViewContract.ViewModel vm, ITaskStorage storage) { 14 | this.view = view; 15 | this.vm = vm; 16 | this.storage = storage; 17 | } 18 | 19 | 20 | @Override 21 | public void onViewEvent(TasksListViewEvent event) { 22 | switch (event.getEvent()) { 23 | case ON_START: 24 | onStart(); 25 | break; 26 | case ON_LIST_ITEM_SELECTED: 27 | onItemSelected((int)event.getValue()); 28 | break; 29 | case ON_BACK_PRESSED: 30 | onBackPressed(); 31 | break; 32 | } 33 | } 34 | 35 | private void onBackPressed() { 36 | view.navigateToDayView(); 37 | } 38 | 39 | private void onItemSelected(int position) { 40 | int id = vm.getTasks().get()[position].getTaskId(); 41 | 42 | view.navigateToTaskView(id); 43 | } 44 | 45 | private void onDone() { 46 | 47 | } 48 | 49 | private void onStart() { 50 | storage.getTasks( 51 | new Continuation() { 52 | @Override 53 | public void onSuccess(Tasks result) { 54 | vm.setTasks(result); 55 | view.setTasks(result); 56 | } 57 | 58 | @Override 59 | public void onException(Exception e) { 60 | view.showMessage(e.getMessage()); 61 | view.navigateToDayView(); 62 | } 63 | } 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managetaskview/TaskActivity.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managetaskview; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.widget.Toast; 8 | 9 | import com.wiseassblog.samsaradayplanner.R; 10 | import com.wiseassblog.samsaradayplanner.SamsaraApp; 11 | import com.wiseassblog.samsaradayplanner.domain.constants.Extras; 12 | import com.wiseassblog.samsaradayplanner.ui.dayview.DayActivity; 13 | import com.wiseassblog.samsaradayplanner.ui.dayview.DayView; 14 | import com.wiseassblog.samsaradayplanner.ui.dayview.buildlogic.DayViewInjector; 15 | import com.wiseassblog.samsaradayplanner.ui.managetaskview.buildlogic.TaskViewInjector; 16 | 17 | import static com.wiseassblog.samsaradayplanner.common.Messages.GENERIC_ERROR_MESSAGE; 18 | 19 | public class TaskActivity extends AppCompatActivity { 20 | 21 | private static final String TASK_VIEW = "TASK_VIEW"; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_manage_task); 27 | 28 | 29 | final Intent i = this.getIntent(); 30 | 31 | if (i == null) { 32 | Toast.makeText(this, 33 | GENERIC_ERROR_MESSAGE, 34 | Toast.LENGTH_SHORT 35 | ).show(); 36 | 37 | startActivity( 38 | new Intent(this, DayActivity.class) 39 | ); 40 | } 41 | 42 | int taskId = i.getIntExtra( 43 | Extras.EXTRA_TASK_ID, 44 | 0 45 | ); 46 | 47 | TaskView fragment = (TaskView) this.getSupportFragmentManager().findFragmentByTag( 48 | TASK_VIEW 49 | ); 50 | 51 | if (fragment == null) { 52 | fragment = TaskView.newInstance(); 53 | } 54 | 55 | this.getSupportFragmentManager().beginTransaction().replace( 56 | R.id.root_manage_task_view, 57 | fragment, 58 | TASK_VIEW 59 | ).commit(); 60 | 61 | TaskViewInjector.build( 62 | fragment, 63 | ((SamsaraApp) getApplication()).getServiceLocator(), 64 | taskId 65 | ); 66 | } 67 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/view_quarter_hour_toggle.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 29 | 30 | 39 | 40 | 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managehourview/HourActivity.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managehourview; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.widget.Toast; 8 | 9 | import com.wiseassblog.samsaradayplanner.R; 10 | import com.wiseassblog.samsaradayplanner.SamsaraApp; 11 | import com.wiseassblog.samsaradayplanner.domain.constants.Extras; 12 | import com.wiseassblog.samsaradayplanner.ui.dayview.DayActivity; 13 | import com.wiseassblog.samsaradayplanner.ui.managehourview.buildlogic.HourViewInjector; 14 | import com.wiseassblog.samsaradayplanner.ui.tasklistview.TaskListView; 15 | import com.wiseassblog.samsaradayplanner.ui.tasklistview.buildlogic.TaskListViewInjector; 16 | 17 | import static com.wiseassblog.samsaradayplanner.common.Messages.GENERIC_ERROR_MESSAGE; 18 | 19 | public class HourActivity extends AppCompatActivity { 20 | 21 | private static final String HOUR_VIEW = "HOUR_VIEW"; 22 | 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_manage_hour); 28 | 29 | final Intent i = this.getIntent(); 30 | 31 | if (i == null) { 32 | Toast.makeText(this, 33 | GENERIC_ERROR_MESSAGE, 34 | Toast.LENGTH_SHORT 35 | ).show(); 36 | 37 | startActivity( 38 | new Intent(this, DayActivity.class) 39 | ); 40 | } 41 | 42 | int hourInteger = i.getIntExtra( 43 | Extras.EXTRA_HOUR_INTEGER, 44 | 0 45 | ); 46 | 47 | HourView fragment = (HourView) this.getSupportFragmentManager().findFragmentByTag( 48 | HOUR_VIEW 49 | ); 50 | 51 | if (fragment == null) { 52 | fragment = HourView.newInstance(); 53 | } 54 | 55 | this.getSupportFragmentManager().beginTransaction().replace( 56 | R.id.root_manage_hour_view, 57 | fragment, 58 | HOUR_VIEW 59 | ).commit(); 60 | 61 | 62 | HourViewInjector.build( 63 | hourInteger, 64 | fragment, 65 | ((SamsaraApp) getApplication()).getServiceLocator() 66 | ); 67 | } 68 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/common/ColorUtility.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.common; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | 6 | import androidx.core.content.ContextCompat; 7 | 8 | import com.wiseassblog.samsaradayplanner.R; 9 | import com.wiseassblog.samsaradayplanner.domain.constants.COLOR; 10 | 11 | public class ColorUtility { 12 | 13 | public static int getColorResId(Context context, COLOR color) { 14 | switch (color) { 15 | case DARK_BLUE: 16 | return ContextCompat.getColor( 17 | context, 18 | R.color.darkBlue 19 | ); 20 | case BURNT_ORANGE: 21 | return ContextCompat.getColor( 22 | context, 23 | R.color.burntOrange 24 | ); 25 | case GREEN: 26 | return ContextCompat.getColor( 27 | context, 28 | R.color.green 29 | ); 30 | case DARK_RED: 31 | return ContextCompat.getColor( 32 | context, 33 | R.color.red 34 | ); 35 | case DARK_LIME: 36 | return ContextCompat.getColor( 37 | context, 38 | R.color.lime 39 | ); 40 | case LIGHT_BLUE: 41 | return ContextCompat.getColor( 42 | context, 43 | R.color.lightBlue 44 | ); 45 | case MAUVE: 46 | return ContextCompat.getColor( 47 | context, 48 | R.color.mauve 49 | ); 50 | case BROWN: 51 | return ContextCompat.getColor( 52 | context, 53 | R.color.brown 54 | ); 55 | case TEAL: 56 | return ContextCompat.getColor( 57 | context, 58 | R.color.teal 59 | ); 60 | default: 61 | FREE_TIME: 62 | return ContextCompat.getColor( 63 | context, 64 | R.color.lightBlue 65 | ); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_task.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 21 | 22 | 37 | 38 | 44 | 45 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_hour_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 16 | 17 | 26 | 27 | 36 | 37 | 46 | 47 | 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/tasklistview/TaskGridItemViewAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.tasklistview; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.AdapterView; 7 | import android.widget.BaseAdapter; 8 | 9 | import androidx.annotation.NonNull; 10 | 11 | import com.wiseassblog.samsaradayplanner.common.ColorUtility; 12 | import com.wiseassblog.samsaradayplanner.common.IconUtility; 13 | import com.wiseassblog.samsaradayplanner.domain.Task; 14 | 15 | class TaskGridItemViewAdapter extends BaseAdapter implements AdapterView.OnItemClickListener { 16 | 17 | private final Task[] taskItems; 18 | private TaskGridAdapterCallback callback; 19 | 20 | @Override 21 | public void onItemClick(AdapterView adapterView, View view, int position, long l) { 22 | if (callback != null) callback.onItemClick(taskItems[position].getTaskId()); 23 | } 24 | 25 | 26 | interface TaskGridAdapterCallback { 27 | public void onItemClick(int taskId); 28 | } 29 | 30 | public void setCallback(TaskGridAdapterCallback callback) { 31 | this.callback = callback; 32 | } 33 | 34 | public TaskGridItemViewAdapter(@NonNull Context context, Task[] taskItems) { 35 | this.taskItems = taskItems; 36 | } 37 | 38 | @Override 39 | public int getCount() { 40 | return taskItems.length; 41 | } 42 | 43 | @Override 44 | public Object getItem(int i) { 45 | return taskItems[i]; 46 | } 47 | 48 | @Override 49 | public long getItemId(int i) { 50 | return taskItems[i].getTaskId(); 51 | } 52 | 53 | @Override 54 | public View getView(int position, View view, ViewGroup parent) { 55 | TaskGridItemView gridItem = (TaskGridItemView) view; 56 | if (gridItem == null) { 57 | gridItem = new TaskGridItemView(parent.getContext()); 58 | } 59 | 60 | gridItem.setListItemBackground( 61 | ColorUtility.getColorResId( 62 | parent.getContext(), 63 | taskItems[position].getTaskColor() 64 | ) 65 | ); 66 | 67 | gridItem.setListItemIcon( 68 | IconUtility.getResIdFromEnum( 69 | parent.getContext(), 70 | taskItems[position].getTaskIcon() 71 | ) 72 | ); 73 | 74 | gridItem.setListItemText(taskItems[position].getTaskName()); 75 | 76 | return gridItem; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managehourview/HourViewEvent.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managehourview; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.constants.QUARTER; 4 | import com.wiseassblog.samsaradayplanner.ui.managetaskview.TaskViewEvent; 5 | 6 | public class HourViewEvent { 7 | private final HourViewEvent.Event event; 8 | private final Object value; 9 | private QUARTER quarter; 10 | private int position; 11 | private boolean isActive; 12 | 13 | public QUARTER getQuarter() { 14 | return quarter; 15 | } 16 | 17 | public int getPosition() { 18 | return position; 19 | } 20 | 21 | public boolean isActive() { 22 | return isActive; 23 | } 24 | 25 | public HourViewEvent(HourViewEvent.Event event, Object value){ 26 | this.event = event; 27 | this.value = value; 28 | } 29 | 30 | private HourViewEvent( 31 | HourViewEvent.Event event, 32 | Object value, 33 | QUARTER quarter, 34 | int position){ 35 | this.event = event; 36 | this.value = value; 37 | this.quarter = quarter; 38 | this.position = position; 39 | this.isActive = false; 40 | } 41 | 42 | private HourViewEvent( 43 | HourViewEvent.Event event, 44 | Object value, 45 | QUARTER quarter, 46 | boolean isActive){ 47 | this.event = event; 48 | this.value = value; 49 | this.quarter = quarter; 50 | this.isActive = isActive; 51 | this.position = 0; 52 | } 53 | 54 | /** 55 | * Convenience method for creating events with multiple parameters safely 56 | * @param quarter 57 | * @param position 58 | * @return 59 | */ 60 | public static HourViewEvent getOnTaskSelectedEvent( 61 | QUARTER quarter, 62 | int position 63 | ){ 64 | 65 | return new HourViewEvent(Event.ON_TASK_SELECTED, null, quarter, position); 66 | } 67 | 68 | /** 69 | * Convenience method for creating events with multiple parameters safely 70 | * @param quarter 71 | * @param isActive 72 | * @return 73 | */ 74 | public static HourViewEvent getOnQuarterToggleEvent( 75 | QUARTER quarter, 76 | boolean isActive 77 | ){ 78 | 79 | return new HourViewEvent(Event.ON_QUARTER_TOGGLE, null, quarter, isActive); 80 | } 81 | 82 | 83 | public HourViewEvent.Event getEvent() { 84 | return event; 85 | } 86 | 87 | public Object getValue() { 88 | return value; 89 | } 90 | 91 | public enum Event { 92 | ON_QUARTER_TOGGLE, 93 | ON_DONE_CLICK, 94 | ON_TASK_SELECTED, 95 | ON_START 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/common/TimeFormatUtility.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.common; 2 | 3 | import com.wiseassblog.samsaradayplanner.domain.Hour; 4 | import com.wiseassblog.samsaradayplanner.domain.constants.HOUR_MODE; 5 | import com.wiseassblog.samsaradayplanner.domain.constants.QUARTER; 6 | 7 | public class TimeFormatUtility { 8 | public static String getHourBlockText(int hour, HOUR_MODE mode) { 9 | String suffix = ""; 10 | String hourText = Integer.toString(hour); 11 | 12 | //Twelve hour clock is stupid 13 | if (mode == HOUR_MODE.TWELVE_HOUR) { 14 | if (hour == 0) { 15 | suffix = "AM"; 16 | hourText = "12"; 17 | } 18 | if (hour == 12) suffix = "PM"; 19 | else if (hour > 12) { 20 | //hour is 13-23 (1PM - 11PM) 21 | suffix = "PM"; 22 | hourText = Integer.toString(hour - 12); 23 | } else { 24 | //hour is 01-11 (1PM - 11PM) 25 | suffix = "AM"; 26 | } 27 | } else if (mode == HOUR_MODE.TWENTY_FOUR_HOUR) { 28 | //else if included for legibility, in case you were wondering 29 | if (hour == 0) { 30 | //military clock uses 00, not 0 for 12:00AM equivalent 31 | hourText = "00"; 32 | } 33 | //either way suffix is the same 34 | suffix = ":00"; 35 | } 36 | 37 | return hourText + suffix; 38 | } 39 | 40 | public static String getHourToggleViewFormattedText(QUARTER q, int hour, HOUR_MODE mode) { 41 | String suffix = ""; 42 | String quarterText = getQuarterText(q); 43 | String hourText = Integer.toString(hour); 44 | 45 | //Twelve hour clock is stupid 46 | if (mode == HOUR_MODE.TWELVE_HOUR) { 47 | if (hour == 0) { 48 | suffix = "AM"; 49 | hourText = "12"; 50 | } else if (hour == 12) suffix = "PM"; 51 | else if (hour > 12) { 52 | //hour is 13-23 (1PM - 11PM) 53 | suffix = "PM"; 54 | hourText = Integer.toString(hour - 12); 55 | } else { 56 | //hour is 01-11 (1PM - 11PM) 57 | suffix = "AM"; 58 | } 59 | } else if (mode == HOUR_MODE.TWENTY_FOUR_HOUR) { 60 | //else if included for legibility, in case you were wondering 61 | if (hour == 0) { 62 | //military clock uses 00, not 0 for 12:00AM equivalent 63 | hourText = "00"; 64 | } 65 | } 66 | 67 | return hourText + quarterText + suffix; 68 | } 69 | 70 | private static String getQuarterText(QUARTER q) { 71 | switch (q) { 72 | case FIFTEEN: return ":15"; 73 | case THIRTY: return ":30"; 74 | case FOURTY_FIVE: return ":45"; 75 | default: return ":00"; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_day_view_full_hour.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 18 | 27 | 28 | 34 | 35 | 56 | 57 | 67 | 68 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/managetaskview/ColorPickerView.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.managetaskview; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | import android.widget.ImageButton; 7 | 8 | import androidx.annotation.NonNull; 9 | import androidx.annotation.Nullable; 10 | import androidx.constraintlayout.widget.ConstraintLayout; 11 | 12 | import com.wiseassblog.samsaradayplanner.R; 13 | import com.wiseassblog.samsaradayplanner.domain.constants.COLOR; 14 | 15 | public class ColorPickerView extends ConstraintLayout implements View.OnClickListener { 16 | 17 | ImageButton darkBlue, burntOrange, green, red, darkLime, lightBlue, mauve, brown, teal; 18 | private ColorPickerViewClickHandler callback; 19 | 20 | @Override 21 | public void onClick(View view) { 22 | int id = view.getId(); 23 | 24 | switch (id) { 25 | case R.id.imb_dark_blue: 26 | callback.onColorSelected(COLOR.DARK_BLUE); 27 | break; 28 | case R.id.imb_burnt_orange: 29 | callback.onColorSelected(COLOR.BURNT_ORANGE); 30 | break; 31 | case R.id.imb_green: 32 | callback.onColorSelected(COLOR.GREEN); 33 | break; 34 | case R.id.imb_red: 35 | callback.onColorSelected(COLOR.DARK_RED); 36 | break; 37 | case R.id.imb_dark_lime: 38 | callback.onColorSelected(COLOR.DARK_LIME); 39 | break; 40 | case R.id.imb_light_blue: 41 | callback.onColorSelected(COLOR.LIGHT_BLUE); 42 | break; 43 | case R.id.imb_mauve: 44 | callback.onColorSelected(COLOR.MAUVE); 45 | break; 46 | case R.id.imb_brown: 47 | callback.onColorSelected(COLOR.BROWN); 48 | break; 49 | case R.id.imb_teal: 50 | callback.onColorSelected(COLOR.TEAL); 51 | break; 52 | } 53 | } 54 | 55 | interface ColorPickerViewClickHandler { 56 | void onColorSelected(COLOR color); 57 | } 58 | 59 | public void setCallback(ColorPickerViewClickHandler callback) { 60 | this.callback = callback; 61 | } 62 | 63 | 64 | public ColorPickerView(@NonNull Context context, @Nullable AttributeSet attrs) { 65 | super(context, attrs); 66 | 67 | build(); 68 | } 69 | 70 | private void build() { 71 | inflate(getContext(), R.layout.view_color_picker_sheet, this); 72 | 73 | darkBlue = findViewById(R.id.imb_dark_blue); 74 | darkBlue.setOnClickListener(this); 75 | 76 | burntOrange = findViewById(R.id.imb_burnt_orange); 77 | burntOrange.setOnClickListener(this); 78 | 79 | green = findViewById(R.id.imb_green); 80 | green.setOnClickListener(this); 81 | 82 | red = findViewById(R.id.imb_red); 83 | red.setOnClickListener(this); 84 | 85 | darkLime = findViewById(R.id.imb_dark_lime); 86 | darkLime.setOnClickListener(this); 87 | 88 | lightBlue = findViewById(R.id.imb_light_blue); 89 | lightBlue.setOnClickListener(this); 90 | 91 | mauve = findViewById(R.id.imb_mauve); 92 | mauve.setOnClickListener(this); 93 | 94 | brown = findViewById(R.id.imb_brown); 95 | brown.setOnClickListener(this); 96 | 97 | teal = findViewById(R.id.imb_teal); 98 | teal.setOnClickListener(this); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/wiseassblog/samsaradayplanner/ui/dayview/DayViewLogic.java: -------------------------------------------------------------------------------- 1 | package com.wiseassblog.samsaradayplanner.ui.dayview; 2 | 3 | import com.wiseassblog.samsaradayplanner.common.BaseViewLogic; 4 | import com.wiseassblog.samsaradayplanner.common.Continuation; 5 | import com.wiseassblog.samsaradayplanner.common.Messages; 6 | import com.wiseassblog.samsaradayplanner.domain.Day; 7 | import com.wiseassblog.samsaradayplanner.domain.IDayStorage; 8 | import com.wiseassblog.samsaradayplanner.domain.ITaskStorage; 9 | import com.wiseassblog.samsaradayplanner.domain.Tasks; 10 | 11 | //Decision maker (logic) class for the Front End 12 | public class DayViewLogic extends BaseViewLogic { 13 | 14 | private final IDayViewContract.View view; 15 | private final IDayViewContract.ViewModel vm; 16 | 17 | //backend IO devices 18 | //this is an example of the Facade Pattern 19 | //Hide the details of a sub-system 20 | //A more useful advanced pattern is the Observer Pattern/Publisher Subscriber (RxJava well) 21 | //I learned patterns from a book called 22 | // Design Patterns Explained James R. Trott & Alan Shalloway 23 | private final IDayStorage dayStorage; 24 | private final ITaskStorage taskStorage; 25 | 26 | public DayViewLogic(IDayViewContract.View view, IDayViewContract.ViewModel vm, IDayStorage dayStorage, ITaskStorage taskStorage) { 27 | this.view = view; 28 | this.vm = vm; 29 | this.dayStorage = dayStorage; 30 | this.taskStorage = taskStorage; 31 | } 32 | 33 | @Override 34 | public void onViewEvent(DayViewEvent event) { 35 | switch (event.getEvent()) { 36 | case ON_START: 37 | onStart(); 38 | break; 39 | case ON_HOUR_SELECTED: 40 | onHourSelected((int)event.getValue()); 41 | break; 42 | case ON_MANAGE_TASKS_SELECTED: 43 | onManageTaskSelected(); 44 | break; 45 | } 46 | } 47 | 48 | private void onManageTaskSelected() { 49 | view.navigateToTasksView(); 50 | } 51 | 52 | private void onHourSelected(int hourInteger) { 53 | view.navigateToHourView(hourInteger); 54 | } 55 | 56 | /** 57 | * 1. Get data from both data sources 58 | * 2. Give data to the VMs 59 | * 3. Give data to the Views 60 | * 61 | * 62 | * 63 | */ 64 | private void onStart() { 65 | dayStorage.getDay(new Continuation() { 66 | @Override 67 | public void onSuccess(Day result) { 68 | getTasks(result); 69 | } 70 | 71 | @Override 72 | public void onException(Exception e) { 73 | view.showMessage(Messages.GENERIC_ERROR_MESSAGE); 74 | view.restartFeature(); 75 | } 76 | }); 77 | } 78 | 79 | private void getTasks(Day dayResult) { 80 | taskStorage.getTasks(new Continuation() { 81 | @Override 82 | public void onSuccess(Tasks taskResult) { 83 | bindData(dayResult, taskResult); 84 | } 85 | 86 | @Override 87 | public void onException(Exception e) { 88 | view.showMessage(Messages.GENERIC_ERROR_MESSAGE); 89 | view.restartFeature(); 90 | } 91 | }); 92 | } 93 | 94 | private void bindData(Day dayResult, Tasks taskResult) { 95 | vm.setDay(dayResult); 96 | vm.setTasks(taskResult); 97 | view.setData(dayResult, taskResult); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_manage_task.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 47 | 48 | 59 | 60 | 61 |