From 50e7bf14d45c7d98d6be2e8931e6f3526e9dcd42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 20 Mar 2021 18:03:12 +0100 Subject: [PATCH 01/15] [Gradle] Extract material-about-library dependency. --- app/build.gradle | 2 +- .../modules/settings/SettingsNewFragment.java | 240 +++---- app/src/main/res/values/styles.xml | 6 - material-about-library/build.gradle | 38 -- .../src/main/AndroidManifest.xml | 4 - .../ConvenienceBuilder.java | 357 ----------- .../MaterialAboutActivity.java | 186 ------ .../MaterialAboutFragment.java | 132 ---- .../adapters/MaterialAboutItemAdapter.java | 167 ----- .../adapters/MaterialAboutListAdapter.java | 237 ------- .../holders/MaterialAboutItemViewHolder.java | 12 - .../items/MaterialAboutActionItem.java | 488 -------------- .../items/MaterialAboutActionSwitchItem.java | 606 ------------------ .../items/MaterialAboutCheckboxItem.java | 538 ---------------- .../items/MaterialAboutItem.java | 23 - .../MaterialAboutItemOnChangeAction.java | 5 - .../items/MaterialAboutItemOnClickAction.java | 5 - .../items/MaterialAboutProfileItem.java | 352 ---------- .../items/MaterialAboutSwitchItem.java | 548 ---------------- .../items/MaterialAboutTitleItem.java | 400 ------------ .../model/MaterialAboutCard.java | 156 ----- .../model/MaterialAboutList.java | 45 -- .../util/DefaultViewTypeManager.java | 108 ---- .../util/OpenSourceLicense.java | 22 - .../util/ViewTypeManager.java | 35 - .../layout/mal_material_about_action_item.xml | 58 -- .../mal_material_about_action_switch_item.xml | 83 --- .../layout/mal_material_about_activity.xml | 33 - .../mal_material_about_checkbox_item.xml | 65 -- .../layout/mal_material_about_fragment.xml | 14 - .../layout/mal_material_about_list_card.xml | 54 -- .../mal_material_about_profile_item.xml | 66 -- .../layout/mal_material_about_switch_item.xml | 67 -- .../layout/mal_material_about_title_item.xml | 60 -- .../src/main/res/values/attrs.xml | 10 - .../src/main/res/values/colors.xml | 8 - .../src/main/res/values/dimens.xml | 16 - .../src/main/res/values/strings.xml | 94 --- .../src/main/res/values/styles.xml | 17 - settings.gradle | 2 +- 40 files changed, 108 insertions(+), 5251 deletions(-) delete mode 100644 material-about-library/build.gradle delete mode 100644 material-about-library/src/main/AndroidManifest.xml delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/ConvenienceBuilder.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/MaterialAboutActivity.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/MaterialAboutFragment.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/adapters/MaterialAboutItemAdapter.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/adapters/MaterialAboutListAdapter.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/holders/MaterialAboutItemViewHolder.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutActionItem.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutActionSwitchItem.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutCheckboxItem.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItem.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItemOnChangeAction.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItemOnClickAction.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutProfileItem.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutSwitchItem.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutTitleItem.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/model/MaterialAboutCard.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/model/MaterialAboutList.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/DefaultViewTypeManager.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/OpenSourceLicense.java delete mode 100644 material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/ViewTypeManager.java delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_action_item.xml delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_action_switch_item.xml delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_activity.xml delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_checkbox_item.xml delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_fragment.xml delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_list_card.xml delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_profile_item.xml delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_switch_item.xml delete mode 100644 material-about-library/src/main/res/layout/mal_material_about_title_item.xml delete mode 100644 material-about-library/src/main/res/values/attrs.xml delete mode 100644 material-about-library/src/main/res/values/colors.xml delete mode 100644 material-about-library/src/main/res/values/dimens.xml delete mode 100644 material-about-library/src/main/res/values/strings.xml delete mode 100644 material-about-library/src/main/res/values/styles.xml diff --git a/app/build.gradle b/app/build.gradle index 880d6f0f..0c95ebd6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -169,7 +169,7 @@ dependencies { implementation project(":agendacalendarview") implementation project(":cafebar") - implementation project(":material-about-library") + implementation "eu.szkolny:material-about-library:0534abf316" implementation project(":mhttp") implementation project(":nachos") //implementation project(":Navigation") diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java index 555bc3fd..e1541d54 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java @@ -21,7 +21,6 @@ import com.danielstone.materialaboutlibrary.items.MaterialAboutActionItem; import com.danielstone.materialaboutlibrary.items.MaterialAboutActionSwitchItem; import com.danielstone.materialaboutlibrary.items.MaterialAboutItem; import com.danielstone.materialaboutlibrary.items.MaterialAboutItemOnClickAction; -import com.danielstone.materialaboutlibrary.items.MaterialAboutProfileItem; import com.danielstone.materialaboutlibrary.items.MaterialAboutSwitchItem; import com.danielstone.materialaboutlibrary.items.MaterialAboutTitleItem; import com.danielstone.materialaboutlibrary.model.MaterialAboutCard; @@ -156,12 +155,12 @@ public class SettingsNewFragment extends MaterialAboutFragment { roundDrawable.setCircular(true); return roundDrawable;*/ } - private MaterialAboutProfileItem profileCardTitleItem; + private MaterialAboutTitleItem profileCardTitleItem; private ArrayList getProfileCard(boolean expandedOnly) { ArrayList items = new ArrayList<>(); if (!expandedOnly) { - profileCardTitleItem = new MaterialAboutProfileItem( + profileCardTitleItem = new MaterialAboutTitleItem( app.getProfile().getName(), app.getProfile().getSubname(), getProfileDrawable() @@ -267,20 +266,20 @@ public class SettingsNewFragment extends MaterialAboutFragment { else { items.add( - new MaterialAboutSwitchItem( - getString(R.string.settings_profile_sync_text), - getString(R.string.settings_profile_sync_subtext), - new IconicsDrawable(activity) + new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_profile_sync_text) + .subText(R.string.settings_profile_sync_subtext) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon.cmd_account_convert) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getProfile().getSyncEnabled()) - .setOnChangeAction(((isChecked, tag) -> { + .setOnCheckedChanged(((item, isChecked) -> { app.getProfile().setSyncEnabled(isChecked); app.profileSave(); return true; })) + .build() ); } @@ -300,20 +299,20 @@ public class SettingsNewFragment extends MaterialAboutFragment { Date today = Date.getToday(); if (today.month == 12 || today.month == 1) { items.add( - new MaterialAboutSwitchItem( - getString(R.string.settings_theme_snowfall_text), - getString(R.string.settings_theme_snowfall_subtext), - new IconicsDrawable(activity) + new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_theme_snowfall_text) + .subText(R.string.settings_theme_snowfall_subtext) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_snowflake) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getConfig().getUi().getSnowfall()) - .setOnChangeAction((isChecked, tag) -> { + .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getUi().setSnowfall(isChecked); activity.recreate(); return true; }) + .build() ); } @@ -343,24 +342,24 @@ public class SettingsNewFragment extends MaterialAboutFragment { ); items.add( - new MaterialAboutSwitchItem( - getString(R.string.settings_theme_mini_drawer_text), - getString(R.string.settings_theme_mini_drawer_subtext), - new IconicsDrawable(activity) + new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_theme_mini_drawer_text) + .subText(R.string.settings_theme_mini_drawer_subtext) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon.cmd_dots_vertical) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) - .setChecked(app.getConfig().getUi().getMiniMenuVisible()) - .setOnChangeAction((isChecked, tag) -> { - // 0,1 1 - // 0,0 0 - // 1,1 0 - // 1,0 1 - app.getConfig().getUi().setMiniMenuVisible(isChecked); - activity.getNavView().drawer.setMiniDrawerVisiblePortrait(isChecked); - return true; - }) + .color(IconicsColor.colorInt(iconColor))) + .setChecked(app.getConfig().getUi().getMiniMenuVisible()) + .setOnCheckedChanged((item, isChecked) -> { + // 0,1 1 + // 0,0 0 + // 1,1 0 + // 1,0 1 + app.getConfig().getUi().setMiniMenuVisible(isChecked); + activity.getNavView().drawer.setMiniDrawerVisiblePortrait(isChecked); + return true; + }) + .build() ); items.add(getMoreItem(() -> addCardItems(CARD_THEME, getThemeCard(true)))); @@ -496,19 +495,18 @@ public class SettingsNewFragment extends MaterialAboutFragment { ); items.add( - new MaterialAboutSwitchItem( - getString(R.string.settings_theme_open_drawer_on_back_pressed_text), - null, - new IconicsDrawable(activity) + new MaterialAboutSwitchItem.Builder( ) + .text(R.string.settings_theme_open_drawer_on_back_pressed_text) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_menu_open) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getConfig().getUi().getOpenDrawerOnBackPressed()) - .setOnChangeAction((isChecked, tag) -> { + .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getUi().setOpenDrawerOnBackPressed(isChecked); return true; }) + .build() ); } return items; @@ -548,20 +546,20 @@ public class SettingsNewFragment extends MaterialAboutFragment { ); } private MaterialAboutItem getSyncCardWifiItem() { - return new MaterialAboutSwitchItem( - getString(R.string.settings_sync_wifi_text), - getString(R.string.settings_sync_wifi_subtext), - new IconicsDrawable(activity) + return new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_sync_wifi_text) + .subText(R.string.settings_sync_wifi_subtext) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_wifi_strength_2) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getConfig().getSync().getOnlyWifi()) - .setOnChangeAction((isChecked, tag) -> { + .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getSync().setOnlyWifi(isChecked); SyncWorker.Companion.rescheduleNext(app); return true; - }); + }) + .build(); } private MaterialAboutActionSwitchItem syncCardIntervalItem; private MaterialAboutActionSwitchItem syncCardQuietHoursItem; @@ -569,14 +567,14 @@ public class SettingsNewFragment extends MaterialAboutFragment { ArrayList items = new ArrayList<>(); if (!expandedOnly) { - syncCardIntervalItem = new MaterialAboutActionSwitchItem( - getString(R.string.settings_sync_sync_interval_text), - getString(R.string.settings_sync_sync_interval_subtext_disabled), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_download_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ); + syncCardIntervalItem = new MaterialAboutActionSwitchItem.Builder() + .text(R.string.settings_sync_sync_interval_text) + .subText(R.string.settings_sync_sync_interval_subtext_disabled) + .icon(new IconicsDrawable(activity) + .icon(CommunityMaterial.Icon.cmd_download_outline) + .size(IconicsSize.dp(iconSizeDp)) + .color(IconicsColor.colorInt(iconColor))) + .build(); syncCardIntervalItem.setSubTextChecked(getSyncCardIntervalSubText()); syncCardIntervalItem.setChecked(app.getConfig().getSync().getEnabled()); syncCardIntervalItem.setOnClickAction(() -> { @@ -625,7 +623,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { }) .show(); }); - syncCardIntervalItem.setOnChangeAction((isChecked, tag) -> { + syncCardIntervalItem.setOnCheckedChangedAction((item, isChecked) -> { if (isChecked && !app.getConfig().getSync().getEnabled()) { addCardItem(CARD_SYNC, 1, getSyncCardWifiItem()); } @@ -660,14 +658,14 @@ public class SettingsNewFragment extends MaterialAboutFragment { );*/ - syncCardQuietHoursItem = new MaterialAboutActionSwitchItem( - getString(R.string.settings_sync_quiet_hours_text), - getString(R.string.settings_sync_quiet_hours_subtext_disabled), - new IconicsDrawable(activity) + syncCardQuietHoursItem = new MaterialAboutActionSwitchItem.Builder() + .text(R.string.settings_sync_quiet_hours_text) + .subText(R.string.settings_sync_quiet_hours_subtext_disabled) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon.cmd_bell_sleep_outline) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ); + .color(IconicsColor.colorInt(iconColor))) + .build(); syncCardQuietHoursItem.setChecked(app.getConfig().getSync().getQuietHoursEnabled()); syncCardQuietHoursItem.setSubTextChecked(getSyncCardQuietHoursSubText()); syncCardQuietHoursItem.setOnClickAction(() -> { @@ -707,7 +705,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { }) .show(); }); - syncCardQuietHoursItem.setOnChangeAction((isChecked, tag) -> { + syncCardQuietHoursItem.setOnCheckedChangedAction((item, isChecked) -> { app.getConfig().getSync().setQuietHoursEnabled(isChecked); if (isChecked && app.getConfig().getSync().getQuietHoursStart() == null) { app.getConfig().getSync().setQuietHoursStart(new Time(22, 30, 0)); @@ -752,20 +750,19 @@ public class SettingsNewFragment extends MaterialAboutFragment { );*/ items.add( - new MaterialAboutSwitchItem( - getString(R.string.settings_sync_updates_text), - null, - new IconicsDrawable(activity) + new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_sync_updates_text) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon.cmd_cellphone_arrow_down) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getConfig().getSync().getNotifyAboutUpdates()) - .setOnChangeAction((isChecked, tag) -> { + .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getSync().setNotifyAboutUpdates(isChecked); UpdateWorker.Companion.rescheduleNext(app); return true; }) + .build() ); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { @@ -846,16 +843,15 @@ public class SettingsNewFragment extends MaterialAboutFragment { ); } private MaterialAboutItem getRegisterCardSharedEventsItem() { - return new MaterialAboutSwitchItem( - getString(R.string.settings_register_shared_events_text), - getString(R.string.settings_register_shared_events_subtext), - new IconicsDrawable(activity) + return new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_register_shared_events_text) + .subText(R.string.settings_register_shared_events_subtext) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_share_outline) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getProfile().getEnableSharedEvents()) - .setOnChangeAction((isChecked, tag) -> { + .setOnCheckedChanged((item, isChecked) -> { app.getProfile().setEnableSharedEvents(isChecked); app.profileSave(); if (isChecked) new MaterialDialog.Builder(activity) @@ -869,7 +865,8 @@ public class SettingsNewFragment extends MaterialAboutFragment { .positiveText(R.string.ok) .show(); return true; - }); + }) + .build(); } private MaterialAboutSwitchItem registerCardAllowRegistrationItem; @@ -895,16 +892,16 @@ public class SettingsNewFragment extends MaterialAboutFragment { .color(IconicsColor.colorInt(iconColor)) ).setOnClickAction(() -> new AttendanceConfigDialog(activity, false, null, null))); - registerCardAllowRegistrationItem = new MaterialAboutSwitchItem( - getString(R.string.settings_register_allow_registration_text), - getString(R.string.settings_register_allow_registration_subtext), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_account_circle_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ); + registerCardAllowRegistrationItem = new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_register_allow_registration_text) + .subText(R.string.settings_register_allow_registration_subtext) + .icon(new IconicsDrawable(activity) + .icon(CommunityMaterial.Icon.cmd_account_circle_outline) + .size(IconicsSize.dp(iconSizeDp)) + .color(IconicsColor.colorInt(iconColor))) + .build(); registerCardAllowRegistrationItem.setChecked(app.getProfile().getRegistration() == REGISTRATION_ENABLED); - registerCardAllowRegistrationItem.setOnChangeAction((isChecked, tag) -> { + registerCardAllowRegistrationItem.setOnCheckedChangedAction((item, isChecked) -> { if (isChecked) new MaterialDialog.Builder(activity) .title(getString(R.string.settings_register_allow_registration_dialog_enabled_title)) .content(getString(R.string.settings_register_allow_registration_dialog_enabled_text)) @@ -1025,55 +1022,53 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(registerCardBellSyncItem); items.add( - new MaterialAboutSwitchItem( - getString(R.string.settings_register_count_in_seconds_text), - getString(R.string.settings_register_count_in_seconds_subtext), - new IconicsDrawable(activity) + new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_register_count_in_seconds_text) + .subText(R.string.settings_register_count_in_seconds_subtext) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_timer) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getConfig().getTimetable().getCountInSeconds()) - .setOnChangeAction((isChecked, tag) -> { + .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getTimetable().setCountInSeconds(isChecked); return true; }) + .build() ); if (app.getProfile().getLoginStoreType() == LoginStore.LOGIN_TYPE_LIBRUS) { items.add( - new MaterialAboutSwitchItem( - getString(R.string.settings_register_show_teacher_absences_text), - null, - new IconicsDrawable(activity) + new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_register_show_teacher_absences_text) + .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon.cmd_account_arrow_right_outline) .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getProfile().getStudentData("showTeacherAbsences", true)) - .setOnChangeAction((isChecked, tag) -> { + .setOnCheckedChanged((item, isChecked) -> { app.getProfile().putStudentData("showTeacherAbsences", isChecked); app.profileSave(); return true; }) + .build() ); } if (App.Companion.getDevMode()) { items.add( - new MaterialAboutSwitchItem( - getString(R.string.settings_register_hide_sticks_from_old), - null, - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_numeric_1_box_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) - ) + new MaterialAboutSwitchItem.Builder() + .text(R.string.settings_register_hide_sticks_from_old) + .icon(new IconicsDrawable(activity) + .icon(CommunityMaterial.Icon2.cmd_numeric_1_box_outline) + .size(IconicsSize.dp(iconSizeDp)) + .color(IconicsColor.colorInt(iconColor))) .setChecked(app.getConfig().forProfile().getGrades().getHideSticksFromOld()) - .setOnChangeAction((isChecked, tag) -> { + .setOnCheckedChanged((item, isChecked) -> { app.getConfig().forProfile().getGrades().setHideSticksFromOld(isChecked); return true; }) + .build() ); } @@ -1097,15 +1092,11 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutTitleItem.Builder() .text(R.string.app_name) .desc(R.string.settings_about_title_subtext) - .textColor(primaryTextOnPrimaryBg) - .descColor(secondaryTextOnPrimaryBg) .icon(R.mipmap.ic_splash) .build()); pref_about_version = new MaterialAboutActionItem.Builder() .text(R.string.settings_about_version_text) - .textColor(primaryTextOnPrimaryBg) - .subTextColor(secondaryTextOnPrimaryBg) .subText(BuildConfig.VERSION_NAME + ", " + BuildConfig.BUILD_TYPE) .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_information_outline) @@ -1129,8 +1120,6 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_privacy_policy_text) - .textColor(primaryTextOnPrimaryBg) - .subTextColor(secondaryTextOnPrimaryBg) .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_shield_outline) .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) @@ -1140,8 +1129,6 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_discord_text) - .textColor(primaryTextOnPrimaryBg) - .subTextColor(secondaryTextOnPrimaryBg) .subText(R.string.settings_about_discord_subtext) .icon(new IconicsDrawable(activity) .icon(SzkolnyFont.Icon.szf_discord_outline) @@ -1152,8 +1139,6 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_language_text) - .textColor(primaryTextOnPrimaryBg) - .subTextColor(secondaryTextOnPrimaryBg) .subText(R.string.settings_about_language_subtext) .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_translate) @@ -1193,8 +1178,6 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_update_text) .subText(R.string.settings_about_update_subtext) - .textColor(primaryTextOnPrimaryBg) - .subTextColor(secondaryTextOnPrimaryBg) .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_update) .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) @@ -1218,8 +1201,6 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_changelog_text) - .textColor(primaryTextOnPrimaryBg) - .subTextColor(secondaryTextOnPrimaryBg) .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon2.cmd_radar) .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) @@ -1229,8 +1210,6 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_licenses_text) - .textColor(primaryTextOnPrimaryBg) - .subTextColor(secondaryTextOnPrimaryBg) .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon.cmd_code_braces) .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) @@ -1267,8 +1246,6 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_crash_text) .subText(R.string.settings_about_crash_subtext) - .textColor(primaryTextOnPrimaryBg) - .subTextColor(secondaryTextOnPrimaryBg) .icon(new IconicsDrawable(activity) .icon(CommunityMaterial.Icon.cmd_bug_outline) .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) @@ -1304,11 +1281,6 @@ public class SettingsNewFragment extends MaterialAboutFragment { return materialAboutList; } - @Override - protected int getTheme() { - return Themes.INSTANCE.getAppTheme(); - } - /* _____ _ ____ _ _ / ____| | | | _ \ | | | | | | _ _ ___| |_ ___ _ __ ___ | |_) | __ _ ___| | ____ _ _ __ ___ _ _ _ __ __| |___ diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9983ecf0..512c6ade 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -111,12 +111,9 @@ ?colorAccent ?android:textColorPrimary - @style/Theme.Mal.Toolbar.Dark - @style/Theme.Mal.Toolbar.Light ?android:textColorPrimary ?android:textColorSecondary ?colorSurface - @color/dividerColor @drawable/timetable_lesson_bg_light #9f9f9f @@ -147,12 +144,9 @@ ?colorAccent ?android:textColorPrimary - @style/Theme.Mal.Toolbar.Dark - @style/Theme.Mal.Toolbar.Dark @color/primaryTextDark @color/secondaryTextDark ?colorSurface - @color/dividerColor @drawable/timetable_lesson_bg_dark #838383 diff --git a/material-about-library/build.gradle b/material-about-library/build.gradle deleted file mode 100644 index c79c427c..00000000 --- a/material-about-library/build.gradle +++ /dev/null @@ -1,38 +0,0 @@ -apply plugin: 'com.android.library' - -group = 'com.github.daniel-stoneuk' - -def versionMajor = 2 -def versionMinor = 3 -def versionPatch = 0 -def versionBuild = 0 // bump for dogfood builds, public betas, etc. - -android { - compileSdkVersion setup.compileSdk - - defaultConfig { - minSdkVersion 14 - targetSdkVersion setup.targetSdk - versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild - versionName "${versionMajor}.${versionMinor}" + (versionPatch == 0 ? "" : ".${versionPatch}") - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - debugMinify { - debuggable = true - minifyEnabled = true - proguardFiles 'proguard-android.txt' - } - } -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "androidx.appcompat:appcompat:${versions.appcompat}" - implementation "androidx.cardview:cardview:${versions.cardview}" - implementation "com.google.android.material:material:${versions.material}" -} diff --git a/material-about-library/src/main/AndroidManifest.xml b/material-about-library/src/main/AndroidManifest.xml deleted file mode 100644 index 71d1ecd9..00000000 --- a/material-about-library/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/ConvenienceBuilder.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/ConvenienceBuilder.java deleted file mode 100644 index f0e17e95..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/ConvenienceBuilder.java +++ /dev/null @@ -1,357 +0,0 @@ -package com.danielstone.materialaboutlibrary; - -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import android.webkit.WebView; -import android.widget.Toast; - -import com.danielstone.materialaboutlibrary.items.MaterialAboutActionItem; -import com.danielstone.materialaboutlibrary.items.MaterialAboutItemOnClickAction; -import com.danielstone.materialaboutlibrary.items.MaterialAboutTitleItem; -import com.danielstone.materialaboutlibrary.model.MaterialAboutCard; -import com.danielstone.materialaboutlibrary.util.OpenSourceLicense; - -@SuppressWarnings("JavaDoc") -public class ConvenienceBuilder { - - public static MaterialAboutTitleItem createAppTitleItem(String appName, Drawable applicationIcon) { - return new MaterialAboutTitleItem(appName, null, applicationIcon); - } - - public static MaterialAboutTitleItem createAppTitleItem(Context c) { - Context applicationContext = c.getApplicationContext(); - PackageManager packageManager = applicationContext.getPackageManager(); - ApplicationInfo applicationInfo = applicationContext.getApplicationInfo(); - CharSequence appName = packageManager.getApplicationLabel(applicationInfo); - Drawable applicationIcon = packageManager.getApplicationIcon(applicationInfo); - return createAppTitleItem(appName == null ? "" : appName.toString(), applicationIcon); - } - - /** - * Creates an item with version info read from the PackageManager for current application. - * - * @param c context - * @param icon - * @param text - * @param includeVersionCode - * @return Item to add to card. - */ - public static MaterialAboutActionItem createVersionActionItem(Context c, Drawable icon, CharSequence text, boolean includeVersionCode) { - String versionName = ""; - int versionCode = 0; - try { - PackageInfo pInfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0); - versionName = pInfo.versionName; - versionCode = pInfo.versionCode; - } catch (PackageManager.NameNotFoundException ignored) { - // This shouldn't happen. - } - return new MaterialAboutActionItem.Builder() - .text(text) - .subText(versionName + (includeVersionCode ? " (" + versionCode + ")" : "")) - .icon(icon) - .build(); - } - - public static MaterialAboutItemOnClickAction createWebViewDialogOnClickAction(final Context c, final CharSequence dialogTitle, final String htmlString, final boolean isStringUrl, final boolean supportZoom) { - return createWebViewDialogOnClickAction(c, dialogTitle, c.getString(R.string.mal_close), htmlString, isStringUrl, supportZoom); - } - - public static MaterialAboutItemOnClickAction createWebViewDialogOnClickAction(final Context c, final CharSequence dialogTitle, final CharSequence dialogNegativeButton, final String htmlString, final boolean isStringUrl, final boolean supportZoom) { - - return new MaterialAboutItemOnClickAction() { - @Override - public void onClick() { - AlertDialog.Builder alertBuilder = new AlertDialog.Builder(c); - alertBuilder.setTitle(dialogTitle); - - final WebView wv = new WebView(c); - wv.getSettings().setSupportZoom(supportZoom); - if (!supportZoom) { - wv.getSettings().setLoadWithOverviewMode(true); - wv.getSettings().setUseWideViewPort(true); - } - if (isStringUrl) { - wv.loadUrl(htmlString); - } else { - wv.loadData(htmlString, "text/html; charset=utf-8", "UTF-8"); - } - - alertBuilder.setView(wv); - alertBuilder.setNegativeButton(dialogNegativeButton, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - wv.destroy(); - dialog.dismiss(); - } - }); - - final AlertDialog dialog = alertBuilder.create(); - dialog.show(); - } - }; - } - - - public static MaterialAboutActionItem createWebViewDialogItem(Context c, Drawable icon, CharSequence text, @Nullable CharSequence subText, CharSequence dialogTitle, String htmlString, boolean isStringUrl, boolean supportZoom) { - return createWebViewDialogItem(c, icon, text, subText, dialogTitle, c.getString(R.string.mal_close), htmlString, isStringUrl, supportZoom); - } - - public static MaterialAboutActionItem createWebViewDialogItem(Context c, Drawable icon, CharSequence text, @Nullable CharSequence subText, CharSequence dialogTitle, CharSequence dialogNegativeButton, String htmlString, boolean isStringUrl, boolean supportZoom) { - return new MaterialAboutActionItem.Builder() - .text(text) - .subText(subText) - .icon(icon) - .setOnClickAction(createWebViewDialogOnClickAction(c, dialogTitle, dialogNegativeButton, htmlString, isStringUrl, supportZoom)) - .build(); - } - - - public static MaterialAboutItemOnClickAction createWebsiteOnClickAction(final Context c, final Uri websiteUrl) { - return new MaterialAboutItemOnClickAction() { - @Override - public void onClick() { - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(websiteUrl); - try { - c.startActivity(i); - } catch (Exception e) { - // No activity to handle intent - Toast.makeText(c, R.string.mal_activity_exception, Toast.LENGTH_SHORT).show(); - } - } - }; - } - - /** - * Creates an ActionItem which will open a url when tapped - * - * @param c context - * @param text - * @param icon - * @param websiteUrl (subText) - * @return Item to add to card. - */ - public static MaterialAboutActionItem createWebsiteActionItem(Context c, Drawable icon, CharSequence text, boolean showAddress, final Uri websiteUrl) { - return new MaterialAboutActionItem.Builder() - .text(text) - .subText((showAddress ? websiteUrl.toString() : null)) - .icon(icon) - .setOnClickAction(createWebsiteOnClickAction(c, websiteUrl)) - .build(); - } - - /** - * Creates a MaterialAboutItemOnClickAction that will open - * the Google Play store listing for the app. - * - * @param c context - * @return onClickAction - */ - public static MaterialAboutItemOnClickAction createRateOnClickAction(final Context c) { - Uri uri = Uri.parse("market://details?id=" + c.getPackageName()); - final Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | - Intent.FLAG_ACTIVITY_NEW_DOCUMENT | - Intent.FLAG_ACTIVITY_MULTIPLE_TASK); - } else { - goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | - Intent.FLAG_ACTIVITY_MULTIPLE_TASK); - } - - return new MaterialAboutItemOnClickAction() { - @Override - public void onClick() { - try { - c.startActivity(goToMarket); - } catch (ActivityNotFoundException e) { - c.startActivity(new Intent(Intent.ACTION_VIEW, - Uri.parse("http://play.google.com/store/apps/details?id=" + c.getPackageName()))); - } - } - }; - } - - /** - * Creates an ActionItem which will open the play store when tapped - * - * @param c context - * @param text - * @param subText - * @param icon - * @return Item to add to card. - */ - public static MaterialAboutActionItem createRateActionItem(Context c, Drawable icon, CharSequence text, @Nullable CharSequence subText) { - - return new MaterialAboutActionItem.Builder() - .text(text) - .subText(subText) - .icon(icon) - .setOnClickAction(createRateOnClickAction(c)) - .build(); - } - - public static MaterialAboutItemOnClickAction createEmailOnClickAction(final Context c, String email, String emailSubject) { - return createEmailOnClickAction(c, email, emailSubject, c.getString(R.string.mal_send_email)); - } - - /** - * Creates a MaterialAboutItemOnClickAction that will open - * an email intent with specified address. - * - * @param c context - * @param email email address - * @return onClickAction - */ - public static MaterialAboutItemOnClickAction createEmailOnClickAction(final Context c, String email, String emailSubject, final CharSequence chooserTitle) { - - final Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + email)); - emailIntent.putExtra(Intent.EXTRA_SUBJECT, emailSubject); - - return new MaterialAboutItemOnClickAction() { - @Override - public void onClick() { - try { - c.startActivity(Intent.createChooser(emailIntent, chooserTitle)); - } catch (Exception e) { - // No activity to handle intent - Toast.makeText(c, R.string.mal_activity_exception, Toast.LENGTH_SHORT).show(); - } - } - }; - } - - /** - * Creates an ActionItem which will open the an email intent when tapped - * - * @param c context - * @param text - * @param icon - * @param email email address (also used as subText) - * @return Item to add to card. - */ - public static MaterialAboutActionItem createEmailItem(Context c, Drawable icon, CharSequence text, boolean showEmail, String email, String emailSubject, CharSequence chooserTitle) { - return new MaterialAboutActionItem.Builder() - .text(text) - .subText((showEmail ? email : null)) - .icon(icon) - .setOnClickAction(createEmailOnClickAction(c, email, emailSubject, chooserTitle)) - .build(); - } - - public static MaterialAboutActionItem createEmailItem(Context c, Drawable icon, CharSequence text, boolean showEmail, String email, String emailSubject) { - return createEmailItem(c, icon, text, showEmail, email, emailSubject, c.getString(R.string.mal_send_email)); - } - - /** - * Creates a MaterialAboutItemOnClickAction that will open - * the dialer with specified number. - * - * @param c context - * @param number phone number - * @return onClickAction - */ - public static MaterialAboutItemOnClickAction createPhoneOnClickAction(final Context c, String number) { - final Intent phoneIntent = new Intent(Intent.ACTION_DIAL); - phoneIntent.setData(Uri.parse("tel:" + number)); - - return new MaterialAboutItemOnClickAction() { - @Override - public void onClick() { - try { - c.startActivity(phoneIntent); - } catch (Exception e) { - // No activity to handle intent - Toast.makeText(c, R.string.mal_activity_exception, Toast.LENGTH_SHORT).show(); - } - } - }; - } - - /** - * Creates an ActionItem which will open the dialer when tapped - * - * @param c context - * @param text - * @param icon - * @param number phone number (also used as subText) - * @return Item to add to card. - */ - public static MaterialAboutActionItem createPhoneItem(Context c, Drawable icon, CharSequence text, boolean showNumber, String number) { - return new MaterialAboutActionItem.Builder() - .text(text) - .subText((showNumber ? number : null)) - .icon(icon) - .setOnClickAction(createPhoneOnClickAction(c, number)) - .build(); - } - - /** - * Creates a MaterialAboutItemOnClickAction that will open - * maps with a query. - * Query can be either lat,lng(label) or written address - * - * @param c context - * @param addressQuery address query - * @return onClickAction - */ - public static MaterialAboutItemOnClickAction createMapOnClickAction(final Context c, String addressQuery) { - final Intent mapIntent = new Intent(Intent.ACTION_VIEW); - mapIntent.setData(Uri.parse("geo:0,0").buildUpon().appendQueryParameter("q", addressQuery).build()); - return new MaterialAboutItemOnClickAction() { - @Override - public void onClick() { - try { - c.startActivity(mapIntent); - } catch (Exception e) { - // No activity to handle intent - Toast.makeText(c, R.string.mal_activity_exception, Toast.LENGTH_SHORT).show(); - } - } - }; - } - - /** - * Creates an ActionItem which will open maps when tapped - * Query can be either lat,lng(label) or written address - * - * @param c context - * @param text - * @param subText can be set to null - * @param icon - * @param addressQuery addressQuery - * @return Item to add to card. - */ - public static MaterialAboutActionItem createMapItem(Context c, Drawable icon, CharSequence text, CharSequence subText, String addressQuery) { - return new MaterialAboutActionItem.Builder() - .text(text) - .subText(subText) - .icon(icon) - .setOnClickAction(createMapOnClickAction(c, addressQuery)) - .build(); - } - - public static MaterialAboutCard createLicenseCard(Context c, Drawable icon, CharSequence libraryTitle, CharSequence year, CharSequence name, OpenSourceLicense license) { - - MaterialAboutActionItem licenseItem = new MaterialAboutActionItem.Builder() - .icon(icon) - .setIconGravity(MaterialAboutActionItem.GRAVITY_TOP) - .text(libraryTitle) - .subText(String.format(c.getString(license.getResourceId()), year, name)) - .build(); - - return new MaterialAboutCard.Builder().addItem(licenseItem).build(); - } - -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/MaterialAboutActivity.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/MaterialAboutActivity.java deleted file mode 100644 index 9a5ec841..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/MaterialAboutActivity.java +++ /dev/null @@ -1,186 +0,0 @@ -package com.danielstone.materialaboutlibrary; - - -import android.content.Context; -import android.os.AsyncTask; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.google.android.material.appbar.AppBarLayout; -import androidx.interpolator.view.animation.FastOutSlowInInterpolator; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.SimpleItemAnimator; -import androidx.appcompat.widget.Toolbar; -import android.util.TypedValue; -import android.view.MenuItem; - -import com.danielstone.materialaboutlibrary.adapters.MaterialAboutListAdapter; -import com.danielstone.materialaboutlibrary.model.MaterialAboutList; -import com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -import java.lang.ref.WeakReference; - -public abstract class MaterialAboutActivity extends AppCompatActivity { - - private MaterialAboutList list = new MaterialAboutList.Builder().build(); - private Toolbar toolbar; - private RecyclerView recyclerView; - private MaterialAboutListAdapter adapter; - - @NonNull - protected abstract MaterialAboutList getMaterialAboutList(@NonNull Context context); - - @Nullable - protected abstract CharSequence getActivityTitle(); - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - verifyAttributesExist(); - - setContentView(R.layout.mal_material_about_activity); - - CharSequence title = getActivityTitle(); - if (title == null) - setTitle(R.string.mal_title_about); - else - setTitle(title); - - - assignViews(); - initViews(); - - ListTask task = new ListTask(this); - task.execute(); - } - - private void verifyAttributesExist() { - TypedValue typedValue = new TypedValue(); - boolean malColorPrimaryExists = - getTheme().resolveAttribute(R.attr.mal_color_primary, typedValue, true); - boolean malColorSecondaryExists = - getTheme().resolveAttribute(R.attr.mal_color_secondary, typedValue, true); - if (!malColorPrimaryExists || !malColorSecondaryExists) { - throw new IllegalStateException(String.format("The current theme doesn't provide %s " + - "and/or %s. Please use a theme provided by the library or an extension.", - getResources().getResourceEntryName(R.attr.mal_color_primary), - getResources().getResourceEntryName(R.attr.mal_color_secondary))); - } - } - - private void assignViews() { - toolbar = (Toolbar) findViewById(R.id.mal_toolbar); - recyclerView = (RecyclerView) findViewById(R.id.mal_recyclerview); - recyclerView.setAlpha(0f); - recyclerView.setTranslationY(20); - } - - private void initViews() { - setSupportActionBar(toolbar); - ActionBar actionBar = getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - } - adapter = new MaterialAboutListAdapter(getViewTypeManager()); - recyclerView.setLayoutManager(new LinearLayoutManager(this)); - recyclerView.setAdapter(adapter); - RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); - if (animator instanceof SimpleItemAnimator) { - ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); - } - } - - @NonNull - protected ViewTypeManager getViewTypeManager() { - return new DefaultViewTypeManager(); - } - - @NonNull - protected MaterialAboutList getList() { - return list; - } - - protected boolean shouldAnimate() { - return true; - } - - protected void refreshMaterialAboutList() { - setMaterialAboutList(list); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - onBackPressed(); - return true; - } - return super.onOptionsItemSelected(item); - } - - private void onTaskFinished(@Nullable MaterialAboutList materialAboutList) { - if (materialAboutList != null) { - list = materialAboutList; - adapter.setData(list.getCards()); - - if (shouldAnimate()) { - recyclerView.animate() - .alpha(1f) - .translationY(0f) - .setDuration(600) - .setInterpolator(new FastOutSlowInInterpolator()).start(); - } else { - recyclerView.setAlpha(1f); - recyclerView.setTranslationY(0f); - } - } else { - finish();//?? why we remain here anyway? - } - } - - protected void setMaterialAboutList(MaterialAboutList materialAboutList) { - list = materialAboutList; - adapter.setData(list.getCards()); - } - - protected void setScrollToolbar(boolean scrollToolbar) { - if (toolbar != null) { - AppBarLayout.LayoutParams params = - (AppBarLayout.LayoutParams) toolbar.getLayoutParams(); - if (scrollToolbar) { - params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL - | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - } else { - params.setScrollFlags(0); - } - } - } - - private static class ListTask extends AsyncTask { - - private WeakReference context; - - ListTask(MaterialAboutActivity context) { - this.context = new WeakReference<>(context); - } - - @Override - protected MaterialAboutList doInBackground(String... params) { - return isCancelled() || context.get() == null ? null : context.get().getMaterialAboutList(context.get()); - } - - @Override - protected void onPostExecute(MaterialAboutList materialAboutList) { - super.onPostExecute(materialAboutList); - if (context.get() != null) { - if (!context.get().isFinishing()) { - context.get().onTaskFinished(materialAboutList); - } - } - context = null; - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/MaterialAboutFragment.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/MaterialAboutFragment.java deleted file mode 100644 index c3ad1f04..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/MaterialAboutFragment.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.danielstone.materialaboutlibrary; - -import android.content.Context; -import android.os.AsyncTask; -import android.os.Bundle; - -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.interpolator.view.animation.FastOutSlowInInterpolator; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.SimpleItemAnimator; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.danielstone.materialaboutlibrary.adapters.MaterialAboutListAdapter; -import com.danielstone.materialaboutlibrary.model.MaterialAboutList; -import com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -public abstract class MaterialAboutFragment extends Fragment { - - private MaterialAboutList list = new MaterialAboutList.Builder().build(); - private RecyclerView recyclerView; - private MaterialAboutListAdapter adapter; - - public static MaterialAboutFragment newInstance(MaterialAboutFragment fragment) { - return fragment; - } - - protected abstract MaterialAboutList getMaterialAboutList(Context activityContext); - - protected int getTheme() { - return R.style.Theme_Mal_Light; - } - - protected boolean shouldAnimate() { - return true; - } - - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - int style = getTheme(); - - // create ContextThemeWrapper from the original Activity Context with the custom theme - final Context contextThemeWrapper = new android.view.ContextThemeWrapper(getActivity(), style); - LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper); - View rootView = localInflater.inflate(R.layout.mal_material_about_fragment, container, false); - - recyclerView = (RecyclerView) rootView.findViewById(R.id.mal_recyclerview); - adapter = new MaterialAboutListAdapter(getViewTypeManager()); - recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - recyclerView.setAdapter(adapter); - - RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); - if (animator instanceof SimpleItemAnimator) { - ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); - } - - recyclerView.setAlpha(0f); - recyclerView.setTranslationY(20); - - ListTask task = new ListTask(getActivity()); - task.execute(); - - return rootView; - } - - protected ViewTypeManager getViewTypeManager() { - return new DefaultViewTypeManager(); - } - - protected MaterialAboutList getList() { - return list; - } - - protected void setMaterialAboutList(MaterialAboutList materialAboutList) { - //recyclerView.stopScroll(); - //recyclerView.getRecycledViewPool().clear(); - list = materialAboutList; - adapter.setData(list.getCards()); - } - - @Override - public void onPause() { - super.onPause(); - } - - protected void refreshMaterialAboutList() { - setMaterialAboutList(list); - } - - private class ListTask extends AsyncTask { - - Context fragmentContext; - - public ListTask(Context activityContext) { - this.fragmentContext = activityContext; - } - - @Override - protected String doInBackground(String... params) { - list = getMaterialAboutList(fragmentContext); - return null; - } - - @Override - protected void onPostExecute(String s) { - if (list == null) - return;// TODO: 2019-05-09 dirty fix tbh - adapter.setData(list.getCards()); - - if (shouldAnimate()) { - recyclerView.animate() - .alpha(1f) - .translationY(0f) - .setDuration(600) - .setInterpolator(new FastOutSlowInInterpolator()) - .start(); - } else { - recyclerView.setAlpha(1f); - recyclerView.setTranslationY(0f); - } - - super.onPostExecute(s); - fragmentContext = null; - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/adapters/MaterialAboutItemAdapter.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/adapters/MaterialAboutItemAdapter.java deleted file mode 100644 index a3cd1e47..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/adapters/MaterialAboutItemAdapter.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.danielstone.materialaboutlibrary.adapters; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.AsyncListDiffer; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.RecyclerView; - -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.items.MaterialAboutItem; -import com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -public class MaterialAboutItemAdapter extends RecyclerView.Adapter { - - private final AsyncListDiffer differ = new AsyncListDiffer(this, DIFF_CALLBACK); - - private ViewTypeManager viewTypeManager; - - private Context context; - - private List data = new ArrayList<>(); - private List oldData = new ArrayList<>(); - - MaterialAboutItemAdapter() { - setHasStableIds(true); - this.viewTypeManager = new DefaultViewTypeManager(); - } - - MaterialAboutItemAdapter(ViewTypeManager customViewTypeManager) { - //Log.d("MaterialItem", "Created adapter"); - setHasStableIds(true); - this.viewTypeManager = customViewTypeManager; - } - - @NonNull - @Override - public MaterialAboutItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { - context = viewGroup.getContext(); - if (!(viewGroup instanceof RecyclerView)) { - throw new RuntimeException("Not bound to RecyclerView"); - } - - int layoutId = viewTypeManager.getLayout(viewType); - - View view = LayoutInflater.from(viewGroup.getContext()).inflate(layoutId, viewGroup, false); - view.setFocusable(true); - - return viewTypeManager.getViewHolder(viewType, view); - } - - @Override - public void onBindViewHolder(MaterialAboutItemViewHolder holder, int position) { - /*if (data.get(position) instanceof MaterialAboutSwitchItem) { - Log.d("MaterialAdapter", "Item "+((MaterialAboutSwitchItem) data.get(position)).getText()+" checked "+((MaterialAboutSwitchItem) data.get(position)).getChecked()); - }*/ - //Log.d("MaterialItem", "Binding "+data.get(position).getDetailString()); - viewTypeManager.setupItem(getItemViewType(position), holder, data.get(position), context); - } - - - @Override - public long getItemId(int position) { - return UUID.fromString(data.get(position).getId()).getMostSignificantBits() & Long.MAX_VALUE; - } - - @Override - public int getItemCount() { - return data.size(); - } - - @Override - public int getItemViewType(int position) { - return data.get(position).getType(); - } - - public void setData(ArrayList data) { - this.data = data; - - notifyDataSetChanged(); - // diff this with previous data - /*DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyDiffCallback(oldData, data)); - try { - diffResult.dispatchUpdatesTo(this); - } - catch (IllegalStateException e) { - e.printStackTrace(); - } - - // clone the new data to make further diffs - oldData = new ArrayList<>(); - for (MaterialAboutItem item : data) { - oldData.add(item.clone()); - }*/ - - /*List newData = new ArrayList<>(); - for (MaterialAboutItem item : data) { - newData.add(item.clone()); - } - differ.submitList(newData);*/ - } - - public List getData() { - return data; - } - - - public static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @Override - public boolean areItemsTheSame(MaterialAboutItem oldItem, MaterialAboutItem newItem) { - return oldItem.getId().equals(newItem.getId()); - } - - @Override - public boolean areContentsTheSame(MaterialAboutItem oldItem, MaterialAboutItem newItem) { - return oldItem.getDetailString().equals(newItem.getDetailString()); - } - }; - - public class MyDiffCallback extends DiffUtil.Callback{ - - List oldPersons; - List newPersons; - - public MyDiffCallback(List newPersons, List oldPersons) { - this.newPersons = newPersons; - this.oldPersons = oldPersons; - } - - @Override - public int getOldListSize() { - return oldPersons.size(); - } - - @Override - public int getNewListSize() { - return newPersons.size(); - } - - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return oldPersons.get(oldItemPosition).getId().equals(newPersons.get(newItemPosition).getId()); - } - - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return oldPersons.get(oldItemPosition).getDetailString().equals(newPersons.get(newItemPosition).getDetailString()); - } - - @Nullable - @Override - public Object getChangePayload(int oldItemPosition, int newItemPosition) { - //you can return particular field for changed item. - return super.getChangePayload(oldItemPosition, newItemPosition); - } - } - -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/adapters/MaterialAboutListAdapter.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/adapters/MaterialAboutListAdapter.java deleted file mode 100644 index e795ee31..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/adapters/MaterialAboutListAdapter.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.danielstone.materialaboutlibrary.adapters; - -import android.content.Context; - -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.AsyncListDiffer; -import androidx.recyclerview.widget.DiffUtil; -import androidx.cardview.widget.CardView; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.danielstone.materialaboutlibrary.R; -import com.danielstone.materialaboutlibrary.model.MaterialAboutCard; -import com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; -import com.google.android.material.card.MaterialCardView; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -public class MaterialAboutListAdapter extends RecyclerView.Adapter { - - private final AsyncListDiffer differ = new AsyncListDiffer(this, DIFF_CALLBACK); - - private ViewTypeManager viewTypeManager; - - private Context context; - - private List data = new ArrayList<>(); - private List oldData = new ArrayList<>(); - - public MaterialAboutListAdapter() { - setHasStableIds(true); - this.viewTypeManager = new DefaultViewTypeManager(); - } - - public MaterialAboutListAdapter(ViewTypeManager customViewTypeManager) { - //Log.d("MaterialList", "Created list adapter"); - setHasStableIds(true); - this.viewTypeManager = customViewTypeManager; - } - - @Override - public MaterialAboutListViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - context = viewGroup.getContext(); - if (viewGroup instanceof RecyclerView) { - View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.mal_material_about_list_card, viewGroup, false); - view.setFocusable(true); - return new MaterialAboutListViewHolder(view); - } else { - throw new RuntimeException("Not bound to RecyclerView"); - } - } - - @Override - public void onBindViewHolder(MaterialAboutListViewHolder holder, int position) { - MaterialAboutCard card = data.get(position); - - if (holder.cardView instanceof CardView) { - CardView cardView = (CardView) holder.cardView; - int cardColor = card.getCardColor(); - if (cardColor != 0) { - cardView.setCardBackgroundColor(cardColor); - } - } - - CharSequence title = card.getTitle(); - int titleRes = card.getTitleRes(); - - holder.title.setVisibility(View.VISIBLE); - if (title != null) { - holder.title.setText(title); - } else if (titleRes != 0) { - holder.title.setText(titleRes); - } else { - holder.title.setVisibility(View.GONE); - } - - int titleColor = card.getTitleColor(); - - if (holder.title.getVisibility() == View.VISIBLE) { - if (titleColor != 0) { - holder.title.setTextColor(titleColor); - } else { - holder.title.setTextColor(holder.title.getTextColors().getDefaultColor()); - } - } - - if (card.getCustomAdapter() != null) { - holder.useCustomAdapter(card.getCustomAdapter()); - } else { - holder.useMaterialAboutItemAdapter(); - ((MaterialAboutItemAdapter) holder.adapter).setData(card.getItems()); - } - } - - @Override - public long getItemId(int position) { - return UUID.fromString(data.get(position).getId()).getMostSignificantBits() & Long.MAX_VALUE; - } - - @Override - public int getItemCount() { - return data.size(); - } - - public void setData(ArrayList data) { - this.data = data; - - notifyDataSetChanged(); - - /*// diff this with previous data - DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new MyDiffCallback(oldData, data)); - try { - diffResult.dispatchUpdatesTo(this); - } - catch (IllegalStateException e) { - e.printStackTrace(); - } - - // clone the new data to make further diffs - oldData = new ArrayList<>(); - for (MaterialAboutCard card : data) { - oldData.add(card.clone()); - }*/ - //differ.submitList(newData); - } - - - List getData() { - return data; - } - - class MaterialAboutListViewHolder extends RecyclerView.ViewHolder { - - final View cardView; - final TextView title; - final RecyclerView recyclerView; - RecyclerView.Adapter adapter; - - MaterialAboutListViewHolder(View view) { - super(view); - cardView = view.findViewById(R.id.mal_list_card); - title = (TextView) view.findViewById(R.id.mal_list_card_title); - recyclerView = (RecyclerView) view.findViewById(R.id.mal_card_recyclerview); - adapter = new MaterialAboutItemAdapter(viewTypeManager); - recyclerView.setLayoutManager(new LinearLayoutManager(context)); - recyclerView.setAdapter(adapter); - recyclerView.setNestedScrollingEnabled(false); - } - - public void useMaterialAboutItemAdapter() { - if (!(adapter instanceof MaterialAboutItemAdapter)) { - adapter = new MaterialAboutItemAdapter(viewTypeManager); - recyclerView.setLayoutManager(new LinearLayoutManager(context)); - recyclerView.setAdapter(adapter); - } - } - - public void useCustomAdapter(RecyclerView.Adapter newAdapter) { - if (adapter instanceof MaterialAboutItemAdapter) { - recyclerView.setLayoutManager(new LinearLayoutManager(context)); - recyclerView.setAdapter(newAdapter); - } - } - } - - - public static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @Override - public boolean areItemsTheSame(MaterialAboutCard oldItem, MaterialAboutCard newItem) { - return oldItem.getId().equals(newItem.getId()); - } - - @Override - public boolean areContentsTheSame(MaterialAboutCard oldCard, MaterialAboutCard newCard) { - boolean result; - result = oldCard.toString().equals(newCard.toString()); - if (oldCard.getItems().size() != newCard.getItems().size()) return false; - for (int i = 0; i < oldCard.getItems().size(); i++) { - if (!oldCard.getItems().get(i).getDetailString().equals(newCard.getItems().get(i).getDetailString())) return false; - } - return result; - } - }; - - public class MyDiffCallback extends DiffUtil.Callback{ - - List oldPersons; - List newPersons; - - public MyDiffCallback(List newPersons, List oldPersons) { - this.newPersons = newPersons; - this.oldPersons = oldPersons; - } - - @Override - public int getOldListSize() { - return oldPersons.size(); - } - - @Override - public int getNewListSize() { - return newPersons.size(); - } - - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return oldPersons.get(oldItemPosition).getId().equals(newPersons.get(newItemPosition).getId()); - } - - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - boolean result; - result = oldPersons.get(oldItemPosition).toString().equals(newPersons.get(newItemPosition).toString()); - if (oldPersons.get(oldItemPosition).getItems().size() != newPersons.get(newItemPosition).getItems().size()) return false; - for (int i = 0; i < oldPersons.get(oldItemPosition).getItems().size(); i++) { - if (!oldPersons.get(oldItemPosition).getItems().get(i).getDetailString().equals(newPersons.get(newItemPosition).getItems().get(i).getDetailString())) return false; - } - return result; - } - - @Nullable - @Override - public Object getChangePayload(int oldItemPosition, int newItemPosition) { - //you can return particular field for changed item. - return super.getChangePayload(oldItemPosition, newItemPosition); - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/holders/MaterialAboutItemViewHolder.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/holders/MaterialAboutItemViewHolder.java deleted file mode 100644 index 6188817b..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/holders/MaterialAboutItemViewHolder.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.danielstone.materialaboutlibrary.holders; - -import androidx.recyclerview.widget.RecyclerView; -import android.view.View; - -public abstract class MaterialAboutItemViewHolder extends RecyclerView.ViewHolder { - - public MaterialAboutItemViewHolder(View itemView) { - super(itemView); - } - -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutActionItem.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutActionItem.java deleted file mode 100644 index c69f106d..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutActionItem.java +++ /dev/null @@ -1,488 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Build; - -import androidx.annotation.ColorInt; -import androidx.annotation.DrawableRes; -import androidx.annotation.IntDef; -import androidx.annotation.StringRes; -import android.text.Html; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.danielstone.materialaboutlibrary.R; -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import static android.view.View.GONE; - -public class MaterialAboutActionItem extends MaterialAboutItem { - - public static final int GRAVITY_TOP = 0; - public static final int GRAVITY_MIDDLE = 1; - public static final int GRAVITY_BOTTOM = 2; - private CharSequence text = null; - private int textRes = 0; - private CharSequence subText = null; - private int subTextRes = 0; - private int textColor = -1; - private int subTextColor = -1; - private Drawable icon = null; - private int iconRes = 0; - private boolean showIcon = true; - private int iconGravity = GRAVITY_MIDDLE; - private MaterialAboutItemOnClickAction onClickAction = null; - private MaterialAboutItemOnClickAction onLongClickAction = null; - - private MaterialAboutActionItem(Builder builder) { - super(); - this.text = builder.text; - this.textRes = builder.textRes; - - this.subText = builder.subText; - this.subTextRes = builder.subTextRes; - - this.textColor = builder.textColor; - this.subTextColor = builder.subTextColor; - - this.icon = builder.icon; - this.iconRes = builder.iconRes; - - this.showIcon = builder.showIcon; - - this.iconGravity = builder.iconGravity; - - this.onClickAction = builder.onClickAction; - this.onLongClickAction = builder.onLongClickAction; - } - - public MaterialAboutActionItem(CharSequence text, CharSequence subText, Drawable icon, MaterialAboutItemOnClickAction onClickAction) { - this.text = text; - this.subText = subText; - this.icon = icon; - this.onClickAction = onClickAction; - } - - public MaterialAboutActionItem(CharSequence text, CharSequence subText, Drawable icon) { - this.text = text; - this.subText = subText; - this.icon = icon; - } - - public MaterialAboutActionItem(int textRes, int subTextRes, int iconRes, MaterialAboutItemOnClickAction onClickAction) { - this.textRes = textRes; - this.subTextRes = subTextRes; - this.iconRes = iconRes; - this.onClickAction = onClickAction; - } - - public MaterialAboutActionItem(int textRes, int subTextRes, int iconRes) { - this.textRes = textRes; - this.subTextRes = subTextRes; - this.iconRes = iconRes; - } - - public static MaterialAboutItemViewHolder getViewHolder(View view) { - return new MaterialAboutActionItemViewHolder(view); - } - - public static void setupItem(MaterialAboutActionItemViewHolder holder, MaterialAboutActionItem item, Context context) { - CharSequence text = item.getText(); - int textRes = item.getTextRes(); - - holder.text.setVisibility(View.VISIBLE); - if (text != null) { - holder.text.setText(text); - } else if (textRes != 0) { - holder.text.setText(textRes); - } else { - holder.text.setVisibility(GONE); - } - - CharSequence subText = item.getSubText(); - int subTextRes = item.getSubTextRes(); - - holder.subText.setVisibility(View.VISIBLE); - if (subText != null) { - holder.subText.setText(subText); - } else if (subTextRes != 0) { - holder.subText.setText(subTextRes); - } else { - holder.subText.setVisibility(GONE); - } - - if (item.getTextColor() != -1) { - holder.text.setTextColor(item.getTextColor()); - } - if (item.getSubTextColor() != -1) { - holder.subText.setTextColor(item.getSubTextColor()); - } - - if (item.shouldShowIcon()) { - holder.icon.setVisibility(View.VISIBLE); - Drawable drawable = item.getIcon(); - int drawableRes = item.getIconRes(); - if (drawable != null) { - holder.icon.setImageDrawable(drawable); - } else if (drawableRes != 0) { - holder.icon.setImageResource(drawableRes); - } - } else { - holder.icon.setVisibility(GONE); - } - - LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) holder.icon.getLayoutParams(); - switch (item.getIconGravity()) { - case MaterialAboutActionItem.GRAVITY_TOP: - params.gravity = Gravity.TOP; - break; - case MaterialAboutActionItem.GRAVITY_MIDDLE: - params.gravity = Gravity.CENTER_VERTICAL; - break; - case MaterialAboutActionItem.GRAVITY_BOTTOM: - params.gravity = Gravity.BOTTOM; - break; - } - holder.icon.setLayoutParams(params); - - int pL = 0, pT = 0, pR = 0, pB = 0; - if (Build.VERSION.SDK_INT < 21) { - pL = holder.view.getPaddingLeft(); - pT = holder.view.getPaddingTop(); - pR = holder.view.getPaddingRight(); - pB = holder.view.getPaddingBottom(); - } - - if (item.getOnClickAction() != null || item.getOnLongClickAction() != null) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, true); - holder.view.setBackgroundResource(outValue.resourceId); - } else { - holder.view.setBackgroundResource(0); - } - holder.setOnClickAction(item.getOnClickAction()); - holder.setOnLongClickAction(item.getOnLongClickAction()); - - if (Build.VERSION.SDK_INT < 21) { - holder.view.setPadding(pL, pT, pR, pB); - } - } - - @Override - public int getType() { - return ViewTypeManager.ItemType.ACTION_ITEM; - } - - @Override - public String getDetailString() { - return "MaterialAboutActionItem{" + - "text=" + text + - ", textRes=" + textRes + - ", subText=" + subText + - ", subTextRes=" + subTextRes + - ", textColor=" + textColor + - ", descColor=" + subTextColor + - ", icon=" + icon + - ", iconRes=" + iconRes + - ", showIcon=" + showIcon + - ", iconGravity=" + iconGravity + - ", onClickAction=" + onClickAction + - ", onLongClickAction=" + onLongClickAction + - '}'; - } - - public MaterialAboutActionItem(MaterialAboutActionItem item) { - this.id = item.getId(); - this.text = item.getText(); - this.textRes = item.getTextRes(); - this.subText = item.getSubText(); - this.subTextRes = item.getSubTextRes(); - this.textColor = item.getTextColor(); - this.subTextColor = item.getSubTextColor(); - this.icon = item.getIcon(); - this.iconRes = item.getIconRes(); - this.showIcon = item.showIcon; - this.iconGravity = item.iconGravity; - this.onClickAction = item.onClickAction; - this.onLongClickAction = item.onLongClickAction; - } - - @Override - public MaterialAboutItem clone() { - return new MaterialAboutActionItem(this); - } - - public CharSequence getText() { - return text; - } - public MaterialAboutActionItem setText(CharSequence text) { - this.textRes = 0; - this.text = text; - return this; - } - - public int getTextRes() { - return textRes; - } - - public MaterialAboutActionItem setTextRes(int textRes) { - this.text = null; - this.textRes = textRes; - return this; - } - - public CharSequence getSubText() { - return subText; - } - - public MaterialAboutActionItem setSubText(CharSequence subText) { - this.subTextRes = 0; - this.subText = subText; - return this; - } - - public int getSubTextRes() { - return subTextRes; - } - - public MaterialAboutActionItem setSubTextRes(int subTextRes) { - this.subText = null; - this.subTextRes = subTextRes; - return this; - } - - public int getTextColor() { - return textColor; - } - - public MaterialAboutActionItem setTextColor(int textColor) { - this.textColor = textColor; - return this; - } - - public int getSubTextColor() { - return subTextColor; - } - - public MaterialAboutActionItem setSubTextColor(int subTextColor) { - this.subTextColor = subTextColor; - return this; - } - - public Drawable getIcon() { - return icon; - } - - public MaterialAboutActionItem setIcon(Drawable icon) { - this.iconRes = 0; - this.icon = icon; - return this; - } - - public int getIconRes() { - return iconRes; - } - - public MaterialAboutActionItem setIconRes(int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public boolean shouldShowIcon() { - return showIcon; - } - - public MaterialAboutActionItem setShouldShowIcon(boolean showIcon) { - this.showIcon = showIcon; - return this; - } - - @IconGravity - public int getIconGravity() { - return iconGravity; - } - - public MaterialAboutActionItem setIconGravity(int iconGravity) { - this.iconGravity = iconGravity; - return this; - } - - public MaterialAboutItemOnClickAction getOnClickAction() { - return onClickAction; - } - - public MaterialAboutActionItem setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - return this; - } - - public MaterialAboutItemOnClickAction getOnLongClickAction() { - return onLongClickAction; - } - - public MaterialAboutActionItem setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - return this; - } - - @Retention(RetentionPolicy.SOURCE) - @IntDef({GRAVITY_TOP, GRAVITY_MIDDLE, GRAVITY_BOTTOM}) - public @interface IconGravity { - } - - public static class MaterialAboutActionItemViewHolder extends MaterialAboutItemViewHolder implements View.OnClickListener, View.OnLongClickListener { - public final View view; - public final ImageView icon; - public final TextView text; - public final TextView subText; - private MaterialAboutItemOnClickAction onClickAction; - private MaterialAboutItemOnClickAction onLongClickAction; - - MaterialAboutActionItemViewHolder(View view) { - super(view); - this.view = view; - icon = (ImageView) view.findViewById(R.id.mal_item_image); - text = (TextView) view.findViewById(R.id.mal_item_text); - subText = (TextView) view.findViewById(R.id.mal_action_item_subtext); - } - - public void setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - view.setOnClickListener(onClickAction != null ? this : null); - } - - public void setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - view.setOnLongClickListener(onLongClickAction != null ? this : null); - } - - @Override - public void onClick(View v) { - if (onClickAction != null) { - onClickAction.onClick(); - } - } - - @Override - public boolean onLongClick(View v) { - if (onLongClickAction != null) { - onLongClickAction.onClick(); - return true; - } - return false; - } - } - - public static class Builder { - - MaterialAboutItemOnClickAction onClickAction = null; - MaterialAboutItemOnClickAction onLongClickAction = null; - private CharSequence text = null; - @StringRes - private int textRes = 0; - private CharSequence subText = null; - @StringRes - private int subTextRes = 0; - @ColorInt - private int textColor = -1; - @ColorInt - private int subTextColor = -1; - private Drawable icon = null; - @DrawableRes - private int iconRes = 0; - private boolean showIcon = true; - @IconGravity - private int iconGravity = GRAVITY_MIDDLE; - - public Builder text(CharSequence text) { - this.text = text; - this.textRes = 0; - return this; - } - - public Builder text(@StringRes int text) { - this.textRes = text; - this.text = null; - return this; - } - - public Builder subText(CharSequence subText) { - this.subText = subText; - this.subTextRes = 0; - return this; - } - - public Builder subText(@StringRes int subTextRes) { - this.subText = null; - this.subTextRes = subTextRes; - return this; - } - - public Builder textColor(@ColorInt int textColor) { - this.textColor = textColor; - return this; - } - - public Builder subTextColor(@ColorInt int subTextColor) { - this.subTextColor = subTextColor; - return this; - } - - public Builder subTextHtml(String subTextHtml) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - this.subText = Html.fromHtml(subTextHtml, Html.FROM_HTML_MODE_LEGACY); - } else { - //noinspection deprecation - this.subText = Html.fromHtml(subTextHtml); - } - this.subTextRes = 0; - return this; - } - - public Builder icon(Drawable icon) { - this.icon = icon; - this.iconRes = 0; - return this; - } - - public Builder icon(@DrawableRes int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public Builder showIcon(boolean showIcon) { - this.showIcon = showIcon; - return this; - } - - public Builder setIconGravity(@IconGravity int iconGravity) { - this.iconGravity = iconGravity; - return this; - } - - public Builder setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - return this; - } - - public Builder setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - return this; - } - - public MaterialAboutActionItem build() { - return new MaterialAboutActionItem(this); - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutActionSwitchItem.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutActionSwitchItem.java deleted file mode 100644 index eb6d9411..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutActionSwitchItem.java +++ /dev/null @@ -1,606 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Build; -import androidx.annotation.DrawableRes; -import androidx.annotation.IntDef; -import androidx.annotation.StringRes; -import androidx.appcompat.widget.SwitchCompat; - -import android.text.Html; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.Switch; -import android.widget.TextView; - -import com.danielstone.materialaboutlibrary.R; -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import static android.view.View.GONE; - -public class MaterialAboutActionSwitchItem extends MaterialAboutItem { - - public static final int GRAVITY_TOP = 0; - public static final int GRAVITY_MIDDLE = 1; - public static final int GRAVITY_BOTTOM = 2; - private CharSequence text = null; - private int textRes = 0; - private CharSequence subText = null; - private int subTextRes = 0; - private CharSequence subTextChecked = null; - private int subTextCheckedRes = 0; - private Drawable icon = null; - private int iconRes = 0; - private boolean showIcon = true; - private int iconGravity = GRAVITY_MIDDLE; - private boolean checked = false; - private int tag = -1; - private MaterialAboutItemOnClickAction onClickAction = null; - private MaterialAboutItemOnClickAction onLongClickAction = null; - private MaterialAboutItemOnChangeAction onChangeAction = null; - - private MaterialAboutActionSwitchItem(Builder builder) { - super(); - this.text = builder.text; - this.textRes = builder.textRes; - - this.subText = builder.subText; - this.subTextRes = builder.subTextRes; - - this.subTextChecked = builder.subTextChecked; - this.subTextCheckedRes = builder.subTextCheckedRes; - - this.icon = builder.icon; - this.iconRes = builder.iconRes; - - this.showIcon = builder.showIcon; - - this.iconGravity = builder.iconGravity; - - this.checked = builder.checked; - - this.tag = builder.tag; - - this.onClickAction = builder.onClickAction; - this.onLongClickAction = builder.onLongClickAction; - this.onChangeAction = builder.onChangeAction; - } - - public MaterialAboutActionSwitchItem(CharSequence text, CharSequence subText, Drawable icon, MaterialAboutItemOnChangeAction onChangeAction) { - this.text = text; - this.subText = subText; - this.icon = icon; - this.onChangeAction = onChangeAction; - } - - public MaterialAboutActionSwitchItem(CharSequence text, CharSequence subText, Drawable icon) { - this.text = text; - this.subText = subText; - this.icon = icon; - } - - public MaterialAboutActionSwitchItem(int textRes, int subTextRes, int iconRes, MaterialAboutItemOnChangeAction onChangeAction) { - this.textRes = textRes; - this.subTextRes = subTextRes; - this.iconRes = iconRes; - this.onChangeAction = onChangeAction; - } - - public MaterialAboutActionSwitchItem(int textRes, int subTextRes, int iconRes) { - this.textRes = textRes; - this.subTextRes = subTextRes; - this.iconRes = iconRes; - } - - public static void setupItem(MaterialAboutActionSwitchItemViewHolder holder, MaterialAboutActionSwitchItem item, Context context) { - holder.switchItem = item; - - CharSequence text = item.getText(); - int textRes = item.getTextRes(); - - holder.text.setVisibility(View.VISIBLE); - if (text != null) { - holder.text.setText(text); - } else if (textRes != 0) { - holder.text.setText(textRes); - } else { - holder.text.setVisibility(GONE); - } - - CharSequence subText = item.getSubText(); - int subTextRes = item.getSubTextRes(); - - holder.subText.setVisibility(View.VISIBLE); - if (subText != null) { - holder.subText.setText(subText); - } else if (subTextRes != 0) { - holder.subText.setText(subTextRes); - } else { - holder.subText.setVisibility(GONE); - } - - if (item.shouldShowIcon()) { - holder.icon.setVisibility(View.VISIBLE); - Drawable drawable = item.getIcon(); - int drawableRes = item.getIconRes(); - if (drawable != null) { - holder.icon.setImageDrawable(drawable); - } else if (drawableRes != 0) { - holder.icon.setImageResource(drawableRes); - } - } else { - holder.icon.setVisibility(GONE); - } - - LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) holder.icon.getLayoutParams(); - switch (item.getIconGravity()) { - case MaterialAboutActionSwitchItem.GRAVITY_TOP: - params.gravity = Gravity.TOP; - break; - case MaterialAboutActionSwitchItem.GRAVITY_MIDDLE: - params.gravity = Gravity.CENTER_VERTICAL; - break; - case MaterialAboutActionSwitchItem.GRAVITY_BOTTOM: - params.gravity = Gravity.BOTTOM; - break; - } - holder.icon.setLayoutParams(params); - - int pL = 0, pT = 0, pR = 0, pB = 0; - if (Build.VERSION.SDK_INT < 21) { - pL = holder.view.getPaddingLeft(); - pT = holder.view.getPaddingTop(); - pR = holder.view.getPaddingRight(); - pB = holder.view.getPaddingBottom(); - } - - holder.setChecked(item.getChecked()); - - if (item.getOnChangeAction() != null || item.getOnClickAction() != null || item.getOnLongClickAction() != null) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, true); - holder.view.setBackgroundResource(outValue.resourceId); - } else { - holder.view.setBackgroundResource(0); - } - holder.setOnClickAction(item.getOnClickAction()); - holder.setOnLongClickAction(item.getOnLongClickAction()); - holder.setOnChangeAction(item.getOnChangeAction()); - - if (Build.VERSION.SDK_INT < 21) { - holder.view.setPadding(pL, pT, pR, pB); - } - } - - public static MaterialAboutItemViewHolder getViewHolder(View view) { - return new MaterialAboutActionSwitchItemViewHolder(view); - } - - public static class MaterialAboutActionSwitchItemViewHolder extends MaterialAboutItemViewHolder implements View.OnClickListener, View.OnLongClickListener, CompoundButton.OnCheckedChangeListener { - public final View view; - public final ImageView icon; - public final TextView text; - public final TextView subText; - public final SwitchCompat switchView; - private MaterialAboutItemOnClickAction onClickAction; - private MaterialAboutItemOnClickAction onLongClickAction; - private MaterialAboutItemOnChangeAction onChangeAction; - private MaterialAboutActionSwitchItem switchItem; - - MaterialAboutActionSwitchItemViewHolder(View view) { - super(view); - this.view = view.findViewById(R.id.mal_action_root); - icon = view.findViewById(R.id.mal_item_image); - text = view.findViewById(R.id.mal_item_text); - subText = view.findViewById(R.id.mal_action_item_subtext); - switchView = view.findViewById(R.id.mal_switch); - } - - public void setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - view.setOnClickListener(onClickAction != null ? this : null); - } - - public void setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - view.setOnLongClickListener(onLongClickAction != null ? this : null); - } - - public void setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - switchView.setOnCheckedChangeListener(this); - } - - public void setChecked(boolean checked) { - switchView.setChecked(checked); - switchItem.checked = checked; - updateSubText(checked); - } - - public void updateSubText(boolean checked) { - if (checked && switchItem.subTextChecked != null) { - subText.setText(switchItem.subTextChecked); - } - else if (checked && switchItem.subTextCheckedRes != 0) { - subText.setText(switchItem.subTextCheckedRes); - } - else if (switchItem.subText != null) { - subText.setText(switchItem.subText); - } - else if (switchItem.subTextRes != 0) { - subText.setText(switchItem.subTextRes); - } - } - - @Override - public void onClick(View v) { - if (onClickAction != null) { - onClickAction.onClick(); - } - } - - @Override - public boolean onLongClick(View v) { - if (onLongClickAction != null) { - onLongClickAction.onClick(); - return true; - } - return false; - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - updateSubText(isChecked); - if (onChangeAction != null) { - if (!onChangeAction.onChange(isChecked, switchItem.getTag())) { - setChecked(!isChecked); - } - else { - switchItem.checked = isChecked; - } - } - else { - setChecked(!isChecked); - } - } - } - - @Override - public int getType() { - return ViewTypeManager.ItemType.ACTION_SWITCH_ITEM; - } - - @Override - public String getDetailString() { - return "MaterialAboutActionSwitchItem{" + - "text=" + text + - ", textRes=" + textRes + - ", subText=" + subText + - ", subTextRes=" + subTextRes + - ", subTextChecked=" + subTextChecked + - ", subTextCheckedRes=" + subTextCheckedRes + - ", icon=" + icon + - ", iconRes=" + iconRes + - ", showIcon=" + showIcon + - ", iconGravity=" + iconGravity + - ", checked=" + checked + - ", tag=" + tag + - ", onClickAction=" + onClickAction + - ", onLongClickAction=" + onLongClickAction + - ", onChangeAction=" + onChangeAction + - '}'; - } - - public MaterialAboutActionSwitchItem(MaterialAboutActionSwitchItem item) { - this.id = item.getId(); - this.text = item.getText(); - this.textRes = item.getTextRes(); - this.subText = item.getSubText(); - this.subTextRes = item.getSubTextRes(); - this.subTextChecked = item.getSubTextChecked(); - this.subTextCheckedRes = item.getSubTextCheckedRes(); - this.icon = item.getIcon(); - this.iconRes = item.getIconRes(); - this.showIcon = item.showIcon; - this.iconGravity = item.iconGravity; - this.checked = item.checked; - this.tag = item.tag; - this.onClickAction = item.onClickAction; - this.onLongClickAction = item.onLongClickAction; - this.onChangeAction = item.onChangeAction; - } - - @Override - public MaterialAboutItem clone() { - return new MaterialAboutActionSwitchItem(this); - } - - public int getTag() { - return tag; - } - public MaterialAboutActionSwitchItem setTag(int tag) { - this.tag = tag; - return this; - } - - public CharSequence getText() { - return text; - } - public MaterialAboutActionSwitchItem setText(CharSequence text) { - this.textRes = 0; - this.text = text; - return this; - } - - public int getTextRes() { - return textRes; - } - - public MaterialAboutActionSwitchItem setTextRes(int textRes) { - this.text = null; - this.textRes = textRes; - return this; - } - - public CharSequence getSubText() { - return subText; - } - - public MaterialAboutActionSwitchItem setSubText(CharSequence subText) { - this.subTextRes = 0; - this.subText = subText; - return this; - } - - public int getSubTextRes() { - return subTextRes; - } - - public MaterialAboutActionSwitchItem setSubTextRes(int subTextRes) { - this.subText = null; - this.subTextRes = subTextRes; - return this; - } - - public CharSequence getSubTextChecked() { - return subTextChecked; - } - - public MaterialAboutActionSwitchItem setSubTextChecked(CharSequence subTextChecked) { - this.subTextCheckedRes = 0; - this.subTextChecked = subTextChecked; - return this; - } - - public int getSubTextCheckedRes() { - return subTextCheckedRes; - } - - public MaterialAboutActionSwitchItem setSubTextCheckedRes(int subTextCheckedRes) { - this.subTextChecked = null; - this.subTextCheckedRes = subTextCheckedRes; - return this; - } - - public Drawable getIcon() { - return icon; - } - - public MaterialAboutActionSwitchItem setIcon(Drawable icon) { - this.iconRes = 0; - this.icon = icon; - return this; - } - - public int getIconRes() { - return iconRes; - } - - public MaterialAboutActionSwitchItem setIconRes(int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public boolean shouldShowIcon() { - return showIcon; - } - - public MaterialAboutActionSwitchItem setShouldShowIcon(boolean showIcon) { - this.showIcon = showIcon; - return this; - } - - @IconGravity - public int getIconGravity() { - return iconGravity; - } - - public MaterialAboutActionSwitchItem setIconGravity(int iconGravity) { - this.iconGravity = iconGravity; - return this; - } - - public boolean getChecked() { - return checked; - } - - public MaterialAboutActionSwitchItem setChecked(boolean checked) { - this.checked = checked; - return this; - } - - public MaterialAboutItemOnClickAction getOnClickAction() { - return onClickAction; - } - - public MaterialAboutActionSwitchItem setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - return this; - } - - public MaterialAboutItemOnClickAction getOnLongClickAction() { - return onLongClickAction; - } - - public MaterialAboutActionSwitchItem setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - return this; - } - - public MaterialAboutItemOnChangeAction getOnChangeAction() { - return onChangeAction; - } - - public MaterialAboutActionSwitchItem setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - return this; - } - - @Retention(RetentionPolicy.SOURCE) - @IntDef({GRAVITY_TOP, GRAVITY_MIDDLE, GRAVITY_BOTTOM}) - public @interface IconGravity { - } - - public static class Builder { - - MaterialAboutItemOnClickAction onClickAction = null; - MaterialAboutItemOnClickAction onLongClickAction = null; - MaterialAboutItemOnChangeAction onChangeAction = null; - private CharSequence text = null; - @StringRes - private int textRes = 0; - private CharSequence subText = null; - @StringRes - private int subTextRes = 0; - private CharSequence subTextChecked = null; - @StringRes - private int subTextCheckedRes = 0; - private Drawable icon = null; - @DrawableRes - private int iconRes = 0; - private boolean showIcon = true; - @IconGravity - private int iconGravity = GRAVITY_MIDDLE; - private boolean checked = false; - private int tag = -1; - - public Builder tag(int tag) { - this.tag = tag; - return this; - } - - public Builder text(CharSequence text) { - this.text = text; - this.textRes = 0; - return this; - } - - public Builder text(@StringRes int text) { - this.textRes = text; - this.text = null; - return this; - } - - public Builder subText(CharSequence subText) { - this.subText = subText; - this.subTextRes = 0; - return this; - } - - public Builder subText(@StringRes int subTextRes) { - this.subText = null; - this.subTextRes = subTextRes; - return this; - } - - public Builder subTextHtml(String subTextHtml) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - this.subText = Html.fromHtml(subTextHtml, Html.FROM_HTML_MODE_LEGACY); - } else { - //noinspection deprecation - this.subText = Html.fromHtml(subTextHtml); - } - this.subTextRes = 0; - return this; - } - - public Builder subTextChecked(CharSequence subTextChecked) { - this.subTextChecked = subTextChecked; - this.subTextCheckedRes = 0; - return this; - } - - public Builder subTextChecked(@StringRes int subTextCheckedRes) { - this.subTextChecked = null; - this.subTextCheckedRes = subTextCheckedRes; - return this; - } - - public Builder subTextCheckedHtml(String subTextCheckedHtml) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - this.subTextChecked = Html.fromHtml(subTextCheckedHtml, Html.FROM_HTML_MODE_LEGACY); - } else { - //noinspection deprecation - this.subTextChecked = Html.fromHtml(subTextCheckedHtml); - } - this.subTextCheckedRes = 0; - return this; - } - - public Builder icon(Drawable icon) { - this.icon = icon; - this.iconRes = 0; - return this; - } - - public Builder icon(@DrawableRes int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public Builder showIcon(boolean showIcon) { - this.showIcon = showIcon; - return this; - } - - public Builder setIconGravity(@IconGravity int iconGravity) { - this.iconGravity = iconGravity; - return this; - } - - public Builder setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - return this; - } - - public Builder setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - return this; - } - - public Builder setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - return this; - } - - public Builder checked(boolean isChecked) { - this.checked = isChecked; - return this; - } - - public MaterialAboutActionSwitchItem build() { - return new MaterialAboutActionSwitchItem(this); - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutCheckboxItem.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutCheckboxItem.java deleted file mode 100644 index 16a6cd45..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutCheckboxItem.java +++ /dev/null @@ -1,538 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Build; -import androidx.annotation.DrawableRes; -import androidx.annotation.IntDef; -import androidx.annotation.StringRes; -import android.text.Html; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.danielstone.materialaboutlibrary.R; -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import static android.view.View.GONE; - -public class MaterialAboutCheckboxItem extends MaterialAboutItem { - - public static final int GRAVITY_TOP = 0; - public static final int GRAVITY_MIDDLE = 1; - public static final int GRAVITY_BOTTOM = 2; - private CharSequence text = null; - private int textRes = 0; - private CharSequence subText = null; - private int subTextRes = 0; - private CharSequence subTextChecked = null; - private int subTextCheckedRes = 0; - private Drawable icon = null; - private int iconRes = 0; - private boolean showIcon = true; - private int iconGravity = GRAVITY_MIDDLE; - private boolean checked = false; - private int tag = -1; - private MaterialAboutItemOnChangeAction onChangeAction = null; - - private MaterialAboutCheckboxItem(Builder builder) { - super(); - this.text = builder.text; - this.textRes = builder.textRes; - - this.subText = builder.subText; - this.subTextRes = builder.subTextRes; - - this.subTextChecked = builder.subTextChecked; - this.subTextCheckedRes = builder.subTextCheckedRes; - - this.icon = builder.icon; - this.iconRes = builder.iconRes; - - this.showIcon = builder.showIcon; - - this.iconGravity = builder.iconGravity; - - this.checked = builder.checked; - - this.tag = builder.tag; - - this.onChangeAction = builder.onChangeAction; - } - - public MaterialAboutCheckboxItem(CharSequence text, CharSequence subText, Drawable icon, MaterialAboutItemOnChangeAction onChangeAction) { - this.text = text; - this.subText = subText; - this.icon = icon; - this.onChangeAction = onChangeAction; - } - - public MaterialAboutCheckboxItem(CharSequence text, CharSequence subText, Drawable icon) { - this.text = text; - this.subText = subText; - this.icon = icon; - } - - public MaterialAboutCheckboxItem(int textRes, int subTextRes, int iconRes, MaterialAboutItemOnChangeAction onChangeAction) { - this.textRes = textRes; - this.subTextRes = subTextRes; - this.iconRes = iconRes; - this.onChangeAction = onChangeAction; - } - - public MaterialAboutCheckboxItem(int textRes, int subTextRes, int iconRes) { - this.textRes = textRes; - this.subTextRes = subTextRes; - this.iconRes = iconRes; - } - - public static MaterialAboutItemViewHolder getViewHolder(View view) { - return new MaterialAboutCheckboxItemViewHolder(view); - } - - public static void setupItem(MaterialAboutCheckboxItemViewHolder holder, MaterialAboutCheckboxItem item, Context context) { - holder.switchItem = item; - - CharSequence text = item.getText(); - int textRes = item.getTextRes(); - - holder.text.setVisibility(View.VISIBLE); - if (text != null) { - holder.text.setText(text); - } else if (textRes != 0) { - holder.text.setText(textRes); - } else { - holder.text.setVisibility(GONE); - } - - CharSequence subText = item.getSubText(); - int subTextRes = item.getSubTextRes(); - - holder.subText.setVisibility(View.VISIBLE); - if (subText != null) { - holder.subText.setText(subText); - } else if (subTextRes != 0) { - holder.subText.setText(subTextRes); - } else { - holder.subText.setVisibility(GONE); - } - - if (item.shouldShowIcon()) { - holder.icon.setVisibility(View.VISIBLE); - Drawable drawable = item.getIcon(); - int drawableRes = item.getIconRes(); - if (drawable != null) { - holder.icon.setImageDrawable(drawable); - } else if (drawableRes != 0) { - holder.icon.setImageResource(drawableRes); - } - } else { - holder.icon.setVisibility(GONE); - } - - LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) holder.icon.getLayoutParams(); - switch (item.getIconGravity()) { - case MaterialAboutCheckboxItem.GRAVITY_TOP: - params.gravity = Gravity.TOP; - break; - case MaterialAboutCheckboxItem.GRAVITY_MIDDLE: - params.gravity = Gravity.CENTER_VERTICAL; - break; - case MaterialAboutCheckboxItem.GRAVITY_BOTTOM: - params.gravity = Gravity.BOTTOM; - break; - } - holder.icon.setLayoutParams(params); - - int pL = 0, pT = 0, pR = 0, pB = 0; - if (Build.VERSION.SDK_INT < 21) { - pL = holder.view.getPaddingLeft(); - pT = holder.view.getPaddingTop(); - pR = holder.view.getPaddingRight(); - pB = holder.view.getPaddingBottom(); - } - - - if (item.getOnChangeAction() != null) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, true); - holder.view.setBackgroundResource(outValue.resourceId); - } else { - holder.view.setBackgroundResource(0); - } - holder.setOnChangeAction(item.getOnChangeAction()); - - if (Build.VERSION.SDK_INT < 21) { - holder.view.setPadding(pL, pT, pR, pB); - } - } - - @Override - public int getType() { - return ViewTypeManager.ItemType.CHECKBOX_ITEM; - } - - @Override - public String getDetailString() { - return "MaterialAboutCheckboxItem{" + - "text=" + text + - ", textRes=" + textRes + - ", subText=" + subText + - ", subTextRes=" + subTextRes + - ", subTextChecked=" + subTextChecked + - ", subTextCheckedRes=" + subTextCheckedRes + - ", icon=" + icon + - ", iconRes=" + iconRes + - ", showIcon=" + showIcon + - ", iconGravity=" + iconGravity + - ", checked=" + checked + - ", tag=" + tag + - ", onChangeAction=" + onChangeAction + - '}'; - } - - public MaterialAboutCheckboxItem(MaterialAboutCheckboxItem item) { - this.id = item.getId(); - this.text = item.getText(); - this.textRes = item.getTextRes(); - this.subText = item.getSubText(); - this.subTextRes = item.getSubTextRes(); - this.subTextChecked = item.getSubTextChecked(); - this.subTextCheckedRes = item.getSubTextCheckedRes(); - this.icon = item.getIcon(); - this.iconRes = item.getIconRes(); - this.showIcon = item.showIcon; - this.iconGravity = item.iconGravity; - this.checked = item.checked; - this.tag = item.tag; - this.onChangeAction = item.onChangeAction; - } - - @Override - public MaterialAboutItem clone() { - return new MaterialAboutCheckboxItem(this); - } - - public int getTag() { - return tag; - } - public MaterialAboutCheckboxItem setTag(int tag) { - this.tag = tag; - return this; - } - - public CharSequence getText() { - return text; - } - public MaterialAboutCheckboxItem setText(CharSequence text) { - this.textRes = 0; - this.text = text; - return this; - } - - public int getTextRes() { - return textRes; - } - - public MaterialAboutCheckboxItem setTextRes(int textRes) { - this.text = null; - this.textRes = textRes; - return this; - } - - public CharSequence getSubText() { - return subText; - } - - public MaterialAboutCheckboxItem setSubText(CharSequence subText) { - this.subTextRes = 0; - this.subText = subText; - return this; - } - - public int getSubTextRes() { - return subTextRes; - } - - public MaterialAboutCheckboxItem setSubTextRes(int subTextRes) { - this.subText = null; - this.subTextRes = subTextRes; - return this; - } - - public CharSequence getSubTextChecked() { - return subTextChecked; - } - - public MaterialAboutCheckboxItem setSubTextChecked(CharSequence subTextChecked) { - this.subTextCheckedRes = 0; - this.subTextChecked = subTextChecked; - return this; - } - - public int getSubTextCheckedRes() { - return subTextCheckedRes; - } - - public MaterialAboutCheckboxItem setSubTextCheckedRes(int subTextCheckedRes) { - this.subTextChecked = null; - this.subTextCheckedRes = subTextCheckedRes; - return this; - } - - public Drawable getIcon() { - return icon; - } - - public MaterialAboutCheckboxItem setIcon(Drawable icon) { - this.iconRes = 0; - this.icon = icon; - return this; - } - - public int getIconRes() { - return iconRes; - } - - public MaterialAboutCheckboxItem setIconRes(int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public boolean shouldShowIcon() { - return showIcon; - } - - public MaterialAboutCheckboxItem setShouldShowIcon(boolean showIcon) { - this.showIcon = showIcon; - return this; - } - - @IconGravity - public int getIconGravity() { - return iconGravity; - } - - public MaterialAboutCheckboxItem setIconGravity(int iconGravity) { - this.iconGravity = iconGravity; - return this; - } - - public boolean getChecked() { - return checked; - } - - public MaterialAboutCheckboxItem setChecked(boolean checked) { - this.checked = checked; - return this; - } - - public MaterialAboutItemOnChangeAction getOnChangeAction() { - return onChangeAction; - } - - public MaterialAboutCheckboxItem setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - return this; - } - - @Retention(RetentionPolicy.SOURCE) - @IntDef({GRAVITY_TOP, GRAVITY_MIDDLE, GRAVITY_BOTTOM}) - public @interface IconGravity { - } - - public static class MaterialAboutCheckboxItemViewHolder extends MaterialAboutItemViewHolder implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { - public final View view; - public final ImageView icon; - public final TextView text; - public final TextView subText; - public final CheckBox checkBox; - private MaterialAboutItemOnChangeAction onChangeAction; - private MaterialAboutCheckboxItem switchItem; - - MaterialAboutCheckboxItemViewHolder(View view) { - super(view); - this.view = view; - icon = view.findViewById(R.id.mal_item_image); - text = view.findViewById(R.id.mal_item_text); - subText = view.findViewById(R.id.mal_action_item_subtext); - checkBox = view.findViewById(R.id.mal_checkbox); - } - - public void setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - view.setOnClickListener(onChangeAction != null ? this : null); - checkBox.setOnCheckedChangeListener(this); - } - - public void setChecked(boolean checked) { - checkBox.setOnCheckedChangeListener(null); - checkBox.setChecked(checked); - checkBox.setOnCheckedChangeListener(this); - updateSubText(checked); - } - - public void updateSubText(boolean checked) { - if (checked && switchItem.subTextChecked != null) { - subText.setText(switchItem.subTextChecked); - } - else if (checked && switchItem.subTextCheckedRes != 0) { - subText.setText(switchItem.subTextCheckedRes); - } - else if (switchItem.subText != null) { - subText.setText(switchItem.subText); - } - else if (switchItem.subTextRes != 0) { - subText.setText(switchItem.subTextRes); - } - } - - @Override - public void onClick(View v) { - checkBox.toggle(); - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - updateSubText(isChecked); - if (onChangeAction != null) { - if (!onChangeAction.onChange(isChecked, switchItem.getTag())) - setChecked(!isChecked); - } - else { - setChecked(!isChecked); - } - } - } - - public static class Builder { - - MaterialAboutItemOnChangeAction onChangeAction = null; - private CharSequence text = null; - @StringRes - private int textRes = 0; - private CharSequence subText = null; - @StringRes - private int subTextRes = 0; - private CharSequence subTextChecked = null; - @StringRes - private int subTextCheckedRes = 0; - private Drawable icon = null; - @DrawableRes - private int iconRes = 0; - private boolean showIcon = true; - @IconGravity - private int iconGravity = GRAVITY_MIDDLE; - private boolean checked = false; - private int tag = -1; - - public Builder tag(int tag) { - this.tag = tag; - return this; - } - - public Builder text(CharSequence text) { - this.text = text; - this.textRes = 0; - return this; - } - - public Builder text(@StringRes int text) { - this.textRes = text; - this.text = null; - return this; - } - - public Builder subText(CharSequence subText) { - this.subText = subText; - this.subTextRes = 0; - return this; - } - - public Builder subText(@StringRes int subTextRes) { - this.subText = null; - this.subTextRes = subTextRes; - return this; - } - - public Builder subTextHtml(String subTextHtml) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - this.subText = Html.fromHtml(subTextHtml, Html.FROM_HTML_MODE_LEGACY); - } else { - //noinspection deprecation - this.subText = Html.fromHtml(subTextHtml); - } - this.subTextRes = 0; - return this; - } - - public Builder subTextChecked(CharSequence subTextChecked) { - this.subTextChecked = subTextChecked; - this.subTextCheckedRes = 0; - return this; - } - - public Builder subTextChecked(@StringRes int subTextCheckedRes) { - this.subTextChecked = null; - this.subTextCheckedRes = subTextCheckedRes; - return this; - } - - public Builder subTextCheckedHtml(String subTextCheckedHtml) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - this.subTextChecked = Html.fromHtml(subTextCheckedHtml, Html.FROM_HTML_MODE_LEGACY); - } else { - //noinspection deprecation - this.subTextChecked = Html.fromHtml(subTextCheckedHtml); - } - this.subTextCheckedRes = 0; - return this; - } - - public Builder icon(Drawable icon) { - this.icon = icon; - this.iconRes = 0; - return this; - } - - public Builder icon(@DrawableRes int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public Builder showIcon(boolean showIcon) { - this.showIcon = showIcon; - return this; - } - - public Builder setIconGravity(@IconGravity int iconGravity) { - this.iconGravity = iconGravity; - return this; - } - - public Builder setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - return this; - } - - public Builder checked(boolean isChecked) { - this.checked = isChecked; - return this; - } - - public MaterialAboutCheckboxItem build() { - return new MaterialAboutCheckboxItem(this); - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItem.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItem.java deleted file mode 100644 index 2d6a5f48..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItem.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - -import java.util.UUID; - -public abstract class MaterialAboutItem { - - public String id = "NO-UUID"; - - public MaterialAboutItem() { - this.id = UUID.randomUUID().toString(); - } - - public String getId() { - return id; - } - - public abstract int getType(); - - public abstract String getDetailString(); - - public abstract MaterialAboutItem clone(); - -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItemOnChangeAction.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItemOnChangeAction.java deleted file mode 100644 index 836883db..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItemOnChangeAction.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - -public interface MaterialAboutItemOnChangeAction { - boolean onChange(boolean isChecked, int tag); -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItemOnClickAction.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItemOnClickAction.java deleted file mode 100644 index ca1cd610..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutItemOnClickAction.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - -public interface MaterialAboutItemOnClickAction { - void onClick(); -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutProfileItem.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutProfileItem.java deleted file mode 100644 index aeb4d4fe..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutProfileItem.java +++ /dev/null @@ -1,352 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Build; -import androidx.annotation.DrawableRes; -import androidx.annotation.StringRes; - -import android.util.Log; -import android.util.TypedValue; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.danielstone.materialaboutlibrary.R; -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -import static android.view.View.GONE; - -public class MaterialAboutProfileItem extends MaterialAboutItem { - - private CharSequence text = null; - private int textRes = 0; - private CharSequence desc = null; - private int descRes = 0; - private Drawable icon = null; - private int iconRes = 0; - private MaterialAboutItemOnClickAction onClickAction = null; - private MaterialAboutItemOnClickAction onLongClickAction = null; - - private MaterialAboutProfileItem(MaterialAboutProfileItem.Builder builder) { - super(); - this.text = builder.text; - this.textRes = builder.textRes; - - this.desc = builder.desc; - this.descRes = builder.descRes; - - this.icon = builder.icon; - this.iconRes = builder.iconRes; - - this.onClickAction = builder.onClickAction; - this.onLongClickAction = builder.onLongClickAction; - } - - public MaterialAboutProfileItem(CharSequence text, CharSequence desc, Drawable icon) { - this.text = text; - this.desc = desc; - this.icon = icon; - } - - public MaterialAboutProfileItem(int textRes, int descRes, int iconRes) { - this.textRes = textRes; - this.descRes = descRes; - this.iconRes = iconRes; - } - - public static MaterialAboutItemViewHolder getViewHolder(View view) { - return new MaterialAboutProfileItem.MaterialAboutProfileItemViewHolder(view); - } - - public static void setupItem(MaterialAboutProfileItemViewHolder holder, MaterialAboutProfileItem item, Context context) { - - CharSequence text = item.getText(); - int textRes = item.getTextRes(); - - holder.text.setVisibility(View.VISIBLE); - if (text != null) { - holder.text.setText(text); - } else if (textRes != 0) { - holder.text.setText(textRes); - } else { - holder.text.setVisibility(GONE); - } - - CharSequence desc = item.getDesc(); - int descRes = item.getDescRes(); - - holder.desc.setVisibility(View.VISIBLE); - if (desc != null) { - holder.desc.setText(desc); - } else if (descRes != 0) { - holder.desc.setText(descRes); - } else { - holder.desc.setVisibility(GONE); - } - - Drawable drawable = item.getIcon(); - int drawableRes = item.getIconRes(); - if (drawable != null) { - holder.icon.setImageDrawable(drawable); - } else if (drawableRes != 0) { - holder.icon.setImageResource(drawableRes); - } - - int pL = 0, pT = 0, pR = 0, pB = 0; - if (Build.VERSION.SDK_INT < 21) { - pL = holder.view.getPaddingLeft(); - pT = holder.view.getPaddingTop(); - pR = holder.view.getPaddingRight(); - pB = holder.view.getPaddingBottom(); - } - - if (item.getOnClickAction() != null || item.getOnLongClickAction() != null) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, true); - holder.view.setBackgroundResource(outValue.resourceId); - } else { - holder.view.setBackgroundResource(0); - } - holder.setOnClickAction(item.getOnClickAction()); - holder.setOnLongClickAction(item.getOnLongClickAction()); - - if (Build.VERSION.SDK_INT < 21) { - holder.view.setPadding(pL, pT, pR, pB); - } - } - - @Override - public int getType() { - return ViewTypeManager.ItemType.PROFILE_ITEM; - } - - @Override - public String getDetailString() { - return "MaterialAboutProfileItem{" + - "text=" + text + - ", textRes=" + textRes + - ", desc=" + desc + - ", descRes=" + descRes + - ", icon=" + icon + - ", iconRes=" + iconRes + - ", onClickAction=" + onClickAction + - ", onLongClickAction=" + onLongClickAction + - '}'; - } - - public MaterialAboutProfileItem(MaterialAboutProfileItem item) { - this.id = item.getId(); - this.text = item.getText(); - this.textRes = item.getTextRes(); - this.desc = item.getDesc(); - this.descRes = item.getDescRes(); - this.icon = item.getIcon(); - this.iconRes = item.getIconRes(); - this.onClickAction = item.getOnClickAction(); - this.onLongClickAction = item.getOnLongClickAction(); - } - - @Override - public MaterialAboutProfileItem clone() { - return new MaterialAboutProfileItem(this); - } - - public CharSequence getText() { - return text; - } - - public MaterialAboutProfileItem setText(CharSequence text) { - this.textRes = 0; - this.text = text; - return this; - } - - public int getTextRes() { - return textRes; - } - - public MaterialAboutProfileItem setTextRes(int textRes) { - this.text = null; - this.textRes = textRes; - return this; - } - - public CharSequence getDesc() { - return desc; - } - - public MaterialAboutProfileItem setDesc(CharSequence desc) { - this.descRes = 0; - this.desc = desc; - return this; - } - - public int getDescRes() { - return descRes; - } - - public MaterialAboutProfileItem setDescRes(int descRes) { - this.desc = null; - this.descRes = textRes; - return this; - } - - public Drawable getIcon() { - return icon; - } - - public MaterialAboutProfileItem setIcon(Drawable icon) { - this.iconRes = 0; - this.icon = icon; - return this; - } - - public int getIconRes() { - return iconRes; - } - - public MaterialAboutProfileItem setIconRes(int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public MaterialAboutItemOnClickAction getOnClickAction() { - return onClickAction; - } - - public MaterialAboutProfileItem setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - return this; - } - - public MaterialAboutItemOnClickAction getOnLongClickAction() { - return onLongClickAction; - } - - public MaterialAboutProfileItem setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - return this; - } - public static class MaterialAboutProfileItemViewHolder extends MaterialAboutItemViewHolder implements View.OnClickListener, View.OnLongClickListener { - public final View view; - public final ImageView icon; - public final TextView text; - public final TextView desc; - private MaterialAboutItemOnClickAction onClickAction; - private MaterialAboutItemOnClickAction onLongClickAction; - - MaterialAboutProfileItemViewHolder(View view) { - super(view); - this.view = view; - icon = (ImageView) view.findViewById(R.id.mal_item_image); - text = (TextView) view.findViewById(R.id.mal_item_text); - desc = (TextView) view.findViewById(R.id.mal_item_desc); - } - - public void setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - if (onClickAction != null) { - view.setOnClickListener(this); - } else { - view.setClickable(false); - } - } - - public void setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - if (onLongClickAction != null) { - view.setOnLongClickListener(this); - } else { - view.setLongClickable(false); - } - } - - @Override - public void onClick(View v) { - if (onClickAction != null) { - onClickAction.onClick(); - } - } - - @Override - public boolean onLongClick(View v) { - if (onLongClickAction != null) { - onLongClickAction.onClick(); - return true; - } - return false; - } - } - - public static class Builder { - - MaterialAboutItemOnClickAction onClickAction = null; - MaterialAboutItemOnClickAction onLongClickAction = null; - private CharSequence text = null; - @StringRes - private int textRes = 0; - private CharSequence desc = null; - @StringRes - private int descRes = 0; - private Drawable icon = null; - @DrawableRes - private int iconRes = 0; - - public MaterialAboutProfileItem.Builder text(CharSequence text) { - this.text = text; - this.textRes = 0; - return this; - } - - - public MaterialAboutProfileItem.Builder text(@StringRes int text) { - this.textRes = text; - this.text = null; - return this; - } - - public MaterialAboutProfileItem.Builder desc(CharSequence desc) { - this.desc = desc; - this.descRes = 0; - return this; - } - - - public MaterialAboutProfileItem.Builder desc(@StringRes int desc) { - this.descRes = desc; - this.desc = null; - return this; - } - - public MaterialAboutProfileItem.Builder icon(Drawable icon) { - this.icon = icon; - this.iconRes = 0; - return this; - } - - - public MaterialAboutProfileItem.Builder icon(@DrawableRes int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public MaterialAboutProfileItem.Builder setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - return this; - } - - public MaterialAboutProfileItem.Builder setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - return this; - } - - public MaterialAboutProfileItem build() { - return new MaterialAboutProfileItem(this); - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutSwitchItem.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutSwitchItem.java deleted file mode 100644 index 4ce55683..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutSwitchItem.java +++ /dev/null @@ -1,548 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Build; -import androidx.annotation.DrawableRes; -import androidx.annotation.IntDef; -import androidx.annotation.StringRes; -import androidx.appcompat.widget.SwitchCompat; - -import android.text.Html; -import android.util.Log; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.Switch; -import android.widget.TextView; - -import com.danielstone.materialaboutlibrary.R; -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import static android.view.View.GONE; - -public class MaterialAboutSwitchItem extends MaterialAboutItem { - - public static final int GRAVITY_TOP = 0; - public static final int GRAVITY_MIDDLE = 1; - public static final int GRAVITY_BOTTOM = 2; - private CharSequence text = null; - private int textRes = 0; - private CharSequence subText = null; - private int subTextRes = 0; - private CharSequence subTextChecked = null; - private int subTextCheckedRes = 0; - private Drawable icon = null; - private int iconRes = 0; - private boolean showIcon = true; - private int iconGravity = GRAVITY_MIDDLE; - private boolean checked = false; - private int tag = -1; - private MaterialAboutItemOnChangeAction onChangeAction = null; - - private MaterialAboutSwitchItem(Builder builder) { - super(); - this.text = builder.text; - this.textRes = builder.textRes; - - this.subText = builder.subText; - this.subTextRes = builder.subTextRes; - - this.subTextChecked = builder.subTextChecked; - this.subTextCheckedRes = builder.subTextCheckedRes; - - this.icon = builder.icon; - this.iconRes = builder.iconRes; - - this.showIcon = builder.showIcon; - - this.iconGravity = builder.iconGravity; - - this.checked = builder.checked; - - this.tag = builder.tag; - - this.onChangeAction = builder.onChangeAction; - } - - public MaterialAboutSwitchItem(CharSequence text, CharSequence subText, Drawable icon, MaterialAboutItemOnChangeAction onChangeAction) { - this.text = text; - this.subText = subText; - this.icon = icon; - this.onChangeAction = onChangeAction; - } - - public MaterialAboutSwitchItem(CharSequence text, CharSequence subText, Drawable icon) { - this.text = text; - this.subText = subText; - this.icon = icon; - } - - public MaterialAboutSwitchItem(int textRes, int subTextRes, int iconRes, MaterialAboutItemOnChangeAction onChangeAction) { - this.textRes = textRes; - this.subTextRes = subTextRes; - this.iconRes = iconRes; - this.onChangeAction = onChangeAction; - } - - public MaterialAboutSwitchItem(int textRes, int subTextRes, int iconRes) { - this.textRes = textRes; - this.subTextRes = subTextRes; - this.iconRes = iconRes; - } - - public static void setupItem(MaterialAboutSwitchItemViewHolder holder, MaterialAboutSwitchItem item, Context context) { - holder.switchItem = item; - - CharSequence text = item.getText(); - int textRes = item.getTextRes(); - - holder.text.setVisibility(View.VISIBLE); - if (text != null) { - holder.text.setText(text); - } else if (textRes != 0) { - holder.text.setText(textRes); - } else { - holder.text.setVisibility(GONE); - } - - CharSequence subText = item.getSubText(); - int subTextRes = item.getSubTextRes(); - - holder.subText.setVisibility(View.VISIBLE); - if (subText != null) { - holder.subText.setText(subText); - } else if (subTextRes != 0) { - holder.subText.setText(subTextRes); - } else { - holder.subText.setVisibility(GONE); - } - - if (item.shouldShowIcon()) { - holder.icon.setVisibility(View.VISIBLE); - Drawable drawable = item.getIcon(); - int drawableRes = item.getIconRes(); - if (drawable != null) { - holder.icon.setImageDrawable(drawable); - } else if (drawableRes != 0) { - holder.icon.setImageResource(drawableRes); - } - } else { - holder.icon.setVisibility(GONE); - } - - LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) holder.icon.getLayoutParams(); - switch (item.getIconGravity()) { - case MaterialAboutSwitchItem.GRAVITY_TOP: - params.gravity = Gravity.TOP; - break; - case MaterialAboutSwitchItem.GRAVITY_MIDDLE: - params.gravity = Gravity.CENTER_VERTICAL; - break; - case MaterialAboutSwitchItem.GRAVITY_BOTTOM: - params.gravity = Gravity.BOTTOM; - break; - } - holder.icon.setLayoutParams(params); - - int pL = 0, pT = 0, pR = 0, pB = 0; - if (Build.VERSION.SDK_INT < 21) { - pL = holder.view.getPaddingLeft(); - pT = holder.view.getPaddingTop(); - pR = holder.view.getPaddingRight(); - pB = holder.view.getPaddingBottom(); - } - - holder.setChecked(item.getChecked()); - - if (item.getOnChangeAction() != null) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, true); - holder.view.setBackgroundResource(outValue.resourceId); - } else { - holder.view.setBackgroundResource(0); - } - holder.setOnChangeAction(item.getOnChangeAction()); - - if (Build.VERSION.SDK_INT < 21) { - holder.view.setPadding(pL, pT, pR, pB); - } - } - - public static MaterialAboutItemViewHolder getViewHolder(View view) { - return new MaterialAboutSwitchItemViewHolder(view); - } - - public static class MaterialAboutSwitchItemViewHolder extends MaterialAboutItemViewHolder implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { - public final View view; - public final ImageView icon; - public final TextView text; - public final TextView subText; - public final SwitchCompat switchView; - private MaterialAboutItemOnChangeAction onChangeAction; - private MaterialAboutSwitchItem switchItem; - - MaterialAboutSwitchItemViewHolder(View view) { - super(view); - this.view = view; - icon = view.findViewById(R.id.mal_item_image); - text = view.findViewById(R.id.mal_item_text); - subText = view.findViewById(R.id.mal_action_item_subtext); - switchView = view.findViewById(R.id.mal_switch); - } - - public void setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - view.setOnClickListener(onChangeAction != null ? this : null); - switchView.setOnCheckedChangeListener(this); - } - - public void setChecked(boolean checked) { - switchView.setOnCheckedChangeListener(null); - switchView.setChecked(checked); - switchView.setOnCheckedChangeListener(this); - switchItem.setChecked(checked); - updateSubText(checked); - } - - public void updateSubText(boolean checked) { - if (checked && switchItem.subTextChecked != null) { - subText.setText(switchItem.subTextChecked); - } - else if (checked && switchItem.subTextCheckedRes != 0) { - subText.setText(switchItem.subTextCheckedRes); - } - else if (switchItem.subText != null) { - subText.setText(switchItem.subText); - } - else if (switchItem.subTextRes != 0) { - subText.setText(switchItem.subTextRes); - } - } - - @Override - public void onClick(View v) { - switchView.toggle(); - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - updateSubText(isChecked); - if (onChangeAction != null) { - if (!onChangeAction.onChange(isChecked, switchItem.getTag())) { - setChecked(!isChecked); - } - else { - switchItem.setChecked(isChecked); - } - } - else { - setChecked(!isChecked); - } - } - } - - @Override - public int getType() { - return ViewTypeManager.ItemType.SWITCH_ITEM; - } - - @Override - public String getDetailString() { - return "MaterialAboutSwitchItem{" + - "text=" + text + - ", textRes=" + textRes + - ", subText=" + subText + - ", subTextRes=" + subTextRes + - ", subTextChecked=" + subTextChecked + - ", subTextCheckedRes=" + subTextCheckedRes + - ", icon=" + icon + - ", iconRes=" + iconRes + - ", showIcon=" + showIcon + - ", iconGravity=" + iconGravity + - ", checked=" + checked + - ", tag=" + tag + - ", onChangeAction=" + onChangeAction + - '}'; - } - - public MaterialAboutSwitchItem(MaterialAboutSwitchItem item) { - this.id = item.getId(); - this.text = item.getText(); - this.textRes = item.getTextRes(); - this.subText = item.getSubText(); - this.subTextRes = item.getSubTextRes(); - this.subTextChecked = item.getSubTextChecked(); - this.subTextCheckedRes = item.getSubTextCheckedRes(); - this.icon = item.getIcon(); - this.iconRes = item.getIconRes(); - this.showIcon = item.showIcon; - this.iconGravity = item.iconGravity; - this.checked = item.checked; - this.tag = item.tag; - this.onChangeAction = item.onChangeAction; - } - - @Override - public MaterialAboutItem clone() { - return new MaterialAboutSwitchItem(this); - } - - public int getTag() { - return tag; - } - public MaterialAboutSwitchItem setTag(int tag) { - this.tag = tag; - return this; - } - - public CharSequence getText() { - return text; - } - public MaterialAboutSwitchItem setText(CharSequence text) { - this.textRes = 0; - this.text = text; - return this; - } - - public int getTextRes() { - return textRes; - } - - public MaterialAboutSwitchItem setTextRes(int textRes) { - this.text = null; - this.textRes = textRes; - return this; - } - - public CharSequence getSubText() { - return subText; - } - - public MaterialAboutSwitchItem setSubText(CharSequence subText) { - this.subTextRes = 0; - this.subText = subText; - return this; - } - - public int getSubTextRes() { - return subTextRes; - } - - public MaterialAboutSwitchItem setSubTextRes(int subTextRes) { - this.subText = null; - this.subTextRes = subTextRes; - return this; - } - - public CharSequence getSubTextChecked() { - return subTextChecked; - } - - public MaterialAboutSwitchItem setSubTextChecked(CharSequence subTextChecked) { - this.subTextCheckedRes = 0; - this.subTextChecked = subTextChecked; - return this; - } - - public int getSubTextCheckedRes() { - return subTextCheckedRes; - } - - public MaterialAboutSwitchItem setSubTextCheckedRes(int subTextCheckedRes) { - this.subTextChecked = null; - this.subTextCheckedRes = subTextCheckedRes; - return this; - } - - public Drawable getIcon() { - return icon; - } - - public MaterialAboutSwitchItem setIcon(Drawable icon) { - this.iconRes = 0; - this.icon = icon; - return this; - } - - public int getIconRes() { - return iconRes; - } - - public MaterialAboutSwitchItem setIconRes(int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public boolean shouldShowIcon() { - return showIcon; - } - - public MaterialAboutSwitchItem setShouldShowIcon(boolean showIcon) { - this.showIcon = showIcon; - return this; - } - - @IconGravity - public int getIconGravity() { - return iconGravity; - } - - public MaterialAboutSwitchItem setIconGravity(int iconGravity) { - this.iconGravity = iconGravity; - return this; - } - - public boolean getChecked() { - return checked; - } - - public MaterialAboutSwitchItem setChecked(boolean checked) { - //Log.d("MaterialItem", "Setting item "+getText()+" to checked "+checked); - this.checked = checked; - return this; - } - - public MaterialAboutItemOnChangeAction getOnChangeAction() { - return onChangeAction; - } - - public MaterialAboutSwitchItem setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - return this; - } - - @Retention(RetentionPolicy.SOURCE) - @IntDef({GRAVITY_TOP, GRAVITY_MIDDLE, GRAVITY_BOTTOM}) - public @interface IconGravity { - } - - public static class Builder { - - MaterialAboutItemOnChangeAction onChangeAction = null; - private CharSequence text = null; - @StringRes - private int textRes = 0; - private CharSequence subText = null; - @StringRes - private int subTextRes = 0; - private CharSequence subTextChecked = null; - @StringRes - private int subTextCheckedRes = 0; - private Drawable icon = null; - @DrawableRes - private int iconRes = 0; - private boolean showIcon = true; - @IconGravity - private int iconGravity = GRAVITY_MIDDLE; - private boolean checked = false; - private int tag = -1; - - public Builder tag(int tag) { - this.tag = tag; - return this; - } - - public Builder text(CharSequence text) { - this.text = text; - this.textRes = 0; - return this; - } - - public Builder text(@StringRes int text) { - this.textRes = text; - this.text = null; - return this; - } - - public Builder subText(CharSequence subText) { - this.subText = subText; - this.subTextRes = 0; - return this; - } - - public Builder subText(@StringRes int subTextRes) { - this.subText = null; - this.subTextRes = subTextRes; - return this; - } - - public Builder subTextHtml(String subTextHtml) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - this.subText = Html.fromHtml(subTextHtml, Html.FROM_HTML_MODE_LEGACY); - } else { - //noinspection deprecation - this.subText = Html.fromHtml(subTextHtml); - } - this.subTextRes = 0; - return this; - } - - public Builder subTextChecked(CharSequence subTextChecked) { - this.subTextChecked = subTextChecked; - this.subTextCheckedRes = 0; - return this; - } - - public Builder subTextChecked(@StringRes int subTextCheckedRes) { - this.subTextChecked = null; - this.subTextCheckedRes = subTextCheckedRes; - return this; - } - - public Builder subTextCheckedHtml(String subTextCheckedHtml) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - this.subTextChecked = Html.fromHtml(subTextCheckedHtml, Html.FROM_HTML_MODE_LEGACY); - } else { - //noinspection deprecation - this.subTextChecked = Html.fromHtml(subTextCheckedHtml); - } - this.subTextCheckedRes = 0; - return this; - } - - public Builder icon(Drawable icon) { - this.icon = icon; - this.iconRes = 0; - return this; - } - - public Builder icon(@DrawableRes int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public Builder showIcon(boolean showIcon) { - this.showIcon = showIcon; - return this; - } - - public Builder setIconGravity(@IconGravity int iconGravity) { - this.iconGravity = iconGravity; - return this; - } - - public Builder setOnChangeAction(MaterialAboutItemOnChangeAction onChangeAction) { - this.onChangeAction = onChangeAction; - return this; - } - - public Builder checked(boolean isChecked) { - this.checked = isChecked; - return this; - } - - public MaterialAboutSwitchItem build() { - return new MaterialAboutSwitchItem(this); - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutTitleItem.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutTitleItem.java deleted file mode 100644 index a1b1bc72..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/items/MaterialAboutTitleItem.java +++ /dev/null @@ -1,400 +0,0 @@ -package com.danielstone.materialaboutlibrary.items; - - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Build; - -import androidx.annotation.ColorInt; -import androidx.annotation.DrawableRes; -import androidx.annotation.StringRes; -import android.util.TypedValue; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.danielstone.materialaboutlibrary.R; -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.util.ViewTypeManager; - -import static android.view.View.GONE; - -public class MaterialAboutTitleItem extends MaterialAboutItem { - - private CharSequence text = null; - private int textRes = 0; - private CharSequence desc = null; - private int descRes = 0; - private int textColor = -1; - private int descColor = -1; - private Drawable icon = null; - private int iconRes = 0; - private MaterialAboutItemOnClickAction onClickAction = null; - private MaterialAboutItemOnClickAction onLongClickAction = null; - - private MaterialAboutTitleItem(MaterialAboutTitleItem.Builder builder) { - super(); - this.text = builder.text; - this.textRes = builder.textRes; - - this.desc = builder.desc; - this.descRes = builder.descRes; - - this.textColor = builder.textColor; - this.descColor = builder.descColor; - - this.icon = builder.icon; - this.iconRes = builder.iconRes; - - this.onClickAction = builder.onClickAction; - this.onLongClickAction = builder.onLongClickAction; - } - - public MaterialAboutTitleItem(CharSequence text, CharSequence desc, Drawable icon) { - this.text = text; - this.desc = desc; - this.icon = icon; - } - - public MaterialAboutTitleItem(int textRes, int descRes, int iconRes) { - this.textRes = textRes; - this.descRes = descRes; - this.iconRes = iconRes; - } - - public static MaterialAboutItemViewHolder getViewHolder(View view) { - return new MaterialAboutTitleItem.MaterialAboutTitleItemViewHolder(view); - } - - public static void setupItem(MaterialAboutTitleItemViewHolder holder, MaterialAboutTitleItem item, Context context) { - - CharSequence text = item.getText(); - int textRes = item.getTextRes(); - - holder.text.setVisibility(View.VISIBLE); - if (text != null) { - holder.text.setText(text); - } else if (textRes != 0) { - holder.text.setText(textRes); - } else { - holder.text.setVisibility(GONE); - } - - CharSequence desc = item.getDesc(); - int descRes = item.getDescRes(); - - holder.desc.setVisibility(View.VISIBLE); - if (desc != null) { - holder.desc.setText(desc); - } else if (descRes != 0) { - holder.desc.setText(descRes); - } else { - holder.desc.setVisibility(GONE); - } - - if (item.getTextColor() != -1) { - holder.text.setTextColor(item.getTextColor()); - } - if (item.getDescColor() != -1) { - holder.desc.setTextColor(item.getDescColor()); - } - - Drawable drawable = item.getIcon(); - int drawableRes = item.getIconRes(); - if (drawable != null) { - holder.icon.setImageDrawable(drawable); - } else if (drawableRes != 0) { - holder.icon.setImageResource(drawableRes); - } - - int pL = 0, pT = 0, pR = 0, pB = 0; - if (Build.VERSION.SDK_INT < 21) { - pL = holder.view.getPaddingLeft(); - pT = holder.view.getPaddingTop(); - pR = holder.view.getPaddingRight(); - pB = holder.view.getPaddingBottom(); - } - - if (item.getOnClickAction() != null || item.getOnLongClickAction() != null) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, true); - holder.view.setBackgroundResource(outValue.resourceId); - } else { - holder.view.setBackgroundResource(0); - } - holder.setOnClickAction(item.getOnClickAction()); - holder.setOnLongClickAction(item.getOnLongClickAction()); - - if (Build.VERSION.SDK_INT < 21) { - holder.view.setPadding(pL, pT, pR, pB); - } - } - - @Override - public int getType() { - return ViewTypeManager.ItemType.TITLE_ITEM; - } - - @Override - public String getDetailString() { - return "MaterialAboutTitleItem{" + - "text=" + text + - ", textRes=" + textRes + - ", desc=" + desc + - ", descRes=" + descRes + - ", textColor=" + textColor + - ", descColor=" + descColor + - ", icon=" + icon + - ", iconRes=" + iconRes + - ", onClickAction=" + onClickAction + - ", onLongClickAction=" + onLongClickAction + - '}'; - } - - public MaterialAboutTitleItem(MaterialAboutTitleItem item) { - this.id = item.getId(); - this.text = item.getText(); - this.textRes = item.getTextRes(); - this.desc = item.getDesc(); - this.descRes = item.getDescRes(); - this.textColor = item.getTextColor(); - this.descColor = item.getDescColor(); - this.icon = item.getIcon(); - this.iconRes = item.getIconRes(); - this.onClickAction = item.getOnClickAction(); - this.onLongClickAction = item.getOnLongClickAction(); - } - - @Override - public MaterialAboutTitleItem clone() { - return new MaterialAboutTitleItem(this); - } - - public CharSequence getText() { - return text; - } - - public MaterialAboutTitleItem setText(CharSequence text) { - this.textRes = 0; - this.text = text; - return this; - } - - public int getTextRes() { - return textRes; - } - - public MaterialAboutTitleItem setTextRes(int textRes) { - this.text = null; - this.textRes = textRes; - return this; - } - - public CharSequence getDesc() { - return desc; - } - - public MaterialAboutTitleItem setDesc(CharSequence desc) { - this.descRes = 0; - this.desc = desc; - return this; - } - - public int getDescRes() { - return descRes; - } - - public MaterialAboutTitleItem setDescRes(int descRes) { - this.desc = null; - this.descRes = textRes; - return this; - } - - public int getTextColor() { - return textColor; - } - - public MaterialAboutTitleItem setTextColor(int textColor) { - this.textColor = textColor; - return this; - } - - public int getDescColor() { - return descColor; - } - - public MaterialAboutTitleItem setDescColor(int descColor) { - this.descColor = descColor; - return this; - } - - public Drawable getIcon() { - return icon; - } - - public MaterialAboutTitleItem setIcon(Drawable icon) { - this.iconRes = 0; - this.icon = icon; - return this; - } - - public int getIconRes() { - return iconRes; - } - - public MaterialAboutTitleItem setIconRes(int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public MaterialAboutItemOnClickAction getOnClickAction() { - return onClickAction; - } - - public MaterialAboutTitleItem setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - return this; - } - - public MaterialAboutItemOnClickAction getOnLongClickAction() { - return onLongClickAction; - } - - public MaterialAboutTitleItem setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - return this; - } - public static class MaterialAboutTitleItemViewHolder extends MaterialAboutItemViewHolder implements View.OnClickListener, View.OnLongClickListener { - public final View view; - public final ImageView icon; - public final TextView text; - public final TextView desc; - private MaterialAboutItemOnClickAction onClickAction; - private MaterialAboutItemOnClickAction onLongClickAction; - - MaterialAboutTitleItemViewHolder(View view) { - super(view); - this.view = view; - icon = (ImageView) view.findViewById(R.id.mal_item_image); - text = (TextView) view.findViewById(R.id.mal_item_text); - desc = (TextView) view.findViewById(R.id.mal_item_desc); - } - - public void setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - if (onClickAction != null) { - view.setOnClickListener(this); - } else { - view.setClickable(false); - } - } - - public void setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - if (onLongClickAction != null) { - view.setOnLongClickListener(this); - } else { - view.setLongClickable(false); - } - } - - @Override - public void onClick(View v) { - if (onClickAction != null) { - onClickAction.onClick(); - } - } - - @Override - public boolean onLongClick(View v) { - if (onLongClickAction != null) { - onLongClickAction.onClick(); - return true; - } - return false; - } - } - - public static class Builder { - - MaterialAboutItemOnClickAction onClickAction = null; - MaterialAboutItemOnClickAction onLongClickAction = null; - private CharSequence text = null; - @StringRes - private int textRes = 0; - private CharSequence desc = null; - @StringRes - private int descRes = 0; - @ColorInt - private int textColor = -1; - @ColorInt - private int descColor = -1; - private Drawable icon = null; - @DrawableRes - private int iconRes = 0; - - public MaterialAboutTitleItem.Builder text(CharSequence text) { - this.text = text; - this.textRes = 0; - return this; - } - - - public MaterialAboutTitleItem.Builder text(@StringRes int text) { - this.textRes = text; - this.text = null; - return this; - } - - public MaterialAboutTitleItem.Builder desc(CharSequence desc) { - this.desc = desc; - this.descRes = 0; - return this; - } - - - public MaterialAboutTitleItem.Builder desc(@StringRes int desc) { - this.descRes = desc; - this.desc = null; - return this; - } - - public MaterialAboutTitleItem.Builder textColor(@ColorInt int textColor) { - this.textColor = textColor; - return this; - } - - public MaterialAboutTitleItem.Builder descColor(@ColorInt int descColor) { - this.descColor = descColor; - return this; - } - - public MaterialAboutTitleItem.Builder icon(Drawable icon) { - this.icon = icon; - this.iconRes = 0; - return this; - } - - - public MaterialAboutTitleItem.Builder icon(@DrawableRes int iconRes) { - this.icon = null; - this.iconRes = iconRes; - return this; - } - - public MaterialAboutTitleItem.Builder setOnClickAction(MaterialAboutItemOnClickAction onClickAction) { - this.onClickAction = onClickAction; - return this; - } - - public MaterialAboutTitleItem.Builder setOnLongClickAction(MaterialAboutItemOnClickAction onLongClickAction) { - this.onLongClickAction = onLongClickAction; - return this; - } - - public MaterialAboutTitleItem build() { - return new MaterialAboutTitleItem(this); - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/model/MaterialAboutCard.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/model/MaterialAboutCard.java deleted file mode 100644 index ecbffb18..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/model/MaterialAboutCard.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.danielstone.materialaboutlibrary.model; - - -import androidx.annotation.ColorInt; -import androidx.annotation.StringRes; -import androidx.annotation.StyleRes; -import androidx.recyclerview.widget.RecyclerView; - -import com.danielstone.materialaboutlibrary.items.MaterialAboutItem; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.UUID; - -public class MaterialAboutCard { - - private String id = "NO-UUID"; - - private CharSequence title = null; - private int titleRes = 0; - - private int titleColor = 0; - private int cardColor = 0; - - private RecyclerView.Adapter customAdapter = null; - private ArrayList items = new ArrayList<>(); - - - private MaterialAboutCard(Builder builder) { - this.id = UUID.randomUUID().toString(); - this.title = builder.title; - this.titleRes = builder.titleRes; - this.titleColor = builder.titleColor; - this.cardColor = builder.cardColor; - this.items = builder.items; - this.customAdapter = builder.customAdapter; - } - - public MaterialAboutCard(CharSequence title, MaterialAboutItem... materialAboutItems) { - this.title = title; - Collections.addAll(items, materialAboutItems); - } - - public MaterialAboutCard(int titleRes, MaterialAboutItem... materialAboutItems) { - this.titleRes = titleRes; - Collections.addAll(items, materialAboutItems); - } - - public CharSequence getTitle() { - return title; - } - - public int getTitleRes() { - return titleRes; - } - - public int getTitleColor() { - return titleColor; - } - - public int getCardColor() { - return cardColor; - } - - public ArrayList getItems() { - return items; - } - - public static class Builder { - private CharSequence title = null; - @StringRes - private int titleRes = 0; - - @ColorInt - private int titleColor = 0; - - @ColorInt - private int cardColor = 0; - - private ArrayList items = new ArrayList<>(); - private RecyclerView.Adapter customAdapter = null; - - public Builder title(CharSequence title) { - this.title = title; - this.titleRes = 0; - return this; - } - - public Builder title(@StringRes int titleRes) { - this.titleRes = titleRes; - this.title = null; - return this; - } - - public Builder titleColor(@ColorInt int color) { - this.titleColor = color; - return this; - } - - public Builder cardColor(@ColorInt int cardColor) { - this.cardColor = cardColor; - return this; - } - - public Builder addItem(MaterialAboutItem item) { - this.items.add(item); - return this; - } - - public Builder customAdapter(RecyclerView.Adapter customAdapter) { - this.customAdapter = customAdapter; - return this; - } - - public MaterialAboutCard build() { - return new MaterialAboutCard(this); - } - } - - public String getId() { - return id; - } - - public RecyclerView.Adapter getCustomAdapter() { - return customAdapter; - } - - @Override - public String toString() { - String result = "MaterialAboutCard{" + - "id='" + id + '\'' + - ", title=" + title + - ", titleRes=" + titleRes + - ", titleColor=" + titleColor + - ", customAdapter=" + customAdapter + - ", cardColor=" + cardColor + '}'; - return result; - } - - public MaterialAboutCard(MaterialAboutCard card) { - this.id = card.getId(); - this.title = card.getTitle(); - this.titleRes = card.getTitleRes(); - this.titleColor = card.getTitleColor(); - this.cardColor = card.getCardColor(); - this.items = new ArrayList<>(); - this.customAdapter = card.getCustomAdapter(); - for (MaterialAboutItem item : card.items) { - this.items.add(item.clone()); - } - } - public MaterialAboutCard clone() { - return new MaterialAboutCard(this); - } - -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/model/MaterialAboutList.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/model/MaterialAboutList.java deleted file mode 100644 index 910dcc53..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/model/MaterialAboutList.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.danielstone.materialaboutlibrary.model; - - -import java.util.ArrayList; -import java.util.Collections; - -public class MaterialAboutList { - - private ArrayList cards = new ArrayList<>(); - - private MaterialAboutList(Builder builder) { - this.cards = builder.cards; - } - - public MaterialAboutList(MaterialAboutCard... materialAboutCards) { - Collections.addAll(cards, materialAboutCards); - } - - public MaterialAboutList addCard(MaterialAboutCard card) { - cards.add(card); - return this; - } - - public MaterialAboutList clearCards(MaterialAboutCard card) { - cards.clear(); - return this; - } - - public ArrayList getCards() { - return cards; - } - - public static class Builder { - private ArrayList cards = new ArrayList<>(); - - public Builder addCard(MaterialAboutCard card) { - this.cards.add(card); - return this; - } - - public MaterialAboutList build() { - return new MaterialAboutList(this); - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/DefaultViewTypeManager.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/DefaultViewTypeManager.java deleted file mode 100644 index 8097c972..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/DefaultViewTypeManager.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.danielstone.materialaboutlibrary.util; - -import android.content.Context; -import android.view.View; - -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.items.MaterialAboutActionItem; -import com.danielstone.materialaboutlibrary.items.MaterialAboutActionSwitchItem; -import com.danielstone.materialaboutlibrary.items.MaterialAboutCheckboxItem; -import com.danielstone.materialaboutlibrary.items.MaterialAboutItem; -import com.danielstone.materialaboutlibrary.items.MaterialAboutProfileItem; -import com.danielstone.materialaboutlibrary.items.MaterialAboutSwitchItem; -import com.danielstone.materialaboutlibrary.items.MaterialAboutTitleItem; - -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemLayout.ACTION_LAYOUT; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemLayout.ACTION_SWITCH_LAYOUT; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemLayout.CHECKBOX_LAYOUT; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemLayout.PROFILE_LAYOUT; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemLayout.SWITCH_LAYOUT; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemLayout.TITLE_LAYOUT; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemType.ACTION_ITEM; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemType.ACTION_SWITCH_ITEM; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemType.CHECKBOX_ITEM; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemType.PROFILE_ITEM; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemType.SWITCH_ITEM; -import static com.danielstone.materialaboutlibrary.util.DefaultViewTypeManager.ItemType.TITLE_ITEM; - -public class DefaultViewTypeManager extends ViewTypeManager { - - public static final class ItemType { - public static final int ACTION_ITEM = ViewTypeManager.ItemType.ACTION_ITEM; - public static final int TITLE_ITEM = ViewTypeManager.ItemType.TITLE_ITEM; - public static final int SWITCH_ITEM = ViewTypeManager.ItemType.SWITCH_ITEM; - public static final int ACTION_SWITCH_ITEM = ViewTypeManager.ItemType.ACTION_SWITCH_ITEM; - public static final int CHECKBOX_ITEM = ViewTypeManager.ItemType.CHECKBOX_ITEM; - public static final int PROFILE_ITEM = ViewTypeManager.ItemType.PROFILE_ITEM; - } - - public static final class ItemLayout { - public static final int ACTION_LAYOUT = ViewTypeManager.ItemLayout.ACTION_LAYOUT; - public static final int TITLE_LAYOUT = ViewTypeManager.ItemLayout.TITLE_LAYOUT; - public static final int SWITCH_LAYOUT = ViewTypeManager.ItemLayout.SWITCH_LAYOUT; - public static final int ACTION_SWITCH_LAYOUT = ViewTypeManager.ItemLayout.ACTION_SWITCH_LAYOUT; - public static final int CHECKBOX_LAYOUT = ViewTypeManager.ItemLayout.CHECKBOX_LAYOUT; - public static final int PROFILE_LAYOUT = ViewTypeManager.ItemLayout.PROFILE_LAYOUT; - } - - public int getLayout(int itemType) { - switch (itemType) { - case ACTION_ITEM: - return ACTION_LAYOUT; - case TITLE_ITEM: - return TITLE_LAYOUT; - case SWITCH_ITEM: - return SWITCH_LAYOUT; - case ACTION_SWITCH_ITEM: - return ACTION_SWITCH_LAYOUT; - case CHECKBOX_ITEM: - return CHECKBOX_LAYOUT; - case PROFILE_ITEM: - return PROFILE_LAYOUT; - default: - return -1; - } - } - - public MaterialAboutItemViewHolder getViewHolder(int itemType, View view) { - switch (itemType) { - case ACTION_ITEM: - return MaterialAboutActionItem.getViewHolder(view); - case TITLE_ITEM: - return MaterialAboutTitleItem.getViewHolder(view); - case SWITCH_ITEM: - return MaterialAboutSwitchItem.getViewHolder(view); - case ACTION_SWITCH_ITEM: - return MaterialAboutActionSwitchItem.getViewHolder(view); - case CHECKBOX_ITEM: - return MaterialAboutCheckboxItem.getViewHolder(view); - case PROFILE_ITEM: - return MaterialAboutProfileItem.getViewHolder(view); - default: - return null; - } - } - - public void setupItem(int itemType, MaterialAboutItemViewHolder holder, MaterialAboutItem item, Context context) { - switch (itemType) { - case ACTION_ITEM: - MaterialAboutActionItem.setupItem((MaterialAboutActionItem.MaterialAboutActionItemViewHolder) holder, (MaterialAboutActionItem) item, context); - break; - case TITLE_ITEM: - MaterialAboutTitleItem.setupItem((MaterialAboutTitleItem.MaterialAboutTitleItemViewHolder) holder, (MaterialAboutTitleItem) item, context); - break; - case SWITCH_ITEM: - MaterialAboutSwitchItem.setupItem((MaterialAboutSwitchItem.MaterialAboutSwitchItemViewHolder) holder, (MaterialAboutSwitchItem) item, context); - break; - case ACTION_SWITCH_ITEM: - MaterialAboutActionSwitchItem.setupItem((MaterialAboutActionSwitchItem.MaterialAboutActionSwitchItemViewHolder) holder, (MaterialAboutActionSwitchItem) item, context); - break; - case CHECKBOX_ITEM: - MaterialAboutCheckboxItem.setupItem((MaterialAboutCheckboxItem.MaterialAboutCheckboxItemViewHolder) holder, (MaterialAboutCheckboxItem) item, context); - break; - case PROFILE_ITEM: - MaterialAboutProfileItem.setupItem((MaterialAboutProfileItem.MaterialAboutProfileItemViewHolder) holder, (MaterialAboutProfileItem) item, context); - break; - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/OpenSourceLicense.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/OpenSourceLicense.java deleted file mode 100644 index c916b2b6..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/OpenSourceLicense.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.danielstone.materialaboutlibrary.util; - -import com.danielstone.materialaboutlibrary.R; - -public enum OpenSourceLicense { - APACHE_2, MIT, GNU_GPL_3, BSD; - - public int getResourceId() { - switch (this) { - case APACHE_2: - return R.string.license_apache2; - case MIT: - return R.string.license_mit; - case GNU_GPL_3: - return R.string.license_gpl; - case BSD: - return R.string.license_bsd; - default: - return -1; - } - } -} diff --git a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/ViewTypeManager.java b/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/ViewTypeManager.java deleted file mode 100644 index d496dadd..00000000 --- a/material-about-library/src/main/java/com/danielstone/materialaboutlibrary/util/ViewTypeManager.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.danielstone.materialaboutlibrary.util; - -import android.content.Context; -import android.view.View; - -import com.danielstone.materialaboutlibrary.R; -import com.danielstone.materialaboutlibrary.holders.MaterialAboutItemViewHolder; -import com.danielstone.materialaboutlibrary.items.MaterialAboutItem; - -public abstract class ViewTypeManager { - - public static final class ItemType { - public static final int ACTION_ITEM = 0; - public static final int TITLE_ITEM = 1; - public static final int SWITCH_ITEM = 2; - public static final int ACTION_SWITCH_ITEM = 3; - public static final int CHECKBOX_ITEM = 4; - public static final int PROFILE_ITEM = 5; - } - - public static final class ItemLayout { - public static final int ACTION_LAYOUT = R.layout.mal_material_about_action_item; - public static final int TITLE_LAYOUT = R.layout.mal_material_about_title_item; - public static final int SWITCH_LAYOUT = R.layout.mal_material_about_switch_item; - public static final int ACTION_SWITCH_LAYOUT = R.layout.mal_material_about_action_switch_item; - public static final int CHECKBOX_LAYOUT = R.layout.mal_material_about_checkbox_item; - public static final int PROFILE_LAYOUT = R.layout.mal_material_about_profile_item; - } - - public abstract int getLayout(int itemType); - - public abstract MaterialAboutItemViewHolder getViewHolder(int itemType, View view); - - public abstract void setupItem(int itemType, MaterialAboutItemViewHolder holder, MaterialAboutItem item, Context context); -} diff --git a/material-about-library/src/main/res/layout/mal_material_about_action_item.xml b/material-about-library/src/main/res/layout/mal_material_about_action_item.xml deleted file mode 100644 index 5edc81d4..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_action_item.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/layout/mal_material_about_action_switch_item.xml b/material-about-library/src/main/res/layout/mal_material_about_action_switch_item.xml deleted file mode 100644 index 9e1dd978..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_action_switch_item.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/layout/mal_material_about_activity.xml b/material-about-library/src/main/res/layout/mal_material_about_activity.xml deleted file mode 100644 index 42f77361..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_activity.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - diff --git a/material-about-library/src/main/res/layout/mal_material_about_checkbox_item.xml b/material-about-library/src/main/res/layout/mal_material_about_checkbox_item.xml deleted file mode 100644 index 659bbd1f..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_checkbox_item.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/layout/mal_material_about_fragment.xml b/material-about-library/src/main/res/layout/mal_material_about_fragment.xml deleted file mode 100644 index f8bdb8e0..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_fragment.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/layout/mal_material_about_list_card.xml b/material-about-library/src/main/res/layout/mal_material_about_list_card.xml deleted file mode 100644 index 0d1f73e8..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_list_card.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/layout/mal_material_about_profile_item.xml b/material-about-library/src/main/res/layout/mal_material_about_profile_item.xml deleted file mode 100644 index a90ccba1..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_profile_item.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/layout/mal_material_about_switch_item.xml b/material-about-library/src/main/res/layout/mal_material_about_switch_item.xml deleted file mode 100644 index b888bc0f..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_switch_item.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/layout/mal_material_about_title_item.xml b/material-about-library/src/main/res/layout/mal_material_about_title_item.xml deleted file mode 100644 index e77e04c8..00000000 --- a/material-about-library/src/main/res/layout/mal_material_about_title_item.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/values/attrs.xml b/material-about-library/src/main/res/values/attrs.xml deleted file mode 100644 index 9d555688..00000000 --- a/material-about-library/src/main/res/values/attrs.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/values/colors.xml b/material-about-library/src/main/res/values/colors.xml deleted file mode 100644 index 057f6cb3..00000000 --- a/material-about-library/src/main/res/values/colors.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - #de000000 - #8a000000 - - #ff9b9b9b - \ No newline at end of file diff --git a/material-about-library/src/main/res/values/dimens.xml b/material-about-library/src/main/res/values/dimens.xml deleted file mode 100644 index 06796bac..00000000 --- a/material-about-library/src/main/res/values/dimens.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - 16dp - 8dp - - 24dp - 32dp - 40dp - - 4dp - 4dp - - - \ No newline at end of file diff --git a/material-about-library/src/main/res/values/strings.xml b/material-about-library/src/main/res/values/strings.xml deleted file mode 100644 index cbe49a18..00000000 --- a/material-about-library/src/main/res/values/strings.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - About - - Close - Send email - - No apps to handle action - - - "\nCopyright %1$s %2$s\n" - - "\nLicensed under the Apache License, Version 2.0 (the \"License\");" - "you may not use this file except in compliance with the License." - "You may obtain a copy of the License at\n" - - "\nhttp://www.apache.org/licenses/LICENSE-2.0\n" - - "\nUnless required by applicable law or agreed to in writing, software" - "distributed under the License is distributed on an \"AS IS\" BASIS," - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." - "See the License for the specific language governing permissions and" - "limitations under the License." - - - - "\nMIT License\n" - - "\nCopyright © %1$s %2$s\n" - - "\nPermission is hereby granted, free of charge, to any person obtaining a copy" - "of this software and associated documentation files (the "Software"), to deal" - "in the Software without restriction, including without limitation the rights" - "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell" - "copies of the Software, and to permit persons to whom the Software is" - "furnished to do so, subject to the following conditions:\n" - - "\nThe above copyright notice and this permission notice shall be included in all" - "copies or substantial portions of the Software.\n" - - "\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR" - "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY," - "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE" - "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER" - "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM," - "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE" - "SOFTWARE." - - - - "\nCopyright © %1$s %2$s\n" - - "\nThis program is free software: you can redistribute it and/or modify" - "it under the terms of the GNU General Public License as published by" - "the Free Software Foundation, either version 3 of the License, or" - "(at your option) any later version.\n" - - "\nThis program is distributed in the hope that it will be useful," - "but WITHOUT ANY WARRANTY; without even the implied warranty of" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" - "GNU General Public License for more details.\n" - - "\nYou should have received a copy of the GNU General Public License" - "along with this program. If not, see http://www.gnu.org/licenses.\n" - - - - "\nCopyright © %1$s %2$s\n" - - "\nRedistribution and use in source and binary forms, with or without" - "modification, are permitted provided that the following conditions are met:\n" - - "\n1. Redistributions of source code must retain the above copyright notice, this" - " list of conditions and the following disclaimer.\n" - "2. Redistributions in binary form must reproduce the above copyright notice," - " this list of conditions and the following disclaimer in the documentation" - " and/or other materials provided with the distribution.\n" - - "\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND" - "ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED" - "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE" - "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR" - "ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES" - "(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;" - "LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND" - "ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT" - "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS" - "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" - - "\nThe views and conclusions contained in the software and documentation are those" - "of the authors and should not be interpreted as representing official policies," - "either expressed or implied, of the FreeBSD Project.\n" - - diff --git a/material-about-library/src/main/res/values/styles.xml b/material-about-library/src/main/res/values/styles.xml deleted file mode 100644 index d0c6188b..00000000 --- a/material-about-library/src/main/res/values/styles.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index ef628913..955021f9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,7 +3,7 @@ include ':wear' include ':codegen' include ':annotation' rootProject.name='Szkolny.eu' -include ':app', ':agendacalendarview', ':mhttp', ':cafebar', ':szkolny-font', ':nachos' +include ':app', ':agendacalendarview', ':mhttp', ':szkolny-font', ':nachos' /* include ':Navigation' project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/ From 15f9db5ca6e10c6fa59815635909b27b547ce66d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 20 Mar 2021 20:11:50 +0100 Subject: [PATCH 03/15] [Gradle] Extract nachos dependency. --- app/build.gradle | 2 +- nachos/build.gradle | 23 - nachos/maven_push.gradle | 111 -- nachos/src/main/AndroidManifest.xml | 5 - .../hootsuite/nachos/ChipConfiguration.java | 78 -- .../com/hootsuite/nachos/NachoTextView.java | 1165 ----------------- .../java/com/hootsuite/nachos/chip/Chip.java | 30 - .../hootsuite/nachos/chip/ChipCreator.java | 44 - .../com/hootsuite/nachos/chip/ChipInfo.java | 20 - .../com/hootsuite/nachos/chip/ChipSpan.java | 511 -------- .../nachos/chip/ChipSpanChipCreator.java | 60 - .../terminator/ChipTerminatorHandler.java | 95 -- .../DefaultChipTerminatorHandler.java | 115 -- .../nachos/terminator/TextIterator.java | 63 - .../nachos/tokenizer/BaseChipTokenizer.java | 89 -- .../nachos/tokenizer/ChipTokenizer.java | 134 -- .../nachos/tokenizer/SpanChipTokenizer.java | 248 ---- .../validator/ChipifyingNachoValidator.java | 32 - .../validator/IllegalCharacterIdentifier.java | 5 - .../nachos/validator/NachoValidator.java | 30 - nachos/src/main/project.properties | 2 - .../res/color/chip_material_background.xml | 4 - nachos/src/main/res/values/attrs.xml | 12 - nachos/src/main/res/values/colors.xml | 5 - nachos/src/main/res/values/dimens.xml | 7 - nachos/src/main/res/values/strings.xml | 3 - nachos/src/main/res/values/styles.xml | 10 - settings.gradle | 2 +- 28 files changed, 2 insertions(+), 2903 deletions(-) delete mode 100644 nachos/build.gradle delete mode 100644 nachos/maven_push.gradle delete mode 100644 nachos/src/main/AndroidManifest.xml delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/ChipConfiguration.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/NachoTextView.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/chip/Chip.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/chip/ChipCreator.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/chip/ChipInfo.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/chip/ChipSpan.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/chip/ChipSpanChipCreator.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/terminator/ChipTerminatorHandler.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/terminator/DefaultChipTerminatorHandler.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/terminator/TextIterator.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/tokenizer/BaseChipTokenizer.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/tokenizer/ChipTokenizer.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/tokenizer/SpanChipTokenizer.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/validator/ChipifyingNachoValidator.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/validator/IllegalCharacterIdentifier.java delete mode 100644 nachos/src/main/java/com/hootsuite/nachos/validator/NachoValidator.java delete mode 100644 nachos/src/main/project.properties delete mode 100644 nachos/src/main/res/color/chip_material_background.xml delete mode 100644 nachos/src/main/res/values/attrs.xml delete mode 100644 nachos/src/main/res/values/colors.xml delete mode 100644 nachos/src/main/res/values/dimens.xml delete mode 100644 nachos/src/main/res/values/strings.xml delete mode 100644 nachos/src/main/res/values/styles.xml diff --git a/app/build.gradle b/app/build.gradle index 56f5e4f4..2f2211d8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -171,7 +171,7 @@ dependencies { implementation "eu.szkolny:cafebar:5bf0c618de" implementation "eu.szkolny:material-about-library:0534abf316" implementation project(":mhttp") - implementation project(":nachos") + implementation "eu.szkolny:nachos:0e5dfcaceb" //implementation project(":Navigation") implementation project(":szkolny-font") diff --git a/nachos/build.gradle b/nachos/build.gradle deleted file mode 100644 index 821a4a83..00000000 --- a/nachos/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion setup.compileSdk - - defaultConfig { - minSdkVersion 15 - targetSdkVersion setup.targetSdk - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "com.android.support:support-compat:28.0.0" -} \ No newline at end of file diff --git a/nachos/maven_push.gradle b/nachos/maven_push.gradle deleted file mode 100644 index 946f7859..00000000 --- a/nachos/maven_push.gradle +++ /dev/null @@ -1,111 +0,0 @@ -apply plugin: 'maven' -apply plugin: 'signing' - -def isReleaseBuild() { - return VERSION_NAME.contains("SNAPSHOT") == false -} - -def getReleaseRepositoryUrl() { - return ARTIFACT_REPO -} - -def getSnapshotRepositoryUrl() { - return ARTIFACT_SNAPSHOT_REPO -} - -def getRepositoryUsername() { - return System.properties['username'] -} - -def getRepositoryPassword() { - return System.properties['password'] -} - -afterEvaluate { project -> - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - pom.groupId = GROUP - pom.artifactId = POM_ARTIFACT_ID - pom.version = VERSION_NAME - - repository(url: getReleaseRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } - snapshotRepository(url: getSnapshotRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } - - pom.project { - name POM_NAME - packaging POM_PACKAGING - description POM_DESCRIPTION - url POM_URL - - scm { - url POM_SCM_URL - connection POM_SCM_CONNECTION - developerConnection POM_SCM_DEV_CONNECTION - } - - licenses { - license { - name POM_LICENCE_NAME - url POM_LICENCE_URL - distribution POM_LICENCE_DIST - } - } - - developers { - developer { - id POM_DEVELOPER_ID - name POM_DEVELOPER_NAME - } - } - } - } - } - } - - task installArchives(type: Upload) { - description "Installs the artifacts to the local Maven repository." - configuration = configurations['archives'] - repositories { - mavenDeployer { - pom.groupId = GROUP - pom.artifactId = POM_ARTIFACT_ID - pom.version = VERSION_NAME - - repository url: "file://${System.properties['user.home']}/.m2/repository" - } - } - } - - signing { - required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } - sign configurations.archives - } - - task androidJavadocs(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - failOnError = false - } - - task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { - classifier = 'javadoc' - from androidJavadocs.destinationDir - } - - task androidSourcesJar(type: Jar) { - classifier = 'sources' - from android.sourceSets.main.java.srcDirs - } - - artifacts { - archives androidSourcesJar - archives androidJavadocsJar - } -} \ No newline at end of file diff --git a/nachos/src/main/AndroidManifest.xml b/nachos/src/main/AndroidManifest.xml deleted file mode 100644 index ad3cc65f..00000000 --- a/nachos/src/main/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/nachos/src/main/java/com/hootsuite/nachos/ChipConfiguration.java b/nachos/src/main/java/com/hootsuite/nachos/ChipConfiguration.java deleted file mode 100644 index 0b8fb3b7..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/ChipConfiguration.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.hootsuite.nachos; - -import android.content.res.ColorStateList; - -public class ChipConfiguration { - - private final int mChipHorizontalSpacing; - private final ColorStateList mChipBackground; - private final int mChipCornerRadius; - private final int mChipTextColor; - private final int mChipTextSize; - private final int mChipHeight; - private final int mChipVerticalSpacing; - private final int mMaxAvailableWidth; - - /** - * Creates a new ChipConfiguration. You can pass in {@code -1} or {@code null} for any of the parameters to indicate that parameter should be - * ignored. - * - * @param chipHorizontalSpacing the amount of horizontal space (in pixels) to put between consecutive chips - * @param chipBackground the {@link ColorStateList} to set as the background of the chips - * @param chipCornerRadius the corner radius of the chip background, in pixels - * @param chipTextColor the color to set as the text color of the chips - * @param chipTextSize the font size (in pixels) to use for the text of the chips - * @param chipHeight the height (in pixels) of each chip - * @param chipVerticalSpacing the amount of vertical space (in pixels) to put between chips on consecutive lines - * @param maxAvailableWidth the maximum available with for a chip (the width of a full line of text in the text view) - */ - ChipConfiguration(int chipHorizontalSpacing, - ColorStateList chipBackground, - int chipCornerRadius, - int chipTextColor, - int chipTextSize, - int chipHeight, - int chipVerticalSpacing, - int maxAvailableWidth) { - mChipHorizontalSpacing = chipHorizontalSpacing; - mChipBackground = chipBackground; - mChipCornerRadius = chipCornerRadius; - mChipTextColor = chipTextColor; - mChipTextSize = chipTextSize; - mChipHeight = chipHeight; - mChipVerticalSpacing = chipVerticalSpacing; - mMaxAvailableWidth = maxAvailableWidth; - } - - public int getChipHorizontalSpacing() { - return mChipHorizontalSpacing; - } - - public ColorStateList getChipBackground() { - return mChipBackground; - } - - public int getChipCornerRadius() { - return mChipCornerRadius; - } - - public int getChipTextColor() { - return mChipTextColor; - } - - public int getChipTextSize() { - return mChipTextSize; - } - - public int getChipHeight() { - return mChipHeight; - } - - public int getChipVerticalSpacing() { - return mChipVerticalSpacing; - } - - public int getMaxAvailableWidth() { - return mMaxAvailableWidth; - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/NachoTextView.java b/nachos/src/main/java/com/hootsuite/nachos/NachoTextView.java deleted file mode 100644 index b2cb81ab..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/NachoTextView.java +++ /dev/null @@ -1,1165 +0,0 @@ -package com.hootsuite.nachos; - -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.graphics.Paint; -import android.text.Editable; -import android.text.Layout; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.AttributeSet; -import android.util.Log; -import android.util.Pair; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.View; -import android.view.inputmethod.EditorInfo; -import android.widget.Adapter; -import android.widget.AdapterView; -import android.widget.AutoCompleteTextView; -import android.widget.ListAdapter; -import android.widget.MultiAutoCompleteTextView; - -import androidx.annotation.ColorInt; -import androidx.annotation.ColorRes; -import androidx.annotation.DimenRes; -import androidx.annotation.Dimension; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; - -import com.hootsuite.nachos.chip.Chip; -import com.hootsuite.nachos.chip.ChipInfo; -import com.hootsuite.nachos.chip.ChipSpan; -import com.hootsuite.nachos.chip.ChipSpanChipCreator; -import com.hootsuite.nachos.terminator.ChipTerminatorHandler; -import com.hootsuite.nachos.terminator.DefaultChipTerminatorHandler; -import com.hootsuite.nachos.tokenizer.ChipTokenizer; -import com.hootsuite.nachos.tokenizer.SpanChipTokenizer; -import com.hootsuite.nachos.validator.ChipifyingNachoValidator; -import com.hootsuite.nachos.validator.IllegalCharacterIdentifier; -import com.hootsuite.nachos.validator.NachoValidator; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** - * An editable TextView extending {@link MultiAutoCompleteTextView} that supports "chipifying" pieces of text and displaying suggestions for segments of the text. - *

The ChipTokenizer

- * To customize chipifying with this class you can provide a custom {@link ChipTokenizer} by calling {@link #setChipTokenizer(ChipTokenizer)}. - * By default the {@link SpanChipTokenizer} is used. - *

Chip Terminators

- * To set which characters trigger the creation of a chip, call {@link #addChipTerminator(char, int)} or {@link #setChipTerminators(Map)}. - * For example if tapping enter should cause all unchipped text to become chipped, call - * {@code chipSuggestionTextView.addChipTerminator('\n', ChipTerminatorHandler.BEHAVIOR_CHIPIFY_ALL);} - * To completely customize how chips are created when text is entered in this text view you can provide a custom {@link ChipTerminatorHandler} - * through {@link #setChipTerminatorHandler(ChipTerminatorHandler)} - *

Illegal Characters

- * To prevent a character from being typed you can call {@link #setIllegalCharacterIdentifier(IllegalCharacterIdentifier)}} to identify characters - * that should be considered illegal. - *

Suggestions

- * To provide suggestions you must provide an {@link android.widget.Adapter} by calling {@link #setAdapter(ListAdapter)} - *

UI Customization

- * This view defines six custom attributes (all of which are optional): - *
    - *
  • chipHorizontalSpacing - the horizontal space between chips
  • - *
  • chipBackground - the background color of the chip
  • - *
  • chipCornerRadius - the corner radius of the chip background
  • - *
  • chipTextColor - the color of the chip text
  • - *
  • chipTextSize - the font size of the chip text
  • - *
  • chipHeight - the height of a single chip
  • - *
  • chipVerticalSpacing - the vertical space between chips on consecutive lines - *
      - *
    • Note: chipVerticalSpacing is only used if a chipHeight is also set
    • - *
    - *
  • - *
- * The values of these attributes will be passed to the ChipTokenizer through {@link ChipTokenizer#applyConfiguration(Editable, ChipConfiguration)} - *

Validation

- * This class can perform validation when certain events occur (such as losing focus). When the validation occurs is decided by - * {@link AutoCompleteTextView}. To perform validation, set a {@link NachoValidator}: - *
- *         nachoTextView.setNachoValidator(new ChipifyingNachoValidator());
- *     
- * Note: The NachoValidator will be ignored if a ChipTokenizer is not set. To perform validation without a ChipTokenizer you can use - * {@link AutoCompleteTextView}'s built-in {@link AutoCompleteTextView.Validator Validator} through {@link #setValidator(Validator)} - *

Editing Chips

- * This class also supports editing chips on touch. To enable this behavior call {@link #enableEditChipOnTouch(boolean, boolean)}. To disable this - * behavior you can call {@link #disableEditChipOnTouch()} - *

Example Setup:

- * A standard setup for this class could look something like the following: - *
- *         String[] suggestions = new String[]{"suggestion 1", "suggestion 2"};
- *         ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, suggestions);
- *         nachoTextView.setAdapter(adapter);
- *         nachoTextView.addChipTerminator('\n', ChipTerminatorHandler.BEHAVIOR_CHIPIFY_ALL);
- *         nachoTextView.addChipTerminator(' ', ChipTerminatorHandler.BEHAVIOR_CHIPIFY_TO_TERMINATOR);
- *         nachoTextView.setIllegalCharacters('@');
- *         nachoTextView.setNachoValidator(new ChipifyingNachoValidator());
- *         nachoTextView.enableEditChipOnTouch(true, true);
- *         nachoTextView.setOnChipClickListener(new NachoTextView.OnChipClickListener() {
- *            {@literal @Override}
- *             public void onChipClick(Chip chip, MotionEvent motionEvent) {
- *                 // Handle click event
- *             }
- *         });
- *         nachoTextView.setOnChipRemoveListener(new NachoTextView.OnChipRemoveListener() {
- *            {@literal @Override}
- *             public void onChipRemove(Chip chip) {
- *                 // Handle remove event
- *             }
- *         });
- *     
- * - * @see SpanChipTokenizer - * @see DefaultChipTerminatorHandler - * @see ChipifyingNachoValidator - */ -public class NachoTextView extends MultiAutoCompleteTextView implements TextWatcher, AdapterView.OnItemClickListener { - - // UI Attributes - private int mChipHorizontalSpacing = -1; - private ColorStateList mChipBackground = null; - private int mChipCornerRadius = -1; - private int mChipTextColor = Color.TRANSPARENT; - private int mChipTextSize = -1; - private int mChipHeight = -1; - private int mChipVerticalSpacing = -1; - - private int mDefaultPaddingTop = 0; - private int mDefaultPaddingBottom = 0; - /** - * Flag to keep track of the padding state so we only update the padding when necessary - */ - private boolean mUsingDefaultPadding = true; - - // Touch events - @Nullable - private OnChipClickListener mOnChipClickListener; - private GestureDetector singleTapDetector; - private boolean mEditChipOnTouchEnabled; - private boolean mMoveChipToEndOnEdit; - private boolean mChipifyUnterminatedTokensOnEdit; - - // Text entry - @Nullable - private ChipTokenizer mChipTokenizer; - @Nullable - private ChipTerminatorHandler mChipTerminatorHandler; - @Nullable - private NachoValidator mNachoValidator; - @Nullable - private IllegalCharacterIdentifier illegalCharacterIdentifier; - - @Nullable - private OnChipRemoveListener mOnChipRemoveListener; - private List mChipsToRemove = new ArrayList<>(); - private boolean mIgnoreTextChangedEvents; - private int mTextChangedStart; - private int mTextChangedEnd; - private boolean mIsPasteEvent; - - // Measurement - private boolean mMeasured; - - // Layout - private boolean mLayoutComplete; - - public NachoTextView(Context context) { - super(context); - init(null); - } - - public NachoTextView(Context context, AttributeSet attrs) { - super(context, attrs); - init(attrs); - } - - public NachoTextView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(attrs); - } - - private void init(@Nullable AttributeSet attrs) { - Context context = getContext(); - - if (attrs != null) { - TypedArray attributes = context.getTheme().obtainStyledAttributes( - attrs, - R.styleable.NachoTextView, - 0, - R.style.DefaultChipSuggestionTextView); - - try { - mChipHorizontalSpacing = attributes.getDimensionPixelSize(R.styleable.NachoTextView_chipHorizontalSpacing, -1); - mChipBackground = attributes.getColorStateList(R.styleable.NachoTextView_chipBackground); - mChipCornerRadius = attributes.getDimensionPixelSize(R.styleable.NachoTextView_chipCornerRadius, -1); - mChipTextColor = attributes.getColor(R.styleable.NachoTextView_chipTextColor, Color.TRANSPARENT); - mChipTextSize = attributes.getDimensionPixelSize(R.styleable.NachoTextView_chipTextSize, -1); - mChipHeight = attributes.getDimensionPixelSize(R.styleable.NachoTextView_chipHeight, -1); - mChipVerticalSpacing = attributes.getDimensionPixelSize(R.styleable.NachoTextView_chipVerticalSpacing, -1); - } finally { - attributes.recycle(); - } - } - - mDefaultPaddingTop = getPaddingTop(); - mDefaultPaddingBottom = getPaddingBottom(); - - singleTapDetector = new GestureDetector(getContext(), new SingleTapListener()); - - setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN); - addTextChangedListener(this); - setChipTokenizer(new SpanChipTokenizer<>(context, new ChipSpanChipCreator(), ChipSpan.class)); - setChipTerminatorHandler(new DefaultChipTerminatorHandler()); - setOnItemClickListener(this); - - updatePadding(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - if (!mMeasured && getWidth() > 0) { - // Refresh the tokenizer for width changes - invalidateChips(); - mMeasured = true; - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - if (!mLayoutComplete) { - invalidateChips(); - mLayoutComplete = true; - } - } - - /** - * Updates the padding based on whether or not any chips are present to avoid the view from changing heights when chips are inserted/deleted. - * Extra padding is added when there are no chips. When there are chips the padding is reverted to its defaults. This only affects top and bottom - * padding because the chips only affect the height of the view. - */ - private void updatePadding() { - if (mChipHeight != -1) { - boolean chipsArePresent = !getAllChips().isEmpty(); - if (!chipsArePresent && mUsingDefaultPadding) { - mUsingDefaultPadding = false; - Paint paint = getPaint(); - Paint.FontMetricsInt fm = paint.getFontMetricsInt(); - int textHeight = fm.descent - fm.ascent; - // Calculate how tall the view should be if there were chips - int newTextHeight = mChipHeight + (mChipVerticalSpacing != -1 ? mChipVerticalSpacing : 0); - // We need to add half our missing height above and below the text by increasing top and bottom padding - int paddingAdjustment = (newTextHeight - textHeight) / 2; - super.setPadding(getPaddingLeft(), mDefaultPaddingTop + paddingAdjustment, getPaddingRight(), mDefaultPaddingBottom + paddingAdjustment); - } else if (chipsArePresent && !mUsingDefaultPadding) { - // If there are chips we can revert to default padding - mUsingDefaultPadding = true; - super.setPadding(getPaddingLeft(), mDefaultPaddingTop, getPaddingRight(), mDefaultPaddingBottom); - } - } - } - - /** - * Sets the padding on this View. The left and right padding will be handled as they normally would in a TextView. The top and bottom padding passed - * here will be the padding that is used when there are one or more chips in the text view. When there are no chips present, the padding will be - * increased to make sure the overall height of the text view stays the same, since chips take up more vertical space than plain text. - * - * @param left the left padding in pixels - * @param top the top padding in pixels - * @param right the right padding in pixels - * @param bottom the bottom padding in pixels - */ - @Override - public void setPadding(int left, int top, int right, int bottom) { - // Call the super method so that left and right padding are updated - // top and bottom padding will be handled in updatePadding() - super.setPadding(left, top, right, bottom); - mDefaultPaddingTop = top; - mDefaultPaddingBottom = bottom; - updatePadding(); - } - - public int getChipHorizontalSpacing() { - return mChipHorizontalSpacing; - } - - public void setChipHorizontalSpacing(@DimenRes int chipHorizontalSpacingResId) { - mChipHorizontalSpacing = getContext().getResources().getDimensionPixelSize(chipHorizontalSpacingResId); - invalidateChips(); - } - - public ColorStateList getChipBackground() { - return mChipBackground; - } - - public void setChipBackgroundResource(@ColorRes int chipBackgroundResId) { - setChipBackground(ContextCompat.getColorStateList(getContext(), chipBackgroundResId)); - } - - public void setChipBackground(ColorStateList chipBackground) { - mChipBackground = chipBackground; - invalidateChips(); - } - - /** - * @return The chip background corner radius value, in pixels. - */ - @Dimension - public int getChipCornerRadius() { - return mChipCornerRadius; - } - - /** - * Sets the chip background corner radius. - * - * @param chipCornerRadiusResId The dimension resource with the corner radius value. - */ - public void setChipCornerRadiusResource(@DimenRes int chipCornerRadiusResId) { - setChipCornerRadius(getContext().getResources().getDimensionPixelSize(chipCornerRadiusResId)); - } - - /** - * Sets the chip background corner radius. - * - * @param chipCornerRadius The corner radius value, in pixels. - */ - public void setChipCornerRadius(@Dimension int chipCornerRadius) { - mChipCornerRadius = chipCornerRadius; - invalidateChips(); - } - - - public int getChipTextColor() { - return mChipTextColor; - } - - public void setChipTextColorResource(@ColorRes int chipTextColorResId) { - setChipTextColor(ContextCompat.getColor(getContext(), chipTextColorResId)); - } - - public void setChipTextColor(@ColorInt int chipTextColor) { - mChipTextColor = chipTextColor; - invalidateChips(); - } - - public int getChipTextSize() { - return mChipTextSize; - } - - public void setChipTextSize(@DimenRes int chipTextSizeResId) { - mChipTextSize = getContext().getResources().getDimensionPixelSize(chipTextSizeResId); - invalidateChips(); - } - - public int getChipHeight() { - return mChipHeight; - } - - public void setChipHeight(@DimenRes int chipHeightResId) { - mChipHeight = getContext().getResources().getDimensionPixelSize(chipHeightResId); - invalidateChips(); - } - - public int getChipVerticalSpacing() { - return mChipVerticalSpacing; - } - - public void setChipVerticalSpacing(@DimenRes int chipVerticalSpacingResId) { - mChipVerticalSpacing = getContext().getResources().getDimensionPixelSize(chipVerticalSpacingResId); - invalidateChips(); - } - - @Nullable - public ChipTokenizer getChipTokenizer() { - return mChipTokenizer; - } - - /** - * Sets the {@link ChipTokenizer} to be used by this ChipSuggestionTextView. - * Note that a Tokenizer set here will override any Tokenizer set by {@link #setTokenizer(Tokenizer)} - * - * @param chipTokenizer the {@link ChipTokenizer} to set - */ - public void setChipTokenizer(@Nullable ChipTokenizer chipTokenizer) { - mChipTokenizer = chipTokenizer; - if (mChipTokenizer != null) { - setTokenizer(new ChipTokenizerWrapper(mChipTokenizer)); - } else { - setTokenizer(null); - } - invalidateChips(); - } - - public void setOnChipClickListener(@Nullable OnChipClickListener onChipClickListener) { - mOnChipClickListener = onChipClickListener; - } - - public void setOnChipRemoveListener(@Nullable OnChipRemoveListener onChipRemoveListener) { - mOnChipRemoveListener = onChipRemoveListener; - } - - public void setChipTerminatorHandler(@Nullable ChipTerminatorHandler chipTerminatorHandler) { - mChipTerminatorHandler = chipTerminatorHandler; - } - - public void setNachoValidator(@Nullable NachoValidator nachoValidator) { - mNachoValidator = nachoValidator; - } - - /** - * @see ChipTerminatorHandler#setChipTerminators(Map) - */ - public void setChipTerminators(@Nullable Map chipTerminators) { - if (mChipTerminatorHandler != null) { - mChipTerminatorHandler.setChipTerminators(chipTerminators); - } - } - - /** - * @see ChipTerminatorHandler#addChipTerminator(char, int) - */ - public void addChipTerminator(char character, int behavior) { - if (mChipTerminatorHandler != null) { - mChipTerminatorHandler.addChipTerminator(character, behavior); - } - } - - /** - * @see ChipTerminatorHandler#setPasteBehavior(int) - */ - public void setPasteBehavior(int pasteBehavior) { - if (mChipTerminatorHandler != null) { - mChipTerminatorHandler.setPasteBehavior(pasteBehavior); - } - } - - /** - * Sets the {@link IllegalCharacterIdentifier} that will identify characters that should - * not show up in the field when typed (i.e. they will be deleted as soon as they are entered). - * If a character is listed as both a chip terminator character and an illegal character, - * it will be treated as an illegal character. - * - * @param illegalCharacterIdentifier the identifier to use - */ - public void setIllegalCharacterIdentifier(@Nullable IllegalCharacterIdentifier illegalCharacterIdentifier) { - this.illegalCharacterIdentifier = illegalCharacterIdentifier; - } - - /** - * Applies any updated configuration parameters to any existing chips and all future chips in the text view. - * - * @see ChipTokenizer#applyConfiguration(Editable, ChipConfiguration) - */ - public void invalidateChips() { - beginUnwatchedTextChange(); - - if (mChipTokenizer != null) { - Editable text = getText(); - int availableWidth = getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight(); - ChipConfiguration configuration = new ChipConfiguration( - mChipHorizontalSpacing, - mChipBackground, - mChipCornerRadius, - mChipTextColor, - mChipTextSize, - mChipHeight, - mChipVerticalSpacing, - availableWidth); - - mChipTokenizer.applyConfiguration(text, configuration); - } - - endUnwatchedTextChange(); - } - - /** - * Enables editing chips on touch events. When a touch event occurs, the touched chip will be put in editing mode. To later disable this behavior - * call {@link #disableEditChipOnTouch()}. - *

- * Note: If an {@link OnChipClickListener} is set it's behavior will override the behavior described here if it's - * {@link OnChipClickListener#onChipClick(Chip, MotionEvent)} method returns true. If that method returns false, the touched chip will be put - * in editing mode as expected. - *

- * - * @param moveChipToEnd if true, the chip will also be moved to the end of the text when it is put in editing mode - * @param chipifyUnterminatedTokens if true, all unterminated tokens will be chipified before the touched chip is put in editing mode - * @see #disableEditChipOnTouch() - */ - public void enableEditChipOnTouch(boolean moveChipToEnd, boolean chipifyUnterminatedTokens) { - mEditChipOnTouchEnabled = true; - mMoveChipToEndOnEdit = moveChipToEnd; - mChipifyUnterminatedTokensOnEdit = chipifyUnterminatedTokens; - } - - /** - * Disables editing chips on touch events. To re-enable this behavior call {@link #enableEditChipOnTouch(boolean, boolean)}. - * - * @see #enableEditChipOnTouch(boolean, boolean) - */ - public void disableEditChipOnTouch() { - mEditChipOnTouchEnabled = false; - } - - /** - * Puts the provided Chip in editing mode (i.e. reverts it to an unchipified token whose text can be edited). - * - * @param chip the chip to edit - * @param moveChipToEnd if true, the chip will also be moved to the end of the text - */ - public void setEditingChip(Chip chip, boolean moveChipToEnd) { - if (mChipTokenizer == null) { - return; - } - - beginUnwatchedTextChange(); - - Editable text = getText(); - if (moveChipToEnd) { - // Move the chip text to the end of the text - text.append(chip.getText()); - // Delete the existing chip - mChipTokenizer.deleteChipAndPadding(chip, text); - // Move the cursor to the end of the text - setSelection(text.length()); - } else { - int chipStart = mChipTokenizer.findChipStart(chip, text); - mChipTokenizer.revertChipToToken(chip, text); - setSelection(mChipTokenizer.findTokenEnd(text, chipStart)); - } - - endUnwatchedTextChange(); - } - - @Override - public boolean onTouchEvent(@NonNull MotionEvent event) { - boolean wasHandled = false; - clearChipStates(); - Chip touchedChip = findTouchedChip(event); - if (touchedChip != null && isFocused() && singleTapDetector.onTouchEvent(event)) { - touchedChip.setState(View.PRESSED_SELECTED_STATE_SET); - if (onChipClicked(touchedChip)) { - wasHandled = true; - } - if (mOnChipClickListener != null) { - mOnChipClickListener.onChipClick(touchedChip, event); - } - } - - // Getting NullPointerException inside Editor.updateFloatingToolbarVisibility (Editor.java:1520) - // primarily seen in Samsung Nougat devices. - boolean superOnTouch = false; - try { - superOnTouch = super.onTouchEvent(event); - } catch (NullPointerException e) { - Log.w("Nacho", String.format("Error during touch event of type [%d]", event.getAction()), e); - // can't handle or reproduce, but will monitor the error - } - - return wasHandled || superOnTouch; - } - - @Nullable - private Chip findTouchedChip(MotionEvent event) { - if (mChipTokenizer == null) { - return null; - } - - Editable text = getText(); - int offset = getOffsetForPosition(event.getX(), event.getY()); - List chips = getAllChips(); - for (Chip chip : chips) { - int chipStart = mChipTokenizer.findChipStart(chip, text); - int chipEnd = mChipTokenizer.findChipEnd(chip, text); // This is actually the index of the character just past the end of the chip - // When a touch event occurs getOffsetForPosition will either return the index of the first character of the span or the index of the - // character one past the end of the span - // This matches up perfectly with chipStart and chipEnd so we can just directly compare them... - if (chipStart <= offset && offset <= chipEnd) { - float startX = getXForIndex(chipStart); - float endX = getXForIndex(chipEnd - 1); - float eventX = event.getX(); - // ... however, when comparing the x coordinate we need to use (chipEnd - 1) because chipEnd will give us the x coordinate of the - // beginning of the next span since that is actually what chipEnd holds. We want the x coordinate of the end of the current span so - // we use (chipEnd - 1) - if (startX <= eventX && eventX <= endX) { - return chip; - } - } - } - return null; - } - - /** - * Implement this method to handle chip clicked events. - * - * @param chip the chip that was clicked - * @return true if the event was handled, otherwise false - */ - public boolean onChipClicked(Chip chip) { - boolean wasHandled = false; - if (mEditChipOnTouchEnabled) { - if (mChipifyUnterminatedTokensOnEdit) { - chipifyAllUnterminatedTokens(); - } - setEditingChip(chip, mMoveChipToEndOnEdit); - wasHandled = true; - } - return wasHandled; - } - - private float getXForIndex(int index) { - Layout layout = getLayout(); - return layout.getPrimaryHorizontal(index); - } - - private void clearChipStates() { - for (Chip chip : getAllChips()) { - chip.setState(View.EMPTY_STATE_SET); - } - } - - @Override - public boolean onTextContextMenuItem(int id) { - int start = getSelectionStart(); - int end = getSelectionEnd(); - switch (id) { - case android.R.id.cut: - try { - setClipboardData(ClipData.newPlainText(null, getTextWithPlainTextSpans(start, end))); - } catch (StringIndexOutOfBoundsException e) { - throw new StringIndexOutOfBoundsException( - String.format( - "%s \nError cutting text index [%s, %s] for text [%s] and substring [%s]", - e.getMessage(), - start, - end, - getText().toString(), - getText().subSequence(start, end))); - } - getText().delete(getSelectionStart(), getSelectionEnd()); - return true; - case android.R.id.copy: - try { - setClipboardData(ClipData.newPlainText(null, getTextWithPlainTextSpans(start, end))); - } catch (StringIndexOutOfBoundsException e) { - throw new StringIndexOutOfBoundsException( - String.format( - "%s \nError copying text index [%s, %s] for text [%s] and substring [%s]", - e.getMessage(), - start, - end, - getText().toString(), - getText().subSequence(start, end))); - } - return true; - case android.R.id.paste: - mIsPasteEvent = true; - boolean returnValue = super.onTextContextMenuItem(id); - mIsPasteEvent = false; - return returnValue; - default: - return super.onTextContextMenuItem(id); - } - } - - private void setClipboardData(ClipData clip) { - ClipboardManager clipboard = (ClipboardManager) getContext(). - getSystemService(Context.CLIPBOARD_SERVICE); - clipboard.setPrimaryClip(clip); - } - - /** - * If a {@link android.widget.AutoCompleteTextView.Validator Validator} was set, this method will validate the entire text. - * (Overrides the superclass method which only validates the current token) - */ - @Override - public void performValidation() { - if (mNachoValidator == null || mChipTokenizer == null) { - super.performValidation(); - return; - } - - CharSequence text = getText(); - if (!TextUtils.isEmpty(text) && !mNachoValidator.isValid(mChipTokenizer, text)) { - setRawText(mNachoValidator.fixText(mChipTokenizer, text)); - } - } - - /** - * From the point this method is called to when {@link #endUnwatchedTextChange()} is called, all TextChanged events will be ignored - */ - private void beginUnwatchedTextChange() { - mIgnoreTextChangedEvents = true; - } - - /** - * After this method is called TextChanged events will resume being handled. - * This method also calls {@link #updatePadding()} in case the unwatched changed created/destroyed chips - */ - private void endUnwatchedTextChange() { - updatePadding(); - mIgnoreTextChangedEvents = false; - } - - /** - * Sets the contents of this text view without performing any processing (nothing will be chipified, no characters will be removed etc.) - * - * @param text the text to set - */ - private void setRawText(CharSequence text) { - beginUnwatchedTextChange(); - super.setText(text); - endUnwatchedTextChange(); - } - - /** - * Sets the contents of this text view to contain the provided list of strings. The text view will be cleared then each string in the list will - * be chipified and appended to the text. - * - * @param chipValues the list of strings to chipify and set as the contents of the text view or null to clear the text view - */ - public void setText(@Nullable List chipValues) { - if (mChipTokenizer == null) { - return; - } - beginUnwatchedTextChange(); - - Editable text = getText(); - text.clear(); - - if (chipValues != null) { - for (String chipValue : chipValues) { - CharSequence chippedText = mChipTokenizer.terminateToken(chipValue, null); - text.append(chippedText); - } - } - setSelection(text.length()); - - endUnwatchedTextChange(); - } - - public void setTextWithChips(@Nullable List chips) { - if (mChipTokenizer == null) { - return; - } - beginUnwatchedTextChange(); - - Editable text = getText(); - text.clear(); - - if (chips != null) { - for (ChipInfo chipInfo : chips) { - CharSequence chippedText = mChipTokenizer.terminateToken(chipInfo.getText(), chipInfo.getData()); - text.append(chippedText); - } - } - setSelection(text.length()); - endUnwatchedTextChange(); - } - - public void addTextWithChips(@Nullable List chips) { - if (mChipTokenizer == null) { - return; - } - beginUnwatchedTextChange(); - - Editable text = getText(); - - if (chips != null) { - for (ChipInfo chipInfo : chips) { - CharSequence chippedText = mChipTokenizer.terminateToken(chipInfo.getText(), chipInfo.getData()); - text.append(chippedText); - } - } - setSelection(text.length()); - endUnwatchedTextChange(); - } - - @Override - public void onItemClick(AdapterView adapterView, View view, int position, long id) { - if (mChipTokenizer == null) { - return; - } - Adapter adapter = getAdapter(); - if (adapter == null) { - return; - } - beginUnwatchedTextChange(); - - Object data = getDataForSuggestion(adapter, position); - CharSequence text = getFilter().convertResultToString(adapter.getItem(position)); - - clearComposingText(); - int end = getSelectionEnd(); - Editable editable = getText(); - int start = mChipTokenizer.findTokenStart(editable, end); - - // guard against java.lang.StringIndexOutOfBoundsException - start = Math.min(Math.max(0, start), editable.length()); - end = Math.min(Math.max(0, end), editable.length()); - if (end < start) { - end = start; - } - - editable.replace(start, end, mChipTokenizer.terminateToken(text, data)); - - endUnwatchedTextChange(); - } - - /** - * Returns a object that will be associated with a chip that is about to be created for the item at {@code position} in {@code adapter} because that - * item was just tapped. - * - * @param adapter the adapter supplying the suggestions - * @param position the position of the suggestion that was tapped - * @return the data object - */ - protected Object getDataForSuggestion(@NonNull Adapter adapter, int position) { - return adapter.getItem(position); - } - - /** - * If there is a ChipTokenizer set, this method will do nothing. Instead we wait until the OnItemClickListener is triggered to actually perform - * the text replacement so we can also associate the suggestion data with it. - *

- * If there is no ChipTokenizer set, we call through to the super method. - * - * @param text the text to be chipified - */ - @Override - protected void replaceText(CharSequence text) { - // If we have a ChipTokenizer, this will be handled by our OnItemClickListener so we can do nothing here. - // If we don't have a ChipTokenizer, we'll use the default behavior - if (mChipTokenizer == null) { - super.replaceText(text); - } - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - if (mIgnoreTextChangedEvents) { - return; - } - - mTextChangedStart = start; - mTextChangedEnd = start + after; - - // Check for backspace - if (mChipTokenizer != null) { - if (count > 0 && after < count) { - int end = start + count; - Editable message = getText(); - Chip[] chips = mChipTokenizer.findAllChips(start, end, message); - - for (Chip chip : chips) { - int spanStart = mChipTokenizer.findChipStart(chip, message); - int spanEnd = mChipTokenizer.findChipEnd(chip, message); - if ((spanStart < end) && (spanEnd > start)) { - // Add to remove list - mChipsToRemove.add(chip); - } - } - } - } - } - - @Override - public void onTextChanged(@NonNull CharSequence textChanged, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable message) { - if (mIgnoreTextChangedEvents) { - return; - } - - // Avoid triggering text changed events from changes we make in this method - beginUnwatchedTextChange(); - - // Handle backspace key - if (mChipTokenizer != null) { - Iterator iterator = mChipsToRemove.iterator(); - while (iterator.hasNext()) { - Chip chip = iterator.next(); - iterator.remove(); - mChipTokenizer.deleteChip(chip, message); - if (mOnChipRemoveListener != null) { - mOnChipRemoveListener.onChipRemove(chip); - } - } - } - - // Handle an illegal or chip terminator character - if (message.length() >= mTextChangedEnd && message.length() >= mTextChangedStart) { - handleTextChanged(mTextChangedStart, mTextChangedEnd); - } - - endUnwatchedTextChange(); - } - - private void handleTextChanged(int start, int end) { - if (start == end) { - // If start and end are the same there was text deleted, so this type of event can be ignored - return; - } - - // First remove any illegal characters - Editable text = getText(); - CharSequence subText = text.subSequence(start, end); - CharSequence withoutIllegalCharacters = removeIllegalCharacters(subText); - - // Check if illegal characters were found - if (withoutIllegalCharacters.length() < subText.length()) { - text.replace(start, end, withoutIllegalCharacters); - end = start + withoutIllegalCharacters.length(); - clearComposingText(); - } - - if (start == end) { - // If start and end are the same here, it means only illegal characters were inserted so there's nothing left to do - return; - } - - // Then handle chip terminator characters - if (mChipTokenizer != null && mChipTerminatorHandler != null) { - int newSelectionIndex = mChipTerminatorHandler.findAndHandleChipTerminators(mChipTokenizer, getText(), start, end, mIsPasteEvent); - if (newSelectionIndex > 0) { - setSelection(newSelectionIndex); - } - } - } - - private CharSequence removeIllegalCharacters(CharSequence text) { - StringBuilder newText = new StringBuilder(); - - for (int i = 0; i < text.length(); i++) { - char theChar = text.charAt(i); - if (!isIllegalCharacter(theChar)) { - newText.append(theChar); - } - } - - return newText; - } - - private boolean isIllegalCharacter(char character) { - if (illegalCharacterIdentifier != null) { - return illegalCharacterIdentifier.isCharacterIllegal(character); - } - return false; - } - - /** - * Chipifies all existing plain text in the field - */ - public void chipifyAllUnterminatedTokens() { - beginUnwatchedTextChange(); - chipifyAllUnterminatedTokens(getText()); - endUnwatchedTextChange(); - } - - private void chipifyAllUnterminatedTokens(Editable text) { - if (mChipTokenizer != null) { - mChipTokenizer.terminateAllTokens(text); - } - } - - /** - * Replaces the text from start (inclusive) to end (exclusive) with a chip - * containing the same text - * - * @param start the index of the first character to replace - * @param end one more than the index of the last character to replace - */ - public void chipify(int start, int end) { - beginUnwatchedTextChange(); - chipify(start, end, getText(), null); - endUnwatchedTextChange(); - } - - private void chipify(int start, int end, Editable text, Object data) { - if (mChipTokenizer != null) { - CharSequence textToChip = text.subSequence(start, end); - CharSequence chippedText = mChipTokenizer.terminateToken(textToChip, data); - text.replace(start, end, chippedText); - } - } - - private CharSequence getTextWithPlainTextSpans(int start, int end) { - Editable editable = getText(); - String selectedText = editable.subSequence(start, end).toString(); - - if (mChipTokenizer != null) { - List chips = Arrays.asList(mChipTokenizer.findAllChips(start, end, editable)); - Collections.reverse(chips); - for (Chip chip : chips) { - String chipText = chip.getText().toString(); - int chipStart = mChipTokenizer.findChipStart(chip, editable) - start; - int chipEnd = mChipTokenizer.findChipEnd(chip, editable) - start; - selectedText = selectedText.substring(0, chipStart) + chipText + selectedText.substring(chipEnd, selectedText.length()); - } - } - return selectedText; - } - - /** - * @return all of the chips currently in the text view - this does not include any unchipped text - */ - @NonNull - public List getAllChips() { - Editable text = getText(); - return mChipTokenizer != null ? Arrays.asList(mChipTokenizer.findAllChips(0, text.length(), text)) : new ArrayList(); - } - - /** - * Returns a List of the string values of all the chips in the text (obtained through {@link Chip#getText()}). - * This does not include the text of any unterminated tokens. - * - * @return the List of chip values - */ - @NonNull - public List getChipValues() { - List chipValues = new ArrayList<>(); - - List chips = getAllChips(); - for (Chip chip : chips) { - chipValues.add(chip.getText().toString()); - } - - return chipValues; - } - - /** - * Returns a List of the string values of all the tokens (unchipped text) in the text - * (obtained through {@link ChipTokenizer#findAllTokens(CharSequence)}). This does not include any chipped text. - * - * @return the List of token values - */ - @NonNull - public List getTokenValues() { - List tokenValues = new ArrayList<>(); - - if (mChipTokenizer != null) { - Editable text = getText(); - List> unterminatedTokenIndexes = mChipTokenizer.findAllTokens(text); - for (Pair indexes : unterminatedTokenIndexes) { - String tokenValue = text.subSequence(indexes.first, indexes.second).toString(); - tokenValues.add(tokenValue); - } - } - - return tokenValues; - } - - /** - * Returns a combination of the chip values and token values in the text. - * - * @return the List of all chip and token values - * @see #getChipValues() - * @see #getTokenValues() - */ - @NonNull - public List getChipAndTokenValues() { - List chipAndTokenValues = new ArrayList<>(); - chipAndTokenValues.addAll(getChipValues()); - chipAndTokenValues.addAll(getTokenValues()); - return chipAndTokenValues; - } - - public boolean ignoreThreshold = false; - - @Override - public boolean enoughToFilter() { - return ignoreThreshold || super.enoughToFilter(); - } - - public OnDismissListener onDismissListener = null; - - @Override - public void dismissDropDown() { - if (onDismissListener != null) - onDismissListener.onDismiss(); - super.dismissDropDown(); - } - - @Override - public String toString() { - try { - return getTextWithPlainTextSpans(0, getText().length()).toString(); - } catch (ClassCastException ex) { // Exception is thrown by cast in getText() on some LG devices - return super.toString(); - } catch (StringIndexOutOfBoundsException e) { - throw new StringIndexOutOfBoundsException(String.format("%s \nError converting toString() [%s]", e.getMessage(), getText().toString())); - } - } - - private class ChipTokenizerWrapper implements Tokenizer { - - @NonNull - private ChipTokenizer mChipTokenizer; - - public ChipTokenizerWrapper(@NonNull ChipTokenizer chipTokenizer) { - mChipTokenizer = chipTokenizer; - } - - @Override - public int findTokenStart(CharSequence text, int cursor) { - return mChipTokenizer.findTokenStart(text, cursor); - } - - @Override - public int findTokenEnd(CharSequence text, int cursor) { - return mChipTokenizer.findTokenEnd(text, cursor); - } - - @Override - public CharSequence terminateToken(CharSequence text) { - return mChipTokenizer.terminateToken(text, null); - } - } - - public interface OnChipClickListener { - - /** - * Called when a chip in this TextView is touched. This callback is triggered by the {@link MotionEvent#ACTION_UP} event. - * - * @param chip the {@link Chip} that was touched - * @param event the {@link MotionEvent} that caused the touch - */ - void onChipClick(Chip chip, MotionEvent event); - } - - public interface OnChipRemoveListener { - - /** - * Called when a chip in this TextView is removed - * - * @param chip the {@link Chip} that was removed - */ - void onChipRemove(Chip chip); - } - - private class SingleTapListener extends GestureDetector.SimpleOnGestureListener { - - /** - * @param e the {@link MotionEvent} passed to the GestureDetector - * @return true if singleTapUp (click) was detected - */ - @Override - public boolean onSingleTapUp(MotionEvent e) { - return true; - } - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/chip/Chip.java b/nachos/src/main/java/com/hootsuite/nachos/chip/Chip.java deleted file mode 100644 index a370eb26..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/chip/Chip.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.hootsuite.nachos.chip; - - -import androidx.annotation.Nullable; - -public interface Chip { - - /** - * @return the text represented by this Chip - */ - CharSequence getText(); - - /** - * @return the data associated with this Chip or null if no data is associated with it - */ - @Nullable - Object getData(); - - /** - * @return the width of the Chip or -1 if the Chip hasn't been given the chance to calculate its width - */ - int getWidth(); - - /** - * Sets the UI state. - * - * @param stateSet one of the state constants in {@link android.view.View} - */ - void setState(int[] stateSet); -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/chip/ChipCreator.java b/nachos/src/main/java/com/hootsuite/nachos/chip/ChipCreator.java deleted file mode 100644 index c38f5cff..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/chip/ChipCreator.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.hootsuite.nachos.chip; - -import android.content.Context; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hootsuite.nachos.ChipConfiguration; - -/** - * Interface to allow the creation and configuration of chips - * - * @param The type of {@link Chip} that the implementation will create/configure - */ -public interface ChipCreator { - - /** - * Creates a chip from the given context and text. Use this method when creating a brand new chip from a piece of text. - * - * @param context the {@link Context} to use to initialize the chip - * @param text the text the Chip should represent - * @param data the data to associate with the Chip, or null to associate no data - * @return the created chip - */ - C createChip(@NonNull Context context, @NonNull CharSequence text, @Nullable Object data); - - /** - * Creates a chip from the given context and existing chip. Use this method when recreating a chip from an existing one. - * - * @param context the {@link Context} to use to initialize the chip - * @param existingChip the chip that the created chip should be based on - * @return the created chip - */ - C createChip(@NonNull Context context, @NonNull C existingChip); - - /** - * Applies the given {@link ChipConfiguration} to the given {@link Chip}. Use this method to customize the appearance/behavior of a chip before - * adding it to the text. - * - * @param chip the chip to configure - * @param chipConfiguration the configuration to apply to the chip - */ - void configureChip(@NonNull C chip, @NonNull ChipConfiguration chipConfiguration); -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/chip/ChipInfo.java b/nachos/src/main/java/com/hootsuite/nachos/chip/ChipInfo.java deleted file mode 100644 index 69b8ea4c..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/chip/ChipInfo.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.hootsuite.nachos.chip; - -public class ChipInfo { - - private final CharSequence mText; - private final Object mData; - - public ChipInfo(CharSequence text, Object data) { - this.mText = text; - this.mData = data; - } - - public CharSequence getText() { - return mText; - } - - public Object getData() { - return mData; - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/chip/ChipSpan.java b/nachos/src/main/java/com/hootsuite/nachos/chip/ChipSpan.java deleted file mode 100644 index 652f5550..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/chip/ChipSpan.java +++ /dev/null @@ -1,511 +0,0 @@ -package com.hootsuite.nachos.chip; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.text.style.ImageSpan; - -import androidx.annotation.Dimension; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; - -import com.hootsuite.nachos.R; - -/** - * A Span that displays text and an optional icon inside of a material design chip. The chip's dimensions, colors etc. can be extensively customized - * through the various setter methods available in this class. - * The basic structure of the chip is the following: - * For chips with the icon on right: - *

- *
- *                                  (chip vertical spacing / 2)
- *                  ----------------------------------------------------------
- *                |                                                            |
- * (left margin)  |  (padding edge)   text   (padding between image)   icon    |   (right margin)
- *                |                                                            |
- *                  ----------------------------------------------------------
- *                                  (chip vertical spacing / 2)
- *
- *      
- * For chips with the icon on the left (see {@link #setShowIconOnLeft(boolean)}): - *
- *
- *                                  (chip vertical spacing / 2)
- *                  ----------------------------------------------------------
- *                |                                                            |
- * (left margin)  |   icon  (padding between image)   text   (padding edge)    |   (right margin)
- *                |                                                            |
- *                  ----------------------------------------------------------
- *                                  (chip vertical spacing / 2)
- *     
- */ -public class ChipSpan extends ImageSpan implements Chip { - - private static final float SCALE_PERCENT_OF_CHIP_HEIGHT = 0.70f; - private static final boolean ICON_ON_LEFT_DEFAULT = true; - - private int[] mStateSet = new int[]{}; - - private String mEllipsis; - - private ColorStateList mDefaultBackgroundColor; - private ColorStateList mBackgroundColor; - private int mTextColor; - private int mCornerRadius = -1; - private int mIconBackgroundColor; - - private int mTextSize = -1; - private int mPaddingEdgePx; - private int mPaddingBetweenImagePx; - private int mLeftMarginPx; - private int mRightMarginPx; - private int mMaxAvailableWidth = -1; - - private CharSequence mText; - private String mTextToDraw; - - private Drawable mIcon; - private boolean mShowIconOnLeft = ICON_ON_LEFT_DEFAULT; - - private int mChipVerticalSpacing = 0; - private int mChipHeight = -1; - private int mChipWidth = -1; - private int mIconWidth; - - private int mCachedSize = -1; - - private Object mData; - - /** - * Constructs a new ChipSpan. - * - * @param context a {@link Context} that will be used to retrieve default configurations from resource files - * @param text the text for the ChipSpan to display - * @param icon an optional icon (can be {@code null}) for the ChipSpan to display - */ - public ChipSpan(@NonNull Context context, @NonNull CharSequence text, @Nullable Drawable icon, Object data) { - super(icon); - mIcon = icon; - mText = text; - mTextToDraw = mText.toString(); - - mEllipsis = context.getString(R.string.chip_ellipsis); - - mDefaultBackgroundColor = ContextCompat.getColorStateList(context, R.color.chip_material_background); - mBackgroundColor = mDefaultBackgroundColor; - - mTextColor = ContextCompat.getColor(context, R.color.chip_default_text_color); - mIconBackgroundColor = ContextCompat.getColor(context, R.color.chip_default_icon_background_color); - - Resources resources = context.getResources(); - mPaddingEdgePx = resources.getDimensionPixelSize(R.dimen.chip_default_padding_edge); - mPaddingBetweenImagePx = resources.getDimensionPixelSize(R.dimen.chip_default_padding_between_image); - mLeftMarginPx = resources.getDimensionPixelSize(R.dimen.chip_default_left_margin); - mRightMarginPx = resources.getDimensionPixelSize(R.dimen.chip_default_right_margin); - - mData = data; - } - - /** - * Copy constructor to recreate a ChipSpan from an existing one - * - * @param context a {@link Context} that will be used to retrieve default configurations from resource files - * @param chipSpan the ChipSpan to copy - */ - public ChipSpan(@NonNull Context context, @NonNull ChipSpan chipSpan) { - this(context, chipSpan.getText(), chipSpan.getDrawable(), chipSpan.getData()); - - mDefaultBackgroundColor = chipSpan.mDefaultBackgroundColor; - mTextColor = chipSpan.mTextColor; - mIconBackgroundColor = chipSpan.mIconBackgroundColor; - mCornerRadius = chipSpan.mCornerRadius; - - mTextSize = chipSpan.mTextSize; - mPaddingEdgePx = chipSpan.mPaddingEdgePx; - mPaddingBetweenImagePx = chipSpan.mPaddingBetweenImagePx; - mLeftMarginPx = chipSpan.mLeftMarginPx; - mRightMarginPx = chipSpan.mRightMarginPx; - mMaxAvailableWidth = chipSpan.mMaxAvailableWidth; - - mShowIconOnLeft = chipSpan.mShowIconOnLeft; - - mChipVerticalSpacing = chipSpan.mChipVerticalSpacing; - mChipHeight = chipSpan.mChipHeight; - - mStateSet = chipSpan.mStateSet; - } - - @Override - public Object getData() { - return mData; - } - - /** - * Sets the height of the chip. This height should not include any extra spacing (for extra vertical spacing call {@link #setChipVerticalSpacing(int)}). - * The background of the chip will fill the full height provided here. If this method is never called, the chip will have the height of one full line - * of text by default. If {@code -1} is passed here, the chip will revert to this default behavior. - * - * @param chipHeight the height to set in pixels - */ - public void setChipHeight(int chipHeight) { - mChipHeight = chipHeight; - } - - /** - * Sets the vertical spacing to include in between chips. Half of the value set here will be placed as empty space above the chip and half the value - * will be placed as empty space below the chip. Therefore chips on consecutive lines will have the full value as vertical space in between them. - * This spacing is achieved by adjusting the font metrics used by the text view containing these chips; however it does not come into effect until - * at least one chip is created. Note that vertical spacing is dependent on having a fixed chip height (set in {@link #setChipHeight(int)}). If a - * height is not specified in that method, the value set here will be ignored. - * - * @param chipVerticalSpacing the vertical spacing to set in pixels - */ - public void setChipVerticalSpacing(int chipVerticalSpacing) { - mChipVerticalSpacing = chipVerticalSpacing; - } - - /** - * Sets the font size for the chip's text. If this method is never called, the chip text will have the same font size as the text in the TextView - * containing this chip by default. If {@code -1} is passed here, the chip will revert to this default behavior. - * - * @param size the font size to set in pixels - */ - public void setTextSize(int size) { - mTextSize = size; - invalidateCachedSize(); - } - - /** - * Sets the color for the chip's text. - * - * @param color the color to set (as a hexadecimal number in the form 0xAARRGGBB) - */ - public void setTextColor(int color) { - mTextColor = color; - } - - /** - * Sets where the icon (if an icon was provided in the constructor) will appear. - * - * @param showIconOnLeft if true, the icon will appear on the left, otherwise the icon will appear on the right - */ - public void setShowIconOnLeft(boolean showIconOnLeft) { - this.mShowIconOnLeft = showIconOnLeft; - invalidateCachedSize(); - } - - /** - * Sets the left margin. This margin will appear as empty space (it will not share the chip's background color) to the left of the chip. - * - * @param leftMarginPx the left margin to set in pixels - */ - public void setLeftMargin(int leftMarginPx) { - mLeftMarginPx = leftMarginPx; - invalidateCachedSize(); - } - - /** - * Sets the right margin. This margin will appear as empty space (it will not share the chip's background color) to the right of the chip. - * - * @param rightMarginPx the right margin to set in pixels - */ - public void setRightMargin(int rightMarginPx) { - this.mRightMarginPx = rightMarginPx; - invalidateCachedSize(); - } - - /** - * Sets the background color. To configure which color in the {@link ColorStateList} is shown you can call {@link #setState(int[])}. - * Passing {@code null} here will cause the chip to revert to it's default background. - * - * @param backgroundColor a {@link ColorStateList} containing backgrounds for different states. - * @see #setState(int[]) - */ - public void setBackgroundColor(@Nullable ColorStateList backgroundColor) { - mBackgroundColor = backgroundColor != null ? backgroundColor : mDefaultBackgroundColor; - } - - /** - * Sets the chip background corner radius. - * - * @param cornerRadius The corner radius value, in pixels. - */ - public void setCornerRadius(@Dimension int cornerRadius) { - mCornerRadius = cornerRadius; - } - - /** - * Sets the icon background color. This is the color of the circle that gets drawn behind the icon passed to the - * {@link #ChipSpan(Context, CharSequence, Drawable, Object)} constructor} - * - * @param iconBackgroundColor the icon background color to set (as a hexadecimal number in the form 0xAARRGGBB) - */ - public void setIconBackgroundColor(int iconBackgroundColor) { - mIconBackgroundColor = iconBackgroundColor; - } - - public void setMaxAvailableWidth(int maxAvailableWidth) { - mMaxAvailableWidth = maxAvailableWidth; - invalidateCachedSize(); - } - - /** - * Sets the UI state. This state will be reflected in the background color drawn for the chip. - * - * @param stateSet one of the state constants in {@link android.view.View} - * @see #setBackgroundColor(ColorStateList) - */ - @Override - public void setState(int[] stateSet) { - this.mStateSet = stateSet != null ? stateSet : new int[]{}; - } - - @Override - public CharSequence getText() { - return mText; - } - - @Override - public int getWidth() { - // If we haven't actually calculated a chip width yet just return -1, otherwise return the chip width + margins - return mChipWidth != -1 ? (mLeftMarginPx + mChipWidth + mRightMarginPx) : -1; - } - - @Override - public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { - boolean usingFontMetrics = (fm != null); - - // Adjust the font metrics regardless of whether or not there is a cached size so that the text view can maintain its height - if (usingFontMetrics) { - adjustFontMetrics(paint, fm); - } - - if (mCachedSize == -1 && usingFontMetrics) { - mIconWidth = (mIcon != null) ? calculateChipHeight(fm.top, fm.bottom) : 0; - - int actualWidth = calculateActualWidth(paint); - mCachedSize = actualWidth; - - if (mMaxAvailableWidth != -1) { - int maxAvailableWidthMinusMargins = mMaxAvailableWidth - mLeftMarginPx - mRightMarginPx; - if (actualWidth > maxAvailableWidthMinusMargins) { - mTextToDraw = mText + mEllipsis; - - while ((calculateActualWidth(paint) > maxAvailableWidthMinusMargins) && mTextToDraw.length() > 0) { - int lastCharacterIndex = mTextToDraw.length() - mEllipsis.length() - 1; - if (lastCharacterIndex < 0) { - break; - } - mTextToDraw = mTextToDraw.substring(0, lastCharacterIndex) + mEllipsis; - } - - // Avoid a negative width - mChipWidth = Math.max(0, maxAvailableWidthMinusMargins); - mCachedSize = mMaxAvailableWidth; - } - } - } - - return mCachedSize; - } - - private int calculateActualWidth(Paint paint) { - // Only change the text size if a text size was set - if (mTextSize != -1) { - paint.setTextSize(mTextSize); - } - - int totalPadding = mPaddingEdgePx; - - // Find text width - Rect bounds = new Rect(); - paint.getTextBounds(mTextToDraw, 0, mTextToDraw.length(), bounds); - int textWidth = bounds.width(); - - if (mIcon != null) { - totalPadding += mPaddingBetweenImagePx; - } else { - totalPadding += mPaddingEdgePx; - } - - mChipWidth = totalPadding + textWidth + mIconWidth; - return getWidth(); - } - - public void invalidateCachedSize() { - mCachedSize = -1; - } - - /** - * Adjusts the provided font metrics to make it seem like the font takes up {@code mChipHeight + mChipVerticalSpacing} pixels in height. - * This effectively ensures that the TextView will have a height equal to {@code mChipHeight + mChipVerticalSpacing} + whatever padding it has set. - * In {@link #draw(Canvas, CharSequence, int, int, float, int, int, int, Paint)} the chip itself is drawn to that it is vertically centered with - * {@code mChipVerticalSpacing / 2} pixels of space above and below it - * - * @param paint the paint whose font metrics should be adjusted - * @param fm the font metrics object to populate through {@link Paint#getFontMetricsInt(Paint.FontMetricsInt)} - */ - private void adjustFontMetrics(Paint paint, Paint.FontMetricsInt fm) { - // Only actually adjust font metrics if we have a chip height set - if (mChipHeight != -1) { - paint.getFontMetricsInt(fm); - int textHeight = fm.descent - fm.ascent; - // Break up the vertical spacing in half because half will go above the chip, half will go below the chip - int halfSpacing = mChipVerticalSpacing / 2; - - // Given that the text is centered vertically within the chip, the amount of space above or below the text (inbetween the text and chip) - // is half their difference in height: - int spaceBetweenChipAndText = (mChipHeight - textHeight) / 2; - - int textTop = fm.top; - int chipTop = fm.top - spaceBetweenChipAndText; - - int textBottom = fm.bottom; - int chipBottom = fm.bottom + spaceBetweenChipAndText; - - // The text may have been taller to begin with so we take the most negative coordinate (highest up) to be the top of the content - int topOfContent = Math.min(textTop, chipTop); - // Same as above but we want the largest positive coordinate (lowest down) to be the bottom of the content - int bottomOfContent = Math.max(textBottom, chipBottom); - - // Shift the top up by halfSpacing and the bottom down by halfSpacing - int topOfContentWithSpacing = topOfContent - halfSpacing; - int bottomOfContentWithSpacing = bottomOfContent + halfSpacing; - - // Change the font metrics so that the TextView thinks the font takes up the vertical space of a chip + spacing - fm.ascent = topOfContentWithSpacing; - fm.descent = bottomOfContentWithSpacing; - fm.top = topOfContentWithSpacing; - fm.bottom = bottomOfContentWithSpacing; - } - } - - private int calculateChipHeight(int top, int bottom) { - // If a chip height was set we can return that, otherwise calculate it from top and bottom - return mChipHeight != -1 ? mChipHeight : bottom - top; - } - - @Override - public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { - // Shift everything mLeftMarginPx to the left to create an empty space on the left (creating the margin) - x += mLeftMarginPx; - if (mChipHeight != -1) { - // If we set a chip height, adjust to vertically center chip in the line - // Adding (bottom - top) / 2 shifts the chip down so the top of it will be centered vertically - // Subtracting (mChipHeight / 2) shifts the chip back up so that the center of it will be centered vertically (as desired) - top += ((bottom - top) / 2) - (mChipHeight / 2); - bottom = top + mChipHeight; - } - - // Perform actual drawing - drawBackground(canvas, x, top, bottom, paint); - drawText(canvas, x, top, bottom, paint, mTextToDraw); - if (mIcon != null) { - drawIcon(canvas, x, top, bottom, paint); - } - } - - private void drawBackground(Canvas canvas, float x, int top, int bottom, Paint paint) { - int backgroundColor = mBackgroundColor.getColorForState(mStateSet, mBackgroundColor.getDefaultColor()); - paint.setColor(backgroundColor); - int height = calculateChipHeight(top, bottom); - RectF rect = new RectF(x, top, x + mChipWidth, bottom); - int cornerRadius = (mCornerRadius != -1) ? mCornerRadius : height / 2; - canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint); - paint.setColor(mTextColor); - } - - private void drawText(Canvas canvas, float x, int top, int bottom, Paint paint, CharSequence text) { - if (mTextSize != -1) { - paint.setTextSize(mTextSize); - } - int height = calculateChipHeight(top, bottom); - Paint.FontMetrics fm = paint.getFontMetrics(); - - // The top value provided here is the y coordinate for the very top of the chip - // The y coordinate we are calculating is where the baseline of the text will be drawn - // Our objective is to have the midpoint between the top and baseline of the text be in line with the vertical center of the chip - // First we add height / 2 which will put the baseline at the vertical center of the chip - // Then we add half the height of the text which will lower baseline so that the midpoint is at the vertical center of the chip as desired - float adjustedY = top + ((height / 2) + ((-fm.top - fm.bottom) / 2)); - - // The x coordinate provided here is the left-most edge of the chip - // If there is no icon or the icon is on the right, then the text will start at the left-most edge, but indented with the edge padding, so we - // add mPaddingEdgePx - // If there is an icon and it's on the left, the text will start at the left-most edge, but indented by the combined width of the icon and - // the padding between the icon and text, so we add (mIconWidth + mPaddingBetweenImagePx) - float adjustedX = x + ((mIcon == null || !mShowIconOnLeft) ? mPaddingEdgePx : (mIconWidth + mPaddingBetweenImagePx)); - - canvas.drawText(text, 0, text.length(), adjustedX, adjustedY, paint); - } - - private void drawIcon(Canvas canvas, float x, int top, int bottom, Paint paint) { - drawIconBackground(canvas, x, top, bottom, paint); - drawIconBitmap(canvas, x, top, bottom, paint); - } - - private void drawIconBackground(Canvas canvas, float x, int top, int bottom, Paint paint) { - int height = calculateChipHeight(top, bottom); - - paint.setColor(mIconBackgroundColor); - - // Since it's a circle the diameter is equal to the height, so the radius == diameter / 2 == height / 2 - int radius = height / 2; - // The coordinates that get passed to drawCircle are for the center of the circle - // x is the left edge of the chip, (x + mChipWidth) is the right edge of the chip - // So the center of the circle is one radius distance from either the left or right edge (depending on which side the icon is being drawn on) - float circleX = mShowIconOnLeft ? (x + radius) : (x + mChipWidth - radius); - // The y coordinate is always just one radius distance from the top - canvas.drawCircle(circleX, top + radius, radius, paint); - - paint.setColor(mTextColor); - } - - private void drawIconBitmap(Canvas canvas, float x, int top, int bottom, Paint paint) { - int height = calculateChipHeight(top, bottom); - - // Create a scaled down version of the bitmap to fit within the circle (whose diameter == height) - Bitmap iconBitmap = Bitmap.createBitmap(mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); - Bitmap scaledIconBitMap = scaleDown(iconBitmap, (float) height * SCALE_PERCENT_OF_CHIP_HEIGHT, true); - iconBitmap.recycle(); - Canvas bitmapCanvas = new Canvas(scaledIconBitMap); - mIcon.setBounds(0, 0, bitmapCanvas.getWidth(), bitmapCanvas.getHeight()); - mIcon.draw(bitmapCanvas); - - // We are drawing a square icon inside of a circle - // The coordinates we pass to canvas.drawBitmap have to be for the top-left corner of the bitmap - // The bitmap should be inset by half of (circle width - bitmap width) - // Since it's a circle, the circle's width is equal to it's height which is equal to the chip height - float xInsetWithinCircle = (height - bitmapCanvas.getWidth()) / 2; - - // The icon x coordinate is going to be insetWithinCircle pixels away from the left edge of the circle - // If the icon is on the left, the left edge of the circle is just x - // If the icon is on the right, the left edge of the circle is x + mChipWidth - height - float iconX = mShowIconOnLeft ? (x + xInsetWithinCircle) : (x + mChipWidth - height + xInsetWithinCircle); - - // The y coordinate works the same way (only it's always from the top edge) - float yInsetWithinCircle = (height - bitmapCanvas.getHeight()) / 2; - float iconY = top + yInsetWithinCircle; - - canvas.drawBitmap(scaledIconBitMap, iconX, iconY, paint); - } - - private Bitmap scaleDown(Bitmap realImage, float maxImageSize, boolean filter) { - float ratio = Math.min(maxImageSize / realImage.getWidth(), maxImageSize / realImage.getHeight()); - int width = Math.round(ratio * realImage.getWidth()); - int height = Math.round(ratio * realImage.getHeight()); - return Bitmap.createScaledBitmap(realImage, width, height, filter); - } - - @Override - public String toString() { - return mText.toString(); - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/chip/ChipSpanChipCreator.java b/nachos/src/main/java/com/hootsuite/nachos/chip/ChipSpanChipCreator.java deleted file mode 100644 index 8e0278f0..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/chip/ChipSpanChipCreator.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.hootsuite.nachos.chip; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.graphics.Color; - -import androidx.annotation.NonNull; - -import com.hootsuite.nachos.ChipConfiguration; - -public class ChipSpanChipCreator implements ChipCreator { - - @Override - public ChipSpan createChip(@NonNull Context context, @NonNull CharSequence text, Object data) { - return new ChipSpan(context, text, null, data); - } - - @Override - public ChipSpan createChip(@NonNull Context context, @NonNull ChipSpan existingChip) { - return new ChipSpan(context, existingChip); - } - - @Override - public void configureChip(@NonNull ChipSpan chip, @NonNull ChipConfiguration chipConfiguration) { - int chipHorizontalSpacing = chipConfiguration.getChipHorizontalSpacing(); - ColorStateList chipBackground = chipConfiguration.getChipBackground(); - int chipCornerRadius = chipConfiguration.getChipCornerRadius(); - int chipTextColor = chipConfiguration.getChipTextColor(); - int chipTextSize = chipConfiguration.getChipTextSize(); - int chipHeight = chipConfiguration.getChipHeight(); - int chipVerticalSpacing = chipConfiguration.getChipVerticalSpacing(); - int maxAvailableWidth = chipConfiguration.getMaxAvailableWidth(); - - if (chipHorizontalSpacing != -1) { - chip.setLeftMargin(chipHorizontalSpacing / 2); - chip.setRightMargin(chipHorizontalSpacing / 2); - } - if (chipBackground != null) { - chip.setBackgroundColor(chipBackground); - } - if (chipCornerRadius != -1) { - chip.setCornerRadius(chipCornerRadius); - } - if (chipTextColor != Color.TRANSPARENT) { - chip.setTextColor(chipTextColor); - } - if (chipTextSize != -1) { - chip.setTextSize(chipTextSize); - } - if (chipHeight != -1) { - chip.setChipHeight(chipHeight); - } - if (chipVerticalSpacing != -1) { - chip.setChipVerticalSpacing(chipVerticalSpacing); - } - if (maxAvailableWidth != -1) { - chip.setMaxAvailableWidth(maxAvailableWidth); - } - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/terminator/ChipTerminatorHandler.java b/nachos/src/main/java/com/hootsuite/nachos/terminator/ChipTerminatorHandler.java deleted file mode 100644 index f97d430e..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/terminator/ChipTerminatorHandler.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.hootsuite.nachos.terminator; - -import android.text.Editable; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hootsuite.nachos.tokenizer.ChipTokenizer; - -import java.util.Map; - -/** - * This interface is used to handle the management of characters that should trigger the creation of chips in a text view. - * - * @see ChipTokenizer - */ -public interface ChipTerminatorHandler { - - /** - * When a chip terminator character is encountered in newly inserted text, all tokens in the whole text view will be chipified - */ - int BEHAVIOR_CHIPIFY_ALL = 0; - - /** - * When a chip terminator character is encountered in newly inserted text, only the current token (that in which the chip terminator character - * was found) will be chipified. This token may extend beyond where the chip terminator character was located. - */ - int BEHAVIOR_CHIPIFY_CURRENT_TOKEN = 1; - - /** - * When a chip terminator character is encountered in newly inserted text, only the text from the previous chip up until the chip terminator - * character will be chipified. This may not be an entire token. - */ - int BEHAVIOR_CHIPIFY_TO_TERMINATOR = 2; - - /** - * Constant for use with {@link #setPasteBehavior(int)}. Use this if a paste should behave the same as a standard text input (the chip temrinators - * will all behave according to their pre-determined behavior set through {@link #addChipTerminator(char, int)} or {@link #setChipTerminators(Map)}). - */ - int PASTE_BEHAVIOR_USE_DEFAULT = -1; - - /** - * Sets all the characters that will be marked as chip terminators. This will replace any previously set chip terminators. - * - * @param chipTerminators a map of characters to be marked as chip terminators to behaviors that describe how to respond to the characters, or null - * to remove all chip terminators - */ - void setChipTerminators(@Nullable Map chipTerminators); - - /** - * Adds a character as a chip terminator. When the provided character is encountered in entered text, the nearby text will be chipified according - * to the behavior provided here. - * {@code behavior} Must be one of: - *
    - *
  • {@link #BEHAVIOR_CHIPIFY_ALL}
  • - *
  • {@link #BEHAVIOR_CHIPIFY_CURRENT_TOKEN}
  • - *
  • {@link #BEHAVIOR_CHIPIFY_TO_TERMINATOR}
  • - *
- * - * @param character the character to mark as a chip terminator - * @param behavior the behavior describing how to respond to the chip terminator - */ - void addChipTerminator(char character, int behavior); - - /** - * Customizes the way paste events are handled. - * If one of: - *
    - *
  • {@link #BEHAVIOR_CHIPIFY_ALL}
  • - *
  • {@link #BEHAVIOR_CHIPIFY_CURRENT_TOKEN}
  • - *
  • {@link #BEHAVIOR_CHIPIFY_TO_TERMINATOR}
  • - *
- * is passed, all chip terminators will be handled with that behavior when a paste event occurs. - * If {@link #PASTE_BEHAVIOR_USE_DEFAULT} is passed, whatever behavior is configured for a particular chip terminator - * (through {@link #setChipTerminators(Map)} or {@link #addChipTerminator(char, int)} will be used for that chip terminator - * - * @param pasteBehavior the behavior to use on a paste event - */ - void setPasteBehavior(int pasteBehavior); - - /** - * Parses the provided text looking for characters marked as chip terminators through {@link #addChipTerminator(char, int)} and {@link #setChipTerminators(Map)}. - * The provided {@link Editable} will be modified if chip terminators are encountered. - * - * @param tokenizer the {@link ChipTokenizer} to use to identify and chipify tokens in the text - * @param text the text in which to search for chip terminators tokens to be chipped - * @param start the index at which to begin looking for chip terminators (inclusive) - * @param end the index at which to end looking for chip terminators (exclusive) - * @param isPasteEvent true if this handling is for a paste event in which case the behavior set in {@link #setPasteBehavior(int)} will be used, - * otherwise false - * @return an non-negative integer indicating the index where the cursor (selection) should be placed once the handling is complete, - * or a negative integer indicating that the cursor should not be moved. - */ - int findAndHandleChipTerminators(@NonNull ChipTokenizer tokenizer, @NonNull Editable text, int start, int end, boolean isPasteEvent); -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/terminator/DefaultChipTerminatorHandler.java b/nachos/src/main/java/com/hootsuite/nachos/terminator/DefaultChipTerminatorHandler.java deleted file mode 100644 index 75cb9b0d..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/terminator/DefaultChipTerminatorHandler.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.hootsuite.nachos.terminator; - -import android.text.Editable; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hootsuite.nachos.tokenizer.ChipTokenizer; - -import java.util.HashMap; -import java.util.Map; - -public class DefaultChipTerminatorHandler implements ChipTerminatorHandler { - - @Nullable - private Map mChipTerminators; - private int mPasteBehavior = BEHAVIOR_CHIPIFY_TO_TERMINATOR; - - @Override - public void setChipTerminators(@Nullable Map chipTerminators) { - mChipTerminators = chipTerminators; - } - - @Override - public void addChipTerminator(char character, int behavior) { - if (mChipTerminators == null) { - mChipTerminators = new HashMap<>(); - } - - mChipTerminators.put(character, behavior); - } - - @Override - public void setPasteBehavior(int pasteBehavior) { - mPasteBehavior = pasteBehavior; - } - - @Override - public int findAndHandleChipTerminators(@NonNull ChipTokenizer tokenizer, @NonNull Editable text, int start, int end, boolean isPasteEvent) { - // If we don't have a tokenizer or any chip terminators, there's nothing to look for - if (mChipTerminators == null) { - return -1; - } - - TextIterator textIterator = new TextIterator(text, start, end); - int selectionIndex = -1; - - characterLoop: - while (textIterator.hasNextCharacter()) { - char theChar = textIterator.nextCharacter(); - if (isChipTerminator(theChar)) { - int behavior = (isPasteEvent && mPasteBehavior != PASTE_BEHAVIOR_USE_DEFAULT) ? mPasteBehavior : mChipTerminators.get(theChar); - int newSelection = -1; - switch (behavior) { - case BEHAVIOR_CHIPIFY_ALL: - selectionIndex = handleChipifyAll(textIterator, tokenizer); - break characterLoop; - case BEHAVIOR_CHIPIFY_CURRENT_TOKEN: - newSelection = handleChipifyCurrentToken(textIterator, tokenizer); - break; - case BEHAVIOR_CHIPIFY_TO_TERMINATOR: - newSelection = handleChipifyToTerminator(textIterator, tokenizer); - break; - } - - if (newSelection != -1) { - selectionIndex = newSelection; - } - } - } - - return selectionIndex; - } - - private int handleChipifyAll(TextIterator textIterator, ChipTokenizer tokenizer) { - textIterator.deleteCharacter(true); - tokenizer.terminateAllTokens(textIterator.getText()); - return textIterator.totalLength(); - } - - private int handleChipifyCurrentToken(TextIterator textIterator, ChipTokenizer tokenizer) { - textIterator.deleteCharacter(true); - Editable text = textIterator.getText(); - int index = textIterator.getIndex(); - int tokenStart = tokenizer.findTokenStart(text, index); - int tokenEnd = tokenizer.findTokenEnd(text, index); - if (tokenStart < tokenEnd) { - CharSequence chippedText = tokenizer.terminateToken(text.subSequence(tokenStart, tokenEnd), null); - textIterator.replace(tokenStart, tokenEnd, chippedText); - return tokenStart + chippedText.length(); - } - return -1; - } - - private int handleChipifyToTerminator(TextIterator textIterator, ChipTokenizer tokenizer) { - Editable text = textIterator.getText(); - int index = textIterator.getIndex(); - if (index > 0) { - int tokenStart = tokenizer.findTokenStart(text, index); - if (tokenStart < index) { - CharSequence chippedText = tokenizer.terminateToken(text.subSequence(tokenStart, index), null); - textIterator.replace(tokenStart, index + 1, chippedText); - } else { - textIterator.deleteCharacter(false); - } - } else { - textIterator.deleteCharacter(false); - } - return -1; - } - - private boolean isChipTerminator(char character) { - return mChipTerminators != null && mChipTerminators.keySet().contains(character); - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/terminator/TextIterator.java b/nachos/src/main/java/com/hootsuite/nachos/terminator/TextIterator.java deleted file mode 100644 index 7c25d4c9..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/terminator/TextIterator.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.hootsuite.nachos.terminator; - -import android.text.Editable; - -public class TextIterator { - - private Editable mText; - private int mStart; - private int mEnd; - - private int mIndex; - - public TextIterator(Editable text, int start, int end) { - mText = text; - mStart = start; - mEnd = end; - - mIndex = mStart - 1; // Subtract 1 so that the first call to nextCharacter() will return the first character - } - - public int totalLength() { - return mText.length(); - } - - public int windowLength() { - return mEnd - mStart; - } - - public Editable getText() { - return mText; - } - - public int getIndex() { - return mIndex; - } - - public boolean hasNextCharacter() { - return (mIndex + 1) < mEnd; - } - - public char nextCharacter() { - mIndex++; - return mText.charAt(mIndex); - } - - public void deleteCharacter(boolean maintainIndex) { - mText.replace(mIndex, mIndex + 1, ""); - if (!maintainIndex) { - mIndex--; - } - mEnd--; - } - - public void replace(int replaceStart, int replaceEnd, CharSequence chippedText) { - mText.replace(replaceStart, replaceEnd, chippedText); - - // Update indexes - int newLength = chippedText.length(); - int oldLength = replaceEnd - replaceStart; - mIndex = replaceStart + newLength - 1; - mEnd += newLength - oldLength; - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/tokenizer/BaseChipTokenizer.java b/nachos/src/main/java/com/hootsuite/nachos/tokenizer/BaseChipTokenizer.java deleted file mode 100644 index ba946b5b..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/tokenizer/BaseChipTokenizer.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.hootsuite.nachos.tokenizer; - -import android.text.Editable; -import android.text.Spanned; -import android.util.Pair; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hootsuite.nachos.ChipConfiguration; -import com.hootsuite.nachos.chip.Chip; - -import java.util.ArrayList; -import java.util.List; - -/** - * Base implementation of the {@link ChipTokenizer} interface that performs no actions and returns default values. - * This class allows for the easy creation of a ChipTokenizer that only implements some of the methods of the interface. - */ -public abstract class BaseChipTokenizer implements ChipTokenizer { - - @Override - public void applyConfiguration(Editable text, ChipConfiguration chipConfiguration) { - // Do nothing - } - - @Override - public int findTokenStart(CharSequence charSequence, int i) { - // Do nothing - return 0; - } - - @Override - public int findTokenEnd(CharSequence charSequence, int i) { - // Do nothing - return 0; - } - - @NonNull - @Override - public List> findAllTokens(CharSequence text) { - // Do nothing - return new ArrayList<>(); - } - - @Override - public CharSequence terminateToken(CharSequence charSequence, @Nullable Object data) { - // Do nothing - return charSequence; - } - - @Override - public void terminateAllTokens(Editable text) { - // Do nothing - } - - @Override - public int findChipStart(Chip chip, Spanned text) { - // Do nothing - return 0; - } - - @Override - public int findChipEnd(Chip chip, Spanned text) { - // Do nothing - return 0; - } - - @NonNull - @Override - public Chip[] findAllChips(int start, int end, Spanned text) { - return new Chip[]{}; - } - - @Override - public void revertChipToToken(Chip chip, Editable text) { - // Do nothing - } - - @Override - public void deleteChip(Chip chip, Editable text) { - // Do nothing - } - - @Override - public void deleteChipAndPadding(Chip chip, Editable text) { - // Do nothing - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/tokenizer/ChipTokenizer.java b/nachos/src/main/java/com/hootsuite/nachos/tokenizer/ChipTokenizer.java deleted file mode 100644 index 32d8f061..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/tokenizer/ChipTokenizer.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.hootsuite.nachos.tokenizer; - -import android.text.Editable; -import android.text.Spanned; -import android.util.Pair; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hootsuite.nachos.ChipConfiguration; -import com.hootsuite.nachos.chip.Chip; - -import java.util.List; - -/** - * An extension of {@link android.widget.MultiAutoCompleteTextView.Tokenizer Tokenizer} that provides extra support - * for chipification. - *

- * In the context of this interface, a token is considered to be plain (non-chipped) text. Once a token is terminated it becomes or contains a chip. - *

- *

- * The CharSequences passed to the ChipTokenizer methods may contain both chipped text - * and plain text so the tokenizer must have some method of distinguishing between the two (e.g. using a delimeter character. - * The {@link #terminateToken(CharSequence, Object)} method is where a chip can be formed and returned to replace the plain text. - * Whatever class the implementation deems to represent a chip, must implement the {@link Chip} interface. - *

- * - * @see SpanChipTokenizer - */ -public interface ChipTokenizer { - - /** - * Configures this ChipTokenizer to produce chips with the provided attributes. For each of these attributes, {@code -1} or {@code null} may be - * passed to indicate that the attribute may be ignored. - *

- * This will also apply the provided {@link ChipConfiguration} to any existing chips in the provided text. - *

- * - * @param text the text in which to search for existing chips to apply the configuration to - * @param chipConfiguration a {@link ChipConfiguration} containing customizations for the chips produced by this class - */ - void applyConfiguration(Editable text, ChipConfiguration chipConfiguration); - - /** - * Returns the start of the token that ends at offset - * cursor within text. - */ - int findTokenStart(CharSequence text, int cursor); - - /** - * Returns the end of the token (minus trailing punctuation) - * that begins at offset cursor within text. - */ - int findTokenEnd(CharSequence text, int cursor); - - /** - * Searches through {@code text} for any tokens. - * - * @param text the text in which to search for un-terminated tokens - * @return a list of {@link Pair}s of the form (startIndex, endIndex) containing the locations of all - * unterminated tokens - */ - @NonNull - List> findAllTokens(CharSequence text); - - /** - * Returns text, modified, if necessary, to ensure that - * it ends with a token terminator (for example a space or comma). - */ - CharSequence terminateToken(CharSequence text, @Nullable Object data); - - /** - * Terminates (converts from token into chip) all unterminated tokens in the provided text. - * This method CAN alter the provided text. - * - * @param text the text in which to terminate all tokens - */ - void terminateAllTokens(Editable text); - - /** - * Finds the index of the first character in {@code text} that is a part of {@code chip} - * - * @param chip the chip whose start should be found - * @param text the text in which to search for the start of {@code chip} - * @return the start index of the chip - */ - int findChipStart(Chip chip, Spanned text); - - /** - * Finds the index of the character after the last character in {@code text} that is a part of {@code chip} - * - * @param chip the chip whose end should be found - * @param text the text in which to search for the end of {@code chip} - * @return the end index of the chip - */ - int findChipEnd(Chip chip, Spanned text); - - /** - * Searches through {@code text} for any chips - * - * @param start index to start looking for terminated tokens (inclusive) - * @param end index to end looking for terminated tokens (exclusive) - * @param text the text in which to search for terminated tokens - * @return a list of objects implementing the {@link Chip} interface to represent the terminated tokens - */ - @NonNull - Chip[] findAllChips(int start, int end, Spanned text); - - /** - * Effectively does the opposite of {@link #terminateToken(CharSequence, Object)} by reverting the provided chip back into a token. - * This method CAN alter the provided text. - * - * @param chip the chip to revert into a token - * @param text the text in which the chip resides - */ - void revertChipToToken(Chip chip, Editable text); - - /** - * Removes a chip and any text it encompasses from {@code text}. This method CAN alter the provided text. - * - * @param chip the chip to remove - * @param text the text to remove the chip from - */ - void deleteChip(Chip chip, Editable text); - - /** - * Removes a chip, any text it encompasses AND any padding text (such as spaces) that may have been inserted when the chip was created in - * {@link #terminateToken(CharSequence, Object)} or after. This method CAN alter the provided text. - * - * @param chip the chip to remove - * @param text the text to remove the chip and padding from - */ - void deleteChipAndPadding(Chip chip, Editable text); -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/tokenizer/SpanChipTokenizer.java b/nachos/src/main/java/com/hootsuite/nachos/tokenizer/SpanChipTokenizer.java deleted file mode 100644 index 79410e20..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/tokenizer/SpanChipTokenizer.java +++ /dev/null @@ -1,248 +0,0 @@ -package com.hootsuite.nachos.tokenizer; - -import android.content.Context; -import android.text.Editable; -import android.text.SpannableString; -import android.text.Spanned; -import android.util.Pair; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.hootsuite.nachos.ChipConfiguration; -import com.hootsuite.nachos.chip.Chip; -import com.hootsuite.nachos.chip.ChipCreator; -import com.hootsuite.nachos.chip.ChipSpan; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * A default implementation of {@link ChipTokenizer}. - * This implementation does the following: - *
    - *
  • Surrounds each token with a space and the Unit Separator ASCII control character (31) - See the diagram below - *
      - *
    • The spaces are included so that android keyboards can distinguish the chips as different words and provide accurate - * autocorrect suggestions
    • - *
    - *
  • - *
  • Replaces each token with a {@link ChipSpan} containing the same text, once the token terminates
  • - *
  • Uses the values passed to {@link #applyConfiguration(Editable, ChipConfiguration)} to configure any ChipSpans that get created
  • - *
- * Each terminated token will therefore look like the following (this is what will be returned from {@link #terminateToken(CharSequence, Object)}): - *
- *  -----------------------------------------------------------
- *  | SpannableString                                         |
- *  |   ----------------------------------------------------  |
- *  |   | ChipSpan                                         |  |
- *  |   |                                                  |  |
- *  |   |  space   separator    text    separator   space  |  |
- *  |   |                                                  |  |
- *  |   ----------------------------------------------------  |
- *  -----------------------------------------------------------
- * 
- * - * @see ChipSpan - */ -public class SpanChipTokenizer implements ChipTokenizer { - - /** - * The character used to separate chips internally is the US (Unit Separator) ASCII control character. - * This character is used because it's untypable so we have complete control over when chips are created. - */ - public static final char CHIP_SPAN_SEPARATOR = 31; - public static final char AUTOCORRECT_SEPARATOR = ' '; - - private Context mContext; - - @Nullable - private ChipConfiguration mChipConfiguration; - @NonNull - private ChipCreator mChipCreator; - @NonNull - private Class mChipClass; - - private Comparator> mReverseTokenIndexesSorter = new Comparator>() { - @Override - public int compare(Pair lhs, Pair rhs) { - return rhs.first - lhs.first; - } - }; - - public SpanChipTokenizer(Context context, @NonNull ChipCreator chipCreator, @NonNull Class chipClass) { - mContext = context; - mChipCreator = chipCreator; - mChipClass = chipClass; - } - - @Override - public void applyConfiguration(Editable text, ChipConfiguration chipConfiguration) { - mChipConfiguration = chipConfiguration; - - for (C chip : findAllChips(0, text.length(), text)) { - // Recreate the chips with the new configuration - int chipStart = findChipStart(chip, text); - deleteChip(chip, text); - text.insert(chipStart, terminateToken(mChipCreator.createChip(mContext, chip))); - } - } - - @Override - public int findTokenStart(CharSequence text, int cursor) { - int i = cursor; - - // Work backwards until we find a CHIP_SPAN_SEPARATOR - while (i > 0 && text.charAt(i - 1) != CHIP_SPAN_SEPARATOR) { - i--; - } - // Work forwards to skip over any extra whitespace at the beginning of the token - while (i > 0 && i < text.length() && Character.isWhitespace(text.charAt(i))) { - i++; - } - return i; - } - - @Override - public int findTokenEnd(CharSequence text, int cursor) { - int i = cursor; - int len = text.length(); - - // Work forwards till we find a CHIP_SPAN_SEPARATOR - while (i < len) { - if (text.charAt(i) == CHIP_SPAN_SEPARATOR) { - return (i - 1); // subtract one because the CHIP_SPAN_SEPARATOR will be preceded by a space - } else { - i++; - } - } - return len; - } - - @NonNull - @Override - public List> findAllTokens(CharSequence text) { - List> unterminatedTokens = new ArrayList<>(); - - boolean insideChip = false; - // Iterate backwards through the text (to avoid messing up indexes) - for (int index = text.length() - 1; index >= 0; index--) { - char theCharacter = text.charAt(index); - - // Every time we hit a CHIP_SPAN_SEPARATOR character we switch from being inside to outside - // or outside to inside a chip - // This check must happen before the whitespace check because CHIP_SPAN_SEPARATOR is considered a whitespace character - if (theCharacter == CHIP_SPAN_SEPARATOR) { - insideChip = !insideChip; - continue; - } - - // Completely skip over whitespace - if (Character.isWhitespace(theCharacter)) { - continue; - } - - // If we're ever outside a chip, see if the text we're in is a viable token for chipification - if (!insideChip) { - int tokenStart = findTokenStart(text, index); - int tokenEnd = findTokenEnd(text, index); - - // Can only actually be chipified if there's at least one character between them - if (tokenEnd - tokenStart >= 1) { - unterminatedTokens.add(new Pair<>(tokenStart, tokenEnd)); - index = tokenStart; - } - } - } - return unterminatedTokens; - } - - @Override - public CharSequence terminateToken(CharSequence text, @Nullable Object data) { - // Remove leading/trailing whitespace - CharSequence trimmedText = text.toString().trim(); - return terminateToken(mChipCreator.createChip(mContext, trimmedText, data)); - } - - private CharSequence terminateToken(C chip) { - if (chip == null) - return new SpannableString(""); - // Surround the text with CHIP_SPAN_SEPARATOR and spaces - // The spaces allow autocorrect to correctly identify words - String chipSeparator = Character.toString(CHIP_SPAN_SEPARATOR); - String autoCorrectSeparator = Character.toString(AUTOCORRECT_SEPARATOR); - CharSequence textWithSeparator = autoCorrectSeparator + chipSeparator + chip.getText() + chipSeparator + autoCorrectSeparator; - - // Build the container object to house the ChipSpan and space - SpannableString spannableString = new SpannableString(textWithSeparator); - - // Attach the ChipSpan - if (mChipConfiguration != null) { - mChipCreator.configureChip(chip, mChipConfiguration); - } - spannableString.setSpan(chip, 0, textWithSeparator.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - return spannableString; - } - - @Override - public void terminateAllTokens(Editable text) { - List> unterminatedTokens = findAllTokens(text); - // Sort in reverse order (so index changes don't affect anything) - Collections.sort(unterminatedTokens, mReverseTokenIndexesSorter); - for (Pair indexes : unterminatedTokens) { - int start = indexes.first; - int end = indexes.second; - CharSequence textToChip = text.subSequence(start, end); - CharSequence chippedText = terminateToken(textToChip, null); - text.replace(start, end, chippedText); - } - } - - @Override - public int findChipStart(Chip chip, Spanned text) { - return text.getSpanStart(chip); - } - - @Override - public int findChipEnd(Chip chip, Spanned text) { - return text.getSpanEnd(chip); - } - - @SuppressWarnings("unchecked") - @NonNull - @Override - public C[] findAllChips(int start, int end, Spanned text) { - C[] spansArray = text.getSpans(start, end, mChipClass); - return (spansArray != null) ? spansArray : (C[]) Array.newInstance(mChipClass, 0); - } - - @Override - public void revertChipToToken(Chip chip, Editable text) { - int chipStart = findChipStart(chip, text); - int chipEnd = findChipEnd(chip, text); - text.removeSpan(chip); - text.replace(chipStart, chipEnd, chip.getText()); - } - - @Override - public void deleteChip(Chip chip, Editable text) { - int chipStart = findChipStart(chip, text); - int chipEnd = findChipEnd(chip, text); - text.removeSpan(chip); - // On the emulator for some reason the text automatically gets deleted and chipStart and chipEnd end up both being -1, so in that case we - // don't need to call text.delete(...) - if (chipStart != chipEnd) { - text.delete(chipStart, chipEnd); - } - } - - @Override - public void deleteChipAndPadding(Chip chip, Editable text) { - // This implementation does not add any extra padding outside of the span so we can just delete the chip normally - deleteChip(chip, text); - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/validator/ChipifyingNachoValidator.java b/nachos/src/main/java/com/hootsuite/nachos/validator/ChipifyingNachoValidator.java deleted file mode 100644 index fa1aa571..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/validator/ChipifyingNachoValidator.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.hootsuite.nachos.validator; - -import android.text.SpannableStringBuilder; -import android.util.Pair; - -import androidx.annotation.NonNull; - -import com.hootsuite.nachos.tokenizer.ChipTokenizer; - -import java.util.List; - -/** - * A {@link NachoValidator} that deems text to be invalid if it contains - * unterminated tokens and fixes the text by chipifying all the unterminated tokens. - */ -public class ChipifyingNachoValidator implements NachoValidator { - - @Override - public boolean isValid(@NonNull ChipTokenizer chipTokenizer, CharSequence text) { - - // The text is considered valid if there are no unterminated tokens (everything is a chip) - List> unterminatedTokens = chipTokenizer.findAllTokens(text); - return unterminatedTokens.isEmpty(); - } - - @Override - public CharSequence fixText(@NonNull ChipTokenizer chipTokenizer, CharSequence invalidText) { - SpannableStringBuilder newText = new SpannableStringBuilder(invalidText); - chipTokenizer.terminateAllTokens(newText); - return newText; - } -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/validator/IllegalCharacterIdentifier.java b/nachos/src/main/java/com/hootsuite/nachos/validator/IllegalCharacterIdentifier.java deleted file mode 100644 index 76f3f858..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/validator/IllegalCharacterIdentifier.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.hootsuite.nachos.validator; - -public interface IllegalCharacterIdentifier { - boolean isCharacterIllegal(Character c); -} diff --git a/nachos/src/main/java/com/hootsuite/nachos/validator/NachoValidator.java b/nachos/src/main/java/com/hootsuite/nachos/validator/NachoValidator.java deleted file mode 100644 index 6c798e7c..00000000 --- a/nachos/src/main/java/com/hootsuite/nachos/validator/NachoValidator.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.hootsuite.nachos.validator; - - -import androidx.annotation.NonNull; - -import com.hootsuite.nachos.tokenizer.ChipTokenizer; - -/** - * Interface used to ensure that a given CharSequence complies to a particular format. - */ -public interface NachoValidator { - - /** - * Validates the specified text. - * - * @return true If the text currently in the text editor is valid. - * @see #fixText(ChipTokenizer, CharSequence) - */ - boolean isValid(@NonNull ChipTokenizer chipTokenizer, CharSequence text); - - /** - * Corrects the specified text to make it valid. - * - * @param invalidText A string that doesn't pass validation: isValid(invalidText) - * returns false - * @return A string based on invalidText such as invoking isValid() on it returns true. - * @see #isValid(ChipTokenizer, CharSequence) - */ - CharSequence fixText(@NonNull ChipTokenizer chipTokenizer, CharSequence invalidText); -} diff --git a/nachos/src/main/project.properties b/nachos/src/main/project.properties deleted file mode 100644 index 70c5769d..00000000 --- a/nachos/src/main/project.properties +++ /dev/null @@ -1,2 +0,0 @@ -# See https://github.com/robolectric/robolectric/issues/1334 -android.library.reference.1=../../build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.1' \ No newline at end of file diff --git a/nachos/src/main/res/color/chip_material_background.xml b/nachos/src/main/res/color/chip_material_background.xml deleted file mode 100644 index ec381b24..00000000 --- a/nachos/src/main/res/color/chip_material_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/nachos/src/main/res/values/attrs.xml b/nachos/src/main/res/values/attrs.xml deleted file mode 100644 index dcd632af..00000000 --- a/nachos/src/main/res/values/attrs.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/nachos/src/main/res/values/colors.xml b/nachos/src/main/res/values/colors.xml deleted file mode 100644 index a718d37d..00000000 --- a/nachos/src/main/res/values/colors.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - #DE000000 - #517FA4 - \ No newline at end of file diff --git a/nachos/src/main/res/values/dimens.xml b/nachos/src/main/res/values/dimens.xml deleted file mode 100644 index 8df9e5ad..00000000 --- a/nachos/src/main/res/values/dimens.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 12dp - 8dp - 0dp - 0dp - \ No newline at end of file diff --git a/nachos/src/main/res/values/strings.xml b/nachos/src/main/res/values/strings.xml deleted file mode 100644 index 6c2b508b..00000000 --- a/nachos/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/nachos/src/main/res/values/styles.xml b/nachos/src/main/res/values/styles.xml deleted file mode 100644 index 5ef64347..00000000 --- a/nachos/src/main/res/values/styles.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 955021f9..f2de53d8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,7 +3,7 @@ include ':wear' include ':codegen' include ':annotation' rootProject.name='Szkolny.eu' -include ':app', ':agendacalendarview', ':mhttp', ':szkolny-font', ':nachos' +include ':app', ':agendacalendarview', ':mhttp', ':szkolny-font' /* include ':Navigation' project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/ From 0615593d94de82fe09aad242b73696676b8a5185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 20 Mar 2021 21:34:14 +0100 Subject: [PATCH 04/15] [Gradle] Extract mhttp dependency. --- app/build.gradle | 2 +- mhttp/build.gradle | 51 -- mhttp/gradle.properties | 31 -- mhttp/src/main/AndroidManifest.xml | 4 - .../im/wangchao/mhttp/AbsCallbackHandler.java | 256 --------- .../main/java/im/wangchao/mhttp/Accept.java | 33 -- .../java/im/wangchao/mhttp/Android5SSL.java | 149 ------ .../main/java/im/wangchao/mhttp/BindApi.java | 28 - .../main/java/im/wangchao/mhttp/Callback.java | 40 -- .../java/im/wangchao/mhttp/Converter.java | 12 - .../main/java/im/wangchao/mhttp/HTTPS.java | 179 ------- .../main/java/im/wangchao/mhttp/MHttp.java | 252 --------- .../main/java/im/wangchao/mhttp/Method.java | 25 - .../main/java/im/wangchao/mhttp/Request.java | 503 ------------------ .../java/im/wangchao/mhttp/RequestParams.java | 378 ------------- .../main/java/im/wangchao/mhttp/Response.java | 63 --- .../java/im/wangchao/mhttp/ThreadMode.java | 43 -- .../im/wangchao/mhttp/URLInterceptor.java | 20 - .../java/im/wangchao/mhttp/body/FileBody.java | 53 -- .../java/im/wangchao/mhttp/body/JSONBody.java | 50 -- .../wangchao/mhttp/body/MediaTypeUtils.java | 53 -- .../wangchao/mhttp/body/OctetStreamBody.java | 88 --- .../mhttp/body/ProgressRequestBody.java | 70 --- .../mhttp/callback/BinaryCallbackHandler.java | 30 -- .../mhttp/callback/BitmapCallbackHandler.java | 27 - .../mhttp/callback/CustomCallbackHandler.java | 34 -- .../mhttp/callback/FileCallbackHandler.java | 103 ---- .../callback/JsonArrayCallbackHandler.java | 37 -- .../mhttp/callback/JsonCallbackHandler.java | 48 -- .../mhttp/callback/TextCallbackHandler.java | 27 - .../wangchao/mhttp/executor/BACKGROUND.java | 17 - .../java/im/wangchao/mhttp/executor/MAIN.java | 21 - .../im/wangchao/mhttp/executor/SENDING.java | 27 - .../im/wangchao/mhttp/internal/Singleton.java | 25 - .../im/wangchao/mhttp/internal/Version.java | 21 - .../internal/cookie/ClearableCookieJar.java | 25 - .../internal/cookie/MemoryCookieJar.java | 60 --- .../internal/cookie/PersistentCookieJar.java | 133 ----- .../internal/cookie/cache/CookieCache.java | 38 -- .../cookie/cache/IdentifiableCookie.java | 74 --- .../internal/cookie/cache/SetCookieCache.java | 94 ---- .../cookie/persistence/CookiePersistor.java | 54 -- .../persistence/SerializableCookie.java | 146 ----- .../SharedPrefsCookiePersistor.java | 91 ---- .../internal/exception/ParserException.java | 17 - .../exception/ResponseFailException.java | 14 - .../interceptor/HttpLoggingInterceptor.java | 320 ----------- .../interceptor/MBridgeInterceptor.java | 36 -- .../mhttp/internal/log/LoggerImpl.java | 35 -- .../rxjava2/ResponseEnqueueObservable.java | 133 ----- .../rxjava2/ResponseExecuteObservable.java | 76 --- .../im/wangchao/mhttp/rxjava2/RxRequest.java | 233 -------- settings.gradle | 2 +- 53 files changed, 2 insertions(+), 4379 deletions(-) delete mode 100644 mhttp/build.gradle delete mode 100644 mhttp/gradle.properties delete mode 100644 mhttp/src/main/AndroidManifest.xml delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/AbsCallbackHandler.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/Accept.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/Android5SSL.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/BindApi.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/Callback.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/Converter.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/HTTPS.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/MHttp.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/Method.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/Request.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/RequestParams.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/Response.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/ThreadMode.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/URLInterceptor.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/body/FileBody.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/body/JSONBody.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/body/MediaTypeUtils.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/body/OctetStreamBody.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/body/ProgressRequestBody.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/callback/BinaryCallbackHandler.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/callback/BitmapCallbackHandler.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/callback/CustomCallbackHandler.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/callback/FileCallbackHandler.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/callback/JsonArrayCallbackHandler.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/callback/JsonCallbackHandler.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/callback/TextCallbackHandler.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/executor/BACKGROUND.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/executor/MAIN.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/executor/SENDING.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/Singleton.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/Version.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/ClearableCookieJar.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/MemoryCookieJar.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/PersistentCookieJar.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/CookieCache.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/IdentifiableCookie.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/SetCookieCache.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/CookiePersistor.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/SerializableCookie.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/SharedPrefsCookiePersistor.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/exception/ParserException.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/exception/ResponseFailException.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/interceptor/HttpLoggingInterceptor.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/interceptor/MBridgeInterceptor.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/internal/log/LoggerImpl.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/rxjava2/ResponseEnqueueObservable.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/rxjava2/ResponseExecuteObservable.java delete mode 100644 mhttp/src/main/java/im/wangchao/mhttp/rxjava2/RxRequest.java diff --git a/app/build.gradle b/app/build.gradle index 2f2211d8..d6ccb59b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -170,7 +170,7 @@ dependencies { implementation project(":agendacalendarview") implementation "eu.szkolny:cafebar:5bf0c618de" implementation "eu.szkolny:material-about-library:0534abf316" - implementation project(":mhttp") + implementation "eu.szkolny:mhttp:af4b62e6e9" implementation "eu.szkolny:nachos:0e5dfcaceb" //implementation project(":Navigation") implementation project(":szkolny-font") diff --git a/mhttp/build.gradle b/mhttp/build.gradle deleted file mode 100644 index a17c5b48..00000000 --- a/mhttp/build.gradle +++ /dev/null @@ -1,51 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion setup.compileSdk - - defaultConfig { - minSdkVersion 9 - targetSdkVersion setup.targetSdk - consumerProguardFiles 'proguard-rules.pro' - versionCode 1 - versionName PROJ_VERSION - javaCompileOptions { - annotationProcessorOptions { - includeCompileClasspath = true - } - } - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - debugMinify { - debuggable = true - minifyEnabled = true - proguardFiles 'proguard-android.txt' - } - } - packagingOptions { - exclude 'META-INF/services/javax.annotation.processing.Processor' - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - lintOptions { - textReport true - textOutput 'stdout' - } -} - -dependencies { - compileOnly "androidx.appcompat:appcompat:${versions.appcompat}" - compileOnly 'io.reactivex.rxjava2:rxjava:2.1.3' - api 'com.squareup.okhttp3:okhttp:3.12.0' - api 'com.google.code.gson:gson:2.8.5' - //api deps.mhttpannotations -// implementation project(':mhttp-annotations') -} - -//apply from: 'https://raw.githubusercontent.com/motcwang/Utils/master/bintray-publish/bintray.gradle' \ No newline at end of file diff --git a/mhttp/gradle.properties b/mhttp/gradle.properties deleted file mode 100644 index 58145d18..00000000 --- a/mhttp/gradle.properties +++ /dev/null @@ -1,31 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -PROJ_GROUP=im.wangchao -PROJ_VERSION=1.10.1 -PROJ_NAME=mhttp -PROJ_WEBSITEURL=http://wangchao.im/2015/11/22/mhttpadapter-post.html -PROJ_ISSUETRACKERURL=https://github.com/motcwang/MHttp/issues -PROJ_VCSURL=git@github.com:motcwang/MHttp.git -PROJ_DESCRIPTION= -PROJ_ARTIFACTID=mhttp -PROJ_PACKAGING=aar - -DEVELOPER_ID=mot -DEVELOPER_NAME=Wang Chao -DEVELOPER_EMAIL=magician.of.technique@aliyun.com \ No newline at end of file diff --git a/mhttp/src/main/AndroidManifest.xml b/mhttp/src/main/AndroidManifest.xml deleted file mode 100644 index 1c8f0a8f..00000000 --- a/mhttp/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/mhttp/src/main/java/im/wangchao/mhttp/AbsCallbackHandler.java b/mhttp/src/main/java/im/wangchao/mhttp/AbsCallbackHandler.java deleted file mode 100644 index 32d94c89..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/AbsCallbackHandler.java +++ /dev/null @@ -1,256 +0,0 @@ -package im.wangchao.mhttp; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.text.TextUtils; -import android.util.Log; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import im.wangchao.mhttp.internal.exception.ParserException; -import im.wangchao.mhttp.internal.exception.ResponseFailException; -import okhttp3.Call; -import okhttp3.internal.Util; - -import static im.wangchao.mhttp.Response.IO_EXCEPTION_CODE; - -/** - *

Description : AbsResponseHandler. - * Callback lifecycle as follow: - * onStart() - * ------------------------------------------------------- - * | - * | - * is canceled --- Y --- onCancel() - * | - * N - * | - * onFinish() - * | - * | - * is successful --- N --- onFailure() ------------------ - * | | - * Y | - * | | - * backgroundParser() --is download-- onProgress() | - * | | | - * | | | - * onSuccess() onSuccess() | - * | | | - * | | | - * --------------------------------------------------------- - * onFinally() - *

- *

Author : wangchao.

- *

Date : 15/8/17.

- *

Time : 下午5:56.

- */ -public abstract class AbsCallbackHandler implements Callback, Converter{ - private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool(Util.threadFactory("OkHttp", false)); - - public final static String DEFAULT_CHARSET = "UTF-8"; - - private Request request; - private String responseCharset = DEFAULT_CHARSET; - private boolean isFinished; - private boolean isCanceled; - - private Executor mExecutor; - - /** Working thread depends on {@link #mExecutor}, default UI. */ - public abstract void onSuccess(Parser_Type data, Response response); - /** Working thread depends on {@link #mExecutor}, default UI. */ - public abstract void onFailure(Response response, Throwable throwable); - /** Work on the request thread, that is okhttp thread. */ - @Deprecated - public Parser_Type backgroundParser(Response response) throws Exception{ - return null; - } - /** Work on the request thread, that is okhttp thread. */ - @Override public Parser_Type apply(Response response) throws Exception { - return backgroundParser(response); - } - - /** Working thread depends on {@link #mExecutor}, default UI. */ - public void onStart(){} - /** Working thread depends on {@link #mExecutor}, default UI. */ - public void onCancel(){} - /** Working thread depends on {@link #mExecutor}, default UI. */ - public void onProgress(long bytesWritten, long bytesTotal){} - /** Working thread depends on {@link #mExecutor}, default UI. */ - public void onUploadProgress(int bytesWritten, int bytesTotal){} - /** Working thread depends on {@link #mExecutor}, default UI. */ - public void onFinish(){} - /** Working thread depends on {@link #mExecutor}, default UI. */ - public void onFinally(Response response){} - - - @Override final public void onFailure(@NonNull Call call, @NonNull IOException e) { - if (call.isCanceled()){ - sendCancelEvent(); - return; - } - sendFinishEvent(); - - final Request req = request; - Response response = Response.error(req, - IO_EXCEPTION_CODE, - e.getMessage()); - - sendFailureEvent(response, e); - sendFinallyEvent(response); - } - - @Override final public void onResponse(@NonNull Call call, @NonNull okhttp3.Response response) throws IOException { - if (call.isCanceled()){ - response.close(); - sendCancelEvent(); - return; - } - sendFinishEvent(); - - final Request req = request; - Response okResponse; - if (response.isSuccessful() || response.isRedirect() - || req.allowedErrorCodes().contains(response.code())) { - try { - okResponse = Response.newResponse(req, response); - Parser_Type data = apply(okResponse); - sendSuccessEvent(data, okResponse); - } catch (Exception e) { - sendFailureEvent(okResponse = Response.newResponse(req, response), e); - } - } else { - sendFailureEvent(okResponse = Response.newResponse(req, response), new ResponseFailException()); - } - // todo response.close() - sendFinallyEvent(okResponse); - } - - public AbsCallbackHandler(){} - - @Override public void initialize(Request request){ - isFinished = false; - isCanceled = false; - this.request = request; - this.mExecutor = request.callbackExecutor(); - if (this.mExecutor == null){ - this.mExecutor = request.callbackThreadMode().executor(); - } - } - - public final boolean isFinished(){ - return isFinished; - } - - /** - * Sets the charset for the response string. If not set, the default is UTF-8. - */ - public final void setCharset(@NonNull final String charset) { - this.responseCharset = charset; - } - - /** - * subclass can override this method to change charset. - */ - public String charset() { - return TextUtils.isEmpty(responseCharset) ? DEFAULT_CHARSET : responseCharset; - } - - /** - * @return request accept - */ - @Override public String accept(){ - return Accept.EMPTY; - } - - protected final void print(String message){ - Log.d(AbsCallbackHandler.class.getSimpleName(), message); - } - - @Nullable protected final String byteArrayToString(byte[] bytes){ - try { - return bytes == null ? null : new String(bytes, charset()); - } catch (UnsupportedEncodingException e) { - return null; - } - } - - protected final Request getRequest(){ - return this.request; - } - - public final void sendUploadProgressEvent(final int bytesWritten, final int bytesTotal) { - execute(()->{ - try { - onUploadProgress(bytesWritten, bytesTotal); - } catch (Throwable t) { - //Silent - } - }); - } - - public final void sendProgressEvent(final long bytesWritten, final long bytesTotal) { - execute(()->{ - try { - onProgress(bytesWritten, bytesTotal); - } catch (Throwable t) { - //Silent - } - }); - } - - /*package*/ final void sendSuccessEvent(final Parser_Type data, final Response response) { - execute(() -> onSuccess(data, response)); - } - - /*package*/ final void sendFailureEvent(final Response response, @Nullable final Throwable throwable) { - execute(() -> onFailure(response, throwable)); - } - - /*package*/ final void sendStartEvent() { - if (request.callbackThreadMode() == ThreadMode.BACKGROUND){ - DEFAULT_EXECUTOR_SERVICE.execute(this::onStart); - } else { - execute(this::onStart); - } - } - - /*package*/ final void sendFinishEvent() { - execute(() -> { - AbsCallbackHandler.this.isFinished = true; - onFinish(); - }); - } - - /*package*/ final void sendFinallyEvent(final Response response) { - execute(() -> onFinally(response)); - } - - /*package*/ final synchronized void sendCancelEvent() { - if (isCanceled){ - return; - } - execute(() -> { - AbsCallbackHandler.this.isCanceled = true; - onCancel(); - }); - } - - private void execute(Runnable command){ - if (mExecutor == null || threadInterrupted()){ - return; - } - - mExecutor.execute(command); - } - - private boolean threadInterrupted(){ - return Thread.currentThread().isInterrupted(); - } - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/Accept.java b/mhttp/src/main/java/im/wangchao/mhttp/Accept.java deleted file mode 100644 index 161d227e..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/Accept.java +++ /dev/null @@ -1,33 +0,0 @@ -package im.wangchao.mhttp; - -import androidx.annotation.StringDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - *

Description : Accept.

- *

Author : wangchao.

- *

Date : 16/4/25.

- *

Time : 上午11:06.

- */ -public interface Accept { - String EMPTY = ""; - String ACCEPT_JSON = "application/json;charset=utf-8"; - String ACCEPT_TEXT = "text/html;charset=utf-8"; - String ACCEPT_DATA = "application/octet-stream"; - String ACCEPT_IMAGE = "image/png,image/jpeg,image/*"; - String ACCEPT_FILE = "application/octet-stream"; - - @Retention(RetentionPolicy.SOURCE) - @StringDef({ - Accept.EMPTY, - Accept.ACCEPT_JSON, - Accept.ACCEPT_TEXT, - Accept.ACCEPT_DATA, - Accept.ACCEPT_IMAGE, - Accept.ACCEPT_FILE - }) - public @interface $Accept { - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/Android5SSL.java b/mhttp/src/main/java/im/wangchao/mhttp/Android5SSL.java deleted file mode 100644 index 4ddbc6de..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/Android5SSL.java +++ /dev/null @@ -1,149 +0,0 @@ -package im.wangchao.mhttp; - -import android.os.Build; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.security.GeneralSecurityException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.X509TrustManager; - -/** - *

Description : Android5SSL.

- *

Author : wangchao.

- *

Date : 2018/3/19.

- *

Time : 上午11:09.

- */ -/*package*/ class Android5SSL extends SSLSocketFactory { - private SSLSocketFactory defaultFactory; - // Android 5.0+ (API level21) provides reasonable default settings - // but it still allows SSLv3 - // https://developer.android.com/about/versions/android-5.0-changes.html#ssl - static String protocols[] = null, cipherSuites[] = null; - - static { - try { - SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); - if (socket != null) { - /* set reasonable protocol versions */ - // - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0) - // - remove all SSL versions (especially SSLv3) because they're insecure now - List protocols = new LinkedList<>(); - for (String protocol : socket.getSupportedProtocols()) - if (!protocol.toUpperCase().contains("SSL")) - protocols.add(protocol); - Android5SSL.protocols = protocols.toArray(new String[protocols.size()]); - /* set up reasonable cipher suites */ - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - // choose known secure cipher suites - List allowedCiphers = Arrays.asList( - // TLS 1.2 - "TLS_RSA_WITH_AES_256_GCM_SHA384", - "TLS_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - "TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256", - // maximum interoperability - "TLS_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_RSA_WITH_AES_128_CBC_SHA", - // additionally - "TLS_RSA_WITH_AES_256_CBC_SHA", - "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); - List availableCiphers = Arrays.asList(socket.getSupportedCipherSuites()); - // take all allowed ciphers that are available and put them into preferredCiphers - HashSet preferredCiphers = new HashSet<>(allowedCiphers); - preferredCiphers.retainAll(availableCiphers); - /* For maximum security, preferredCiphers should *replace* enabled ciphers (thus disabling - * ciphers which are enabled by default, but have become unsecure), but I guess for - * the security level of DAVdroid and maximum compatibility, disabling of insecure - * ciphers should be a server-side task */ - // add preferred ciphers to enabled ciphers - HashSet enabledCiphers = preferredCiphers; - enabledCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites()))); - Android5SSL.cipherSuites = enabledCiphers.toArray(new String[enabledCiphers.size()]); - } - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public Android5SSL(X509TrustManager tm) { - try { - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, (tm != null) ? new X509TrustManager[]{tm} : null, null); - defaultFactory = sslContext.getSocketFactory(); - } catch (GeneralSecurityException e) { - throw new AssertionError(); // The system has no TLS. Just give up. - } - } - - private void upgradeTLS(SSLSocket ssl) { - // Android 5.0+ (API level21) provides reasonable default settings - // but it still allows SSLv3 - // https://developer.android.com/about/versions/android-5.0-changes.html#ssl - if (protocols != null) { - ssl.setEnabledProtocols(protocols); - } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && cipherSuites != null) { - ssl.setEnabledCipherSuites(cipherSuites); - } - } - - @Override public String[] getDefaultCipherSuites() { - return cipherSuites; - } - - @Override public String[] getSupportedCipherSuites() { - return cipherSuites; - } - - @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { - Socket ssl = defaultFactory.createSocket(s, host, port, autoClose); - if (ssl instanceof SSLSocket) - upgradeTLS((SSLSocket) ssl); - return ssl; - } - - @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { - Socket ssl = defaultFactory.createSocket(host, port); - if (ssl instanceof SSLSocket) - upgradeTLS((SSLSocket) ssl); - return ssl; - } - - @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { - Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort); - if (ssl instanceof SSLSocket) - upgradeTLS((SSLSocket) ssl); - return ssl; - } - - @Override public Socket createSocket(InetAddress host, int port) throws IOException { - Socket ssl = defaultFactory.createSocket(host, port); - if (ssl instanceof SSLSocket) - upgradeTLS((SSLSocket) ssl); - return ssl; - } - - @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { - Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort); - if (ssl instanceof SSLSocket) - upgradeTLS((SSLSocket) ssl); - return ssl; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/BindApi.java b/mhttp/src/main/java/im/wangchao/mhttp/BindApi.java deleted file mode 100644 index 03f26855..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/BindApi.java +++ /dev/null @@ -1,28 +0,0 @@ -package im.wangchao.mhttp; - - -import android.util.Log; - -/** - *

Description : BindApi.

- *

Author : wangchao.

- *

Date : 15/10/19.

- *

Time : 上午8:23.

- */ -final class BindApi { - /** HttpProcessor.SUFFIX */ - private static final String SUFFIX = "_HttpBinder"; - - @SuppressWarnings("unchecked") public static T bind(Class type) { - String name = type.getName() + SUFFIX; - T obj = null; - try { - obj = (T)Class.forName(name).newInstance(); - } catch (Exception e) { - Log.e(BindApi.class.getSimpleName(), e.getMessage(), e); - } - return obj; - } - - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/Callback.java b/mhttp/src/main/java/im/wangchao/mhttp/Callback.java deleted file mode 100644 index fa617fe2..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/Callback.java +++ /dev/null @@ -1,40 +0,0 @@ -package im.wangchao.mhttp; - -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Response; - -/** - *

Description : OkCallback.

- *

Author : wangchao.

- *

Date : 16/6/3.

- *

Time : 上午10:16.

- */ -public interface Callback extends okhttp3.Callback { - - Callback EMPTY = new Callback() { - @Override public void initialize(Request request) {} - - @Override public String accept() { - return Accept.EMPTY; - } - - @Override public void onFailure(Call call, IOException e) {} - - @Override public void onResponse(Call call, Response response) throws IOException { - response.close(); - } - }; - - /** - * Initialize the callback. - */ - void initialize(Request request); - - /** - * Request accept. - */ - String accept(); - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/Converter.java b/mhttp/src/main/java/im/wangchao/mhttp/Converter.java deleted file mode 100644 index c75bf3f0..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/Converter.java +++ /dev/null @@ -1,12 +0,0 @@ -package im.wangchao.mhttp; - -/** - *

Description : Converter.

- *

Author : wangchao.

- *

Date : 2018/3/20.

- *

Time : 下午10:26.

- */ -public interface Converter { - - R apply(T t) throws Exception; -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/HTTPS.java b/mhttp/src/main/java/im/wangchao/mhttp/HTTPS.java deleted file mode 100644 index c485086f..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/HTTPS.java +++ /dev/null @@ -1,179 +0,0 @@ -package im.wangchao.mhttp; - -import java.io.InputStream; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; - -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -import okhttp3.OkHttpClient; -import okhttp3.internal.Util; - -/** - *

Description : HTTPS.

- *

Author : wangchao.

- *

Date : 16/9/2.

- *

Time : 下午3:58.

- */ -/*package*/ final class HTTPS { - - // 信任所有证书的 TrustManager - private static X509TrustManager TrustAllCertificate = new X509TrustManager() { - @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { - } - - @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { - } - - @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return new java.security.cert.X509Certificate[]{}; - } - }; - - /** - * Trust all certificate for debug - */ - /*package*/ static void trustAllCertificate(OkHttpClient.Builder builder) { - builder.sslSocketFactory(new Android5SSL(TrustAllCertificate), TrustAllCertificate); - } - - /** - * Set Certificate - */ - /*package*/ static void setCertificates(OkHttpClient.Builder builder, - InputStream... certificates) throws Exception { - setCertificates(builder, null, certificates, null, null); - } - - /** - * Set Certificate - */ - /*package*/ static void setCertificates(OkHttpClient.Builder builder, - X509TrustManager trustManager, - InputStream bksFile, - String password) throws Exception { - setCertificates(builder, trustManager, null, bksFile, password); - } - - /** - * Set Certificate - */ - /*package*/ static void setCertificates(OkHttpClient.Builder builder, - InputStream[] certificates, - InputStream bksFile, - String password) throws Exception { - setCertificates(builder, null, certificates, bksFile, password); - } - - /** - * Set Certificate - */ - /*package*/ static void setCertificates(OkHttpClient.Builder builder, - X509TrustManager trustManager, - InputStream[] certificates, - InputStream bksFile, - String password) throws Exception { - TrustManager[] trustManagers = prepareTrustManager(certificates); - KeyManager[] keyManagers = prepareKeyManager(bksFile, password); - - X509TrustManager manager; - if (trustManager != null) { - manager = trustManager; - } else if (trustManagers != null) { - manager = chooseTrustManager(trustManagers); - } else { - manager = TrustAllCertificate; - } - - // 创建TLS类型的SSLContext对象, that uses our finalTrustManager - SSLContext sslContext = SSLContext.getInstance("TLS"); - // 用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书 - // 第一个参数是授权的密钥管理器,用来授权验证,比如授权自签名的证书验证。第二个是被授权的证书管理器,用来验证服务器端的证书 - sslContext.init(keyManagers, new TrustManager[]{manager}, new SecureRandom()); - builder.sslSocketFactory(sslContext.getSocketFactory(), manager); - } - - /*package*/ static TrustManager[] prepareTrustManager(InputStream... certificates) throws Exception { - if (certificates == null || certificates.length <= 0) return null; - - CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - // 创建一个默认类型的KeyStore,存储我们信任的证书 - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null); - int index = 0; - for (InputStream certificate : certificates) { - String certificateAlias = Integer.toString(index++); - keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate)); - Util.closeQuietly(certificate); - } - - TrustManagerFactory trustManagerFactory = TrustManagerFactory. - getInstance(TrustManagerFactory.getDefaultAlgorithm()); - //用我们之前的keyStore实例初始化TrustManagerFactory,使TrustManagerFactory信任keyStore中的证书 - trustManagerFactory.init(keyStore); - return trustManagerFactory.getTrustManagers(); - } - - /*package*/ static KeyManager[] prepareKeyManager(InputStream bksFile, String password) throws Exception{ - if (bksFile == null || password == null) return null; - - KeyStore clientKeyStore = KeyStore.getInstance("BKS"); - clientKeyStore.load(bksFile, password.toCharArray()); - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(clientKeyStore, password.toCharArray()); - return keyManagerFactory.getKeyManagers(); - } - - /*package*/ static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) { - for (TrustManager trustManager : trustManagers) { - if (trustManager instanceof X509TrustManager) { - return (X509TrustManager) trustManager; - } - } - return null; - } - - /* X509TrustManager */ - /*package*/ static class MyTrustManager implements X509TrustManager { - private X509TrustManager defaultTrustManager; - private X509TrustManager localTrustManager; - - /*package*/ MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException { - TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - var4.init((KeyStore) null); - defaultTrustManager = chooseTrustManager(var4.getTrustManagers()); - this.localTrustManager = localTrustManager; - } - - @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { -// try { -// defaultTrustManager.checkClientTrusted(chain, authType); -// } catch (CertificateException e) { -// localTrustManager.checkClientTrusted(chain, authType); -// } - } - - @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { - try { - defaultTrustManager.checkServerTrusted(chain, authType); - } catch (CertificateException e) { - localTrustManager.checkServerTrusted(chain, authType); - } - } - - - @Override public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/MHttp.java b/mhttp/src/main/java/im/wangchao/mhttp/MHttp.java deleted file mode 100644 index af46229b..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/MHttp.java +++ /dev/null @@ -1,252 +0,0 @@ -package im.wangchao.mhttp; - -import android.content.Context; -import android.os.Build; -import android.os.StatFs; -import androidx.annotation.NonNull; - -import java.io.File; -import java.io.InputStream; -import java.net.URL; -import java.util.concurrent.TimeUnit; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.X509TrustManager; - -import im.wangchao.mhttp.internal.interceptor.HttpLoggingInterceptor; -import im.wangchao.mhttp.internal.interceptor.MBridgeInterceptor; -import im.wangchao.mhttp.internal.log.LoggerImpl; -import okhttp3.Cache; -import okhttp3.Call; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; - -/** - *

Description : MHttp.

- *

Author : wangchao.

- *

Date : 16/6/2.

- *

Time : 上午8:40.

- */ -public final class MHttp { - private static volatile MHttp instance; - - private OkHttpClient.Builder mOkBuilder; - private OkHttpClient mInnerClient; - private URLInterceptor mURLInterceptor; - private final HttpLoggingInterceptor mLoggingInterceptor = new HttpLoggingInterceptor(LoggerImpl.instance.get()); - - public static MHttp instance(){ - if (instance == null) { - synchronized (MHttp.class){ - instance = new MHttp(); - } - } - return instance; - } - - /** - * Create annotation api - */ - public static T create(Class api){ - return BindApi.bind(api); - } - - /** - * OkHttpClient - */ - public MHttp customOkHttpClient(@NonNull OkHttpClient client){ - mOkBuilder = client.newBuilder() - .addInterceptor(MBridgeInterceptor.instance.get()); - return this; - } - - /** - * Set logging level - */ - public MHttp loggingLevel(HttpLoggingInterceptor.Level level){ - mLoggingInterceptor.setLevel(level); - LoggerImpl.instance.get().setLevel(level); - if (!mOkBuilder.interceptors().contains(mLoggingInterceptor)) { - mOkBuilder.addInterceptor(mLoggingInterceptor); - } - return this; - } - - /** - * Set cache Dir - */ - public MHttp cache(Context context, String dirName) { - File cache = new File(context.getApplicationContext().getCacheDir(), dirName); - if (!cache.exists()) { - //noinspection ResultOfMethodCallIgnored - cache.mkdirs(); - } - long size = 5 * 1024 * 1024; - try { - StatFs statFs = new StatFs(cache.getAbsolutePath()); - long count, blockSize; - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1){ - count = statFs.getBlockCountLong(); - blockSize = statFs.getBlockSizeLong(); - } else { - count = statFs.getBlockCount(); - blockSize = statFs.getBlockSize(); - } - long available = count * blockSize; - // Target 2% of the total space. - size = available / 50; - } catch (IllegalArgumentException ignored) { - } - // Bound inside min/max size for disk cache. - size = Math.max(Math.min(size, size * 10), size); - - mOkBuilder.cache(new Cache(cache, size)); - return this; - } - - /** - * Set connect, read and write time with {@link TimeUnit#SECONDS} - */ - public MHttp timeout(int timeout){ - timeout(timeout, TimeUnit.SECONDS); - return this; - } - - public MHttp timeout(int timeout, TimeUnit unit){ - connectTimeout(timeout, unit); - readTimeout(timeout, unit); - writeTimeout(timeout, unit); - return this; - } - - public MHttp connectTimeout(long timeout, TimeUnit unit){ - mOkBuilder.connectTimeout(timeout, unit); - return this; - } - - public MHttp readTimeout(long timeout, TimeUnit unit){ - mOkBuilder.readTimeout(timeout, unit); - return this; - } - - public MHttp writeTimeout(long timeout, TimeUnit unit){ - mOkBuilder.writeTimeout(timeout, unit); - return this; - } - - public MHttp setURLInterceptor(URLInterceptor interceptor){ - this.mURLInterceptor = interceptor; - return this; - } - - /** - * Trust all certificate for debug - */ - public MHttp trustAllCertificate(){ - HTTPS.trustAllCertificate(mOkBuilder); - return this; - } - - /** - * Set Certificate - */ - public MHttp setCertificates(InputStream... certificates){ - return setCertificates(certificates, null, null); - } - - /** - * Set Certificate - */ - public MHttp setCertificates(X509TrustManager trustManager, InputStream bksFile, String password) { - try { - HTTPS.setCertificates(mOkBuilder, trustManager, null, bksFile, password); - } catch (Exception e) { - throw new RuntimeException(e); - } - return this; - } - - /** - * Set Certificate - */ - public MHttp setCertificates(InputStream[] certificates, InputStream bksFile, String password) { - try { - HTTPS.setCertificates(mOkBuilder, null, certificates, bksFile, password); - } catch (Exception e) { - throw new RuntimeException(e); - } - return this; - } - - public MHttp hostnameVerifier(HostnameVerifier hostnameVerifier){ - mOkBuilder.hostnameVerifier(hostnameVerifier); - return this; - } - - /** - * @return Current client. - */ - public OkHttpClient client(){ - if (mOkBuilder == null){ - throw new IllegalArgumentException("OkHttpClient cannot be null, please call the MHttp#client(OkHttpClient client) method first."); - } - if (mInnerClient == null){ - mInnerClient = mOkBuilder.build(); - } - return mInnerClient; - } - - /** - * Cancel all request. - */ - public MHttp cancelAll(){ - client().dispatcher().cancelAll(); - return this; - } - - /** - * Cancel request with {@code tag} - */ - public MHttp cancel(Object tag){ - for (Call call : client().dispatcher().queuedCalls()) { - if (tag.equals(call.request().tag())) { - call.cancel(); - } - } - for (Call call : client().dispatcher().runningCalls()) { - if (tag.equals(call.request().tag())) { - call.cancel(); - } - } - return this; - } - - /*package*/ String proceedURL(String url){ - if (mURLInterceptor != null){ - return mURLInterceptor.interceptor(url); - } - return url; - } - - /*package*/ HttpUrl proceedURL(HttpUrl url){ - if (mURLInterceptor != null){ - return mURLInterceptor.interceptor(url); - } - return url; - } - - /*package*/ URL proceedURL(URL url){ - if (mURLInterceptor != null){ - return mURLInterceptor.interceptor(url); - } - return url; - } - - //@private - private MHttp(){ - //default instance - mOkBuilder = new OkHttpClient.Builder() - .addInterceptor(MBridgeInterceptor.instance.get()); - } - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/Method.java b/mhttp/src/main/java/im/wangchao/mhttp/Method.java deleted file mode 100644 index f7453aab..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/Method.java +++ /dev/null @@ -1,25 +0,0 @@ -package im.wangchao.mhttp; - -import androidx.annotation.StringDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - *

Description : Method.

- *

Author : wangchao.

- *

Date : 16/3/8.

- *

Time : 下午4:08.

- */ -public interface Method { - String POST = "POST"; - String GET = "GET"; - String HEAD = "HEAD"; - String DELETE = "DELETE"; - String PUT = "PUT"; - String PATCH = "PATCH"; - - @Retention(RetentionPolicy.SOURCE) - @StringDef({Method.POST, Method.GET, Method.HEAD, Method.DELETE, Method.PUT, Method.PATCH}) - @interface MethodType{} -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/Request.java b/mhttp/src/main/java/im/wangchao/mhttp/Request.java deleted file mode 100644 index 426b0eab..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/Request.java +++ /dev/null @@ -1,503 +0,0 @@ -package im.wangchao.mhttp; - -import androidx.annotation.NonNull; -import android.util.Pair; -import android.util.Log; - -import com.google.gson.JsonObject; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executor; - -import im.wangchao.mhttp.body.JSONBody; -import im.wangchao.mhttp.body.MediaTypeUtils; -import okhttp3.CacheControl; -import okhttp3.Call; -import okhttp3.Headers; -import okhttp3.HttpUrl; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.RequestBody; -import okio.Buffer; -import okio.BufferedSink; - -/** - *

Description : MRequest.

- *

Author : wangchao.

- *

Date : 16/6/2.

- *

Time : 下午4:16.

- */ -public final class Request { - public static Builder builder(){ - return new Builder(); - } - - private final okhttp3.Request mRawRequest; - private final RequestParams mRequestParams; - private final Callback mCallback; - private final MediaType mMediaType; - private final Executor mExecutor; - private final ThreadMode mThreadMode; - private final JsonObject mJsonBody; - private final okhttp3.OkHttpClient mOkHttpClient; - private final List mAllowedErrorCodes; - private final String mTextBody; - - private okhttp3.Call mRawCall; - - private Request(Builder builder){ - mRawRequest = builder.mRawRequest; - mRequestParams = builder.mRequestParams; - mCallback = builder.mCallback; - mMediaType = builder.mMediaType; - mExecutor = builder.mExecutor; - mThreadMode = builder.mThreadMode; - mJsonBody = builder.mJsonBody; - mOkHttpClient = builder.mOkHttpClient; - mAllowedErrorCodes = builder.mAllowedErrorCodes; - mTextBody = builder.mTextBody; - } - - public okhttp3.Request raw() { - return mRawRequest; - } - - public HttpUrl url() { - return mRawRequest.url(); - } - - public String method() { - return mRawRequest.method(); - } - - public Headers headers() { - return mRawRequest.headers(); - } - - public String header(String name) { - return mRawRequest.header(name); - } - - public List headers(String name) { - return mRawRequest.headers(name); - } - - public RequestBody body() { - return mRawRequest.body(); - } - - public String bodyToString(){ - try { - final Buffer buffer = new Buffer(); - body().writeTo(buffer); - return buffer.readUtf8(); - } catch (final Exception e) { - return "did not work. "+e.getMessage(); - } - } - - public Object tag() { - return mRawRequest.tag(); - } - - public Builder newBuilder() { - return new Builder(this); - } - - public Callback callback() { - return mCallback; - } - - public JsonObject jsonBody() { - return mJsonBody; - } - - public String textBody() { - return mTextBody; - } - - public OkHttpClient okHttpClient() { - return mOkHttpClient; - } - - public List allowedErrorCodes() { - return mAllowedErrorCodes; - } - - /** - * Returns the cache control directives for this response. This is never null, even if this - * response contains no {@code Cache-Control} header. - */ - public CacheControl cacheControl() { - return mRawRequest.cacheControl(); - } - - public boolean isHttps() { - return mRawRequest.isHttps(); - } - - /** - * The executor used for {@link Callback} methods on which thread work. - */ - public Executor callbackExecutor() { - return mExecutor; - } - - /** - * {@link Callback} methods on which thread work. - */ - public ThreadMode callbackThreadMode() { - return mThreadMode; - } - - public RequestParams requestParams(){ - return mRequestParams; - } - - /** - * Send the async request. - */ - public Request enqueue(){ - Callback callback = callback(); - callback.initialize(this); - if (callback instanceof AbsCallbackHandler){ - ((AbsCallbackHandler) callback).sendStartEvent(); - } - rawCall().enqueue(callback); - return this; - } - - /** - * Send the sync request. - */ - public Response execute() throws IOException { - return Response.newResponse(this, rawCall().execute()); - } - - /** - * Cancel this request - */ - public Request cancel(){ - if (rawCall().isCanceled()){ - return this; - } - rawCall().cancel(); - return this; - } - - private Call rawCall(){ - if (mRawCall == null){ - OkHttpClient client; - if (mOkHttpClient == null) { - client = MHttp.instance().client(); - } - else { - client = mOkHttpClient; - } - mRawCall = client.newCall(raw()); - } - return mRawCall; - } - - @Override public String toString() { - return mRawRequest.toString(); - } - - public static class Builder { - private static final String TAG = Builder.class.getSimpleName(); - - okhttp3.Request mRawRequest; - okhttp3.Request.Builder mRawBuilder; - RequestParams mRequestParams; - Callback mCallback; - String mMethod; - MediaType mMediaType; - Executor mExecutor; - ThreadMode mThreadMode; - JsonObject mJsonBody; - OkHttpClient mOkHttpClient; - List mAllowedErrorCodes; - String mTextBody; - - public Builder() { - mCallback = Callback.EMPTY; - mMethod = Method.GET; - mRawBuilder = new okhttp3.Request.Builder(); - mRequestParams = new RequestParams(); - mThreadMode = ThreadMode.BACKGROUND; - mJsonBody = null; - mOkHttpClient = null; - mAllowedErrorCodes = new ArrayList<>(); - mTextBody = null; - } - - private Builder(Request request) { - mCallback = request.mCallback; - mMethod = request.method(); - mRequestParams = request.mRequestParams; - mRawBuilder = request.mRawRequest.newBuilder(); - mExecutor = request.mExecutor; - mThreadMode = request.mThreadMode; - mMediaType = request.mMediaType; - mJsonBody = request.mJsonBody; - mOkHttpClient = request.mOkHttpClient; - mAllowedErrorCodes = request.mAllowedErrorCodes; - mTextBody = request.mTextBody; - } - - public Builder url(HttpUrl url) { - mRawBuilder.url(MHttp.instance().proceedURL(url)); - return this; - } - - public Builder url(String url) { - mRawBuilder.url(MHttp.instance().proceedURL(url)); - return this; - } - - public Builder url(URL url) { - mRawBuilder.url(MHttp.instance().proceedURL(url)); - return this; - } - - public Builder header(String name, String value) { - mRawBuilder.header(name, value); - return this; - } - - public Builder addHeader(String name, String value) { - mRawBuilder.addHeader(name, value); - return this; - } - - public Builder removeHeader(String name) { - mRawBuilder.removeHeader(name); - return this; - } - - public Builder headers(Headers headers) { - mRawBuilder.headers(headers); - return this; - } - - public Builder cacheControl(CacheControl cacheControl) { - mRawBuilder.cacheControl(cacheControl); - return this; - } - - public Builder withClient(OkHttpClient okHttpClient) { - mOkHttpClient = okHttpClient; - return this; - } - - public Builder get() { - return method(Method.GET); - } - - public Builder head() { - return method(Method.HEAD); - } - - public Builder post() { - return method(Method.POST); - } - - public Builder postJson() { - return method(Method.POST).contentType(MediaTypeUtils.APPLICATION_JSON); - } - - public Builder delete() { - return method(Method.DELETE); - } - - public Builder put() { - return method(Method.PUT); - } - - public Builder patch() { - return method(Method.PATCH); - } - - public Builder setJsonBody(JsonObject jsonBody) { - mJsonBody = jsonBody; - return method(Method.POST).contentType(MediaTypeUtils.APPLICATION_JSON); - } - - public Builder setTextBody(String textBody, String mediaType) { - mTextBody = textBody; - return method(Method.POST).contentType(mediaType); - } - - public Builder allowErrorCode(int code) { - mAllowedErrorCodes.add(code); - return this; - } - - /** - * Simple to add request parameter - */ - public Builder addParameter(String key, Object value){ - mRequestParams.put(key, value); - return this; - } - - /** - * Simple to add request parameter - */ - public Builder addParameter(String key, InputStream stream, String name){ - mRequestParams.put(key, stream, name); - return this; - } - - /** - * Simple to add request parameter - */ - public Builder addParameter(String key, InputStream stream, String name, String contentType){ - mRequestParams.put(key, stream, name, contentType); - return this; - } - - /** - * Simple to add request parameter - */ - public Builder addParameter(String key, File file, String contentType){ - try { - mRequestParams.put(key, file, contentType); - } catch (FileNotFoundException e) { - Log.e(TAG, e.getMessage(), e); - } - return this; - } - - public Builder requestParams(RequestParams params) { - if (params != null){ - mRequestParams = params; - } - return this; - } - - public Builder addParams(List> params) { - if (params != null){ - mRequestParams.put(params); - } - return this; - } - - public Builder method(@NonNull String method) { - this.mMethod = method; - return this; - } - - public Builder tag(Object tag) { - mRawBuilder.tag(tag); - return this; - } - - public Builder callback(@NonNull Callback callback){ - mCallback = callback; - return this; - } - - public Builder callbackExecutor(Executor executor){ - mExecutor = executor; - return this; - } - - public Builder callbackThreadMode(ThreadMode threadMode){ - mThreadMode = threadMode; - return this; - } - - public Builder userAgent(String ua){ - header("User-Agent", ua); - return this; - } - - public Builder contentType(@NonNull String contentType){ - this.mMediaType = MediaType.parse(contentType); - header("Content-Type", contentType); - return this; - } - - public Builder contentType(@NonNull MediaType mediaType){ - this.mMediaType = mediaType; - header("Content-Type", this.mMediaType.toString()); - return this; - } - - public Request build() { - if (mMediaType == null){ - // judgment request header - List headers = mRawBuilder.build().headers("Content-Type"); - final int len = headers.size(); - if (len != 0){ - StringBuilder mediaType = new StringBuilder(); - for (int i = 0; i < len; i++){ - mediaType.append(headers.get(i)); - } - mMediaType = MediaType.parse(mediaType.toString()); - if (mMediaType == null){ - mMediaType = MediaTypeUtils.DEFAULT; - } - } - // default is application/x-www-form-urlencoded - else { - mMediaType = MediaTypeUtils.DEFAULT; - } - } - - if (!Accept.EMPTY.equals(mCallback.accept())) { - addHeader("Accept", mCallback.accept()); - } - - switch (mMethod) { - case Method.GET: - mRawBuilder.method(mMethod, null); - mRawRequest = mRawBuilder.build(); - mRawRequest = mRawBuilder.url(mRequestParams.formatURLParams(mRawRequest.url())).build(); - break; - case Method.HEAD: - mRawBuilder.method(mMethod, null); - mRawRequest = mRawBuilder.build(); - break; - default: - if (MediaTypeUtils.isJSON(mMediaType) && mJsonBody != null) { - mRawBuilder.method(mMethod, new JSONBody(mJsonBody.toString())); - } - else if (mTextBody != null) { - mRawBuilder.method(mMethod, new RequestBody() { - @Override - public MediaType contentType() { - return mMediaType; - } - - @Override - public void writeTo(BufferedSink sink) throws IOException { - sink.write(mTextBody.getBytes(), 0, mTextBody.getBytes().length); - } - - @Override - public long contentLength() throws IOException { - return mTextBody.getBytes().length; - } - }); - } - else { - // inject callback if exist. - mRawBuilder.method(mMethod, mRequestParams.requestBody(mMediaType, - (mCallback instanceof AbsCallbackHandler ? (AbsCallbackHandler) mCallback : null))); - } - mRawRequest = mRawBuilder.build(); - break; - } - - return new Request(this); - } - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/RequestParams.java b/mhttp/src/main/java/im/wangchao/mhttp/RequestParams.java deleted file mode 100644 index 822338ac..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/RequestParams.java +++ /dev/null @@ -1,378 +0,0 @@ -package im.wangchao.mhttp; - -import androidx.annotation.NonNull; -import android.text.TextUtils; -import android.util.Pair; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import im.wangchao.mhttp.body.FileBody; -import im.wangchao.mhttp.body.JSONBody; -import im.wangchao.mhttp.body.MediaTypeUtils; -import im.wangchao.mhttp.body.OctetStreamBody; -import im.wangchao.mhttp.body.ProgressRequestBody; -import okhttp3.FormBody; -import okhttp3.HttpUrl; -import okhttp3.MediaType; -import okhttp3.MultipartBody; -import okhttp3.RequestBody; - -import static im.wangchao.mhttp.body.MediaTypeUtils.APPLICATION_OCTET_STREAM; - -/** - *

Description : RequestParams.

- *

Author : wangchao.

- *

Date : 15/8/17.

- *

Time : 下午2:16.

- */ -public class RequestParams{ - final private static String UTF_8_STR = "utf-8"; - final private static Charset UTF_8 = Charset.forName(UTF_8_STR); - - //params - final private List> urlParams = new ArrayList<>(); - final private ConcurrentHashMap streamParams = new ConcurrentHashMap<>(); - final private ConcurrentHashMap fileParams = new ConcurrentHashMap<>(); - - //default - private String contentEncoding = UTF_8_STR; - - public RequestParams(){ - this((Map)null); - } - - public RequestParams(Map params){ - if (params != null){ - for(Map.Entry entry : params.entrySet()){ - put(entry.getKey(), entry.getValue()); - } - } - } - - public RequestParams(Object...keysAndValues){ - int len = keysAndValues.length; - if (len % 2 != 0){ - throw new IllegalArgumentException("Supplied arguments must be even."); - } - for (int i = 0; i < len; i += 2){ - String key = String.valueOf(keysAndValues[i]); - String val = String.valueOf(keysAndValues[i + 1]); - put(key, val); - } - } - - public RequestParams(RequestParams params){ - if (params == null){ - return; - } - this.urlParams.addAll(params.getUrlParams()); - this.streamParams.putAll(params.getStreamParams()); - this.fileParams.putAll(params.getFileParams()); - this.contentEncoding = params.contentEncoding(); - } - - RequestBody requestBody(MediaType mediaType, AbsCallbackHandler callback){ - if (isJSON(mediaType)){ - Charset charset = mediaType.charset(); - if (charset == null){ - charset = UTF_8; - } - return new JSONBody(parseJSON(), charset.name()); - } - - if (isForm(mediaType)){ - return formBody(); - } - - MultipartBody.Builder builder = new MultipartBody.Builder(); - builder.setType(MultipartBody.FORM); - //form - for (Pair entry: urlParams){ - builder.addFormDataPart(entry.first, String.valueOf(entry.second)); - } - //stream - for (Map.Entry streamEntry: streamParams.entrySet()){ - builder.addPart( - okhttp3.Headers.of("Content-Disposition", - String.format("form-data;name=\"%s\";filename=\"%s\"", streamEntry.getKey(), streamEntry.getValue().name), - "Content-Transfer-Encoding", "binary"), - uploadProgressRequestBody( - new OctetStreamBody(streamEntry.getValue().inputStream, streamEntry.getValue().contentType), - callback)); - } - //file - for (Map.Entry file: fileParams.entrySet()){ - builder.addPart(uploadProgressRequestBody( - new FileBody(file.getValue().file, file.getValue().contentType), - callback - )); - } - - return builder.build(); - } - - private ProgressRequestBody uploadProgressRequestBody(RequestBody requestBody, AbsCallbackHandler callback){ - return new ProgressRequestBody(requestBody, callback); - } - - private FormBody formBody(){ - FormBody.Builder builder = new FormBody.Builder(); - for (Pair entry: urlParams){ - builder.add(entry.first, String.valueOf(entry.second)); - } - return builder.build(); - } - - /** - * @return Request body media type is JSON. - */ - private boolean isJSON(MediaType mediaType){ - return MediaTypeUtils.isJSON(mediaType) && streamParams.size() == 0 - && fileParams.size() == 0; - } - - /** - * @return Request body media type is Form. - */ - private boolean isForm(MediaType mediaType){ - return MediaTypeUtils.isFORM(mediaType) && streamParams.size() == 0 - && fileParams.size() == 0; - } - - /** - * Request body encoding. - */ - public RequestParams contentEncoding(@NonNull String encoding) { - if (Charset.isSupported(encoding)){ - this.contentEncoding = encoding; - } - return this; - } - - public String contentEncoding(){ - return contentEncoding; - } - - public void put(Map params){ - if (params != null){ - for(Map.Entry entry : params.entrySet()){ - put(entry.getKey(), entry.getValue()); - } - } - } - - public void put(List> params){ - if (params != null){ - urlParams.addAll(params); - } - } - - public void put(String key, String value) { - if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) { - urlParams.add(new Pair<>(key, value)); - } - } - - public void put(String key, Object value) { - if (!TextUtils.isEmpty(key) && (value != null)) { - if (value instanceof File){ - try { - put(key, (File)value); - } catch (FileNotFoundException e) { - // Silent - } - } else { - urlParams.add(new Pair<>(key, value)); - } - } - } - - - - public void put(String key, InputStream stream){ - put(key, stream, null); - } - - public void put(String key, InputStream stream, String name){ - put(key, stream, name, null); - } - - public void put(String key, InputStream stream, String name, String contentType){ - if (!TextUtils.isEmpty(key) && stream != null){ - streamParams.put(key, StreamWrapper.newInstance(stream, name, contentType)); - } - } - - public void put(File file) throws FileNotFoundException { - put(file, null); - } - - public void put(File file, String contentType) throws FileNotFoundException { - put(RequestParams.class.getSimpleName(), file, contentType); - } - - public void put(String key, File file) throws FileNotFoundException { - put(key, file, null); - } - - public void put(String key, File file, String contentType) throws FileNotFoundException { - if (file == null || !file.exists()){ - throw new FileNotFoundException(); - } - if (!TextUtils.isEmpty(key)){ - fileParams.put(key, new FileWrapper(file, contentType)); - } - } - - public void remove(String key){ - Pair removing = null; - for (Pair entry: urlParams) { - if (entry.first.equals(key)) { - removing = entry; - } - } - urlParams.remove(removing); - streamParams.remove(key); - fileParams.remove(key); - } - - public boolean has(String key){ - for (Pair entry: urlParams) { - if (entry.first.equals(key)) { - return true; - } - } - return (streamParams.containsKey(key) || fileParams.containsKey(key)); - } - - public boolean isEmpty(){ - return urlParams.isEmpty() && streamParams.isEmpty() && fileParams.isEmpty(); - } - - private String parseJSON(){ - JSONObject json = new JSONObject(); - - String key; - Object value; - for (Pair entry: urlParams){ - key = entry.first; - value = entry.second; - - if (key.isEmpty() || value == null){ - continue; - } - - try { - json.put(key, value); - } catch (JSONException e) { - // Silent - } - } - - return json.toString(); - } - - public ConcurrentHashMap getStreamParams() { - return streamParams; - } - - public ConcurrentHashMap getFileParams() { - return fileParams; - } - - public List> getUrlParams() { - return urlParams; - } - - public HttpUrl formatURLParams(HttpUrl url) { - HttpUrl.Builder builder = url.newBuilder(); - if (urlParams.size() != 0) { - for (Pair entry : urlParams) { - try { - builder.addEncodedQueryParameter(URLEncoder.encode(entry.first, contentEncoding), - URLEncoder.encode(String.valueOf(entry.second), contentEncoding)); - } catch (UnsupportedEncodingException e) { - //Silent - } - } - } - return builder.build(); - } - - /** - * Format get params. - */ - public String formatURLParams() { - StringBuilder sb = new StringBuilder(); - if (urlParams.size() != 0) { - for (Pair entry : urlParams) { - String encode = ""; - try { - encode = URLEncoder.encode(String.valueOf(entry.second), contentEncoding); - } catch (UnsupportedEncodingException e) { - //Silent - } - sb.append(entry.first).append("=").append(encode); - sb.append("&"); - } - sb.deleteCharAt(sb.length() - 1); - } - - return sb.toString().replace(" ", "%20"); - } - - /** - * Url params convert to {@link List}. - */ - public List> getParamsList(){ - List> params = new LinkedList<>(); - - for (Pair entry : urlParams) { - params.add(new Pair<>(entry.first, entry.second)); - } - - return params; - } - - public static class FileWrapper { - public final File file; - public final String contentType; - - public FileWrapper(File file, String contentType) { - this.file = file; - this.contentType = contentType; - } - } - - public static class StreamWrapper { - public final InputStream inputStream; - public final String name; - public final String contentType; - - public StreamWrapper(InputStream inputStream, String name, String contentType) { - this.inputStream = inputStream; - this.name = name; - this.contentType = contentType; - } - - static StreamWrapper newInstance(InputStream inputStream, String name, String contentType) { - return new StreamWrapper( - inputStream, - name, - TextUtils.isEmpty(contentType) ? APPLICATION_OCTET_STREAM : contentType); - } - } -} \ No newline at end of file diff --git a/mhttp/src/main/java/im/wangchao/mhttp/Response.java b/mhttp/src/main/java/im/wangchao/mhttp/Response.java deleted file mode 100644 index 8d1e16d7..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/Response.java +++ /dev/null @@ -1,63 +0,0 @@ -package im.wangchao.mhttp; - -import okhttp3.Headers; -import okhttp3.Protocol; - -/** - *

Description : MResponse.

- *

Author : wangchao.

- *

Date : 16/6/3.

- *

Time : 下午3:03.

- */ -public final class Response { - public final static int IO_EXCEPTION_CODE = 1000; - - public static Response error(Request request, int code, String message){ - if (message == null){ - message = "unknown exception."; - } - return new Response(request, new okhttp3.Response.Builder() - .request(request.raw()) - .protocol(Protocol.HTTP_1_1) - .code(code) - .message(message) - .build()); - } - - public static Response newResponse(Request request, okhttp3.Response raw){ - return new Response(request, raw); - } - - private final Request request; - private final okhttp3.Response rawResponse; - public String parserErrorBody = null; - - private Response(Request request, okhttp3.Response rawResponse){ - this.request = request; - this.rawResponse = rawResponse; - } - - public Request request() { - return request; - } - - public okhttp3.Response raw() { - return rawResponse; - } - - /** HTTP status code. */ - public int code() { - return rawResponse.code(); - } - - /** HTTP status message or null if unknown. */ - public String message() { - return rawResponse.message(); - } - - /** HTTP headers. */ - public Headers headers() { - return rawResponse.headers(); - } - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/ThreadMode.java b/mhttp/src/main/java/im/wangchao/mhttp/ThreadMode.java deleted file mode 100644 index 49a23195..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/ThreadMode.java +++ /dev/null @@ -1,43 +0,0 @@ -package im.wangchao.mhttp; - -import java.util.concurrent.Executor; - -import im.wangchao.mhttp.executor.BACKGROUND; -import im.wangchao.mhttp.executor.MAIN; -import im.wangchao.mhttp.executor.SENDING; - -/** - *

Description : ThreadMode.

- *

Author : wangchao.

- *

Date : 16/8/3.

- *

Time : 下午12:44.

- */ -public enum ThreadMode { - /** - * Callback will be called in the same thread, which is sending the request. - */ - SENDING{ - @Override public Executor executor() { - return new SENDING(); - } - }, - /** - * Callback will be called in Android's main thread (UI thread). - */ - MAIN{ - @Override public Executor executor() { - return new MAIN(); - } - }, - - /** - * Callback will be called in a background thread. That is, work on the request thread(okhttp thread). - */ - BACKGROUND{ - @Override public Executor executor() { - return new BACKGROUND(); - } - }; - - public abstract Executor executor(); -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/URLInterceptor.java b/mhttp/src/main/java/im/wangchao/mhttp/URLInterceptor.java deleted file mode 100644 index 739a24f2..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/URLInterceptor.java +++ /dev/null @@ -1,20 +0,0 @@ -package im.wangchao.mhttp; - -import java.net.URL; - -import okhttp3.HttpUrl; - -/** - *

Description : URLInterceptor.

- *

Author : wangchao.

- *

Date : 2018/1/15.

- *

Time : 上午11:01.

- */ -public interface URLInterceptor { - - String interceptor(String origin); - - HttpUrl interceptor(HttpUrl origin); - - URL interceptor(URL origin); -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/body/FileBody.java b/mhttp/src/main/java/im/wangchao/mhttp/body/FileBody.java deleted file mode 100644 index 051dce2c..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/body/FileBody.java +++ /dev/null @@ -1,53 +0,0 @@ -package im.wangchao.mhttp.body; - -import androidx.annotation.NonNull; -import android.text.TextUtils; - -import java.io.File; -import java.io.IOException; - -import okhttp3.MediaType; -import okhttp3.RequestBody; -import okhttp3.internal.Util; -import okio.BufferedSink; -import okio.Okio; -import okio.Source; - -/** - *

Description : FileBody.

- *

Author : wangchao.

- *

Date : 16/3/8.

- *

Time : 下午6:10.

- */ -public final class FileBody extends RequestBody{ - private final static MediaType CONTENT_TYPE = MediaTypeUtils.OCTET; - private final MediaType contentType; - private final File file; - - public FileBody(File file){ - this(file, null); - } - - public FileBody(File file, String contentType){ - this.file = file; - this.contentType = TextUtils.isEmpty(contentType) ? CONTENT_TYPE : MediaType.parse(contentType); - } - - @Override public MediaType contentType() { - return contentType; - } - - @Override public long contentLength() throws IOException { - return file.length(); - } - - @Override public void writeTo(@NonNull BufferedSink sink) throws IOException { - Source source = null; - try { - source = Okio.source(file); - sink.writeAll(source); - } finally { - Util.closeQuietly(source); - } - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/body/JSONBody.java b/mhttp/src/main/java/im/wangchao/mhttp/body/JSONBody.java deleted file mode 100644 index 8449625c..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/body/JSONBody.java +++ /dev/null @@ -1,50 +0,0 @@ -package im.wangchao.mhttp.body; - -import androidx.annotation.NonNull; -import android.text.TextUtils; - -import java.io.IOException; - -import okhttp3.MediaType; -import okhttp3.RequestBody; -import okio.BufferedSink; - -/** - *

Description : JSONBody.

- *

Author : wangchao.

- *

Date : 16/3/8.

- *

Time : 下午4:31.

- */ -public final class JSONBody extends RequestBody{ - private final static MediaType CONTENT_TYPE = MediaTypeUtils.JSON; - private final MediaType contentType; - private final byte[] bytes; - - public JSONBody(String content){ - this(content, null); - } - - public JSONBody(String content, String charset){ - if (TextUtils.isEmpty(content)){ - throw new NullPointerException("content == null"); - } - if (TextUtils.isEmpty(charset)){ - charset = "utf-8"; - } - this.contentType = TextUtils.isEmpty(charset) ? CONTENT_TYPE : MediaType.parse("application/json; charset=" + charset); - bytes = content.getBytes(contentType.charset()); - } - - @Override public MediaType contentType() { - return contentType; - } - - @Override public long contentLength() throws IOException { - return bytes.length; - } - - @Override public void writeTo(@NonNull BufferedSink sink) throws IOException { - sink.write(bytes, 0, bytes.length); - } - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/body/MediaTypeUtils.java b/mhttp/src/main/java/im/wangchao/mhttp/body/MediaTypeUtils.java deleted file mode 100644 index ff665962..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/body/MediaTypeUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -package im.wangchao.mhttp.body; - -import androidx.annotation.NonNull; -import android.text.TextUtils; - -import okhttp3.MediaType; - -/** - *

Description : MediaType.

- *

Author : wangchao.

- *

Date : 2017/6/23.

- *

Time : 下午2:15.

- */ -public final class MediaTypeUtils { - /** MediaType String */ - public static final String APPLICATION_OCTET_STREAM = "application/octet-stream"; - public static final String APPLICATION_JSON = "application/json; charset=utf-8"; - public static final String APPLICATION_FORM = "application/x-www-form-urlencoded"; - public static final String APPLICATION_XML = "application/xml"; - - /** MediaType */ - public static final MediaType JSON = MediaType.parse(APPLICATION_JSON); - public static final MediaType OCTET = MediaType.parse(APPLICATION_OCTET_STREAM); - public static final MediaType FORM = MediaType.parse(APPLICATION_FORM); - public static final MediaType XML = MediaType.parse(APPLICATION_XML); - public static final MediaType DEFAULT = FORM; - - /** - * 判断两个 MediaType 是否相等,只判断 type 和 subType。 - */ - public static boolean equals(@NonNull MediaType first, @NonNull MediaType second){ - String first_type_subType = first.type().concat(first.subtype()); - String second_type_subType = second.type().concat(second.subtype()); - - return TextUtils.equals(first_type_subType, second_type_subType); - } - - public static boolean isJSON(@NonNull MediaType mediaType){ - return equals(mediaType, JSON); - } - - public static boolean isOCTET(@NonNull MediaType mediaType){ - return equals(mediaType, OCTET); - } - - public static boolean isFORM(@NonNull MediaType mediaType){ - return equals(mediaType, FORM); - } - - public static boolean isXML(@NonNull MediaType mediaType){ - return equals(mediaType, XML); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/body/OctetStreamBody.java b/mhttp/src/main/java/im/wangchao/mhttp/body/OctetStreamBody.java deleted file mode 100644 index faf1c113..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/body/OctetStreamBody.java +++ /dev/null @@ -1,88 +0,0 @@ -package im.wangchao.mhttp.body; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.text.TextUtils; - -import java.io.IOException; -import java.io.InputStream; - -import okhttp3.MediaType; -import okhttp3.RequestBody; -import okhttp3.internal.Util; -import okio.Buffer; -import okio.BufferedSink; -import okio.Okio; -import okio.Source; - -/** - *

Description : OctetStreamBody.

- *

Author : wangchao.

- *

Date : 16/3/8.

- *

Time : 下午4:31.

- */ -public final class OctetStreamBody extends RequestBody{ - private final static MediaType CONTENT_TYPE = MediaTypeUtils.OCTET; - private final MediaType contentType; - private final InputStream stream; - private long contentLength = -1L; - private Buffer buffer; - - public OctetStreamBody(InputStream stream){ - this(stream, null); - } - - public OctetStreamBody(InputStream stream, String contentType){ - this.stream = stream; - this.contentType = TextUtils.isEmpty(contentType) ? CONTENT_TYPE : MediaType.parse(contentType); - } - - @Override public MediaType contentType() { - return contentType; - } - - @Override public long contentLength() throws IOException { - long result = contentLength; - if (result != -1L) return result; - return contentLength = writeOrCountBytes(null, true); - } - - @Override public void writeTo(@NonNull BufferedSink sink) throws IOException { - contentLength = writeOrCountBytes(sink, false); - } - - private long writeOrCountBytes(@Nullable BufferedSink sink, boolean countBytes) throws IOException{ - long byteCount = 0L; - - if (countBytes) { - buffer = new Buffer(); - Source source = null; - try { - source = Okio.source(stream); - buffer.writeAll(source); - } finally { - Util.closeQuietly(source); - } - - byteCount = buffer.size(); - - return byteCount; - } else { - if (sink == null){ - return byteCount; - } - Source source = null; - try { - source = Okio.source(buffer == null ? stream : buffer.inputStream()); - return sink.writeAll(source); - } finally { - if (buffer != null){ - buffer.clear(); - } - Util.closeQuietly(source); - } - } - - } - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/body/ProgressRequestBody.java b/mhttp/src/main/java/im/wangchao/mhttp/body/ProgressRequestBody.java deleted file mode 100644 index 2ea2b901..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/body/ProgressRequestBody.java +++ /dev/null @@ -1,70 +0,0 @@ -package im.wangchao.mhttp.body; - -import androidx.annotation.NonNull; - -import java.io.IOException; - -import im.wangchao.mhttp.AbsCallbackHandler; -import okhttp3.MediaType; -import okhttp3.RequestBody; -import okio.Buffer; -import okio.BufferedSink; -import okio.ForwardingSink; -import okio.Okio; -import okio.Sink; - -/** - *

Description : ProgressRequestBody.

- *

Author : wangchao.

- *

Date : 2018/1/30.

- *

Time : 下午8:25.

- */ -public class ProgressRequestBody extends RequestBody { - - private final RequestBody mRequestBody; - private final AbsCallbackHandler mCallback; - private BufferedSink mBufferedSink; - - public ProgressRequestBody(RequestBody requestBody, AbsCallbackHandler callback){ - this.mRequestBody = requestBody; - this.mCallback = callback; - } - - @Override public MediaType contentType() { - return mRequestBody.contentType(); - } - - @Override public long contentLength() throws IOException { - return mRequestBody.contentLength(); - } - - @Override public void writeTo(@NonNull BufferedSink sink) throws IOException { - if (mCallback == null){ - mRequestBody.writeTo(sink); - return; - } - if (mBufferedSink == null){ - mBufferedSink = Okio.buffer(forward(sink)); - } - - mRequestBody.writeTo(mBufferedSink); - mBufferedSink.flush(); - } - - private Sink forward(Sink sink){ - return new ForwardingSink(sink) { - private long bytesWritten = 0L; - private long contentLength = 0L; - - @Override public void write(@NonNull Buffer source, long byteCount) throws IOException { - super.write(source, byteCount); - if (contentLength == 0) { - contentLength = contentLength(); - } - bytesWritten += byteCount; - - mCallback.sendUploadProgressEvent((int) bytesWritten, (int) contentLength); - } - }; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/callback/BinaryCallbackHandler.java b/mhttp/src/main/java/im/wangchao/mhttp/callback/BinaryCallbackHandler.java deleted file mode 100644 index 05b763b9..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/callback/BinaryCallbackHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package im.wangchao.mhttp.callback; - -import im.wangchao.mhttp.AbsCallbackHandler; -import im.wangchao.mhttp.Accept; -import im.wangchao.mhttp.Response; - -/** - *

Description : BinaryResponseHandler.

- *

Author : wangchao.

- *

Date : 15/10/18.

- *

Time : 下午2:49.

- */ -public class BinaryCallbackHandler extends AbsCallbackHandler { - - @Override public void onSuccess(byte[] data, Response response) { - - } - - @Override public void onFailure(Response response, Throwable throwable) { - - } - - @Override public byte[] backgroundParser(Response response) throws Exception { - return response.raw().body().bytes(); - } - - @Override public String accept() { - return Accept.ACCEPT_DATA; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/callback/BitmapCallbackHandler.java b/mhttp/src/main/java/im/wangchao/mhttp/callback/BitmapCallbackHandler.java deleted file mode 100644 index 3193703f..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/callback/BitmapCallbackHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package im.wangchao.mhttp.callback; - -import android.graphics.Bitmap; - -import im.wangchao.mhttp.AbsCallbackHandler; -import im.wangchao.mhttp.Accept; -import im.wangchao.mhttp.Response; - -/** - *

Description : ImageResponseHandler.

- *

Author : wangchao.

- *

Date : 15/10/18.

- *

Time : 下午2:49.

- */ -public abstract class BitmapCallbackHandler extends AbsCallbackHandler { - @Override public void onSuccess(Bitmap bitmap, Response response) { - } - - @Override public void onFailure(Response response, Throwable throwable) { - - } - - @Override public String accept() { - return Accept.ACCEPT_IMAGE; - } - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/callback/CustomCallbackHandler.java b/mhttp/src/main/java/im/wangchao/mhttp/callback/CustomCallbackHandler.java deleted file mode 100644 index 537cb735..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/callback/CustomCallbackHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -package im.wangchao.mhttp.callback; - -import im.wangchao.mhttp.Response; -import im.wangchao.mhttp.internal.exception.ParserException; - -/** - *

Description : GSONResponseHandler.

- *

Author : wangchao.

- *

Date : 16/3/20.

- *

Time : 上午9:06.

- */ -public abstract class CustomCallbackHandler extends TextCallbackHandler { - - @Override final public void onSuccess(String data, Response response) { - if (data != null) { - onSuccess(parser(data)); - } - else { - onFailure(response, new ParserException()); - } - } - - @Override public void onFailure(Response response, Throwable throwable) { - - } - - /** parser Json to T */ - protected abstract T parser(String data); - - public void onSuccess(T t){ - - } - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/callback/FileCallbackHandler.java b/mhttp/src/main/java/im/wangchao/mhttp/callback/FileCallbackHandler.java deleted file mode 100644 index 796ec1cf..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/callback/FileCallbackHandler.java +++ /dev/null @@ -1,103 +0,0 @@ -package im.wangchao.mhttp.callback; - -import android.content.Context; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URLDecoder; - -import im.wangchao.mhttp.AbsCallbackHandler; -import im.wangchao.mhttp.Accept; -import im.wangchao.mhttp.Response; -import okhttp3.internal.Util; - -/** - *

Description : FileResponseHandler.

- *

Author : wangchao.

- *

Date : 15/10/18.

- *

Time : 下午2:39.

- */ -public class FileCallbackHandler extends AbsCallbackHandler { - private File file; - final private static int BUFFER_SIZE = 4096; - - public FileCallbackHandler(Context context){ - this.file = getTempFile(context); - } - - public FileCallbackHandler(File file){ - this.file = file; - } - - protected File getFile(){ - return file; - } - - @Override public void onSuccess(File file, Response response){ - - } - - @Override public void onFailure(Response response, Throwable throwable) { - - } - - @Override public File backgroundParser(Response response) throws IOException{ - writeFile(response.raw(), file); - return file; - } - - @Override public String accept() { - return Accept.ACCEPT_FILE; - } - - private File getTempFile(Context context){ - try { - return File.createTempFile("temp", "_handled", context.getCacheDir()); - } catch (IOException e) { - return null; - } - } - - /** - * write file , send progress message - */ - protected void writeFile(okhttp3.Response response, File file) throws IOException { - if (file == null){ - throw new IllegalArgumentException("File == null"); - } - if (this.file.isDirectory()) { - String contentDisposition = response.header("content-disposition"); - if (contentDisposition != null) { - if (contentDisposition.contains("*=UTF-8")) { - contentDisposition = contentDisposition.replace("*=UTF-8''", "\"") + "\""; - contentDisposition = URLDecoder.decode(contentDisposition, "UTF-8"); - } - String filename = contentDisposition.substring(contentDisposition.indexOf("\"") + 1, contentDisposition.lastIndexOf("\"")); - this.file = new File(file, filename); - file = this.file; - } - } - InputStream instream = response.body().byteStream(); - long contentLength = response.body().contentLength(); - FileOutputStream buffer = new FileOutputStream(file); - if (instream != null) { - try { - byte[] tmp = new byte[BUFFER_SIZE]; - int l; - long count = 0; - while ((l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) { - count += l; - buffer.write(tmp, 0, l); - - sendProgressEvent(count, contentLength); - } - } finally { - Util.closeQuietly(instream); - buffer.flush(); - Util.closeQuietly(buffer); - } - } - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/callback/JsonArrayCallbackHandler.java b/mhttp/src/main/java/im/wangchao/mhttp/callback/JsonArrayCallbackHandler.java deleted file mode 100644 index c417e097..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/callback/JsonArrayCallbackHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package im.wangchao.mhttp.callback; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import im.wangchao.mhttp.AbsCallbackHandler; -import im.wangchao.mhttp.Accept; -import im.wangchao.mhttp.Response; - -public class JsonArrayCallbackHandler extends AbsCallbackHandler { - - @Override public void onSuccess(JsonArray data, Response response) { - - } - - @Override public void onFailure(Response response, Throwable throwable) { - - } - - @Override public JsonArray backgroundParser(Response response) throws Exception { - try { - byte[] body = response.raw().body().bytes(); - String bodyString = byteArrayToString(body); - JsonArray object = new JsonParser().parse(bodyString).getAsJsonArray(); - return object; - } - catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - @Override public String accept() { - return Accept.ACCEPT_JSON; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/callback/JsonCallbackHandler.java b/mhttp/src/main/java/im/wangchao/mhttp/callback/JsonCallbackHandler.java deleted file mode 100644 index 2c16e9eb..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/callback/JsonCallbackHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -package im.wangchao.mhttp.callback; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import im.wangchao.mhttp.AbsCallbackHandler; -import im.wangchao.mhttp.Accept; -import im.wangchao.mhttp.Response; - -/** - *

Description : JSONResponseHandler.

- *

Author : wangchao.

- *

Date : 15/10/18.

- *

Time : 下午2:25.

- */ -public class JsonCallbackHandler extends AbsCallbackHandler { - - @Override public void onSuccess(JsonObject data, Response response) { - - } - - @Override public void onFailure(Response response, Throwable throwable) { - - } - - @Override public JsonObject backgroundParser(Response response) throws Exception { - try { - byte[] body = response.raw().body().bytes(); - String bodyString = byteArrayToString(body); - try { - return new JsonParser().parse(bodyString).getAsJsonObject(); - } - catch (Exception e) { - e.printStackTrace(); - response.parserErrorBody = bodyString; - return null; - } - } - catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - @Override public String accept() { - return Accept.ACCEPT_JSON; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/callback/TextCallbackHandler.java b/mhttp/src/main/java/im/wangchao/mhttp/callback/TextCallbackHandler.java deleted file mode 100644 index a7781c2e..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/callback/TextCallbackHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package im.wangchao.mhttp.callback; - -import im.wangchao.mhttp.AbsCallbackHandler; -import im.wangchao.mhttp.Accept; -import im.wangchao.mhttp.Response; - -/** - *

Description : TextResponseHandler.

- *

Author : wangchao.

- *

Date : 15/10/18.

- *

Time : 下午2:41.

- */ -public class TextCallbackHandler extends AbsCallbackHandler { - @Override public void onSuccess(String data, Response response) { - } - - @Override public void onFailure(Response response, Throwable throwable) { - } - - @Override public String backgroundParser(Response response) throws Exception { - return byteArrayToString(response.raw().body().bytes()); - } - - @Override public String accept() { - return Accept.ACCEPT_TEXT; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/executor/BACKGROUND.java b/mhttp/src/main/java/im/wangchao/mhttp/executor/BACKGROUND.java deleted file mode 100644 index 20eecd41..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/executor/BACKGROUND.java +++ /dev/null @@ -1,17 +0,0 @@ -package im.wangchao.mhttp.executor; - -import androidx.annotation.NonNull; - -import java.util.concurrent.Executor; - -/** - *

Description : BACKGROUND.

- *

Author : wangchao.

- *

Date : 16/9/2.

- *

Time : 下午4:50.

- */ -public final class BACKGROUND implements Executor { - @Override public void execute(@NonNull Runnable command) { - command.run(); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/executor/MAIN.java b/mhttp/src/main/java/im/wangchao/mhttp/executor/MAIN.java deleted file mode 100644 index 57785d2d..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/executor/MAIN.java +++ /dev/null @@ -1,21 +0,0 @@ -package im.wangchao.mhttp.executor; - -import android.os.Handler; -import android.os.Looper; -import androidx.annotation.NonNull; - -import java.util.concurrent.Executor; - -/** - *

Description : MainThread.

- *

Author : wangchao.

- *

Date : 16/9/2.

- *

Time : 下午4:45.

- */ -public final class MAIN implements Executor{ - private final Handler handler = new Handler(Looper.getMainLooper()); - - @Override public void execute(@NonNull Runnable command) { - handler.post(command); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/executor/SENDING.java b/mhttp/src/main/java/im/wangchao/mhttp/executor/SENDING.java deleted file mode 100644 index 5960bf4e..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/executor/SENDING.java +++ /dev/null @@ -1,27 +0,0 @@ -package im.wangchao.mhttp.executor; - -import android.os.Handler; -import android.os.Looper; -import androidx.annotation.NonNull; - -import java.util.concurrent.Executor; - -/** - *

Description : SENDING.

- *

Author : wangchao.

- *

Date : 16/9/2.

- *

Time : 下午4:47.

- */ -public final class SENDING implements Executor { - private final Handler handler; - public SENDING(){ - if (Looper.myLooper() == null){ - throw new RuntimeException("The Looper of the current thread is null, please call Looper.prepare() on your thread."); - } - handler = new Handler(Looper.myLooper()); - } - - @Override public void execute(@NonNull Runnable command) { - handler.post(command); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/Singleton.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/Singleton.java deleted file mode 100644 index 2a351d6f..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/Singleton.java +++ /dev/null @@ -1,25 +0,0 @@ -package im.wangchao.mhttp.internal; - -/** - *

Description : Singleton.

- *

Author : wangchao.

- *

Date : 16/8/25.

- *

Time : 上午10:37.

- */ -public abstract class Singleton { - private T instance; - - protected abstract T create(); - - public T get(){ - if (instance == null){ - synchronized (this){ - if (instance == null){ - instance = create(); - } - } - } - - return instance; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/Version.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/Version.java deleted file mode 100644 index 847fe87e..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/Version.java +++ /dev/null @@ -1,21 +0,0 @@ -package im.wangchao.mhttp.internal; - -/** - *

Description : Version.

- *

Author : wangchao.

- *

Date : 16/8/24.

- *

Time : 下午2:47.

- */ -public class Version { - private Version(){ - throw new AssertionError(); - } - - public static String userAgent() { - return moduleName().concat("1.10.1"); - } - - public static String moduleName() { - return "mhttp"; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/ClearableCookieJar.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/ClearableCookieJar.java deleted file mode 100644 index 61c6e2ae..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/ClearableCookieJar.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2016 Francisco José Montiel Navarro. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.wangchao.mhttp.internal.cookie; - -import okhttp3.CookieJar; - -public interface ClearableCookieJar extends CookieJar { - - void clear(); - void clearForDomain(String domain); -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/MemoryCookieJar.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/MemoryCookieJar.java deleted file mode 100644 index 34ff5235..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/MemoryCookieJar.java +++ /dev/null @@ -1,60 +0,0 @@ -package im.wangchao.mhttp.internal.cookie; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import im.wangchao.mhttp.internal.cookie.cache.CookieCache; -import okhttp3.Cookie; -import okhttp3.HttpUrl; - -/** - *

Description : MemeryCookieJar.

- *

Author : wangchao.

- *

Date : 16/3/18.

- *

Time : 下午2:20.

- */ -public class MemoryCookieJar implements ClearableCookieJar { - - private CookieCache cache; - - public MemoryCookieJar(CookieCache cache) { - this.cache = cache; - } - - @Override - synchronized public void saveFromResponse(HttpUrl url, List cookies) { - cache.addAll(cookies); - } - - @Override - synchronized public List loadForRequest(HttpUrl url) { - List validCookies = new ArrayList<>(); - - for (Iterator it = cache.iterator(); it.hasNext(); ) { - Cookie currentCookie = it.next(); - - if (isCookieExpired(currentCookie)) { - it.remove(); - - } else if (currentCookie.matches(url)) { - validCookies.add(currentCookie); - } - } - - - return validCookies; - } - - private static boolean isCookieExpired(Cookie cookie) { - return cookie.expiresAt() < System.currentTimeMillis(); - } - - synchronized public void clear() { - cache.clear(); - } - - synchronized public void clearForDomain(String domain) { - cache.clearForDomain(domain); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/PersistentCookieJar.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/PersistentCookieJar.java deleted file mode 100644 index 3a6b5a8c..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/PersistentCookieJar.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2016 Francisco José Montiel Navarro. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.wangchao.mhttp.internal.cookie; - - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import im.wangchao.mhttp.internal.cookie.cache.CookieCache; -import im.wangchao.mhttp.internal.cookie.persistence.CookiePersistor; -import okhttp3.Cookie; -import okhttp3.HttpUrl; - -public class PersistentCookieJar implements ClearableCookieJar { - - private CookieCache cache; - private CookiePersistor persistor; - - public PersistentCookieJar(CookieCache cache, CookiePersistor persistor) { - this.cache = cache; - this.persistor = persistor; - - this.cache.addAll(persistor.loadAll()); - } - - @Override - synchronized public void saveFromResponse(@Nullable HttpUrl url, List cookies) { - // cookies need to be reversed, in order to replace old cookies with these coming later - // (if there are duplicate cookies in the same response) - List reverseCookies = new ArrayList<>(cookies); - Collections.reverse(reverseCookies); - cache.addAll(reverseCookies); - persistor.saveAll(reverseCookies); - } - - @NonNull - @Override - synchronized public List loadForRequest(HttpUrl url) { - List removedCookies = new ArrayList<>(); - List validCookies = new ArrayList<>(); - - for (Iterator it = cache.iterator(); it.hasNext(); ) { - Cookie currentCookie = it.next(); - if (isCookieExpired(currentCookie)) { - removedCookies.add(currentCookie); - it.remove(); - - } else if (currentCookie.matches(url)) { - validCookies.add(currentCookie); - } - } - - persistor.removeAll(removedCookies); - - return validCookies; - } - - @NonNull - synchronized public List getForDomain(String domain) { - List removedCookies = new ArrayList<>(); - List validCookies = new ArrayList<>(); - - for (Iterator it = cache.iterator(); it.hasNext(); ) { - Cookie currentCookie = it.next(); - if (isCookieExpired(currentCookie)) { - removedCookies.add(currentCookie); - it.remove(); - - } else if (domain.equals(currentCookie.domain())) { - validCookies.add(currentCookie); - } - } - - persistor.removeAll(removedCookies); - - return validCookies; - } - - @Nullable - synchronized public String getCookie(String domain, String name) { - String cookieValue = null; - List removedCookies = new ArrayList<>(); - - for (Iterator it = cache.iterator(); it.hasNext(); ) { - Cookie currentCookie = it.next(); - if (isCookieExpired(currentCookie)) { - removedCookies.add(currentCookie); - it.remove(); - - } else if (domain.equals(currentCookie.domain()) && name.equals(currentCookie.name())) { - cookieValue = currentCookie.value(); - break; - } - } - - persistor.removeAll(removedCookies); - - return cookieValue; - } - - private static boolean isCookieExpired(Cookie cookie) { - return cookie.expiresAt() < System.currentTimeMillis(); - } - - synchronized public void clear() { - cache.clear(); - persistor.clear(); - } - - synchronized public void clearForDomain(String domain) { - cache.clearForDomain(domain); - persistor.clearForDomain(domain); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/CookieCache.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/CookieCache.java deleted file mode 100644 index 5b1de024..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/CookieCache.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2016 Francisco José Montiel Navarro. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.wangchao.mhttp.internal.cookie.cache; - -import java.util.Collection; - -import okhttp3.Cookie; - -public interface CookieCache extends Iterable { - - /** - * Add all the new cookies to the session, existing cookies will be overwritten. - * - * @param cookies - */ - void addAll(Collection cookies); - - /** - * Clear all the cookies from the session. - */ - void clear(); - - void clearForDomain(String domain); -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/IdentifiableCookie.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/IdentifiableCookie.java deleted file mode 100644 index e10d269b..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/IdentifiableCookie.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2016 Francisco José Montiel Navarro. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.wangchao.mhttp.internal.cookie.cache; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import okhttp3.Cookie; - -/** - * This class decorates a Cookie to re-implements equals() and hashcode() methods in order to identify - * the cookie by the following attributes: name, domain, path, secure & hostOnly.

- * - * This new behaviour will be useful in determining when an already existing cookie in session must be overwritten. - */ -class IdentifiableCookie { - - private Cookie cookie; - - static List decorateAll(Collection cookies) { - List identifiableCookies = new ArrayList<>(cookies.size()); - for (Cookie cookie : cookies) { - identifiableCookies.add(new IdentifiableCookie(cookie)); - } - return identifiableCookies; - } - - IdentifiableCookie(Cookie cookie) { - this.cookie = cookie; - } - - Cookie getCookie() { - return cookie; - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof IdentifiableCookie)) return false; - IdentifiableCookie that = (IdentifiableCookie) other; - return that.cookie.name().equals(this.cookie.name()) - && that.cookie.domain().equals(this.cookie.domain()) - && that.cookie.path().equals(this.cookie.path()) - && that.cookie.secure() == this.cookie.secure() - && that.cookie.hostOnly() == this.cookie.hostOnly(); - } - - @Override - public int hashCode() { - int hash = 17; - if (cookie == null) - return hash; - hash = 31 * hash + cookie.name().hashCode(); - hash = 31 * hash + cookie.domain().hashCode(); - hash = 31 * hash + cookie.path().hashCode(); - hash = 31 * hash + (cookie.secure() ? 0 : 1); - hash = 31 * hash + (cookie.hostOnly() ? 0 : 1); - return hash; - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/SetCookieCache.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/SetCookieCache.java deleted file mode 100644 index 136df502..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/cache/SetCookieCache.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2016 Francisco José Montiel Navarro. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.wangchao.mhttp.internal.cookie.cache; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import okhttp3.Cookie; - -public class SetCookieCache implements CookieCache { - - private Set cookies; - - public SetCookieCache() { - cookies = new HashSet<>(); - } - - @Override - public void addAll(Collection newCookies) { - updateCookies(IdentifiableCookie.decorateAll(newCookies)); - } - - /** - * All cookies will be added to the collection, already existing cookies will be overwritten by the new ones. - * - * @param cookies - */ - private void updateCookies(Collection cookies) { - this.cookies.removeAll(cookies); - this.cookies.addAll(cookies); - } - - @Override - public void clear() { - cookies.clear(); - } - - @Override - public void clearForDomain(String domain) { - Collection removeCookies = new ArrayList<>(); - for (IdentifiableCookie cookie: cookies) { - if (cookie.getCookie().domain().equals(domain)) { - removeCookies.add(cookie); - } - } - cookies.removeAll(removeCookies); - } - - @Override - public Iterator iterator() { - return new SetCookieCacheIterator(); - } - - private class SetCookieCacheIterator implements Iterator { - - private Iterator iterator; - - public SetCookieCacheIterator() { - iterator = cookies.iterator(); - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public Cookie next() { - return iterator.next().getCookie(); - } - - @Override - public void remove() { - iterator.remove(); - } - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/CookiePersistor.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/CookiePersistor.java deleted file mode 100644 index 1346c662..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/CookiePersistor.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2016 Francisco José Montiel Navarro. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.wangchao.mhttp.internal.cookie.persistence; - -import java.util.Collection; -import java.util.List; - -import okhttp3.Cookie; - -public interface CookiePersistor { - - List loadAll(); - - /** - * Persist all cookies, existing cookies will be overwritten. - * - * @param cookies cookies persist - */ - void saveAll(Collection cookies); - - /** - * Removes indicated cookies from persistence. - * - * @param cookies cookies to remove from persistence - */ - void removeAll(Collection cookies); - - /** - * Clear all cookies from persistence. - */ - void clear(); - - /** - * Clear all cookies from persistence for specified url. - * - * @param domain domain name - */ - void clearForDomain(String domain); - -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/SerializableCookie.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/SerializableCookie.java deleted file mode 100644 index bce2efe8..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/SerializableCookie.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2016 Francisco José Montiel Navarro. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.wangchao.mhttp.internal.cookie.persistence; - -import android.util.Log; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -import okhttp3.Cookie; - -public class SerializableCookie implements Serializable { - private static final String TAG = SerializableCookie.class - .getSimpleName(); - - private transient Cookie cookie; - - public String encode(Cookie cookie) { - this.cookie = cookie; - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - try { - ObjectOutputStream outputStream = new ObjectOutputStream(os); - outputStream.writeObject(this); - } catch (IOException e) { - Log.d(TAG, "IOException in encodeCookie", e); - return null; - } - - return byteArrayToHexString(os.toByteArray()); - } - - /** - * Using some super basic byte array <-> hex conversions so we don't - * have to rely on any large Base64 libraries. Can be overridden if you - * like! - * - * @param bytes byte array to be converted - * @return string containing hex values - */ - private static String byteArrayToHexString(byte[] bytes) { - StringBuilder sb = new StringBuilder(bytes.length * 2); - for (byte element : bytes) { - int v = element & 0xff; - if (v < 16) { - sb.append('0'); - } - sb.append(Integer.toHexString(v)); - } - return sb.toString(); - } - - public Cookie decode(String encodedCookie) { - byte[] bytes = hexStringToByteArray(encodedCookie); - ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( - bytes); - Cookie cookie = null; - try { - ObjectInputStream objectInputStream = new ObjectInputStream( - byteArrayInputStream); - cookie = ((SerializableCookie) objectInputStream.readObject()).cookie; - } catch (IOException e) { - Log.d(TAG, "IOException in decodeCookie", e); - } catch (ClassNotFoundException e) { - Log.d(TAG, "ClassNotFoundException in decodeCookie", e); - } - return cookie; - } - - /** - * Converts hex values from strings to byte array - * - * @param hexString string of hex-encoded values - * @return decoded byte array - */ - private static byte[] hexStringToByteArray(String hexString) { - int len = hexString.length(); - byte[] data = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character - .digit(hexString.charAt(i + 1), 16)); - } - return data; - } - - private static long NON_VALID_EXPIRES_AT = -1l; - - private void writeObject(ObjectOutputStream out) throws IOException { - out.writeObject(cookie.name()); - out.writeObject(cookie.value()); - out.writeLong(cookie.persistent() ? cookie.expiresAt() : NON_VALID_EXPIRES_AT); - out.writeObject(cookie.domain()); - out.writeObject(cookie.path()); - out.writeBoolean(cookie.secure()); - out.writeBoolean(cookie.httpOnly()); - out.writeBoolean(cookie.hostOnly()); - } - - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - Cookie.Builder builder = new Cookie.Builder(); - - builder.name((String) in.readObject()); - - builder.value((String) in.readObject()); - - long expiresAt = in.readLong(); - if (expiresAt != NON_VALID_EXPIRES_AT) { - builder.expiresAt(expiresAt); - } - - final String domain = (String) in.readObject(); - builder.domain(domain); - - builder.path((String) in.readObject()); - - if (in.readBoolean()) - builder.secure(); - - if (in.readBoolean()) - builder.httpOnly(); - - if (in.readBoolean()) - builder.hostOnlyDomain(domain); - - cookie = builder.build(); - } - -} \ No newline at end of file diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/SharedPrefsCookiePersistor.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/SharedPrefsCookiePersistor.java deleted file mode 100644 index b1f82a09..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/cookie/persistence/SharedPrefsCookiePersistor.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2016 Francisco José Montiel Navarro. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.wangchao.mhttp.internal.cookie.persistence; - -import android.content.Context; -import android.content.SharedPreferences; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import okhttp3.Cookie; - -public class SharedPrefsCookiePersistor implements CookiePersistor { - - private SharedPreferences sharedPreferences; - - public SharedPrefsCookiePersistor(Context context) { - final String SHARED_PREFERENCES_NAME = "cookies"; - - sharedPreferences = - context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - } - - @Override - public List loadAll() { - List cookies = new ArrayList<>(); - - for (Map.Entry entry : sharedPreferences.getAll().entrySet()) { - String serializedCookie = (String) entry.getValue(); - Cookie cookie = new SerializableCookie().decode(serializedCookie); - cookies.add(cookie); - } - return cookies; - } - - @Override - public void saveAll(Collection cookies) { - SharedPreferences.Editor editor = sharedPreferences.edit(); - for (Cookie cookie : cookies) { - if (cookie.persistent()) { - editor.putString(createCookieKey(cookie), new SerializableCookie().encode(cookie)); - } - } - editor.apply(); - } - - @Override - public void removeAll(Collection cookies) { - SharedPreferences.Editor editor = sharedPreferences.edit(); - for (Cookie cookie : cookies) { - editor.remove(createCookieKey(cookie)); - } - editor.apply(); - } - - private static String createCookieKey(Cookie cookie) { - return (cookie.secure() ? "https" : "http") + "://" + cookie.domain() + cookie.path() + "|" + cookie.name(); - } - - @Override - public void clear() { - sharedPreferences.edit().clear().apply(); - } - - @Override - public void clearForDomain(String domain) { - List cookies = loadAll(); - SharedPreferences.Editor editor = sharedPreferences.edit(); - for (Cookie cookie : cookies) { - if (cookie.domain().equals(domain)) - editor.remove(createCookieKey(cookie)); - } - editor.apply(); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/exception/ParserException.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/exception/ParserException.java deleted file mode 100644 index 2b12087a..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/exception/ParserException.java +++ /dev/null @@ -1,17 +0,0 @@ -package im.wangchao.mhttp.internal.exception; - -/** - *

Description : ParserException.

- *

Author : wangchao.

- *

Date : 16/4/26.

- *

Time : 下午8:38.

- */ -public class ParserException extends Exception{ - public ParserException(){ - super("Response parse exception."); - } - - public ParserException(Throwable cause) { - super("Response parse exception.", cause); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/exception/ResponseFailException.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/exception/ResponseFailException.java deleted file mode 100644 index bb985e37..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/exception/ResponseFailException.java +++ /dev/null @@ -1,14 +0,0 @@ -package im.wangchao.mhttp.internal.exception; - -/** - *

Description : ResponseFailException.

- *

Author : wangchao.

- *

Date : 16/4/25.

- *

Time : 下午4:06.

- */ -public class ResponseFailException extends Exception{ - //Response Non Successful - public ResponseFailException(){ - super("Response failure exception."); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/interceptor/HttpLoggingInterceptor.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/interceptor/HttpLoggingInterceptor.java deleted file mode 100644 index 0ba2658a..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/interceptor/HttpLoggingInterceptor.java +++ /dev/null @@ -1,320 +0,0 @@ -package im.wangchao.mhttp.internal.interceptor; - -/* - * Copyright (C) 2015 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.io.EOFException; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.concurrent.TimeUnit; - -import okhttp3.Connection; -import okhttp3.Headers; -import okhttp3.Interceptor; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.ResponseBody; -import okhttp3.internal.http.HttpHeaders; -import okhttp3.internal.platform.Platform; -import okio.Buffer; -import okio.BufferedSource; -import okio.GzipSource; - -import static okhttp3.internal.platform.Platform.INFO; - -/** - * An OkHttp interceptor which logs request and response information. Can be applied as an - * {@linkplain OkHttpClient#interceptors() application interceptor} or as a {@linkplain - * OkHttpClient#networkInterceptors() network interceptor}.

The format of the logs created by - * this class should not be considered stable and may change slightly between releases. If you need - * a stable logging format, use your own interceptor. - */ -public final class HttpLoggingInterceptor implements Interceptor { - private static final Charset UTF8 = Charset.forName("UTF-8"); - - public enum Level { - /** No logs. */ - NONE, - /** - * Logs request and response lines. - * - *

Example: - *

{@code
-         * --> POST /greeting http/1.1 (3-byte body)
-         *
-         * <-- 200 OK (22ms, 6-byte body)
-         * }
- */ - BASIC, - /** - * Logs request and response lines and their respective headers. - * - *

Example: - *

{@code
-         * --> POST /greeting http/1.1
-         * Host: example.com
-         * Content-Type: plain/text
-         * Content-Length: 3
-         * --> END POST
-         *
-         * <-- 200 OK (22ms)
-         * Content-Type: plain/text
-         * Content-Length: 6
-         * <-- END HTTP
-         * }
- */ - HEADERS, - /** - * Logs request and response lines and their respective headers and bodies (if present). - * - *

Example: - *

{@code
-         * --> POST /greeting http/1.1
-         * Host: example.com
-         * Content-Type: plain/text
-         * Content-Length: 3
-         *
-         * Hi?
-         * --> END POST
-         *
-         * <-- 200 OK (22ms)
-         * Content-Type: plain/text
-         * Content-Length: 6
-         *
-         * Hello!
-         * <-- END HTTP
-         * }
- */ - BODY - } - - public interface Logger { - void log(String message); - - /** A {@link Logger} defaults output appropriate for the current platform. */ - Logger DEFAULT = new Logger() { - @Override public void log(String message) { - Platform.get().log(INFO, message, null); - } - }; - } - - public HttpLoggingInterceptor() { - this(Logger.DEFAULT); - } - - public HttpLoggingInterceptor(Logger logger) { - this.logger = logger; - } - - private final Logger logger; - - private volatile Level level = Level.NONE; - - /** Change the level at which this interceptor logs. */ - public HttpLoggingInterceptor setLevel(Level level) { - if (level == null) throw new NullPointerException("level == null. Use Level.NONE instead."); - this.level = level; - return this; - } - - public Level getLevel() { - return level; - } - - @Override public Response intercept(Chain chain) throws IOException { - Level level = this.level; - - Request request = chain.request(); - if (level == Level.NONE) { - return chain.proceed(request); - } - - boolean logBody = level == Level.BODY; - boolean logHeaders = logBody || level == Level.HEADERS; - - RequestBody requestBody = request.body(); - boolean hasRequestBody = requestBody != null; - - Connection connection = chain.connection(); - String requestStartMessage = "--> " - + request.method() - + ' ' + request.url() - + (connection != null ? " " + connection.protocol() : ""); - if (!logHeaders && hasRequestBody) { - requestStartMessage += " (" + requestBody.contentLength() + "-byte body)"; - } - logger.log(requestStartMessage); - - if (logHeaders) { - if (hasRequestBody) { - // Request body headers are only present when installed as a network interceptor. Force - // them to be included (when available) so there values are known. - if (requestBody.contentType() != null) { - logger.log("Content-Type: " + requestBody.contentType()); - } - if (requestBody.contentLength() != -1) { - logger.log("Content-Length: " + requestBody.contentLength()); - } - } - - Headers headers = request.headers(); - for (int i = 0, count = headers.size(); i < count; i++) { - String name = headers.name(i); - // Skip headers from the request body as they are explicitly logged above. - if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) { - logger.log(name + ": " + headers.value(i)); - } - } - - if (!logBody || !hasRequestBody) { - logger.log("--> END " + request.method()); - } else if (bodyHasUnknownEncoding(request.headers())) { - logger.log("--> END " + request.method() + " (encoded body omitted)"); - } else { - Buffer buffer = new Buffer(); - requestBody.writeTo(buffer); - - Charset charset = UTF8; - MediaType contentType = requestBody.contentType(); - if (contentType != null) { - charset = contentType.charset(UTF8); - } - - logger.log(""); - if (isPlaintext(buffer)) { - logger.log(buffer.readString(charset)); - logger.log("--> END " + request.method() - + " (" + requestBody.contentLength() + "-byte body)"); - } else { - logger.log("--> END " + request.method() + " (binary " - + requestBody.contentLength() + "-byte body omitted)"); - } - } - } - - long startNs = System.nanoTime(); - Response response; - try { - response = chain.proceed(request); - } catch (Exception e) { - logger.log("<-- HTTP FAILED: " + e); - throw e; - } - long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); - - ResponseBody responseBody = response.body(); - long contentLength = responseBody.contentLength(); - String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length"; - logger.log("<-- " - + response.code() - + (response.message().isEmpty() ? "" : ' ' + response.message()) - + ' ' + response.request().url() - + " (" + tookMs + "ms" + (!logHeaders ? ", " + bodySize + " body" : "") + ')'); - - if (logHeaders) { - Headers headers = response.headers(); - for (int i = 0, count = headers.size(); i < count; i++) { - logger.log(headers.name(i) + ": " + headers.value(i)); - } - - if (!logBody || !HttpHeaders.hasBody(response)) { - logger.log("<-- END HTTP"); - } else if (bodyHasUnknownEncoding(response.headers())) { - logger.log("<-- END HTTP (encoded body omitted)"); - } else { - BufferedSource source = responseBody.source(); - source.request(Long.MAX_VALUE); // Buffer the entire body. - Buffer buffer = source.buffer(); - - Long gzippedLength = null; - if ("gzip".equalsIgnoreCase(headers.get("Content-Encoding"))) { - gzippedLength = buffer.size(); - GzipSource gzippedResponseBody = null; - try { - gzippedResponseBody = new GzipSource(buffer.clone()); - buffer = new Buffer(); - buffer.writeAll(gzippedResponseBody); - } finally { - if (gzippedResponseBody != null) { - gzippedResponseBody.close(); - } - } - } - - Charset charset = UTF8; - MediaType contentType = responseBody.contentType(); - if (contentType != null) { - charset = contentType.charset(UTF8); - } - - if (!isPlaintext(buffer)) { - logger.log(""); - logger.log("<-- END HTTP (binary " + buffer.size() + "-byte body omitted)"); - return response; - } - - if (contentLength != 0) { - logger.log(""); - logger.log(buffer.clone().readString(charset)); - } - - if (gzippedLength != null) { - logger.log("<-- END HTTP (" + buffer.size() + "-byte, " - + gzippedLength + "-gzipped-byte body)"); - } else { - logger.log("<-- END HTTP (" + buffer.size() + "-byte body)"); - } - } - } - - return response; - } - - /** - * Returns true if the body in question probably contains human readable text. Uses a small sample - * of code points to detect unicode control characters commonly used in binary file signatures. - */ - static boolean isPlaintext(Buffer buffer) { - try { - Buffer prefix = new Buffer(); - long byteCount = buffer.size() < 64 ? buffer.size() : 64; - buffer.copyTo(prefix, 0, byteCount); - for (int i = 0; i < 16; i++) { - if (prefix.exhausted()) { - break; - } - int codePoint = prefix.readUtf8CodePoint(); - if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { - return false; - } - } - return true; - } catch (EOFException e) { - return false; // Truncated UTF-8 sequence. - } - } - - private boolean bodyHasUnknownEncoding(Headers headers) { - String contentEncoding = headers.get("Content-Encoding"); - return contentEncoding != null - && !contentEncoding.equalsIgnoreCase("identity") - && !contentEncoding.equalsIgnoreCase("gzip"); - } -} \ No newline at end of file diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/interceptor/MBridgeInterceptor.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/interceptor/MBridgeInterceptor.java deleted file mode 100644 index cd354e97..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/interceptor/MBridgeInterceptor.java +++ /dev/null @@ -1,36 +0,0 @@ -package im.wangchao.mhttp.internal.interceptor; - -import java.io.IOException; - -import im.wangchao.mhttp.internal.Singleton; -import im.wangchao.mhttp.internal.Version; -import okhttp3.Interceptor; -import okhttp3.Request; -import okhttp3.Response; - -/** - *

Description : MBridgeInterceptors.

- *

Author : wangchao.

- *

Date : 16/8/24.

- *

Time : 下午4:32.

- */ -public final class MBridgeInterceptor implements Interceptor { - private MBridgeInterceptor(){} - - public static Singleton instance = new Singleton() { - @Override protected MBridgeInterceptor create() { - return new MBridgeInterceptor(); - } - }; - - @Override public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - Request.Builder builder = request.newBuilder(); - - if (request.header("User-Agent") == null) { - builder.header("User-Agent", Version.userAgent()); - } - - return chain.proceed(builder.build()); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/internal/log/LoggerImpl.java b/mhttp/src/main/java/im/wangchao/mhttp/internal/log/LoggerImpl.java deleted file mode 100644 index d54fe9ce..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/internal/log/LoggerImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package im.wangchao.mhttp.internal.log; - -import android.util.Log; - -import im.wangchao.mhttp.internal.Singleton; -import im.wangchao.mhttp.internal.Version; -import im.wangchao.mhttp.internal.interceptor.HttpLoggingInterceptor; - -/** - *

Description : Logger.

- *

Author : wangchao.

- *

Date : 2018/3/20.

- *

Time : 下午5:36.

- */ -public class LoggerImpl implements HttpLoggingInterceptor.Logger{ - private static final String TAG = Version.moduleName(); - private HttpLoggingInterceptor.Level mLevel; - - public static Singleton instance = new Singleton() { - @Override protected LoggerImpl create() { - return new LoggerImpl(); - } - }; - - public void setLevel(HttpLoggingInterceptor.Level level){ - mLevel = level; - } - - @Override public void log(String message) { - if (mLevel == HttpLoggingInterceptor.Level.NONE){ - return; - } - Log.e(TAG, message); - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/ResponseEnqueueObservable.java b/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/ResponseEnqueueObservable.java deleted file mode 100644 index b61ab6d4..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/ResponseEnqueueObservable.java +++ /dev/null @@ -1,133 +0,0 @@ -package im.wangchao.mhttp.rxjava2; - -import im.wangchao.mhttp.AbsCallbackHandler; -import im.wangchao.mhttp.Request; -import im.wangchao.mhttp.Response; -import io.reactivex.Observable; -import io.reactivex.Observer; -import io.reactivex.disposables.Disposable; -import io.reactivex.exceptions.CompositeException; -import io.reactivex.exceptions.Exceptions; -import io.reactivex.plugins.RxJavaPlugins; - -/** - *

Description : ResponseEnqueueObservable.

- *

Author : wangchao.

- *

Date : 2018/3/19.

- *

Time : 下午4:45.

- */ -public class ResponseEnqueueObservable extends Observable { - private final RxRequest request; - - public ResponseEnqueueObservable(RxRequest request){ - this.request = request; - } - - @Override protected void subscribeActual(Observer observer) { - - AbsCallbackHandler callback = request.callback(); - EnqueueDisposable disposable = new EnqueueDisposable<>(observer, callback); - - observer.onSubscribe(disposable); - request.request().newBuilder().callback(disposable).build().enqueue(); - } - - private static final class EnqueueDisposable extends AbsCallbackHandler implements Disposable{ - private final AbsCallbackHandler originCallback; - private final Observer observer; - private volatile boolean disposed; - boolean terminated = false; - - EnqueueDisposable(Observer observer, AbsCallbackHandler callbackHandler){ - this.observer = observer; - this.originCallback = callbackHandler; - } - - @Override public void dispose() { - disposed = true; - Request request = getRequest(); - request.cancel(); - } - - @Override public boolean isDisposed() { - return disposed; - } - - - @Override public String charset() { - return originCallback.charset(); - } - - @Override public String accept() { - return originCallback.accept(); - } - - @Override public void onStart() { - originCallback.onStart(); - } - - @Override public void onUploadProgress(int bytesWritten, int bytesTotal) { - originCallback.onUploadProgress(bytesWritten, bytesTotal); - } - - @Override public void onProgress(long bytesWritten, long bytesTotal) { - originCallback.onProgress(bytesWritten, bytesTotal); - } - - @Override public void onFinish() { - originCallback.onFinish(); - } - - @Override public void onCancel() { - originCallback.onCancel(); - if (!disposed){ - dispose(); - } - } - - @Override public T apply(Response response) throws Exception { - return originCallback.apply(response); - } - - @Override public void onSuccess(T data, Response response) { - if (disposed) return; - - try { - originCallback.onSuccess(data, response); - - observer.onNext(data); - - if (!disposed) { - terminated = true; - observer.onComplete(); - } - } catch (Throwable t) { - if (terminated) { - RxJavaPlugins.onError(t); - } else if (!disposed) { - try { - observer.onError(t); - } catch (Throwable inner) { - Exceptions.throwIfFatal(inner); - RxJavaPlugins.onError(new CompositeException(t, inner)); - } - } - } - } - - @Override public void onFailure(Response response, Throwable throwable) { - try { - originCallback.onFailure(response, throwable); - - observer.onError(throwable); - } catch (Throwable inner) { - Exceptions.throwIfFatal(inner); - RxJavaPlugins.onError(new CompositeException(throwable, inner)); - } - } - - @Override public void onFinally(Response response) { - originCallback.onFinally(response); - } - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/ResponseExecuteObservable.java b/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/ResponseExecuteObservable.java deleted file mode 100644 index e68dfd2b..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/ResponseExecuteObservable.java +++ /dev/null @@ -1,76 +0,0 @@ -package im.wangchao.mhttp.rxjava2; - -import im.wangchao.mhttp.Converter; -import im.wangchao.mhttp.Request; -import im.wangchao.mhttp.Response; -import io.reactivex.Observable; -import io.reactivex.Observer; -import io.reactivex.disposables.Disposable; -import io.reactivex.exceptions.CompositeException; -import io.reactivex.exceptions.Exceptions; -import io.reactivex.plugins.RxJavaPlugins; - -/** - *

Description : ResponseExecuteObservable.

- *

Author : wangchao.

- *

Date : 2018/3/19.

- *

Time : 下午4:46.

- */ -public class ResponseExecuteObservable extends Observable { - private final RxRequest request; - private final Converter converter; - - public ResponseExecuteObservable(RxRequest request, Converter converter){ - this.request = request; - this.converter = converter; - } - - @Override protected void subscribeActual(Observer observer) { - - ExecuteDisposable disposable = new ExecuteDisposable(request.request()); - observer.onSubscribe(disposable); - - boolean terminated = false; - try { - T response = converter.apply(request.request().execute()); - if (!disposable.isDisposed()) { - observer.onNext(response); - } - if (!disposable.isDisposed()) { - terminated = true; - observer.onComplete(); - } - } catch (Throwable t) { - Exceptions.throwIfFatal(t); - if (terminated) { - RxJavaPlugins.onError(t); - } else if (!disposable.isDisposed()) { - try { - observer.onError(t); - } catch (Throwable inner) { - Exceptions.throwIfFatal(inner); - RxJavaPlugins.onError(new CompositeException(t, inner)); - } - } - } - - } - - private static final class ExecuteDisposable implements Disposable { - private final Request request; - private volatile boolean disposed; - - ExecuteDisposable(Request request) { - this.request = request; - } - - @Override public void dispose() { - disposed = true; - request.cancel(); - } - - @Override public boolean isDisposed() { - return disposed; - } - } -} diff --git a/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/RxRequest.java b/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/RxRequest.java deleted file mode 100644 index ef648ea0..00000000 --- a/mhttp/src/main/java/im/wangchao/mhttp/rxjava2/RxRequest.java +++ /dev/null @@ -1,233 +0,0 @@ -package im.wangchao.mhttp.rxjava2; - -import androidx.annotation.NonNull; - -import java.io.File; -import java.io.InputStream; -import java.net.URL; -import java.util.concurrent.Executor; - -import im.wangchao.mhttp.AbsCallbackHandler; -import im.wangchao.mhttp.Converter; -import im.wangchao.mhttp.Method; -import im.wangchao.mhttp.Request; -import im.wangchao.mhttp.RequestParams; -import im.wangchao.mhttp.Response; -import im.wangchao.mhttp.ThreadMode; -import io.reactivex.Observable; -import okhttp3.CacheControl; -import okhttp3.Headers; -import okhttp3.HttpUrl; -import okhttp3.MediaType; - -/** - *

Description : RxRequest.

- *

Author : wangchao.

- *

Date : 2018/3/26.

- *

Time : 下午5:40.

- */ -public class RxRequest { - public static RxRequest.Builder builder(){ - return new RxRequest.Builder<>(); - } - - private Request request; - private AbsCallbackHandler callback; - - private RxRequest(Builder builder){ - request = builder.request; - callback = builder.callback; - } - - public Request request(){ - return request; - } - - public AbsCallbackHandler callback(){ - return callback; - } - - public RxRequest.Builder newBuilder() { - return new Builder<>(this); - } - - public Observable execute(Converter converter){ - return new ResponseExecuteObservable<>(this, converter); - } - - public Observable enqueue(){ - return new ResponseEnqueueObservable<>(this); - } - - public static final class Builder { - - Request request; - Request.Builder requestBuilder; - AbsCallbackHandler callback; - - public Builder() { - requestBuilder = new Request.Builder(); - callback = new AbsCallbackHandler() { - @Override public void onSuccess(T data, Response response) { - - } - - @Override public void onFailure(Response response, Throwable throwable) { - - } - }; - } - - private Builder(RxRequest request) { - requestBuilder = request.request.newBuilder(); - callback = request.callback; - } - - public Builder url(HttpUrl url) { - requestBuilder.url(url); - return this; - } - - public Builder url(String url) { - requestBuilder.url(url); - return this; - } - - public Builder url(URL url) { - requestBuilder.url(url); - return this; - } - - public Builder header(String name, String value) { - requestBuilder.header(name, value); - return this; - } - - public Builder addHeader(String name, String value) { - requestBuilder.header(name, value); - return this; - } - - public Builder removeHeader(String name) { - requestBuilder.removeHeader(name); - return this; - } - - public Builder headers(Headers headers) { - requestBuilder.headers(headers); - return this; - } - - public Builder cacheControl(CacheControl cacheControl) { - requestBuilder.cacheControl(cacheControl); - return this; - } - - public Builder get() { - return method(Method.GET); - } - - public Builder head() { - return method(Method.HEAD); - } - - public Builder post() { - return method(Method.POST); - } - - public Builder delete() { - return method(Method.DELETE); - } - - public Builder put() { - return method(Method.PUT); - } - - public Builder patch() { - return method(Method.PATCH); - } - - /** - * Simple to add request parameter - */ - public Builder addParameter(String key, Object value){ - requestBuilder.addParameter(key, value); - return this; - } - - /** - * Simple to add request parameter - */ - public Builder addParameter(String key, InputStream stream, String name){ - requestBuilder.addParameter(key, stream, name); - return this; - } - - /** - * Simple to add request parameter - */ - public Builder addParameter(String key, InputStream stream, String name, String contentType){ - requestBuilder.addParameter(key, stream, name, contentType); - return this; - } - - /** - * Simple to add request parameter - */ - public Builder addParameter(String key, File file, String contentType) { - requestBuilder.addParameter(key, file, contentType); - return this; - } - - public Builder requestParams(RequestParams params) { - requestBuilder.requestParams(params); - return this; - } - - public Builder method(@NonNull String method) { - requestBuilder.method(method); - return this; - } - - public Builder tag(Object tag) { - requestBuilder.tag(tag); - return this; - } - - public Builder callback(@NonNull AbsCallbackHandler callback){ - this.callback = callback; - return this; - } - - public Builder callbackExecutor(Executor executor){ - requestBuilder.callbackExecutor(executor); - return this; - } - - public Builder callbackThreadMode(ThreadMode threadMode){ - requestBuilder.callbackThreadMode(threadMode); - return this; - } - - public Builder userAgent(String ua){ - requestBuilder.userAgent(ua); - return this; - } - - public Builder contentType(@NonNull String contentType){ - requestBuilder.contentType(contentType); - return this; - } - - public Builder contentType(@NonNull MediaType mediaType){ - requestBuilder.contentType(mediaType); - return this; - } - - public RxRequest build() { - request = requestBuilder.build(); - - return new RxRequest<>(this); - } - } -} diff --git a/settings.gradle b/settings.gradle index f2de53d8..b47390e3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,7 +3,7 @@ include ':wear' include ':codegen' include ':annotation' rootProject.name='Szkolny.eu' -include ':app', ':agendacalendarview', ':mhttp', ':szkolny-font' +include ':app', ':agendacalendarview', ':szkolny-font' /* include ':Navigation' project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/ From d78dad509036b397b404805ca6c42b1e09526dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 20 Mar 2021 23:41:59 +0100 Subject: [PATCH 05/15] [Gradle] Extract agendacalendarview dependency. --- agendacalendarview/.gitignore | 1 - agendacalendarview/build.gradle | 54 --- .../src/main/AndroidManifest.xml | 3 - .../AgendaCalendarView.java | 264 -------------- .../agendacalendarview/CalendarManager.java | 267 -------------- .../CalendarPickerController.java | 14 - .../agenda/AgendaAdapter.java | 105 ------ .../agenda/AgendaEventView.java | 38 -- .../agenda/AgendaHeaderView.java | 81 ---- .../agenda/AgendaListView.java | 54 --- .../agendacalendarview/agenda/AgendaView.java | 145 -------- .../calendar/CalendarView.java | 279 -------------- .../calendar/weekslist/WeekListView.java | 144 -------- .../calendar/weekslist/WeeksAdapter.java | 321 ---------------- .../models/BaseCalendarEvent.java | 345 ------------------ .../models/CalendarEvent.java | 63 ---- .../agendacalendarview/models/DayItem.java | 145 -------- .../agendacalendarview/models/IDayItem.java | 49 --- .../agendacalendarview/models/IWeekItem.java | 34 -- .../agendacalendarview/models/WeekItem.java | 110 ------ .../render/DefaultEventRenderer.java | 82 ----- .../render/EventRenderer.java | 23 -- .../agendacalendarview/utils/BusProvider.java | 36 -- .../agendacalendarview/utils/DateHelper.java | 135 ------- .../agendacalendarview/utils/Events.java | 43 --- .../utils/ListViewScrollTracker.java | 114 ------ .../widgets/FloatingActionButton.java | 110 ------ .../main/res/drawable/agenda_day_circle.xml | 9 - .../main/res/drawable/event_color_circle.xml | 5 - .../src/main/res/drawable/fab_arrow.xml | 7 - .../drawable/selected_day_color_circle.xml | 8 - .../src/main/res/drawable/shadow.xml | 8 - .../src/main/res/layout/list_item_week.xml | 48 --- .../src/main/res/layout/view_agenda.xml | 23 -- .../src/main/res/layout/view_agenda_event.xml | 53 --- .../main/res/layout/view_agenda_header.xml | 64 ---- .../main/res/layout/view_agendacalendar.xml | 24 -- .../src/main/res/layout/view_calendar.xml | 48 --- .../res/layout/view_day_calendar_header.xml | 9 - .../src/main/res/layout/view_day_cell.xml | 85 ----- .../src/main/res/values-en/strings.xml | 12 - .../src/main/res/values/attrs.xml | 13 - .../src/main/res/values/colors.xml | 21 -- .../src/main/res/values/dimens.xml | 19 - .../src/main/res/values/strings.xml | 14 - .../src/main/res/values/styles.xml | 25 -- app/build.gradle | 4 +- settings.gradle | 2 +- 48 files changed, 2 insertions(+), 3558 deletions(-) delete mode 100644 agendacalendarview/.gitignore delete mode 100644 agendacalendarview/build.gradle delete mode 100644 agendacalendarview/src/main/AndroidManifest.xml delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/AgendaCalendarView.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/CalendarManager.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/CalendarPickerController.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaAdapter.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaEventView.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaHeaderView.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaListView.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaView.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/CalendarView.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/weekslist/WeekListView.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/weekslist/WeeksAdapter.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/BaseCalendarEvent.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/CalendarEvent.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/DayItem.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/IDayItem.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/IWeekItem.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/WeekItem.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/render/DefaultEventRenderer.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/render/EventRenderer.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/BusProvider.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/DateHelper.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/Events.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/ListViewScrollTracker.java delete mode 100644 agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/widgets/FloatingActionButton.java delete mode 100644 agendacalendarview/src/main/res/drawable/agenda_day_circle.xml delete mode 100644 agendacalendarview/src/main/res/drawable/event_color_circle.xml delete mode 100644 agendacalendarview/src/main/res/drawable/fab_arrow.xml delete mode 100644 agendacalendarview/src/main/res/drawable/selected_day_color_circle.xml delete mode 100644 agendacalendarview/src/main/res/drawable/shadow.xml delete mode 100644 agendacalendarview/src/main/res/layout/list_item_week.xml delete mode 100644 agendacalendarview/src/main/res/layout/view_agenda.xml delete mode 100644 agendacalendarview/src/main/res/layout/view_agenda_event.xml delete mode 100644 agendacalendarview/src/main/res/layout/view_agenda_header.xml delete mode 100644 agendacalendarview/src/main/res/layout/view_agendacalendar.xml delete mode 100644 agendacalendarview/src/main/res/layout/view_calendar.xml delete mode 100644 agendacalendarview/src/main/res/layout/view_day_calendar_header.xml delete mode 100644 agendacalendarview/src/main/res/layout/view_day_cell.xml delete mode 100644 agendacalendarview/src/main/res/values-en/strings.xml delete mode 100644 agendacalendarview/src/main/res/values/attrs.xml delete mode 100644 agendacalendarview/src/main/res/values/colors.xml delete mode 100644 agendacalendarview/src/main/res/values/dimens.xml delete mode 100644 agendacalendarview/src/main/res/values/strings.xml delete mode 100644 agendacalendarview/src/main/res/values/styles.xml diff --git a/agendacalendarview/.gitignore b/agendacalendarview/.gitignore deleted file mode 100644 index 796b96d1..00000000 --- a/agendacalendarview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/agendacalendarview/build.gradle b/agendacalendarview/build.gradle deleted file mode 100644 index 92731fb9..00000000 --- a/agendacalendarview/build.gradle +++ /dev/null @@ -1,54 +0,0 @@ -apply plugin: 'com.android.library' -//apply plugin: 'me.tatarka.retrolambda' - -android { - compileSdkVersion setup.compileSdk - - android { - lintOptions { - abortOnError false - } - } - - defaultConfig { - minSdkVersion 14 - targetSdkVersion setup.targetSdk - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - debugMinify { - debuggable = true - minifyEnabled = true - proguardFiles 'proguard-android.txt' - } - } - sourceSets { - main { - assets.srcDirs = ['assets'] - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } -} - -//apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - // Google libraries - implementation "androidx.appcompat:appcompat:${versions.appcompat}" - implementation "androidx.recyclerview:recyclerview:${versions.recyclerView}" - implementation "com.google.android.material:material:${versions.material}" - - // other libraries - //implementation 'se.emilsjolander:stickylistheaders:2.7.0' - implementation 'com.github.edisonw:StickyListHeaders:master-SNAPSHOT@aar' - implementation 'io.reactivex:rxjava:1.1.1' -} diff --git a/agendacalendarview/src/main/AndroidManifest.xml b/agendacalendarview/src/main/AndroidManifest.xml deleted file mode 100644 index 38e54711..00000000 --- a/agendacalendarview/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/AgendaCalendarView.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/AgendaCalendarView.java deleted file mode 100644 index 0d0c0cf4..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/AgendaCalendarView.java +++ /dev/null @@ -1,264 +0,0 @@ -package com.github.tibolte.agendacalendarview; - -import android.animation.Animator; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.os.Handler; -import androidx.annotation.NonNull; -import android.util.AttributeSet; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.github.tibolte.agendacalendarview.agenda.AgendaAdapter; -import com.github.tibolte.agendacalendarview.agenda.AgendaView; -import com.github.tibolte.agendacalendarview.calendar.CalendarView; -import com.github.tibolte.agendacalendarview.models.BaseCalendarEvent; -import com.github.tibolte.agendacalendarview.models.CalendarEvent; -import com.github.tibolte.agendacalendarview.models.DayItem; -import com.github.tibolte.agendacalendarview.models.IDayItem; -import com.github.tibolte.agendacalendarview.models.IWeekItem; -import com.github.tibolte.agendacalendarview.models.WeekItem; -import com.github.tibolte.agendacalendarview.render.DefaultEventRenderer; -import com.github.tibolte.agendacalendarview.render.EventRenderer; -import com.github.tibolte.agendacalendarview.utils.BusProvider; -import com.github.tibolte.agendacalendarview.utils.Events; -import com.github.tibolte.agendacalendarview.utils.ListViewScrollTracker; -import com.github.tibolte.agendacalendarview.widgets.FloatingActionButton; - -import java.util.Calendar; -import java.util.List; -import java.util.Locale; - -import se.emilsjolander.stickylistheaders.StickyListHeadersListView; - -/** - * View holding the agenda and calendar view together. - */ -public class AgendaCalendarView extends FrameLayout implements StickyListHeadersListView.OnStickyHeaderChangedListener { - - private static final String LOG_TAG = AgendaCalendarView.class.getSimpleName(); - - private CalendarView mCalendarView; - private AgendaView mAgendaView; - private FloatingActionButton mFloatingActionButton; - - private int mAgendaCurrentDayTextColor, mCalendarHeaderColor, mCalendarHeaderTextColor, mCalendarBackgroundColor, mCalendarDayTextColor, mCalendarPastDayTextColor, mCalendarCurrentDayColor, mFabColor; - private CalendarPickerController mCalendarPickerController; - - public AgendaView getAgendaView() { - return mAgendaView; - } - - private ListViewScrollTracker mAgendaListViewScrollTracker; - private AbsListView.OnScrollListener mAgendaScrollListener = new AbsListView.OnScrollListener() { - int mCurrentAngle; - int mMaxAngle = 85; - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - int scrollY = mAgendaListViewScrollTracker.calculateScrollY(firstVisibleItem, visibleItemCount); - if (scrollY != 0) { - mFloatingActionButton.show(); - } - //Log.d(LOG_TAG, String.format("Agenda listView scrollY: %d", scrollY)); - /*int toAngle = scrollY / 100; - if (toAngle > mMaxAngle) { - toAngle = mMaxAngle; - } else if (toAngle < -mMaxAngle) { - toAngle = -mMaxAngle; - } - RotateAnimation rotate = new RotateAnimation(mCurrentAngle, toAngle, mFloatingActionButton.getWidth() / 2, mFloatingActionButton.getHeight() / 2); - rotate.setFillAfter(true); - mCurrentAngle = toAngle; - mFloatingActionButton.startAnimation(rotate);*/ - } - }; - - // region Constructors - - public AgendaCalendarView(Context context) { - super(context); - } - - public AgendaCalendarView(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ColorOptionsView, 0, 0); - mAgendaCurrentDayTextColor = a.getColor(R.styleable.ColorOptionsView_agendaCurrentDayTextColor, getResources().getColor(R.color.theme_primary)); - mCalendarHeaderColor = a.getColor(R.styleable.ColorOptionsView_calendarHeaderColor, getResources().getColor(R.color.theme_primary_dark)); - mCalendarHeaderTextColor = a.getColor(R.styleable.ColorOptionsView_calendarHeaderTextColor, getResources().getColor(R.color.theme_text_icons)); - mCalendarBackgroundColor = a.getColor(R.styleable.ColorOptionsView_calendarColor, getResources().getColor(R.color.theme_primary)); - mCalendarDayTextColor = a.getColor(R.styleable.ColorOptionsView_calendarDayTextColor, getResources().getColor(R.color.theme_text_icons)); - mCalendarCurrentDayColor = a.getColor(R.styleable.ColorOptionsView_calendarCurrentDayTextColor, getResources().getColor(R.color.calendar_text_current_day)); - mCalendarPastDayTextColor = a.getColor(R.styleable.ColorOptionsView_calendarPastDayTextColor, getResources().getColor(R.color.theme_light_primary)); - mFabColor = a.getColor(R.styleable.ColorOptionsView_fabColor, getResources().getColor(R.color.theme_accent)); - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(R.layout.view_agendacalendar, this, true); - - setAlpha(0f); - } - - // endregion - - // region Class - View - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mCalendarView = (CalendarView) findViewById(R.id.calendar_view); - mAgendaView = (AgendaView) findViewById(R.id.agenda_view); - mFloatingActionButton = (FloatingActionButton) findViewById(R.id.floating_action_button); - ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{mFabColor}); - mFloatingActionButton.setBackgroundTintList(csl); - - LinearLayout mDayNamesHeader = mCalendarView.findViewById(R.id.cal_day_names); - mDayNamesHeader.setBackgroundColor(mCalendarHeaderColor); - for (int i = 0; i < mDayNamesHeader.getChildCount(); i++) { - TextView txtDay = (TextView) mDayNamesHeader.getChildAt(i); - txtDay.setTextColor(mCalendarHeaderTextColor); - } - mCalendarView.findViewById(R.id.list_week).setBackgroundColor(mCalendarBackgroundColor); - - mAgendaView.getAgendaListView().setOnItemClickListener((AdapterView parent, View view, int position, long id) -> { - mCalendarPickerController.onEventSelected(CalendarManager.getInstance().getEvents().get(position)); - }); - - BusProvider.getInstance().toObserverable() - .subscribe(event -> { - if (event instanceof Events.DayClickedEvent) { - if (mCalendarPickerController != null) - mCalendarPickerController.onDaySelected(((Events.DayClickedEvent) event).getDay()); - } else if (event instanceof Events.EventsFetched) { - ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), 1f).setDuration(500); - alphaAnimation.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - - } - - @Override - public void onAnimationEnd(Animator animation) { - long fabAnimationDelay = 500; - // Just after setting the alpha from this view to 1, we hide the fab. - // It will reappear as soon as the user is scrolling the Agenda view. - new Handler().postDelayed(() -> { - mFloatingActionButton.hide(); - mAgendaListViewScrollTracker = new ListViewScrollTracker(mAgendaView.getAgendaListView()); - mAgendaView.getAgendaListView().setOnScrollListener(mAgendaScrollListener); - mFloatingActionButton.setOnClickListener((v) -> { - mAgendaView.translateList(0); - mAgendaView.getAgendaListView().smoothScrollBy(0, 0); - //mAgendaView.getAgendaListView().getWrappedList().smoothScrollBy(0, 0); - mAgendaView.getAgendaListView().scrollToCurrentDate(CalendarManager.getInstance().getToday()); - new Handler().postDelayed(() -> mFloatingActionButton.hide(), fabAnimationDelay); - }); - }, fabAnimationDelay); - } - - @Override - public void onAnimationCancel(Animator animation) { - - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - alphaAnimation.start(); - } - }); - } - - // endregion - - // region Interface - StickyListHeadersListView.OnStickyHeaderChangedListener - - @Override - public void onStickyHeaderChanged(StickyListHeadersListView stickyListHeadersListView, View header, int position, long headerId) { - //Log.d(LOG_TAG, String.format("onStickyHeaderChanged, position = %d, headerId = %d", position, headerId)); - - if (CalendarManager.getInstance().getEvents().size() > 0) { - CalendarEvent event = CalendarManager.getInstance().getEvents().get(position); - if (event != null) { - mCalendarView.scrollToDate(event); - mCalendarPickerController.onScrollToDate(event.getInstanceDay()); - } - } - } - - // endregion - - // region Public methods - - public void init(List eventList, Calendar minDate, Calendar maxDate, Locale locale, CalendarPickerController calendarPickerController, EventRenderer ... renderers) { - mCalendarPickerController = calendarPickerController; - - CalendarManager.getInstance(getContext()).buildCal(minDate, maxDate, locale, new DayItem(), new WeekItem()); - - // Feed our views with weeks list and events - mCalendarView.init(CalendarManager.getInstance(getContext()), mCalendarDayTextColor, mCalendarCurrentDayColor, mCalendarPastDayTextColor, eventList); - - // Load agenda events and scroll to current day - AgendaAdapter agendaAdapter = new AgendaAdapter(mAgendaCurrentDayTextColor); - mAgendaView.getAgendaListView().setAdapter(agendaAdapter); - mAgendaView.getAgendaListView().setOnStickyHeaderChangedListener(this); - - CalendarManager.getInstance().loadEvents(eventList, new BaseCalendarEvent()); - BusProvider.getInstance().send(new Events.EventsFetched()); - Log.d(LOG_TAG, "CalendarEventTask finished, event count "+eventList.size()); - - // add default event renderer - addEventRenderer(new DefaultEventRenderer()); - for (EventRenderer renderer: renderers) { - addEventRenderer(renderer); - } - } - - public void init(Locale locale, List lWeeks, List lDays, List lEvents, CalendarPickerController calendarPickerController) { - mCalendarPickerController = calendarPickerController; - - CalendarManager.getInstance(getContext()).loadCal(locale, lWeeks, lDays, lEvents); - - // Feed our views with weeks list and events - mCalendarView.init(CalendarManager.getInstance(getContext()), mCalendarDayTextColor, mCalendarCurrentDayColor, mCalendarPastDayTextColor, lEvents); - - // Load agenda events and scroll to current day - AgendaAdapter agendaAdapter = new AgendaAdapter(mAgendaCurrentDayTextColor); - mAgendaView.getAgendaListView().setAdapter(agendaAdapter); - mAgendaView.getAgendaListView().setOnStickyHeaderChangedListener(this); - - // notify that actually everything is loaded - BusProvider.getInstance().send(new Events.EventsFetched()); - Log.d(LOG_TAG, "CalendarEventTask finished"); - - // add default event renderer - addEventRenderer(new DefaultEventRenderer()); - } - - public void addEventRenderer(@NonNull final EventRenderer renderer) { - AgendaAdapter adapter = (AgendaAdapter) mAgendaView.getAgendaListView().getAdapter(); - adapter.addEventRenderer(renderer); - } - - public void enableFloatingIndicator(boolean enable) { - mFloatingActionButton.setVisibility(enable ? VISIBLE : GONE); - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/CalendarManager.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/CalendarManager.java deleted file mode 100644 index c661d32b..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/CalendarManager.java +++ /dev/null @@ -1,267 +0,0 @@ -package com.github.tibolte.agendacalendarview; - -import com.github.tibolte.agendacalendarview.models.CalendarEvent; -import com.github.tibolte.agendacalendarview.models.IDayItem; -import com.github.tibolte.agendacalendarview.models.IWeekItem; -import com.github.tibolte.agendacalendarview.utils.DateHelper; - -import android.content.Context; -import android.util.Log; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -/** - * This class manages information about the calendar. (Events, weather info...) - * Holds reference to the days list of the calendar. - * As the app is using several views, we want to keep everything in one place. - */ -public class CalendarManager { - - private static final String LOG_TAG = CalendarManager.class.getSimpleName(); - - private static CalendarManager mInstance; - - private Context mContext; - private Locale mLocale; - private Calendar mToday = Calendar.getInstance(); - private SimpleDateFormat mWeekdayFormatter; - private SimpleDateFormat mMonthHalfNameFormat; - - /// instances of classes provided from outside - private IDayItem mCleanDay; - private IWeekItem mCleanWeek; - - /** - * List of days used by the calendar - */ - private List mDays = new ArrayList<>(); - /** - * List of weeks used by the calendar - */ - private List mWeeks = new ArrayList<>(); - /** - * List of events instances - */ - private List mEvents = new ArrayList<>(); - - // region Constructors - - public CalendarManager(Context context) { - this.mContext = context; - } - - public static CalendarManager getInstance(Context context) { - if (mInstance == null) { - mInstance = new CalendarManager(context); - } - return mInstance; - } - - public static CalendarManager getInstance() { - return mInstance; - } - - // endregion - - // region Getters/Setters - - public Locale getLocale() { - return mLocale; - } - - public Context getContext() { - return mContext; - } - - public Calendar getToday() { - return mToday; - } - - public void setToday(Calendar today) { - this.mToday = today; - } - - public List getWeeks() { - return mWeeks; - } - - public List getEvents() { - return mEvents; - } - - public List getDays() { - return mDays; - } - - public SimpleDateFormat getWeekdayFormatter() { - return mWeekdayFormatter; - } - - public SimpleDateFormat getMonthHalfNameFormat() { - return mMonthHalfNameFormat; - } - - // endregion - - // region Public methods - - public void buildCal(Calendar minDate, Calendar maxDate, Locale locale, IDayItem cleanDay, IWeekItem cleanWeek) { - if (minDate == null || maxDate == null) { - throw new IllegalArgumentException( - "minDate and maxDate must be non-null."); - } - if (minDate.after(maxDate)) { - throw new IllegalArgumentException( - "minDate must be before maxDate."); - } - if (locale == null) { - throw new IllegalArgumentException("Locale is null."); - } - - setLocale(locale); - - mDays.clear(); - mWeeks.clear(); - mEvents.clear(); - - mCleanDay = cleanDay; - mCleanWeek = cleanWeek; - - Calendar mMinCal = Calendar.getInstance(mLocale); - Calendar mMaxCal = Calendar.getInstance(mLocale); - Calendar mWeekCounter = Calendar.getInstance(mLocale); - - mMinCal.setTime(minDate.getTime()); - mMaxCal.setTime(maxDate.getTime()); - - // maxDate is exclusive, here we bump back to the previous day, as maxDate if December 1st, 2020, - // we don't include that month in our list - mMaxCal.add(Calendar.MINUTE, -1); - - // Now iterate we iterate between mMinCal and mMaxCal so we build our list of weeks - mWeekCounter.setTime(mMinCal.getTime()); - int maxMonth = mMaxCal.get(Calendar.MONTH); - int maxYear = mMaxCal.get(Calendar.YEAR); - - int currentMonth = mWeekCounter.get(Calendar.MONTH); - int currentYear = mWeekCounter.get(Calendar.YEAR); - - // Loop through the weeks - while ((currentMonth <= maxMonth // Up to, including the month. - || currentYear < maxYear) // Up to the year. - && currentYear < maxYear + 1) { // But not > next yr. - - Date date = mWeekCounter.getTime(); - // Build our week list - int currentWeekOfYear = mWeekCounter.get(Calendar.WEEK_OF_YEAR); - - IWeekItem weekItem = cleanWeek.copy(); - weekItem.setWeekInYear(currentWeekOfYear); - weekItem.setYear(currentYear); - weekItem.setDate(date); - weekItem.setMonth(currentMonth); - weekItem.setLabel(mMonthHalfNameFormat.format(date)); - List dayItems = getDayCells(mWeekCounter); // gather days for the built week - weekItem.setDayItems(dayItems); - mWeeks.add(weekItem); - - //Log.d(LOG_TAG, String.format("Adding week: %s", weekItem)); - - mWeekCounter.add(Calendar.WEEK_OF_YEAR, 1); - - currentMonth = mWeekCounter.get(Calendar.MONTH); - currentYear = mWeekCounter.get(Calendar.YEAR); - } - } - - public void loadEvents(List eventList, CalendarEvent noEvent) { - - for (IWeekItem weekItem : getWeeks()) { - for (IDayItem dayItem : weekItem.getDayItems()) { - boolean isEventForDay = false; - boolean isShowBadgeForDay = false; - for (CalendarEvent event : eventList) { - if (DateHelper.isBetweenInclusive(dayItem.getDate(), event.getStartTime(), event.getEndTime())) { - CalendarEvent copy = event.copy(); - - if (copy.getShowBadge()) { - isShowBadgeForDay = true; - } - - Calendar dayInstance = Calendar.getInstance(); - dayInstance.setTime(dayItem.getDate()); - copy.setInstanceDay(dayInstance); - copy.setDayReference(dayItem); - copy.setWeekReference(weekItem); - // add instances in chronological order - getEvents().add(copy); - isEventForDay = true; - } - } - if (!isEventForDay) { - Calendar dayInstance = Calendar.getInstance(); - dayInstance.setTime(dayItem.getDate()); - CalendarEvent copy = noEvent.copy(); - - copy.setInstanceDay(dayInstance); - copy.setDayReference(dayItem); - copy.setWeekReference(weekItem); - copy.setLocation(""); - copy.setTitle(getContext().getResources().getString(R.string.agenda_event_no_events)); - copy.setPlaceholder(true); - getEvents().add(copy); - } - dayItem.setShowBadge(isShowBadgeForDay); - } - } - } - - public void loadCal (Locale locale, List lWeeks, List lDays, List lEvents) { - mWeeks = lWeeks; - mDays = lDays; - mEvents = lEvents; - setLocale(locale); - } - - // endregion - - // region Private methods - - private List getDayCells(Calendar startCal) { - Calendar cal = Calendar.getInstance(mLocale); - cal.setTime(startCal.getTime()); - List dayItems = new ArrayList<>(); - - int firstDayOfWeek = cal.get(Calendar.DAY_OF_WEEK); - int offset = cal.getFirstDayOfWeek() - firstDayOfWeek; - if (offset > 0) { - offset -= 7; - } - cal.add(Calendar.DATE, offset); - - //Log.d(LOG_TAG, String.format("Buiding row week starting at %s", cal.getTime())); - for (int c = 0; c < 7; c++) { - IDayItem dayItem = mCleanDay.copy(); - dayItem.buildDayItemFromCal(cal); - dayItems.add(dayItem); - cal.add(Calendar.DATE, 1); - } - - mDays.addAll(dayItems); - return dayItems; - } - - private void setLocale(Locale locale) { - this.mLocale = locale; - setToday(Calendar.getInstance(mLocale)); - mWeekdayFormatter = new SimpleDateFormat(getContext().getString(R.string.day_name_format), mLocale); - mMonthHalfNameFormat = new SimpleDateFormat(getContext().getString(R.string.month_half_name_format), locale); - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/CalendarPickerController.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/CalendarPickerController.java deleted file mode 100644 index a2a86dde..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/CalendarPickerController.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.github.tibolte.agendacalendarview; - -import com.github.tibolte.agendacalendarview.models.CalendarEvent; -import com.github.tibolte.agendacalendarview.models.IDayItem; - -import java.util.Calendar; - -public interface CalendarPickerController { - void onDaySelected(IDayItem dayItem); - - void onEventSelected(CalendarEvent event); - - void onScrollToDate(Calendar calendar); -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaAdapter.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaAdapter.java deleted file mode 100644 index 2e6c6d31..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaAdapter.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.github.tibolte.agendacalendarview.agenda; - -import com.github.tibolte.agendacalendarview.models.CalendarEvent; -import com.github.tibolte.agendacalendarview.render.DefaultEventRenderer; -import com.github.tibolte.agendacalendarview.render.EventRenderer; - -import androidx.annotation.NonNull; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import java.util.ArrayList; -import java.util.List; - -import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; - -/** - * Adapter for the agenda, implements StickyListHeadersAdapter. - * Days as sections and CalendarEvents as list items. - */ -public class AgendaAdapter extends BaseAdapter implements StickyListHeadersAdapter { - - private List mEvents = new ArrayList<>(); - private List> mRenderers = new ArrayList<>(); - private int mCurrentDayColor; - - // region Constructor - - public AgendaAdapter(int currentDayTextColor) { - this.mCurrentDayColor = currentDayTextColor; - } - - // endregion - - // region Public methods - - public void updateEvents(List events) { - this.mEvents.clear(); - this.mEvents.addAll(events); - notifyDataSetChanged(); - } - - // endregion - - // region Interface - StickyListHeadersAdapter - - @Override - public View getHeaderView(int position, View convertView, ViewGroup parent) { - AgendaHeaderView agendaHeaderView = (AgendaHeaderView) convertView; - if (agendaHeaderView == null) { - agendaHeaderView = AgendaHeaderView.inflate(parent); - } - agendaHeaderView.setDay(getItem(position).getInstanceDay(), mCurrentDayColor, getItem(position).getDayReference().getShowBadge()); - return agendaHeaderView; - } - - @Override - public long getHeaderId(int position) { - return mEvents.get(position).getInstanceDay().getTimeInMillis(); - } - - // endregion - - // region Class - BaseAdapter - - @Override - public int getCount() { - return mEvents.size(); - } - - @Override - public CalendarEvent getItem(int position) { - return mEvents.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - EventRenderer eventRenderer = new DefaultEventRenderer(); - final CalendarEvent event = getItem(position); - - // Search for the correct event renderer - for (EventRenderer renderer : mRenderers) { - if(event.getClass().isAssignableFrom(renderer.getRenderType())) { - eventRenderer = renderer; - break; - } - } - convertView = LayoutInflater.from(parent.getContext()) - .inflate(eventRenderer.getEventLayout(), parent, false); - eventRenderer.render(convertView, event); - return convertView; - } - - public void addEventRenderer(@NonNull final EventRenderer renderer) { - mRenderers.add(renderer); - } - - // endregion -} \ No newline at end of file diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaEventView.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaEventView.java deleted file mode 100644 index 198f65cd..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaEventView.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.github.tibolte.agendacalendarview.agenda; - -import com.github.tibolte.agendacalendarview.R; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -/** - * List item view for the StickyHeaderListView of the agenda view - */ -public class AgendaEventView extends LinearLayout { - public static AgendaEventView inflate(ViewGroup parent) { - return (AgendaEventView) LayoutInflater.from(parent.getContext()).inflate(R.layout.view_agenda_event, parent, false); - } - - // region Constructors - - public AgendaEventView(Context context) { - this(context, null); - } - - public AgendaEventView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public AgendaEventView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - setPadding(getResources().getDimensionPixelSize(R.dimen.agenda_event_view_padding_left), - getResources().getDimensionPixelSize(R.dimen.agenda_event_view_padding_top), - getResources().getDimensionPixelSize(R.dimen.agenda_event_view_padding_right), - getResources().getDimensionPixelSize(R.dimen.agenda_event_view_padding_bottom)); - } - - // endregion -} \ No newline at end of file diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaHeaderView.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaHeaderView.java deleted file mode 100644 index 36b16ddb..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaHeaderView.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.github.tibolte.agendacalendarview.agenda; - -import com.github.tibolte.agendacalendarview.CalendarManager; -import com.github.tibolte.agendacalendarview.R; -import com.github.tibolte.agendacalendarview.utils.DateHelper; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.drawable.GradientDrawable; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.text.SimpleDateFormat; -import java.util.Calendar; - -/** - * Header view for the StickyHeaderListView of the agenda view - */ -public class AgendaHeaderView extends LinearLayout { - - public static AgendaHeaderView inflate(ViewGroup parent) { - return (AgendaHeaderView) LayoutInflater.from(parent.getContext()).inflate(R.layout.view_agenda_header, parent, false); - } - - // region Constructors - - public AgendaHeaderView(Context context) { - super(context); - } - - public AgendaHeaderView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public AgendaHeaderView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - // endregion - - // region Public methods - - public void setDay(Calendar day, int currentDayTextColor, boolean showBadge) { - TextView txtDayOfMonth = (TextView) findViewById(R.id.view_agenda_day_of_month); - TextView txtDayOfWeek = (TextView) findViewById(R.id.view_agenda_day_of_week); - TextView txtDay = (TextView) findViewById(R.id.view_agenda_day_text); - View circleView = findViewById(R.id.view_day_circle_selected); - - Calendar today = CalendarManager.getInstance().getToday(); - - SimpleDateFormat dayWeekFormatter = new SimpleDateFormat(getContext().getString(R.string.day_name_format), CalendarManager.getInstance().getLocale()); - SimpleDateFormat dayWeekLongFormatter = new SimpleDateFormat("EEEE", CalendarManager.getInstance().getLocale()); - - txtDayOfMonth.setTextColor(getResources().getColor(R.color.calendar_text_default)); - txtDayOfWeek.setTextColor(getResources().getColor(R.color.calendar_text_default)); - - if (DateHelper.sameDate(day, today)) { - txtDayOfMonth.setTextColor(currentDayTextColor); - circleView.setVisibility(VISIBLE); - GradientDrawable drawable = (GradientDrawable) circleView.getBackground(); - drawable.setStroke((int) (2 * Resources.getSystem().getDisplayMetrics().density), currentDayTextColor); - } else if (showBadge) { - circleView.setVisibility(VISIBLE); - GradientDrawable drawable = (GradientDrawable) circleView.getBackground(); - drawable.setStroke((int) (2 * Resources.getSystem().getDisplayMetrics().density), 0xffff0000); - } - else { - circleView.setVisibility(INVISIBLE); - } - - txtDayOfMonth.setText(String.valueOf(day.get(Calendar.DAY_OF_MONTH))); - txtDayOfWeek.setText(dayWeekFormatter.format(day.getTime())); - //txtDay.setText(dayWeekLongFormatter.format(day.getTime())); - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaListView.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaListView.java deleted file mode 100644 index 235b04c6..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaListView.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.github.tibolte.agendacalendarview.agenda; - -import com.github.tibolte.agendacalendarview.CalendarManager; -import com.github.tibolte.agendacalendarview.models.CalendarEvent; -import com.github.tibolte.agendacalendarview.utils.DateHelper; - -import android.content.Context; -import android.util.AttributeSet; - -import java.util.Calendar; -import java.util.List; - -import se.emilsjolander.stickylistheaders.StickyListHeadersListView; - -/** - * StickyListHeadersListView to scroll chronologically through events. - */ -public class AgendaListView extends StickyListHeadersListView { - - // region Constructors - - public AgendaListView(Context context) { - super(context); - } - - public AgendaListView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public AgendaListView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - // endregion - - // region Public methods - - public void scrollToCurrentDate(Calendar today) { - List events = CalendarManager.getInstance().getEvents(); - - int toIndex = 0; - for (int i = 0; i < events.size(); i++) { - if (DateHelper.sameDate(today, events.get(i).getInstanceDay())) { - toIndex = i; - break; - } - } - - final int finalToIndex = toIndex; - post(()->setSelection(finalToIndex)); - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaView.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaView.java deleted file mode 100644 index 80b317da..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/agenda/AgendaView.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.github.tibolte.agendacalendarview.agenda; - -import android.animation.Animator; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.FrameLayout; - -import com.github.tibolte.agendacalendarview.CalendarManager; -import com.github.tibolte.agendacalendarview.R; -import com.github.tibolte.agendacalendarview.utils.BusProvider; -import com.github.tibolte.agendacalendarview.utils.Events; - -public class AgendaView extends FrameLayout { - - private AgendaListView mAgendaListView; - private View mShadowView; - - // region Constructors - - public AgendaView(Context context) { - super(context); - } - - public AgendaView(Context context, AttributeSet attrs) { - super(context, attrs); - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(R.layout.view_agenda, this, true); - } - - // endregion - - // region Class - View - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - mAgendaListView = (AgendaListView) findViewById(R.id.agenda_listview); - mShadowView = findViewById(R.id.view_shadow); - - BusProvider.getInstance().toObserverable() - .subscribe(event -> { - if (event instanceof Events.DayClickedEvent) { - Events.DayClickedEvent clickedEvent = (Events.DayClickedEvent) event; - getAgendaListView().scrollToCurrentDate(clickedEvent.getCalendar()); - } else if (event instanceof Events.CalendarScrolledEvent) { - int offset = (int) (3 * getResources().getDimension(R.dimen.day_cell_height)); - translateList(offset); - } else if (event instanceof Events.EventsFetched) { - if (getAgendaListView().getAdapter() != null) - ((AgendaAdapter) getAgendaListView().getAdapter()).updateEvents(CalendarManager.getInstance().getEvents()); - - getViewTreeObserver().addOnGlobalLayoutListener( - new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (getWidth() != 0 && getHeight() != 0) { - // display only two visible rows on the calendar view - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams(); - int height = getHeight(); - int margin = (int) (getContext().getResources().getDimension(R.dimen.calendar_header_height) + 2 * getContext().getResources().getDimension(R.dimen.day_cell_height)); - layoutParams.height = height; - layoutParams.setMargins(0, margin, 0, 0); - setLayoutParams(layoutParams); - - getAgendaListView().scrollToCurrentDate(CalendarManager.getInstance().getToday()); - - getViewTreeObserver().removeGlobalOnLayoutListener(this); - } - } - } - - ); - } else if (event instanceof Events.ForecastFetched) { - ((AgendaAdapter) getAgendaListView().getAdapter()).updateEvents(CalendarManager.getInstance().getEvents()); - } - }); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - int eventaction = event.getAction(); - - switch (eventaction) { - case MotionEvent.ACTION_DOWN: - // if the user touches the listView, we put it back to the top - translateList(0); - break; - default: - break; - } - - return super.dispatchTouchEvent(event); - } - - // endregion - - // region Public methods - - public AgendaListView getAgendaListView() { - return mAgendaListView; - } - - public void translateList(int targetY) { - if (targetY != getTranslationY()) { - ObjectAnimator mover = ObjectAnimator.ofFloat(this, "translationY", targetY); - mover.setDuration(150); - mover.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - //mShadowView.setVisibility(GONE); - } - - @Override - public void onAnimationEnd(Animator animation) { - if (targetY == 0) { - BusProvider.getInstance().send(new Events.AgendaListViewTouchedEvent()); - } - //mShadowView.setVisibility(VISIBLE); - } - - @Override - public void onAnimationCancel(Animator animation) { - - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - mover.start(); - } - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/CalendarView.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/CalendarView.java deleted file mode 100644 index 67d7490c..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/CalendarView.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.github.tibolte.agendacalendarview.calendar; - -import com.github.tibolte.agendacalendarview.CalendarManager; -import com.github.tibolte.agendacalendarview.R; -import com.github.tibolte.agendacalendarview.calendar.weekslist.WeekListView; -import com.github.tibolte.agendacalendarview.calendar.weekslist.WeeksAdapter; -import com.github.tibolte.agendacalendarview.models.CalendarEvent; -import com.github.tibolte.agendacalendarview.models.IDayItem; -import com.github.tibolte.agendacalendarview.models.IWeekItem; -import com.github.tibolte.agendacalendarview.utils.BusProvider; -import com.github.tibolte.agendacalendarview.utils.DateHelper; -import com.github.tibolte.agendacalendarview.utils.Events; - -import android.content.Context; -import androidx.recyclerview.widget.LinearLayoutManager; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.List; -import java.util.Locale; - -/** - * The calendar view is a freely scrolling view that allows the user to browse between days of the - * year. - */ -public class CalendarView extends LinearLayout { - - private static final String LOG_TAG = CalendarView.class.getSimpleName(); - - /** - * Top of the calendar view layout, the week days list - */ - private LinearLayout mDayNamesHeader; - /** - * Part of the calendar view layout always visible, the weeks list - */ - private WeekListView mListViewWeeks; - /** - * The adapter for the weeks list - */ - private WeeksAdapter mWeeksAdapter; - /** - * The current highlighted day in blue - */ - private IDayItem mSelectedDay; - /** - * The current row displayed at top of the list - */ - private int mCurrentListPosition; - - // region Constructors - - public CalendarView(Context context) { - super(context); - } - - public CalendarView(Context context, AttributeSet attrs) { - super(context, attrs); - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(R.layout.view_calendar, this, true); - - setOrientation(VERTICAL); - } - - // endregion - - public IDayItem getSelectedDay() { - return mSelectedDay; - } - - public void setSelectedDay(IDayItem mSelectedDay) { - this.mSelectedDay = mSelectedDay; - } - - public WeekListView getListViewWeeks() { - return mListViewWeeks; - } - - // region Class - View - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - mDayNamesHeader = (LinearLayout) findViewById(R.id.cal_day_names); - mListViewWeeks = (WeekListView) findViewById(R.id.list_week); - mListViewWeeks.setLayoutManager(new LinearLayoutManager(getContext())); - mListViewWeeks.setHasFixedSize(true); - mListViewWeeks.setItemAnimator(null); - mListViewWeeks.setSnapEnabled(true); - - // display only two visible rows on the calendar view - getViewTreeObserver().addOnGlobalLayoutListener( - new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (getWidth() != 0 && getHeight() != 0) { - collapseCalendarView(); - getViewTreeObserver().removeGlobalOnLayoutListener(this); - } - } - } - ); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - BusProvider.getInstance().toObserverable() - .subscribe(event -> { - if (event instanceof Events.CalendarScrolledEvent) { - expandCalendarView(); - } else if (event instanceof Events.AgendaListViewTouchedEvent) { - collapseCalendarView(); - } else if (event instanceof Events.DayClickedEvent) { - Events.DayClickedEvent clickedEvent = (Events.DayClickedEvent) event; - updateSelectedDay(clickedEvent.getCalendar(), clickedEvent.getDay()); - } - }); - } - - // endregion - - // region Public methods - - public void init(CalendarManager calendarManager, int dayTextColor, int currentDayTextColor, int pastDayTextColor, List eventList) { - Calendar today = calendarManager.getToday(); - Locale locale = calendarManager.getLocale(); - SimpleDateFormat weekDayFormatter = calendarManager.getWeekdayFormatter(); - List weeks = calendarManager.getWeeks(); - - setUpHeader(today, weekDayFormatter, locale); - setUpAdapter(today, weeks, dayTextColor, currentDayTextColor, pastDayTextColor, eventList); - scrollToDate(today, weeks); - } - - /** - * Fired when the Agenda list view changes section. - * - * @param calendarEvent The event for the selected position in the agenda listview. - */ - public void scrollToDate(final CalendarEvent calendarEvent) { - mListViewWeeks.post(()->scrollToPosition(updateSelectedDay(calendarEvent.getInstanceDay(), calendarEvent.getDayReference()))); - } - - public void scrollToDate(Calendar today, List weeks) { - Integer currentWeekIndex = null; - - for (int c = 0; c < weeks.size(); c++) { - if (DateHelper.sameWeek(today, weeks.get(c))) { - currentWeekIndex = c; - break; - } - } - - if (currentWeekIndex != null) { - final Integer finalCurrentWeekIndex = currentWeekIndex; - mListViewWeeks.post(() -> scrollToPosition(finalCurrentWeekIndex)); - } - } - - public void setBackgroundColor(int color) { - mListViewWeeks.setBackgroundColor(color); - } - - // endregion - - // region Private methods - - private void scrollToPosition(int targetPosition) { - LinearLayoutManager layoutManager = ((LinearLayoutManager) mListViewWeeks.getLayoutManager()); - layoutManager.scrollToPosition(targetPosition); - } - - private void updateItemAtPosition(int position) { - WeeksAdapter weeksAdapter = (WeeksAdapter) mListViewWeeks.getAdapter(); - weeksAdapter.notifyItemChanged(position); - } - - /** - * Creates a new adapter if necessary and sets up its parameters. - */ - private void setUpAdapter(Calendar today, List weeks, int dayTextColor, int currentDayTextColor, int pastDayTextColor, List events) { - BusProvider.getInstance().toObserverable() - .subscribe(event -> { - if (event instanceof Events.EventsFetched) { - //Log.d("CalendarView", "events size "+events.size()); - if (mWeeksAdapter == null) { - //Log.d(LOG_TAG, "Setting adapter with today's calendar: " + today.toString()); - mWeeksAdapter = new WeeksAdapter(getContext(), today, dayTextColor, currentDayTextColor, pastDayTextColor, events); - mListViewWeeks.setAdapter(mWeeksAdapter); - } - mWeeksAdapter.updateWeeksItems(weeks); - }}); - - } - - private void setUpHeader(Calendar today, SimpleDateFormat weekDayFormatter, Locale locale) { - int daysPerWeek = 7; - String[] dayLabels = new String[daysPerWeek]; - Calendar cal = Calendar.getInstance(CalendarManager.getInstance(getContext()).getLocale()); - cal.setTime(today.getTime()); - int firstDayOfWeek = cal.getFirstDayOfWeek(); - for (int count = 0; count < 7; count++) { - cal.set(Calendar.DAY_OF_WEEK, firstDayOfWeek + count); - if (locale.getLanguage().equals("en")) { - dayLabels[count] = weekDayFormatter.format(cal.getTime()).toUpperCase(locale); - } else { - dayLabels[count] = weekDayFormatter.format(cal.getTime()); - } - } - - for (int i = 0; i < mDayNamesHeader.getChildCount(); i++) { - TextView txtDay = (TextView) mDayNamesHeader.getChildAt(i); - txtDay.setText(dayLabels[i]); - } - } - - private void expandCalendarView() { - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams(); - layoutParams.height = (int) (getResources().getDimension(R.dimen.calendar_header_height) + 5 * getResources().getDimension(R.dimen.day_cell_height)); - setLayoutParams(layoutParams); - } - - private void collapseCalendarView() { - ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams(); - layoutParams.height = (int) (getResources().getDimension(R.dimen.calendar_header_height) + 2 * getResources().getDimension(R.dimen.day_cell_height)); - setLayoutParams(layoutParams); - } - - /** - * Update a selected cell day item. - * - * @param calendar The Calendar instance of the day selected. - * @param dayItem The DayItem information held by the cell item. - * @return The selected row of the weeks list, to be updated. - */ - private int updateSelectedDay(Calendar calendar, IDayItem dayItem) { - Integer currentWeekIndex = null; - - // update highlighted/selected day - if (!dayItem.equals(getSelectedDay())) { - dayItem.setSelected(true); - if (getSelectedDay() != null) { - getSelectedDay().setSelected(false); - } - setSelectedDay(dayItem); - } - - for (int c = 0; c < CalendarManager.getInstance().getWeeks().size(); c++) { - if (DateHelper.sameWeek(calendar, CalendarManager.getInstance().getWeeks().get(c))) { - currentWeekIndex = c; - break; - } - } - - if (currentWeekIndex != null) { - // highlighted day has changed, update the rows concerned - if (currentWeekIndex != mCurrentListPosition) { - updateItemAtPosition(mCurrentListPosition); - } - mCurrentListPosition = currentWeekIndex; - updateItemAtPosition(currentWeekIndex); - } - - return mCurrentListPosition; - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/weekslist/WeekListView.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/weekslist/WeekListView.java deleted file mode 100644 index 099bc6eb..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/weekslist/WeekListView.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.github.tibolte.agendacalendarview.calendar.weekslist; - -import com.github.tibolte.agendacalendarview.utils.BusProvider; -import com.github.tibolte.agendacalendarview.utils.Events; - -import android.content.Context; -import androidx.recyclerview.widget.RecyclerView; -import android.util.AttributeSet; -import android.view.View; - -public class WeekListView extends RecyclerView { - private boolean mUserScrolling = false; - private boolean mScrolling = false; - - // region Constructors - - public WeekListView(Context context) { - super(context); - } - - public WeekListView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public WeekListView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - // endregion - - // region Public methods - - /** - * Enable snapping behaviour for this recyclerView - * - * @param enabled enable or disable the snapping behaviour - */ - public void setSnapEnabled(boolean enabled) { - if (enabled) { - addOnScrollListener(mScrollListener); - } else { - removeOnScrollListener(mScrollListener); - } - } - - // endregion - - // region Private methods - - private OnScrollListener mScrollListener = new OnScrollListener() { - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - } - - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - final WeeksAdapter weeksAdapter = (WeeksAdapter) getAdapter(); - - switch (newState) { - case SCROLL_STATE_IDLE: - if (mUserScrolling) { - scrollToView(getCenterView()); - postDelayed(() -> weeksAdapter.setDragging(false), 700); // Wait for recyclerView to settle - } - - mUserScrolling = false; - mScrolling = false; - break; - // If scroll is caused by a touch (scroll touch, not any touch) - case SCROLL_STATE_DRAGGING: - BusProvider.getInstance().send(new Events.CalendarScrolledEvent()); - // If scroll was initiated already, this is not a user scrolling, but probably a tap, else set userScrolling - if (!mScrolling) { - mUserScrolling = true; - } - weeksAdapter.setDragging(true); - break; - case SCROLL_STATE_SETTLING: - // The user's finger is not touching the list anymore, no need - // for any alpha animation then - weeksAdapter.setAlphaSet(true); - mScrolling = true; - break; - } - } - }; - - private View getChildClosestToPosition(int y) { - if (getChildCount() <= 0) { - return null; - } - - int itemHeight = getChildAt(0).getMeasuredHeight(); - - int closestY = 9999; - View closestChild = null; - - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - - int childCenterY = ((int) child.getY() + (itemHeight / 2)); - int yDistance = childCenterY - y; - - // If child center is closer than previous closest, set it as closest - if (Math.abs(yDistance) < Math.abs(closestY)) { - closestY = yDistance; - closestChild = child; - } - } - - return closestChild; - } - - private View getCenterView() { - return getChildClosestToPosition(getMeasuredHeight() / 2); - } - - private void scrollToView(View child) { - if (child == null) { - return; - } - - stopScroll(); - - int scrollDistance = getScrollDistance(child); - - if (scrollDistance != 0) { - smoothScrollBy(0, scrollDistance); - } - } - - private int getScrollDistance(View child) { - int itemHeight = getChildAt(0).getMeasuredHeight(); - int centerY = getMeasuredHeight() / 2; - - int childCenterY = ((int) child.getY() + (itemHeight / 2)); - - return childCenterY - centerY; - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/weekslist/WeeksAdapter.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/weekslist/WeeksAdapter.java deleted file mode 100644 index df2177df..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/calendar/weekslist/WeeksAdapter.java +++ /dev/null @@ -1,321 +0,0 @@ -package com.github.tibolte.agendacalendarview.calendar.weekslist; - -import com.github.tibolte.agendacalendarview.CalendarManager; -import com.github.tibolte.agendacalendarview.R; -import com.github.tibolte.agendacalendarview.models.CalendarEvent; -import com.github.tibolte.agendacalendarview.models.IDayItem; -import com.github.tibolte.agendacalendarview.models.IWeekItem; -import com.github.tibolte.agendacalendarview.utils.BusProvider; -import com.github.tibolte.agendacalendarview.utils.DateHelper; -import com.github.tibolte.agendacalendarview.utils.Events; - -import android.animation.Animator; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.graphics.Typeface; -import android.graphics.drawable.GradientDrawable; - -import androidx.recyclerview.widget.RecyclerView; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -public class WeeksAdapter extends RecyclerView.Adapter { - - public static final long FADE_DURATION = 250; - - private Context mContext; - private Calendar mToday; - private List mWeeksList = new ArrayList<>(); - private List mEventList = new ArrayList<>(); - private boolean mDragging; - private boolean mAlphaSet; - private int mDayTextColor, mPastDayTextColor, mCurrentDayColor; - - // region Constructor - - public WeeksAdapter(Context context, Calendar today, int dayTextColor, int currentDayTextColor, int pastDayTextColor, List events) { - this.mToday = today; - this.mContext = context; - this.mDayTextColor = dayTextColor; - this.mCurrentDayColor = currentDayTextColor; - this.mPastDayTextColor = pastDayTextColor; - this.mEventList = events; - } - - // endregion - - public void updateWeeksItems(List weekItems) { - this.mWeeksList.clear(); - this.mWeeksList.addAll(weekItems); - notifyDataSetChanged(); - } - - // region Getters/setters - - public List getWeeksList() { - return mWeeksList; - } - - public boolean isDragging() { - return mDragging; - } - - public void setDragging(boolean dragging) { - if (dragging != this.mDragging) { - this.mDragging = dragging; - notifyItemRangeChanged(0, mWeeksList.size()); - } - } - - public boolean isAlphaSet() { - return mAlphaSet; - } - - public void setAlphaSet(boolean alphaSet) { - mAlphaSet = alphaSet; - } - - // endregion - - // region RecyclerView.Adapter methods - - @Override - public WeekViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_week, parent, false); - return new WeekViewHolder(view); - } - - @Override - public void onBindViewHolder(WeekViewHolder weekViewHolder, int position) { - IWeekItem weekItem = mWeeksList.get(position); - weekViewHolder.bindWeek(weekItem, mToday); - } - - @Override - public int getItemCount() { - return mWeeksList.size(); - } - - // endregion - - // region Class - WeekViewHolder - - public class WeekViewHolder extends RecyclerView.ViewHolder { - - /** - * List of layout containers for each day - */ - private List mCells; - private TextView mTxtMonth; - private FrameLayout mMonthBackground; - - public WeekViewHolder(View itemView) { - super(itemView); - mTxtMonth = (TextView) itemView.findViewById(R.id.month_label); - mMonthBackground = (FrameLayout) itemView.findViewById(R.id.month_background); - LinearLayout daysContainer = (LinearLayout) itemView.findViewById(R.id.week_days_container); - setUpChildren(daysContainer); - } - - public void bindWeek(IWeekItem weekItem, Calendar today) { - setUpMonthOverlay(); - - List dayItems = weekItem.getDayItems(); - - for (int c = 0; c < dayItems.size(); c++) { - final IDayItem dayItem = dayItems.get(c); - LinearLayout cellItem = mCells.get(c); - TextView txtDay = (TextView) cellItem.findViewById(R.id.view_day_day_label); - TextView txtMonth = (TextView) cellItem.findViewById(R.id.view_day_month_label); - View circleView = cellItem.findViewById(R.id.view_day_circle_selected); - View eventIndicator1 = cellItem.findViewById(R.id.view_day_event_indicator1); - View eventIndicator2 = cellItem.findViewById(R.id.view_day_event_indicator2); - View eventIndicator3 = cellItem.findViewById(R.id.view_day_event_indicator3); - cellItem.setOnClickListener(v->BusProvider.getInstance().send(new Events.DayClickedEvent(dayItem))); - - eventIndicator1.setVisibility(View.INVISIBLE); - eventIndicator2.setVisibility(View.INVISIBLE); - eventIndicator3.setVisibility(View.INVISIBLE); - - Calendar dayItemCalendar = Calendar.getInstance(); - dayItemCalendar.setTime(dayItem.getDate()); - int eventCount = 0; - for (CalendarEvent event: mEventList) { - if (event.getStartTime().get(Calendar.YEAR) == dayItemCalendar.get(Calendar.YEAR) - && event.getStartTime().get(Calendar.MONTH) == dayItemCalendar.get(Calendar.MONTH) - && event.getStartTime().get(Calendar.DAY_OF_MONTH) == dayItemCalendar.get(Calendar.DAY_OF_MONTH)) { - eventCount++; - if (eventCount == 1) { - eventIndicator1.setVisibility(View.VISIBLE); - eventIndicator1.getBackground().setColorFilter(new PorterDuffColorFilter(event.getColor(),PorterDuff.Mode.MULTIPLY)); - } - if (eventCount == 2) { - eventIndicator2.setVisibility(View.VISIBLE); - eventIndicator2.getBackground().setColorFilter(new PorterDuffColorFilter(event.getColor(),PorterDuff.Mode.MULTIPLY)); - } - if (eventCount == 3) { - eventIndicator3.setVisibility(View.VISIBLE); - eventIndicator3.getBackground().setColorFilter(new PorterDuffColorFilter(event.getColor(),PorterDuff.Mode.MULTIPLY)); - } - } - } - - //Log.d("CalendarView", "Event count for day "+dayItem.getValue()+" is "+eventCount); - - txtMonth.setVisibility(View.GONE); - txtDay.setTextColor(mDayTextColor); - txtMonth.setTextColor(mDayTextColor); - circleView.setVisibility(View.GONE); - - txtDay.setTypeface(null, Typeface.NORMAL); - txtMonth.setTypeface(null, Typeface.NORMAL); - - // Display the day - txtDay.setText(Integer.toString(dayItem.getValue())); - - // Highlight first day of the month - if (dayItem.isFirstDayOfTheMonth() && !dayItem.isSelected()) { - txtMonth.setVisibility(View.VISIBLE); - txtMonth.setText(dayItem.getMonth()); - txtDay.setTypeface(null, Typeface.BOLD); - txtMonth.setTypeface(null, Typeface.BOLD); - } - - // Check if this day is in the past - if (today.getTime().after(dayItem.getDate()) && !DateHelper.sameDate(today, dayItem.getDate())) { - txtDay.setTextColor(mPastDayTextColor); - txtMonth.setTextColor(mPastDayTextColor); - } - - // Highlight the cell if this day is today - if (dayItem.isToday() && !dayItem.isSelected()) { - txtDay.setTextColor(mCurrentDayColor); - } - - if (dayItem.getShowBadge()) { - circleView.setVisibility(View.VISIBLE); - GradientDrawable drawable = (GradientDrawable) circleView.getBackground(); - drawable.setStroke((int) (2 * Resources.getSystem().getDisplayMetrics().density), 0xffff0000); - } - - // Show a circle if the day is selected - if (dayItem.isSelected()) { - txtDay.setTextColor(mDayTextColor); - circleView.setVisibility(View.VISIBLE); - GradientDrawable drawable = (GradientDrawable) circleView.getBackground(); - drawable.setStroke((int) (1 * Resources.getSystem().getDisplayMetrics().density), mDayTextColor); - } - - // Check if the month label has to be displayed - if (dayItem.getValue() == 15) { - mTxtMonth.setVisibility(View.VISIBLE); - SimpleDateFormat monthDateFormat = new SimpleDateFormat(mContext.getResources().getString(R.string.month_name_format), CalendarManager.getInstance().getLocale()); - String month = monthDateFormat.format(weekItem.getDate()).toUpperCase(); - if (today.get(Calendar.YEAR) != weekItem.getYear()) { - month = month + String.format(" %d", weekItem.getYear()); - } - mTxtMonth.setText(month); - } - } - } - - private void setUpChildren(LinearLayout daysContainer) { - mCells = new ArrayList<>(); - for (int i = 0; i < daysContainer.getChildCount(); i++) { - mCells.add((LinearLayout) daysContainer.getChildAt(i)); - } - } - - private void setUpMonthOverlay() { - mTxtMonth.setVisibility(View.GONE); - - if (isDragging()) { - AnimatorSet animatorSetFadeIn = new AnimatorSet(); - animatorSetFadeIn.setDuration(FADE_DURATION); - ObjectAnimator animatorTxtAlphaIn = ObjectAnimator.ofFloat(mTxtMonth, "alpha", mTxtMonth.getAlpha(), 1f); - ObjectAnimator animatorBackgroundAlphaIn = ObjectAnimator.ofFloat(mMonthBackground, "alpha", mMonthBackground.getAlpha(), 1f); - animatorSetFadeIn.playTogether( - animatorTxtAlphaIn - //animatorBackgroundAlphaIn - ); - animatorSetFadeIn.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - - } - - @Override - public void onAnimationEnd(Animator animation) { - setAlphaSet(true); - } - - @Override - public void onAnimationCancel(Animator animation) { - - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - animatorSetFadeIn.start(); - } else { - AnimatorSet animatorSetFadeOut = new AnimatorSet(); - animatorSetFadeOut.setDuration(FADE_DURATION); - ObjectAnimator animatorTxtAlphaOut = ObjectAnimator.ofFloat(mTxtMonth, "alpha", mTxtMonth.getAlpha(), 0f); - ObjectAnimator animatorBackgroundAlphaOut = ObjectAnimator.ofFloat(mMonthBackground, "alpha", mMonthBackground.getAlpha(), 0f); - animatorSetFadeOut.playTogether( - animatorTxtAlphaOut - //animatorBackgroundAlphaOut - ); - animatorSetFadeOut.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - - } - - @Override - public void onAnimationEnd(Animator animation) { - setAlphaSet(false); - } - - @Override - public void onAnimationCancel(Animator animation) { - - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - animatorSetFadeOut.start(); - } - - if (isAlphaSet()) { - //mMonthBackground.setAlpha(1f); - mTxtMonth.setAlpha(1f); - } else { - //mMonthBackground.setAlpha(0f); - mTxtMonth.setAlpha(0f); - } - } - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/BaseCalendarEvent.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/BaseCalendarEvent.java deleted file mode 100644 index 642eea2c..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/BaseCalendarEvent.java +++ /dev/null @@ -1,345 +0,0 @@ -package com.github.tibolte.agendacalendarview.models; - -import java.util.Calendar; - -/** - * Event model class containing the information to be displayed on the agenda view. - */ -public class BaseCalendarEvent implements CalendarEvent { - - /** - * Id of the event. - */ - private long mId; - /** - * Color to be displayed in the agenda view. - */ - private int mColor; - /** - * Text color displayed on the background color - */ - private int mTextColor; - /** - * Title of the event. - */ - private String mTitle; - /** - * Description of the event. - */ - private String mDescription; - /** - * Where the event takes place. - */ - private String mLocation; - /** - * Calendar instance helping sorting the events per section in the agenda view. - */ - private Calendar mInstanceDay; - /** - * Start time of the event. - */ - private Calendar mStartTime; - /** - * End time of the event. - */ - private Calendar mEndTime; - /** - * Indicates if the event lasts all day. - */ - private boolean mAllDay; - /** - * Tells if this BaseCalendarEvent instance is used as a placeholder in the agenda view, if there's - * no event for that day. - */ - private boolean mPlaceHolder; - /** - * Tells if this BaseCalendarEvent instance is used as a forecast information holder in the agenda - * view. - */ - private boolean mWeather; - /** - * Duration of the event. - */ - private String mDuration; - /** - * References to a DayItem instance for that event, used to link interaction between the - * calendar view and the agenda view. - */ - private IDayItem mDayReference; - /** - * References to a WeekItem instance for that event, used to link interaction between the - * calendar view and the agenda view. - */ - private IWeekItem mWeekReference; - /** - * Weather icon string returned by the Dark Sky API. - */ - private String mWeatherIcon; - /** - * Temperature value returned by the Dark Sky API. - */ - private double mTemperature; - - private boolean mShowBadge; - - // region Constructor - - /** - * Initializes the event - * - * @param id The id of the event. - * @param color The color of the event. - * @param textColor The color of the event description text. - * @param title The title of the event. - * @param description The description of the event. - * @param location The location of the event. - * @param dateStart The start date of the event. - * @param dateEnd The end date of the event. - * @param allDay Int that can be equal to 0 or 1. - * @param duration The duration of the event in RFC2445 format. - */ - public BaseCalendarEvent(long id, int color, int textColor, String title, String description, String location, long dateStart, long dateEnd, int allDay, String duration) { - this.mId = id; - this.mColor = color; - this.mTextColor = textColor; - this.mAllDay = (allDay == 1); - this.mDuration = duration; - this.mTitle = title; - this.mDescription = description; - this.mLocation = location; - - this.mStartTime = Calendar.getInstance(); - this.mStartTime.setTimeInMillis(dateStart); - this.mEndTime = Calendar.getInstance(); - this.mEndTime.setTimeInMillis(dateEnd); - } - - public BaseCalendarEvent() { - - } - - /** - * Initializes the event - * @param title The title of the event. - * @param description The description of the event. - * @param location The location of the event. - * @param color The color of the event (for display in the app). - * @param textColor The color of the event description text. - * @param startTime The start time of the event. - * @param endTime The end time of the event. - * @param allDay Indicates if the event lasts the whole day. - */ - public BaseCalendarEvent(String title, String description, String location, int color, int textColor, Calendar startTime, Calendar endTime, boolean allDay) { - this.mTitle = title; - this.mDescription = description; - this.mLocation = location; - this.mColor = color; - this.mTextColor = textColor; - this.mStartTime = startTime; - this.mEndTime = endTime; - this.mAllDay = allDay; - } - - public BaseCalendarEvent(String title, String description, String location, int color, int textColor, Calendar startTime, Calendar endTime, boolean allDay, long id, boolean showBadge) { - this.mTitle = title; - this.mDescription = description; - this.mLocation = location; - this.mColor = color; - this.mTextColor = textColor; - this.mStartTime = startTime; - this.mEndTime = endTime; - this.mAllDay = allDay; - this.mId = id; - this.mShowBadge = showBadge; - } - - public BaseCalendarEvent(BaseCalendarEvent calendarEvent) { - this.mId = calendarEvent.getId(); - this.mColor = calendarEvent.getColor(); - this.mTextColor = calendarEvent.getTextColor(); - this.mAllDay = calendarEvent.isAllDay(); - this.mDuration = calendarEvent.getDuration(); - this.mTitle = calendarEvent.getTitle(); - this.mDescription = calendarEvent.getDescription(); - this.mLocation = calendarEvent.getLocation(); - this.mStartTime = calendarEvent.getStartTime(); - this.mEndTime = calendarEvent.getEndTime(); - this.mShowBadge = calendarEvent.getShowBadge(); - } - - // endregion - - // region Getters/Setters - - public int getColor() { - return mColor; - } - - public void setColor(int mColor) { - this.mColor = mColor; - } - - public int getTextColor() { - return mTextColor; - } - - public void setTextColor(int mTextColor) { - this.mTextColor = mTextColor; - } - - public String getDescription() { - return mDescription; - } - - public boolean isAllDay() { - return mAllDay; - } - - public void setAllDay(boolean allDay) { - this.mAllDay = allDay; - } - - public void setDescription(String mDescription) { - this.mDescription = mDescription; - } - - public Calendar getInstanceDay() { - return mInstanceDay; - } - - public void setInstanceDay(Calendar mInstanceDay) { - this.mInstanceDay = mInstanceDay; - this.mInstanceDay.set(Calendar.HOUR, 0); - this.mInstanceDay.set(Calendar.MINUTE, 0); - this.mInstanceDay.set(Calendar.SECOND, 0); - this.mInstanceDay.set(Calendar.MILLISECOND, 0); - this.mInstanceDay.set(Calendar.AM_PM, 0); - } - - public Calendar getEndTime() { - return mEndTime; - } - - public void setEndTime(Calendar mEndTime) { - this.mEndTime = mEndTime; - } - public void setPlaceholder(boolean placeholder) { - mPlaceHolder = placeholder; - } - public boolean isPlaceholder() { - return mPlaceHolder; - } - - public long getId() { - return mId; - } - - public void setId(long mId) { - this.mId = mId; - } - - public boolean getShowBadge() { - return mShowBadge; - } - - public void setShowBadge(boolean mShowBadge) { - this.mShowBadge = mShowBadge; - } - - public String getLocation() { - return mLocation; - } - - public void setLocation(String mLocation) { - this.mLocation = mLocation; - } - - public Calendar getStartTime() { - return mStartTime; - } - - public void setStartTime(Calendar mStartTime) { - this.mStartTime = mStartTime; - } - - public String getTitle() { - return mTitle; - } - - public void setTitle(String mTitle) { - this.mTitle = mTitle; - } - - public String getDuration() { - return mDuration; - } - - public void setDuration(String duration) { - this.mDuration = duration; - } - - public boolean isPlaceHolder() { - return mPlaceHolder; - } - - public void setPlaceHolder(boolean mPlaceHolder) { - this.mPlaceHolder = mPlaceHolder; - } - - public boolean isWeather() { - return mWeather; - } - - public void setWeather(boolean mWeather) { - this.mWeather = mWeather; - } - - public IDayItem getDayReference() { - return mDayReference; - } - - public void setDayReference(IDayItem mDayReference) { - this.mDayReference = mDayReference; - } - - public IWeekItem getWeekReference() { - return mWeekReference; - } - - public void setWeekReference(IWeekItem mWeekReference) { - this.mWeekReference = mWeekReference; - } - - public String getWeatherIcon() { - return mWeatherIcon; - } - - public void setWeatherIcon(String mWeatherIcon) { - this.mWeatherIcon = mWeatherIcon; - } - - public double getTemperature() { - return mTemperature; - } - - public void setTemperature(double mTemperature) { - this.mTemperature = mTemperature; - } - - @Override - public CalendarEvent copy() { - return new BaseCalendarEvent(this); - } - - // endregion - - @Override - public String toString() { - return "BaseCalendarEvent{" - + "title='" - + mTitle - + ", instanceDay= " - + mInstanceDay.getTime() - + "}"; - } -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/CalendarEvent.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/CalendarEvent.java deleted file mode 100644 index 05df9a0f..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/CalendarEvent.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.github.tibolte.agendacalendarview.models; - -import java.util.Calendar; - -public interface CalendarEvent { - - - void setPlaceholder(boolean placeholder); - - boolean isPlaceholder(); - - public String getLocation(); - - public void setLocation(String mLocation); - - long getId(); - - void setId(long mId); - - boolean getShowBadge(); - - void setShowBadge(boolean mShowBadge); - - int getTextColor(); - - void setTextColor(int mTextColor); - - String getDescription(); - - void setDescription(String mDescription); - - boolean isAllDay(); - - void setAllDay(boolean allDay); - - Calendar getStartTime(); - - void setStartTime(Calendar mStartTime); - - Calendar getEndTime(); - - void setEndTime(Calendar mEndTime); - - String getTitle(); - - void setTitle(String mTitle); - - Calendar getInstanceDay(); - - void setInstanceDay(Calendar mInstanceDay); - - IDayItem getDayReference(); - - void setDayReference(IDayItem mDayReference); - - IWeekItem getWeekReference(); - - void setWeekReference(IWeekItem mWeekReference); - - CalendarEvent copy(); - - int getColor(); -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/DayItem.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/DayItem.java deleted file mode 100644 index 39be4985..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/DayItem.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.github.tibolte.agendacalendarview.models; - -import com.github.tibolte.agendacalendarview.CalendarManager; -import com.github.tibolte.agendacalendarview.utils.DateHelper; - -import java.util.Calendar; -import java.util.Date; - -/** - * Day model class. - */ -public class DayItem implements IDayItem { - private Date mDate; - private int mValue; - private int mDayOfTheWeek; - private boolean mToday; - private boolean mFirstDayOfTheMonth; - private boolean mSelected; - private String mMonth; - private boolean mShowBadge; - - // region Constructor - - public DayItem(Date date, int value, boolean today, String month) { - this.mDate = date; - this.mValue = value; - this.mToday = today; - this.mMonth = month; - } - // only for cleanDay - public DayItem() { - - } - public DayItem(DayItem original) { - - this.mDate = original.getDate(); - this.mValue = original.getValue(); - this.mToday = original.isToday(); - this.mDayOfTheWeek = original.getDayOftheWeek(); - this.mFirstDayOfTheMonth = original.isFirstDayOfTheMonth(); - this.mSelected = original.isSelected(); - this.mMonth = original.getMonth(); - this.mShowBadge = original.mShowBadge; - } - // endregion - - // region Getters/Setters - - public Date getDate() { - return mDate; - } - - public void setDate(Date date) { - this.mDate = date; - } - - public int getValue() { - return mValue; - } - - public void setValue(int value) { - this.mValue = value; - } - - public boolean isToday() { - return mToday; - } - - public void setToday(boolean today) { - this.mToday = today; - } - - public boolean isSelected() { - return mSelected; - } - - public void setSelected(boolean selected) { - this.mSelected = selected; - } - - public boolean isFirstDayOfTheMonth() { - return mFirstDayOfTheMonth; - } - - public void setFirstDayOfTheMonth(boolean firstDayOfTheMonth) { - this.mFirstDayOfTheMonth = firstDayOfTheMonth; - } - - public String getMonth() { - return mMonth; - } - - public void setMonth(String month) { - this.mMonth = month; - } - - public int getDayOftheWeek() { - return mDayOfTheWeek; - } - - public void setDayOftheWeek(int mDayOftheWeek) { - this.mDayOfTheWeek = mDayOftheWeek; - } - - public void setShowBadge(boolean showBadge) { - this.mShowBadge = showBadge; - } - - public boolean getShowBadge() { - return this.mShowBadge; - } - - // region Public methods - - public void buildDayItemFromCal(Calendar calendar) { - Date date = calendar.getTime(); - this.mDate = date; - - this.mValue = calendar.get(Calendar.DAY_OF_MONTH); - this.mToday = DateHelper.sameDate(calendar, CalendarManager.getInstance().getToday()); - this.mMonth = CalendarManager.getInstance().getMonthHalfNameFormat().format(date); - if (this.mValue == 1) { - this.mFirstDayOfTheMonth = true; - } - } - - // endregion - - @Override - public String toString() { - return "DayItem{" - + "Date='" - + mDate.toString() - + ", value=" - + mValue - + '}'; - } - - @Override - public IDayItem copy() { - return new DayItem(this); - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/IDayItem.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/IDayItem.java deleted file mode 100644 index acfe3c76..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/IDayItem.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.github.tibolte.agendacalendarview.models; - -import java.util.Calendar; -import java.util.Date; - -public interface IDayItem { - - // region Getters/Setters - - Date getDate(); - - void setDate(Date date); - - int getValue(); - - void setValue(int value); - - boolean isToday(); - - void setToday(boolean today); - - boolean isSelected(); - - void setSelected(boolean selected); - - boolean isFirstDayOfTheMonth(); - - void setFirstDayOfTheMonth(boolean firstDayOfTheMonth); - - String getMonth(); - - void setMonth(String month); - - int getDayOftheWeek(); - - void setDayOftheWeek(int mDayOftheWeek); - - // endregion - - void buildDayItemFromCal(Calendar calendar); - - String toString(); - - IDayItem copy(); - - void setShowBadge(boolean showBadge); - - boolean getShowBadge(); -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/IWeekItem.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/IWeekItem.java deleted file mode 100644 index bb08b89a..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/IWeekItem.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.github.tibolte.agendacalendarview.models; - -import java.util.Date; -import java.util.List; - -public interface IWeekItem { - - - int getWeekInYear(); - - void setWeekInYear(int weekInYear); - - int getYear(); - - void setYear(int year); - - int getMonth(); - - void setMonth(int month); - - Date getDate(); - - void setDate(Date date); - - String getLabel(); - - void setLabel(String label); - - List getDayItems(); - - void setDayItems(List dayItems); - - IWeekItem copy(); -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/WeekItem.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/WeekItem.java deleted file mode 100644 index 40b94902..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/models/WeekItem.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.github.tibolte.agendacalendarview.models; - -import java.util.Date; -import java.util.List; - -/** - * Week model class. - */ -public class WeekItem implements IWeekItem { - private int mWeekInYear; - private int mYear; - private int mMonth; - private Date mDate; - private String mLabel; - private List mDayItems; - - // region Constructor - - public WeekItem(int weekInYear, int year, Date date, String label, int month) { - this.mWeekInYear = weekInYear; - this.mYear = year; - this.mDate = date; - this.mLabel = label; - this.mMonth = month; - } - public WeekItem(WeekItem original) { - this.mWeekInYear = original.getWeekInYear(); - this.mYear = original.getYear(); - this.mMonth = original.getMonth(); - this.mDate = original.getDate(); - this.mLabel = original.getLabel(); - this.mDayItems = original.getDayItems(); - } - - public WeekItem(){ - - } - - // endregion - - // region Getters/Setters - - public int getWeekInYear() { - return mWeekInYear; - } - - public void setWeekInYear(int weekInYear) { - this.mWeekInYear = weekInYear; - } - - public int getYear() { - return mYear; - } - - public void setYear(int year) { - this.mYear = year; - } - - public int getMonth() { - return mMonth; - } - - public void setMonth(int month) { - this.mMonth = month; - } - - public Date getDate() { - return mDate; - } - - public void setDate(Date date) { - this.mDate = date; - } - - public String getLabel() { - return mLabel; - } - - public void setLabel(String label) { - this.mLabel = label; - } - - public List getDayItems() { - return mDayItems; - } - - public void setDayItems(List dayItems) { - this.mDayItems = dayItems; - } - - @Override - public IWeekItem copy() { - return new WeekItem(this); - } - - // endregion - - @Override - public String toString() { - return "WeekItem{" - + "label='" - + mLabel - + '\'' - + ", weekInYear=" - + mWeekInYear - + ", year=" - + mYear - + '}'; - } -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/render/DefaultEventRenderer.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/render/DefaultEventRenderer.java deleted file mode 100644 index 729ad706..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/render/DefaultEventRenderer.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.github.tibolte.agendacalendarview.render; - -import android.content.Context; -import android.content.res.Resources; -import androidx.annotation.NonNull; -import androidx.cardview.widget.CardView; -import androidx.core.content.ContextCompat; - -import android.graphics.Color; -import android.util.TypedValue; -import android.view.View; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.github.tibolte.agendacalendarview.R; -import com.github.tibolte.agendacalendarview.models.BaseCalendarEvent; -import com.google.android.material.internal.ViewUtils; - -/** - * Class helping to inflate our default layout in the AgendaAdapter - */ -public class DefaultEventRenderer extends EventRenderer { - - public static int themeAttributeToColor(int themeAttributeId, - Context context, - int fallbackColorId) { - TypedValue outValue = new TypedValue(); - Resources.Theme theme = context.getTheme(); - boolean wasResolved = - theme.resolveAttribute( - themeAttributeId, outValue, true); - if (wasResolved) { - return ContextCompat.getColor( - context, outValue.resourceId); - } else { - // fallback colour handling - return fallbackColorId; - } - } - - // region class - EventRenderer - - @Override - public void render(@NonNull View view, @NonNull BaseCalendarEvent event) { - CardView card = view.findViewById(R.id.view_agenda_event_card_view); - TextView txtTitle = view.findViewById(R.id.view_agenda_event_title); - TextView txtLocation = view.findViewById(R.id.view_agenda_event_location); - LinearLayout descriptionContainer = view.findViewById(R.id.view_agenda_event_description_container); - LinearLayout locationContainer = view.findViewById(R.id.view_agenda_event_location_container); - - descriptionContainer.setVisibility(View.VISIBLE); - - txtTitle.setText(event.getTitle()); - txtLocation.setText(event.getLocation()); - if (event.getLocation().length() > 0) { - locationContainer.setVisibility(View.VISIBLE); - txtLocation.setText(event.getLocation()); - } else { - locationContainer.setVisibility(View.GONE); - } - - if (!event.isPlaceholder()/*!event.getTitle().equals(view.getResources().getString(R.string.agenda_event_no_events))*/) { - txtTitle.setTextColor(event.getTextColor()); - card.setCardBackgroundColor(event.getColor()); - txtLocation.setTextColor(event.getTextColor()); - } - else { - card.setCardBackgroundColor(Color.TRANSPARENT); - card.setCardElevation(0); - card.setBackgroundColor(Color.TRANSPARENT); - card.setRadius(0); - card.setBackgroundDrawable(null); - } - } - - @Override - public int getEventLayout() { - return R.layout.view_agenda_event; - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/render/EventRenderer.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/render/EventRenderer.java deleted file mode 100644 index e62f23b5..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/render/EventRenderer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.tibolte.agendacalendarview.render; - -import androidx.annotation.LayoutRes; -import android.view.View; - -import com.github.tibolte.agendacalendarview.models.CalendarEvent; - -import java.lang.reflect.ParameterizedType; - -/** - * Base class for helping layout rendering - */ -public abstract class EventRenderer { - public abstract void render(final View view, final T event); - - @LayoutRes - public abstract int getEventLayout(); - - public Class getRenderType() { - ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass(); - return (Class) type.getActualTypeArguments()[0]; - } -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/BusProvider.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/BusProvider.java deleted file mode 100644 index 99bdbf3d..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/BusProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.github.tibolte.agendacalendarview.utils; - -import rx.Observable; -import rx.subjects.PublishSubject; -import rx.subjects.SerializedSubject; -import rx.subjects.Subject; - -public class BusProvider { - - public static BusProvider mInstance; - - private final Subject mBus = new SerializedSubject<>(PublishSubject.create()); - - // region Constructors - - public static BusProvider getInstance() { - if (mInstance == null) { - mInstance = new BusProvider(); - } - return mInstance; - } - - // endregion - - // region Public methods - - public void send(Object object) { - mBus.onNext(object); - } - - public Observable toObserverable() { - return mBus; - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/DateHelper.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/DateHelper.java deleted file mode 100644 index f9439d04..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/DateHelper.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.github.tibolte.agendacalendarview.utils; - -import com.github.tibolte.agendacalendarview.CalendarManager; -import com.github.tibolte.agendacalendarview.R; -import com.github.tibolte.agendacalendarview.models.IWeekItem; - -import android.content.Context; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; -import java.util.concurrent.TimeUnit; - -/** - * Class containing helper functions for dates - */ -public class DateHelper { - - // region Public methods - - /** - * Check if two Calendar instances have the same time (by month, year and day of month) - * - * @param cal The first Calendar instance. - * @param selectedDate The second Calendar instance. - * @return True if both instances have the same time. - */ - public static boolean sameDate(Calendar cal, Calendar selectedDate) { - return cal.get(Calendar.MONTH) == selectedDate.get(Calendar.MONTH) - && cal.get(Calendar.YEAR) == selectedDate.get(Calendar.YEAR) - && cal.get(Calendar.DAY_OF_MONTH) == selectedDate.get(Calendar.DAY_OF_MONTH); - } - - /** - * Check if a Date instance and a Calendar instance have the same time (by month, year and day - * of month) - * - * @param cal The Calendar instance. - * @param selectedDate The Date instance. - * @return True if both have the same time. - */ - public static boolean sameDate(Calendar cal, Date selectedDate) { - Calendar selectedCal = Calendar.getInstance(); - selectedCal.setTime(selectedDate); - return cal.get(Calendar.MONTH) == selectedCal.get(Calendar.MONTH) - && cal.get(Calendar.YEAR) == selectedCal.get(Calendar.YEAR) - && cal.get(Calendar.DAY_OF_MONTH) == selectedCal.get(Calendar.DAY_OF_MONTH); - } - - /** - * Check if a Date instance is between two Calendar instances' dates (inclusively) in time. - * - * @param selectedDate The date to verify. - * @param startCal The start time. - * @param endCal The end time. - * @return True if the verified date is between the two specified dates. - */ - public static boolean isBetweenInclusive(Date selectedDate, Calendar startCal, Calendar endCal) { - Calendar selectedCal = Calendar.getInstance(); - selectedCal.setTime(selectedDate); - // Check if we deal with the same day regarding startCal and endCal - return sameDate(selectedCal, startCal) || selectedCal.after(startCal) && selectedCal.before(endCal); - } - - /** - * Check if Calendar instance's date is in the same week, as the WeekItem instance. - * - * @param cal The Calendar instance to verify. - * @param week The WeekItem instance to compare to. - * @return True if both instances are in the same week. - */ - public static boolean sameWeek(Calendar cal, IWeekItem week) { - return (cal.get(Calendar.WEEK_OF_YEAR) == week.getWeekInYear() && cal.get(Calendar.YEAR) == week.getYear()); - } - - /** - * Convert a millisecond duration to a string format - * - * @param millis A duration to convert to a string form - * @return A string of the form "Xd" or either "XhXm". - */ - public static String getDuration(Context context, long millis) { - if (millis < 0) { - throw new IllegalArgumentException("Duration must be greater than zero!"); - } - - long days = TimeUnit.MILLISECONDS.toDays(millis); - millis -= TimeUnit.DAYS.toMillis(days); - long hours = TimeUnit.MILLISECONDS.toHours(millis); - millis -= TimeUnit.HOURS.toMillis(hours); - long minutes = TimeUnit.MILLISECONDS.toMinutes(millis); - - StringBuilder sb = new StringBuilder(64); - if (days > 0) { - sb.append(days); - sb.append(context.getResources().getString(R.string.agenda_event_day_duration)); - return (sb.toString()); - } else { - if (hours > 0) { - sb.append(hours); - sb.append("h"); - } - if (minutes > 0) { - sb.append(minutes); - sb.append("m"); - } - } - - return (sb.toString()); - } - - /** - * Used for displaying the date in any section of the agenda view. - * - * @param calendar The date of the section. - * @param locale The locale used by the Sunrise calendar. - * @return The formatted date without the year included. - */ - public static String getYearLessLocalizedDate(Calendar calendar, Locale locale) { - SimpleDateFormat sdf = (SimpleDateFormat) SimpleDateFormat.getDateInstance(DateFormat.FULL, CalendarManager.getInstance().getLocale()); - String pattern = sdf.toPattern(); - - String yearLessPattern = pattern.replaceAll("\\W?[Yy]+\\W?", ""); - SimpleDateFormat yearLessSDF = new SimpleDateFormat(yearLessPattern, locale); - String yearLessDate = yearLessSDF.format(calendar.getTime()).toUpperCase(); - if (yearLessDate.endsWith(",")) { - yearLessDate = yearLessDate.substring(0, yearLessDate.length() - 1); - } - return yearLessDate; - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/Events.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/Events.java deleted file mode 100644 index 98d13f20..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/Events.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.github.tibolte.agendacalendarview.utils; - -import com.github.tibolte.agendacalendarview.models.IDayItem; - -import java.util.Calendar; - -/** - * Events emitted by the bus provider. - */ -public class Events { - - public static class DayClickedEvent { - - public Calendar mCalendar; - public IDayItem mDayItem; - - public DayClickedEvent(IDayItem dayItem) { - this.mCalendar = Calendar.getInstance(); - this.mCalendar.setTime(dayItem.getDate()); - this.mDayItem = dayItem; - } - - public Calendar getCalendar() { - return mCalendar; - } - - public IDayItem getDay() { - return mDayItem; - } - } - - public static class CalendarScrolledEvent { - } - - public static class AgendaListViewTouchedEvent { - } - - public static class EventsFetched { - } - - public static class ForecastFetched { - } -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/ListViewScrollTracker.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/ListViewScrollTracker.java deleted file mode 100644 index 47e16de3..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/utils/ListViewScrollTracker.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.github.tibolte.agendacalendarview.utils; - -import com.github.tibolte.agendacalendarview.agenda.AgendaListView; - -import android.util.SparseArray; -import android.view.View; - -/** - * Helper class calculating the scrolling distance in the AgendaListView. - */ -public class ListViewScrollTracker { - private AgendaListView mListView; - private SparseArray mPositions; - private SparseArray mListViewItemHeights = new SparseArray<>(); - private int mFirstVisiblePosition; - private int mReferencePosition = -1; // Position of the current date in the Agenda listView - - // region Constructor and Accessor(s) - - public ListViewScrollTracker(AgendaListView listView) { - mListView = listView; - } - - public int getReferencePosition() { - return mReferencePosition; - } - - // endregion - - // region Public methods - - /** - * Call from an AbsListView.OnScrollListener to calculate the incremental offset (change in - * scroll offset - * since the last calculation). - * - * @param firstVisiblePosition First visible item position in the list. - * @param visibleItemCount Number of visible items in the list. - * @return The incremental offset, or 0 if it wasn't possible to calculate the offset. - */ - public int calculateIncrementalOffset(int firstVisiblePosition, int visibleItemCount) { - // Remember previous positions, if any - SparseArray previousPositions = mPositions; - - // Store new positions - mPositions = new SparseArray<>(); - for (int i = 0; i < visibleItemCount; i++) { - mPositions.put(firstVisiblePosition + i, mListView.getListChildAt(i).getTop()); - } - - if (previousPositions != null) { - // Find position which exists in both mPositions and previousPositions, then return the difference - // of the new and old Y values. - for (int i = 0; i < previousPositions.size(); i++) { - int previousPosition = previousPositions.keyAt(i); - int previousTop = previousPositions.get(previousPosition); - Integer newTop = mPositions.get(previousPosition); - if (newTop != null) { - return newTop - previousTop; - } - } - } - - return 0; // No view's position was in both previousPositions and mPositions - } - - /** - * Call from an AbsListView.OnScrollListener to calculate the scrollY (Here - * we definite as the distance in pixels compared to the position representing the current - * date). - * - * @param firstVisiblePosition First visible item position in the list. - * @param visibleItemCount Number of visible items in the list. - * @return Distance in pixels compared to current day position (negative if firstVisiblePosition less than mReferencePosition) - */ - public int calculateScrollY(int firstVisiblePosition, int visibleItemCount) { - mFirstVisiblePosition = firstVisiblePosition; - if (mReferencePosition < 0) { - mReferencePosition = mFirstVisiblePosition; - } - - if (visibleItemCount > 0) { - View c = mListView.getListChildAt(0); // this is the first visible row - int scrollY = -c.getTop(); - mListViewItemHeights.put(firstVisiblePosition, c.getMeasuredHeight()); - - if (mFirstVisiblePosition >= mReferencePosition) { - for (int i = mReferencePosition; i < firstVisiblePosition; ++i) { - if (mListViewItemHeights.get(i) == null) { - mListViewItemHeights.put(i, c.getMeasuredHeight()); - } - scrollY += mListViewItemHeights.get(i); // add all heights of the views that are gone - } - return scrollY; - } else { - for (int i = mReferencePosition - 1; i >= firstVisiblePosition; --i) { - if (mListViewItemHeights.get(i) == null) { - mListViewItemHeights.put(i, c.getMeasuredHeight()); - } - scrollY -= mListViewItemHeights.get(i); - } - return scrollY; - } - - } - return 0; - } - - public void clear() { - mPositions = null; - } - - // endregion -} diff --git a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/widgets/FloatingActionButton.java b/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/widgets/FloatingActionButton.java deleted file mode 100644 index bd008910..00000000 --- a/agendacalendarview/src/main/java/com/github/tibolte/agendacalendarview/widgets/FloatingActionButton.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.github.tibolte.agendacalendarview.widgets; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.Interpolator; - -/** - * Floating action button helping to scroll back to the current date. - */ -public class FloatingActionButton extends com.google.android.material.floatingactionbutton.FloatingActionButton { - private static final int TRANSLATE_DURATION_MILLIS = 200; - - private boolean mVisible = true; - - private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); - - // region Constructors - - public FloatingActionButton(Context context) { - super(context); - } - - public FloatingActionButton(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - // endregion - - // region Overrides - - @Override - public void show() { - show(true); - } - - @Override - public void hide() { - hide(true); - } - - // endregion - - // region Public methods - - public void show(boolean animate) { - toggle(true, animate, false); - } - - public void hide(boolean animate) { - toggle(false, animate, false); - } - - public boolean isVisible() { - return mVisible; - } - - // endregion - - // region Private methods - - private void toggle(final boolean visible, final boolean animate, boolean force) { - if (mVisible != visible || force) { - mVisible = visible; - int height = getHeight(); - if (height == 0 && !force) { - ViewTreeObserver vto = getViewTreeObserver(); - if (vto.isAlive()) { - vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - ViewTreeObserver currentVto = getViewTreeObserver(); - if (currentVto.isAlive()) { - currentVto.removeOnPreDrawListener(this); - } - toggle(visible, animate, true); - return true; - } - }); - return; - } - } - int translationY = visible ? 0 : height + getMarginBottom(); - if (animate) { - animate().setInterpolator(mInterpolator) - .setDuration(TRANSLATE_DURATION_MILLIS) - .translationY(translationY); - } else { - setTranslationY(translationY); - } - } - } - - private int getMarginBottom() { - int marginBottom = 0; - final ViewGroup.LayoutParams layoutParams = getLayoutParams(); - if (layoutParams instanceof ViewGroup.MarginLayoutParams) { - marginBottom = ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin; - } - return marginBottom; - } - - // endregion -} diff --git a/agendacalendarview/src/main/res/drawable/agenda_day_circle.xml b/agendacalendarview/src/main/res/drawable/agenda_day_circle.xml deleted file mode 100644 index e1398e00..00000000 --- a/agendacalendarview/src/main/res/drawable/agenda_day_circle.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/drawable/event_color_circle.xml b/agendacalendarview/src/main/res/drawable/event_color_circle.xml deleted file mode 100644 index 3cc72359..00000000 --- a/agendacalendarview/src/main/res/drawable/event_color_circle.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/drawable/fab_arrow.xml b/agendacalendarview/src/main/res/drawable/fab_arrow.xml deleted file mode 100644 index 3b4d3a8c..00000000 --- a/agendacalendarview/src/main/res/drawable/fab_arrow.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/drawable/selected_day_color_circle.xml b/agendacalendarview/src/main/res/drawable/selected_day_color_circle.xml deleted file mode 100644 index 3d53cf8c..00000000 --- a/agendacalendarview/src/main/res/drawable/selected_day_color_circle.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/drawable/shadow.xml b/agendacalendarview/src/main/res/drawable/shadow.xml deleted file mode 100644 index 7ab76207..00000000 --- a/agendacalendarview/src/main/res/drawable/shadow.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/layout/list_item_week.xml b/agendacalendarview/src/main/res/layout/list_item_week.xml deleted file mode 100644 index 846ba637..00000000 --- a/agendacalendarview/src/main/res/layout/list_item_week.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/layout/view_agenda.xml b/agendacalendarview/src/main/res/layout/view_agenda.xml deleted file mode 100644 index 5f4a704e..00000000 --- a/agendacalendarview/src/main/res/layout/view_agenda.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/layout/view_agenda_event.xml b/agendacalendarview/src/main/res/layout/view_agenda_event.xml deleted file mode 100644 index 92329386..00000000 --- a/agendacalendarview/src/main/res/layout/view_agenda_event.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/layout/view_agenda_header.xml b/agendacalendarview/src/main/res/layout/view_agenda_header.xml deleted file mode 100644 index e0391dd5..00000000 --- a/agendacalendarview/src/main/res/layout/view_agenda_header.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/layout/view_agendacalendar.xml b/agendacalendarview/src/main/res/layout/view_agendacalendar.xml deleted file mode 100644 index e2df4255..00000000 --- a/agendacalendarview/src/main/res/layout/view_agendacalendar.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/layout/view_calendar.xml b/agendacalendarview/src/main/res/layout/view_calendar.xml deleted file mode 100644 index 4b3839e0..00000000 --- a/agendacalendarview/src/main/res/layout/view_calendar.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/layout/view_day_calendar_header.xml b/agendacalendarview/src/main/res/layout/view_day_calendar_header.xml deleted file mode 100644 index 2326af49..00000000 --- a/agendacalendarview/src/main/res/layout/view_day_calendar_header.xml +++ /dev/null @@ -1,9 +0,0 @@ - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/layout/view_day_cell.xml b/agendacalendarview/src/main/res/layout/view_day_cell.xml deleted file mode 100644 index cebb97db..00000000 --- a/agendacalendarview/src/main/res/layout/view_day_cell.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/values-en/strings.xml b/agendacalendarview/src/main/res/values-en/strings.xml deleted file mode 100644 index 1d9b1040..00000000 --- a/agendacalendarview/src/main/res/values-en/strings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - Today - Tomorrow - d - All day - No events - - - LLLL - MMM - diff --git a/agendacalendarview/src/main/res/values/attrs.xml b/agendacalendarview/src/main/res/values/attrs.xml deleted file mode 100644 index 6750df84..00000000 --- a/agendacalendarview/src/main/res/values/attrs.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/agendacalendarview/src/main/res/values/colors.xml b/agendacalendarview/src/main/res/values/colors.xml deleted file mode 100644 index 7904509d..00000000 --- a/agendacalendarview/src/main/res/values/colors.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - #000000 - #9C9CA0 - #CCFFFFFF - #F3F3F3 - - - - #00000000 - - - #2196F3 - #1976D2 - #2196F3 - #BBDEFB - #4caf50 - #FFFFFF - - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/values/dimens.xml b/agendacalendarview/src/main/res/values/dimens.xml deleted file mode 100644 index 7b639f8d..00000000 --- a/agendacalendarview/src/main/res/values/dimens.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - 20dp - 52dp - 14dp - 32dp - - - 60dp - - - - - 70dp - 5dp - 15dp - 5dp - \ No newline at end of file diff --git a/agendacalendarview/src/main/res/values/strings.xml b/agendacalendarview/src/main/res/values/strings.xml deleted file mode 100644 index 7c2c5f8a..00000000 --- a/agendacalendarview/src/main/res/values/strings.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - LLLL - E - - - Dziś - Jutro - d - Cały dzień - Brak wydarzeń - - MMM - diff --git a/agendacalendarview/src/main/res/values/styles.xml b/agendacalendarview/src/main/res/values/styles.xml deleted file mode 100644 index b4bf4679..00000000 --- a/agendacalendarview/src/main/res/values/styles.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index d6ccb59b..7b2c0b9a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -163,11 +163,9 @@ dependencies { implementation "org.greenrobot:eventbus:3.1.1" implementation "org.jsoup:jsoup:1.12.1" implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.15" - //implementation "se.emilsjolander:stickylistheaders:2.7.0" - implementation 'com.github.edisonw:StickyListHeaders:master-SNAPSHOT@aar' implementation "uk.co.samuelwall:material-tap-target-prompt:2.14.0" - implementation project(":agendacalendarview") + implementation "eu.szkolny:agendacalendarview:1799f8ef47" implementation "eu.szkolny:cafebar:5bf0c618de" implementation "eu.szkolny:material-about-library:0534abf316" implementation "eu.szkolny:mhttp:af4b62e6e9" diff --git a/settings.gradle b/settings.gradle index b47390e3..680b7d04 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,7 +3,7 @@ include ':wear' include ':codegen' include ':annotation' rootProject.name='Szkolny.eu' -include ':app', ':agendacalendarview', ':szkolny-font' +include ':app', ':szkolny-font' /* include ':Navigation' project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/ From e91d99652c1395bc5f95a0b25691fdf6f3951b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 21 Mar 2021 14:36:30 +0100 Subject: [PATCH 06/15] [Gradle] Extract szkolny-font dependency. Migrate Iconics to v5. --- app/build.gradle | 9 +- .../java/pl/szczodrzynski/edziennik/App.kt | 2 - .../szczodrzynski/edziennik/MainActivity.kt | 12 +- .../ui/modules/agenda/AgendaFragment.kt | 15 +- .../ui/modules/behaviour/NoticesAdapter.kt | 29 ++- .../ui/modules/home/CounterActivity.kt | 11 +- .../edziennik/ui/modules/home/HomeFragment.kt | 7 +- .../modules/home/cards/HomeTimetableCard.kt | 29 ++- .../ui/modules/homework/HomeworkFragment.kt | 2 +- .../ui/modules/login/LoginFormFragment.kt | 11 +- .../ui/modules/messages/MessageFragment.kt | 7 +- .../settings/SettingsLicenseActivity.kt | 9 +- .../modules/settings/SettingsNewFragment.java | 207 +++++------------ .../ui/modules/timetable/TimetableFragment.kt | 2 +- .../ui/modules/views/AttachmentAdapter.kt | 25 ++- .../WidgetNotificationsProvider.kt | 8 +- .../timetable/WidgetTimetableFactory.java | 20 +- .../timetable/WidgetTimetableProvider.kt | 20 +- .../utils/SwipeRefreshLayoutNoIndicator.java | 208 ++++++++++++++++++ .../utils/SwipeRefreshLayoutNoTouch.java | 51 +++++ build.gradle | 2 +- settings.gradle | 2 +- szkolny-font/build.gradle | 50 ----- szkolny-font/consumer-proguard-rules.pro | 1 - szkolny-font/gradle.properties | 40 ---- szkolny-font/src/main/AndroidManifest.xml | 19 -- .../library/szkolny/font/SzkolnyFont.kt | 87 -------- .../main/res/font/szkolny_font_font_v1_1.ttf | Bin 11232 -> 0 bytes .../src/main/res/values/font_addon.xml | 2 - 29 files changed, 441 insertions(+), 446 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/utils/SwipeRefreshLayoutNoIndicator.java create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/utils/SwipeRefreshLayoutNoTouch.java delete mode 100644 szkolny-font/build.gradle delete mode 100644 szkolny-font/consumer-proguard-rules.pro delete mode 100644 szkolny-font/gradle.properties delete mode 100644 szkolny-font/src/main/AndroidManifest.xml delete mode 100644 szkolny-font/src/main/java/com/mikepenz/iconics/typeface/library/szkolny/font/SzkolnyFont.kt delete mode 100644 szkolny-font/src/main/res/font/szkolny_font_font_v1_1.ttf delete mode 100644 szkolny-font/src/main/res/values/font_addon.xml diff --git a/app/build.gradle b/app/build.gradle index 7b2c0b9a..4ad2fc5f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,14 +127,9 @@ dependencies { implementation "com.google.android.material:material:${versions.material}" implementation "com.google.firebase:firebase-messaging:${versions.firebasemessaging}" - //implementation "com.github.kuba2k2.MaterialDrawer:library:e603091449" - implementation "com.mikepenz:crossfader:1.6.0" // do not update - implementation "com.mikepenz:iconics-core:${versions.iconics}" + implementation "pl.szczodrzynski:NavLib:v0.7.0" implementation "com.mikepenz:iconics-views:${versions.iconics}" implementation "com.mikepenz:community-material-typeface:${versions.font_cmd}@aar" - implementation "com.mikepenz:materialize:1.2.1" - - implementation "com.github.kuba2k2:NavLib:${versions.navlib}" implementation "com.afollestad.material-dialogs:commons:${versions.materialdialogs}" implementation "com.afollestad.material-dialogs:core:${versions.materialdialogs}" @@ -171,7 +166,7 @@ dependencies { implementation "eu.szkolny:mhttp:af4b62e6e9" implementation "eu.szkolny:nachos:0e5dfcaceb" //implementation project(":Navigation") - implementation project(":szkolny-font") + implementation "eu.szkolny:szkolny-font:1dab7d64ed" implementation "com.github.ChuckerTeam.Chucker:library:3.0.1" //releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:3.0.1" diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/App.kt b/app/src/main/java/pl/szczodrzynski/edziennik/App.kt index 88bdc603..0bc6f2e0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/App.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/App.kt @@ -26,7 +26,6 @@ import com.google.firebase.messaging.FirebaseMessaging import com.google.gson.Gson import com.hypertrack.hyperlog.HyperLog import com.mikepenz.iconics.Iconics -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont import im.wangchao.mhttp.MHttp import kotlinx.coroutines.* import me.leolin.shortcutbadger.ShortcutBadger @@ -159,7 +158,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope { .errorActivity(CrashActivity::class.java) .apply() Iconics.init(applicationContext) - Iconics.registerFont(SzkolnyFont) App.db = AppDb(this) Themes.themeInt = config.ui.theme devMode = config.debugMode diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index 084cace6..099763d2 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -23,16 +23,16 @@ import androidx.lifecycle.Observer import androidx.navigation.NavOptions import com.danimahardhika.cafebar.CafeBar import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.mikepenz.iconics.IconicsColor import com.mikepenz.iconics.IconicsDrawable -import com.mikepenz.iconics.IconicsSize import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont +import com.mikepenz.iconics.utils.colorInt +import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.materialdrawer.model.DividerDrawerItem import com.mikepenz.materialdrawer.model.ProfileDrawerItem import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem import com.mikepenz.materialdrawer.model.interfaces.* import com.mikepenz.materialdrawer.model.utils.withIsHiddenInMiniDrawer +import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.* import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe @@ -519,7 +519,11 @@ class MainActivity : AppCompatActivity(), CoroutineScope { navView.coordinator.postDelayed({ CafeBar.builder(this) .content(R.string.rate_snackbar_text) - .icon(IconicsDrawable(this).icon(CommunityMaterial.Icon2.cmd_star_outline).size(IconicsSize.dp(20)).color(IconicsColor.colorInt(Themes.getPrimaryTextColor(this)))) + .icon(IconicsDrawable(this).apply { + icon = CommunityMaterial.Icon2.cmd_star_outline + sizeDp = 20 + colorInt = Themes.getPrimaryTextColor(this@MainActivity) + }) .positiveText(R.string.rate_snackbar_positive) .positiveColor(-0xb350b0) .negativeText(R.string.rate_snackbar_negative) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt index ec212cea..35750f43 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt @@ -16,12 +16,12 @@ import com.github.tibolte.agendacalendarview.CalendarPickerController import com.github.tibolte.agendacalendarview.models.BaseCalendarEvent import com.github.tibolte.agendacalendarview.models.CalendarEvent import com.github.tibolte.agendacalendarview.models.IDayItem -import com.mikepenz.iconics.IconicsColor import com.mikepenz.iconics.IconicsDrawable -import com.mikepenz.iconics.IconicsSize import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial.Icon2 -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont +import com.mikepenz.iconics.utils.colorInt +import com.mikepenz.iconics.utils.sizeDp +import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity @@ -278,10 +278,11 @@ class AgendaFragment : Fragment(), CoroutineScope { val unreadEventDates = mutableSetOf() events.forEach { event -> - val eventIcon = IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_checkbox_blank_circle) - .size(IconicsSize.dp(10)) - .color(IconicsColor.colorInt(event.eventColor)) + val eventIcon = IconicsDrawable(activity).apply { + icon = CommunityMaterial.Icon.cmd_checkbox_blank_circle + sizeDp = 10 + colorInt = event.eventColor + } dayList.add(EventDay(event.startTimeCalendar, eventIcon)) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt index f495d61e..93f21191 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt @@ -13,9 +13,9 @@ import androidx.cardview.widget.CardView import androidx.recyclerview.widget.RecyclerView import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont import com.mikepenz.iconics.utils.colorRes import com.mikepenz.iconics.utils.sizeDp +import eu.szkolny.font.SzkolnyFont import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_MOBIDZIENNIK @@ -49,17 +49,26 @@ class NoticesAdapter//getting the context and product list with constructor holder.noticesItemAddedDate.text = Date.fromMillis(notice.addedDate).formattedString if (notice.type == Notice.TYPE_POSITIVE) { - holder.noticesItemType.setImageDrawable(IconicsDrawable(context, CommunityMaterial.Icon2.cmd_plus_circle_outline) - .colorRes(R.color.md_green_600) - .sizeDp(36)) + holder.noticesItemType.setImageDrawable( + IconicsDrawable(context, CommunityMaterial.Icon2.cmd_plus_circle_outline).apply { + colorRes = R.color.md_green_600 + sizeDp = 36 + } + ) } else if (notice.type == Notice.TYPE_NEGATIVE) { - holder.noticesItemType.setImageDrawable(IconicsDrawable(context, CommunityMaterial.Icon.cmd_alert_decagram_outline) - .colorRes(R.color.md_red_600) - .sizeDp(36)) + holder.noticesItemType.setImageDrawable( + IconicsDrawable(context, CommunityMaterial.Icon.cmd_alert_decagram_outline).apply { + colorRes = R.color.md_red_600 + sizeDp = 36 + } + ) } else { - holder.noticesItemType.setImageDrawable(IconicsDrawable(context, SzkolnyFont.Icon.szf_message_processing_outline) - .colorRes(R.color.md_blue_500) - .sizeDp(36)) + holder.noticesItemType.setImageDrawable( + IconicsDrawable(context, SzkolnyFont.Icon.szf_message_processing_outline).apply { + colorRes = R.color.md_blue_500 + sizeDp = 36 + } + ) } if (!notice.seen) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/CounterActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/CounterActivity.kt index e337f720..868b330f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/CounterActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/CounterActivity.kt @@ -7,9 +7,9 @@ package pl.szczodrzynski.edziennik.ui.modules.home import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.mikepenz.iconics.IconicsDrawable -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.sizeDp +import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.entity.Lesson @@ -59,9 +59,12 @@ class CounterActivity : AppCompatActivity(), CoroutineScope { } } - b.bellSync.setImageDrawable(IconicsDrawable(this@CounterActivity, SzkolnyFont.Icon.szf_alarm_bell_outline) - .colorInt(0xff404040.toInt()) - .sizeDp(36)) + b.bellSync.setImageDrawable( + IconicsDrawable(this@CounterActivity, SzkolnyFont.Icon.szf_alarm_bell_outline).apply { + colorInt = 0xff404040.toInt() + sizeDp = 36 + } + ) b.bellSync.onClick { BellSyncTimeChooseDialog(activity = this@CounterActivity) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt index 8afd7c04..944c60e8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt @@ -19,14 +19,13 @@ import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial.Icon -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont +import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.databinding.FragmentHomeBinding import pl.szczodrzynski.edziennik.ui.dialogs.home.StudentNumberDialog import pl.szczodrzynski.edziennik.ui.modules.home.cards.* -import pl.szczodrzynski.edziennik.utils.Themes import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem import kotlin.coroutines.CoroutineContext @@ -75,7 +74,7 @@ class HomeFragment : Fragment(), CoroutineScope { private lateinit var activity: MainActivity private lateinit var b: FragmentHomeBinding - private lateinit var job: Job + private val job: Job = Job() override val coroutineContext: CoroutineContext get() = job + Dispatchers.Main @@ -83,10 +82,8 @@ class HomeFragment : Fragment(), CoroutineScope { activity = (getActivity() as MainActivity?) ?: return null context ?: return null app = activity.application as App - context!!.theme.applyStyle(Themes.appTheme, true) b = FragmentHomeBinding.inflate(inflater) b.refreshLayout.setParent(activity.swipeRefreshLayout) - job = Job() return b.root } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt index 68363ec6..a530eefc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt @@ -15,8 +15,8 @@ import androidx.core.view.setMargins import androidx.lifecycle.Observer import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont import com.mikepenz.iconics.utils.sizeDp +import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.* import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe @@ -87,17 +87,26 @@ class HomeTimetableCard( } holder.root += b.root - b.settings.setImageDrawable(IconicsDrawable(activity, CommunityMaterial.Icon2.cmd_settings_outline) - .colorAttr(activity, R.attr.colorIcon) - .sizeDp(20)) + b.settings.setImageDrawable( + IconicsDrawable(activity, CommunityMaterial.Icon2.cmd_settings_outline).apply { + colorAttr(activity, R.attr.colorIcon) + sizeDp = 20 + } + ) - b.bellSync.setImageDrawable(IconicsDrawable(activity, SzkolnyFont.Icon.szf_alarm_bell_outline) - .colorAttr(activity, R.attr.colorIcon) - .sizeDp(20)) + b.bellSync.setImageDrawable( + IconicsDrawable(activity, SzkolnyFont.Icon.szf_alarm_bell_outline).apply { + colorAttr(activity, R.attr.colorIcon) + sizeDp = 20 + } + ) - b.showCounter.setImageDrawable(IconicsDrawable(activity, CommunityMaterial.Icon.cmd_fullscreen) - .colorAttr(activity, R.attr.colorIcon) - .sizeDp(20)) + b.showCounter.setImageDrawable( + IconicsDrawable(activity, CommunityMaterial.Icon.cmd_fullscreen).apply { + colorAttr(activity, R.attr.colorIcon) + sizeDp = 20 + } + ) b.bellSync.setOnClickListener { BellSyncTimeChooseDialog( diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkFragment.kt index 30abcd02..f757570a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkFragment.kt @@ -12,7 +12,7 @@ import android.view.ViewGroup import android.widget.Toast import androidx.fragment.app.Fragment import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont +import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt index 8776f355..9e00200b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginFormFragment.kt @@ -97,11 +97,12 @@ class LoginFormFragment : Fragment(), CoroutineScope { b.textEdit.id = credential.name b.textEdit.setText(arguments?.getString(credential.keyName) ?: "") - b.textLayout.startIconDrawable = IconicsDrawable(activity) - .icon(credential.icon) - .sizeDp(24) - .paddingDp(2) - .colorAttr(activity, R.attr.colorOnBackground) + b.textLayout.startIconDrawable = IconicsDrawable(activity).apply { + icon = credential.icon + sizeDp = 24 + paddingDp = 2 + colorAttr(activity, R.attr.colorOnBackground) + } this.b.formContainer.addView(b.root) credentials[credential] = b diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt index b2623b64..19106004 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt @@ -65,9 +65,10 @@ class MessageFragment : Fragment(), CoroutineScope { if (!isAdded) return b.closeButton.setImageDrawable( - IconicsDrawable(activity, CommunityMaterial.Icon2.cmd_window_close) - .colorAttr(activity, android.R.attr.textColorSecondary) - .sizeDp(12) + IconicsDrawable(activity, CommunityMaterial.Icon2.cmd_window_close).apply { + colorAttr(activity, android.R.attr.textColorSecondary) + sizeDp = 12 + } ) b.closeButton.setOnClickListener { activity.navigateUp() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsLicenseActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsLicenseActivity.kt index eb1a23e1..192f1273 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsLicenseActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsLicenseActivity.kt @@ -38,10 +38,11 @@ class SettingsLicenseActivity : MaterialAboutActivity() { license: OpenSourceLicense, libraryUrl: String): MaterialAboutCard { val licenseItem = MaterialAboutActionItem.Builder() - .icon(IconicsDrawable(this) - .icon(CommunityMaterial.Icon.cmd_book_outline) - .colorInt(foregroundColor) - .sizeDp(18)) + .icon(IconicsDrawable(this).apply { + icon = CommunityMaterial.Icon.cmd_book_outline + colorInt = foregroundColor + sizeDp = 18 + }) .setIconGravity(MaterialAboutActionItem.GRAVITY_TOP) .text(libraryTitle) .subText(String.format(getString(license.resourceId), copyrightYear, copyrightName)) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java index e1541d54..3a6bffe4 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java @@ -25,11 +25,11 @@ import com.danielstone.materialaboutlibrary.items.MaterialAboutSwitchItem; import com.danielstone.materialaboutlibrary.items.MaterialAboutTitleItem; import com.danielstone.materialaboutlibrary.model.MaterialAboutCard; import com.danielstone.materialaboutlibrary.model.MaterialAboutList; -import com.mikepenz.iconics.IconicsColor; import com.mikepenz.iconics.IconicsDrawable; -import com.mikepenz.iconics.IconicsSize; +import com.mikepenz.iconics.typeface.IIcon; import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial; -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont; +import com.mikepenz.iconics.utils.IconicsConvertersKt; +import com.mikepenz.iconics.utils.IconicsDrawableExtensionsKt; import com.theartofdev.edmodo.cropper.CropImage; import com.theartofdev.edmodo.cropper.CropImageView; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; @@ -40,6 +40,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import eu.szkolny.font.SzkolnyFont; +import kotlin.Unit; import pl.szczodrzynski.edziennik.App; import pl.szczodrzynski.edziennik.BuildConfig; import pl.szczodrzynski.edziennik.ExtensionsKt; @@ -90,6 +92,15 @@ public class SettingsNewFragment extends MaterialAboutFragment { private int secondaryTextOnPrimaryBg = -1; private int iconSizeDp = 20; + private IconicsDrawable icon(IIcon icon, int sizeDp, int color) { + return new IconicsDrawable(activity).apply((drawable) -> { + drawable.setIcon(icon); + IconicsConvertersKt.setSizeDp(drawable, sizeDp); + IconicsDrawableExtensionsKt.setColorInt(drawable, color); + return Unit.INSTANCE; + }); + } + private MaterialAboutCard getCardWithItems(CharSequence title, ArrayList items, boolean primaryColor) { MaterialAboutCard card = new MaterialAboutCard.Builder().title(title).cardColor(0xff1976D2).build(); card.getItems().addAll(items); @@ -120,10 +131,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { return new MaterialAboutActionItem( getString(R.string.settings_more_text), null, - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_chevron_down) - .size(IconicsSize.dp(14)) - .color(IconicsColor.colorInt(iconColor)), + icon(CommunityMaterial.Icon.cmd_chevron_down, 14, iconColor), onClickAction ); } @@ -209,10 +217,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_profile_change_password_text), getString(R.string.settings_profile_change_password_subtext), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_key_variant) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_key_variant, iconSizeDp, iconColor) ) .setOnClickAction(() -> { @@ -223,10 +228,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_add_student_text), getString(R.string.settings_add_student_subtext), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_account_plus_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon.cmd_account_plus_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { startActivity(new Intent(activity, LoginActivity.class)); @@ -237,10 +239,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_profile_notifications_text), getString(R.string.settings_profile_notifications_subtext), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_filter_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon.cmd_filter_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { new NotificationFilterDialog(activity, null, null); @@ -251,10 +250,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_profile_remove_text), getString(R.string.settings_profile_remove_subtext), - new IconicsDrawable(activity) - .icon(SzkolnyFont.Icon.szf_delete_empty_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(SzkolnyFont.Icon.szf_delete_empty_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { new ProfileRemoveDialog(activity, app.getProfile().getId(), app.getProfile().getName(), false); @@ -269,10 +265,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutSwitchItem.Builder() .text(R.string.settings_profile_sync_text) .subText(R.string.settings_profile_sync_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_account_convert) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon.cmd_account_convert, iconSizeDp, iconColor)) .setChecked(app.getProfile().getSyncEnabled()) .setOnCheckedChanged(((item, isChecked) -> { app.getProfile().setSyncEnabled(isChecked); @@ -302,10 +295,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutSwitchItem.Builder() .text(R.string.settings_theme_snowfall_text) .subText(R.string.settings_theme_snowfall_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_snowflake) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon2.cmd_snowflake, iconSizeDp, iconColor)) .setChecked(app.getConfig().getUi().getSnowfall()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getUi().setSnowfall(isChecked); @@ -320,10 +310,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_theme_theme_text), Themes.INSTANCE.getThemeName(activity), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_palette_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_palette_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { new MaterialDialog.Builder(activity) @@ -345,10 +332,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutSwitchItem.Builder() .text(R.string.settings_theme_mini_drawer_text) .subText(R.string.settings_theme_mini_drawer_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_dots_vertical) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon.cmd_dots_vertical, iconSizeDp, iconColor)) .setChecked(app.getConfig().getUi().getMiniMenuVisible()) .setOnCheckedChanged((item, isChecked) -> { // 0,1 1 @@ -370,10 +354,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_theme_mini_drawer_buttons_text), null, - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_format_list_checks) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon.cmd_format_list_checks, iconSizeDp, iconColor) ) .setOnClickAction(() -> { List buttonIds = new ArrayList<>(); @@ -434,10 +415,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_theme_drawer_header_text), null, - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_image_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_image_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { if (app.getConfig().getUi().getHeaderBackground() != null) { @@ -468,10 +446,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_theme_app_background_text), getString(R.string.settings_theme_app_background_subtext), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_image_filter_hdr) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_image_filter_hdr, iconSizeDp, iconColor) ) .setOnClickAction(() -> { if (app.getConfig().getUi().getAppBackground() != null) { @@ -497,10 +472,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add( new MaterialAboutSwitchItem.Builder( ) .text(R.string.settings_theme_open_drawer_on_back_pressed_text) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_menu_open) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon2.cmd_menu_open, iconSizeDp, iconColor)) .setChecked(app.getConfig().getUi().getOpenDrawerOnBackPressed()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getUi().setOpenDrawerOnBackPressed(isChecked); @@ -549,10 +521,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { return new MaterialAboutSwitchItem.Builder() .text(R.string.settings_sync_wifi_text) .subText(R.string.settings_sync_wifi_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_wifi_strength_2) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon2.cmd_wifi_strength_2, iconSizeDp, iconColor)) .setChecked(app.getConfig().getSync().getOnlyWifi()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getSync().setOnlyWifi(isChecked); @@ -570,10 +539,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { syncCardIntervalItem = new MaterialAboutActionSwitchItem.Builder() .text(R.string.settings_sync_sync_interval_text) .subText(R.string.settings_sync_sync_interval_subtext_disabled) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_download_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon.cmd_download_outline, iconSizeDp, iconColor)) .build(); syncCardIntervalItem.setSubTextChecked(getSyncCardIntervalSubText()); syncCardIntervalItem.setChecked(app.getConfig().getSync().getEnabled()); @@ -644,10 +610,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutSwitchItem( "Cisza na lekcjach", "Nie odtwarzaj dźwięku powiadomień podczas lekcji", - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_volume_off) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_volume_off, iconSizeDp, iconColor) ) .setChecked(app.appConfig.quietDuringLessons) .setOnChangeAction((isChecked) -> { @@ -661,10 +624,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { syncCardQuietHoursItem = new MaterialAboutActionSwitchItem.Builder() .text(R.string.settings_sync_quiet_hours_text) .subText(R.string.settings_sync_quiet_hours_subtext_disabled) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_bell_sleep_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon.cmd_bell_sleep_outline, iconSizeDp, iconColor)) .build(); syncCardQuietHoursItem.setChecked(app.getConfig().getSync().getQuietHoursEnabled()); syncCardQuietHoursItem.setSubTextChecked(getSyncCardQuietHoursSubText()); @@ -721,10 +681,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_sync_web_push_text), getString(R.string.settings_sync_web_push_subtext), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_laptop) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_laptop, iconSizeDp, iconColor) ) .setOnClickAction(() -> { activity.loadTarget(MainActivity.TARGET_WEB_PUSH, null); @@ -739,10 +696,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( "Dźwięk powiadomień", "Szkolny.eu", - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_volume_high) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_volume_high, iconSizeDp, iconColor) ) .setOnClickAction(() -> { @@ -752,10 +706,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add( new MaterialAboutSwitchItem.Builder() .text(R.string.settings_sync_updates_text) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_cellphone_arrow_down) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon.cmd_cellphone_arrow_down, iconSizeDp, iconColor)) .setChecked(app.getConfig().getSync().getNotifyAboutUpdates()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getSync().setNotifyAboutUpdates(isChecked); @@ -770,10 +721,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_sync_notifications_settings_text), getString(R.string.settings_sync_notifications_settings_subtext), - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_settings_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_settings_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { String channel = app.getNotificationChannelsManager().getData().getKey(); @@ -846,10 +794,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { return new MaterialAboutSwitchItem.Builder() .text(R.string.settings_register_shared_events_text) .subText(R.string.settings_register_shared_events_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_share_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon2.cmd_share_outline, iconSizeDp, iconColor)) .setChecked(app.getProfile().getEnableSharedEvents()) .setOnCheckedChanged((item, isChecked) -> { app.getProfile().setEnableSharedEvents(isChecked); @@ -877,28 +822,19 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem( getString(R.string.menu_grades_config), null, - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_numeric_5_box_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon2.cmd_numeric_5_box_outline, iconSizeDp, iconColor) ).setOnClickAction(() -> new GradesConfigDialog(activity, false, null, null))); items.add(new MaterialAboutActionItem( getString(R.string.menu_attendance_config), null, - new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_calendar_remove_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(CommunityMaterial.Icon.cmd_calendar_remove_outline, iconSizeDp, iconColor) ).setOnClickAction(() -> new AttendanceConfigDialog(activity, false, null, null))); registerCardAllowRegistrationItem = new MaterialAboutSwitchItem.Builder() .text(R.string.settings_register_allow_registration_text) .subText(R.string.settings_register_allow_registration_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_account_circle_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon.cmd_account_circle_outline, iconSizeDp, iconColor)) .build(); registerCardAllowRegistrationItem.setChecked(app.getProfile().getRegistration() == REGISTRATION_ENABLED); registerCardAllowRegistrationItem.setOnCheckedChangedAction((item, isChecked) -> { @@ -955,10 +891,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { registerCardBellSyncItem = new MaterialAboutActionItem( getString(R.string.settings_register_bell_sync_text), getRegisterCardBellSyncSubText(), - new IconicsDrawable(activity) - .icon(SzkolnyFont.Icon.szf_alarm_bell_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor)) + icon(SzkolnyFont.Icon.szf_alarm_bell_outline, iconSizeDp, iconColor) ); registerCardBellSyncItem.setOnClickAction(() -> { new MaterialDialog.Builder(activity) @@ -1025,10 +958,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutSwitchItem.Builder() .text(R.string.settings_register_count_in_seconds_text) .subText(R.string.settings_register_count_in_seconds_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_timer) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon2.cmd_timer, iconSizeDp, iconColor)) .setChecked(app.getConfig().getTimetable().getCountInSeconds()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getTimetable().setCountInSeconds(isChecked); @@ -1041,10 +971,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add( new MaterialAboutSwitchItem.Builder() .text(R.string.settings_register_show_teacher_absences_text) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_account_arrow_right_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon.cmd_account_arrow_right_outline, iconSizeDp, iconColor)) .setChecked(app.getProfile().getStudentData("showTeacherAbsences", true)) .setOnCheckedChanged((item, isChecked) -> { app.getProfile().putStudentData("showTeacherAbsences", isChecked); @@ -1059,10 +986,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add( new MaterialAboutSwitchItem.Builder() .text(R.string.settings_register_hide_sticks_from_old) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_numeric_1_box_outline) - .size(IconicsSize.dp(iconSizeDp)) - .color(IconicsColor.colorInt(iconColor))) + .icon(icon(CommunityMaterial.Icon2.cmd_numeric_1_box_outline, iconSizeDp, iconColor)) .setChecked(app.getConfig().forProfile().getGrades().getHideSticksFromOld()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().forProfile().getGrades().setHideSticksFromOld(isChecked); @@ -1098,10 +1022,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { pref_about_version = new MaterialAboutActionItem.Builder() .text(R.string.settings_about_version_text) .subText(BuildConfig.VERSION_NAME + ", " + BuildConfig.BUILD_TYPE) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_information_outline) - .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(CommunityMaterial.Icon2.cmd_information_outline, iconSizeDp, primaryTextOnPrimaryBg)) .build(); final int[] clickCounter = {0}; pref_about_version.setOnClickAction(() -> { @@ -1120,30 +1041,21 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_privacy_policy_text) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_shield_outline) - .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(CommunityMaterial.Icon2.cmd_shield_outline, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(ConvenienceBuilder.createWebsiteOnClickAction(activity, Uri.parse("https://szkolny.eu/privacy-policy"))) .build()); items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_discord_text) .subText(R.string.settings_about_discord_subtext) - .icon(new IconicsDrawable(activity) - .icon(SzkolnyFont.Icon.szf_discord_outline) - .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(SzkolnyFont.Icon.szf_discord_outline, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(ConvenienceBuilder.createWebsiteOnClickAction(activity, Uri.parse("https://szkolny.eu/discord"))) .build()); items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_language_text) .subText(R.string.settings_about_language_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_translate) - .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(CommunityMaterial.Icon2.cmd_translate, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(() -> { new MaterialDialog.Builder(activity) .title(getString(R.string.settings_about_language_dialog_title)) @@ -1178,10 +1090,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_update_text) .subText(R.string.settings_about_update_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_update) - .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(CommunityMaterial.Icon2.cmd_update, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(() -> { //open browser or intent here NetworkUtils net = new NetworkUtils(app); @@ -1201,19 +1110,13 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_changelog_text) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_radar) - .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(CommunityMaterial.Icon2.cmd_radar, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(() -> new ChangelogDialog(activity, null, null)) .build()); items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_licenses_text) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_code_braces) - .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(CommunityMaterial.Icon.cmd_code_braces, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(() -> { Intent intent = new Intent(activity, SettingsLicenseActivity.class); startActivity(intent); @@ -1222,10 +1125,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { /*items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_intro_text) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon2.cmd_projector_screen) - .color(IconicsColor.colorInt(iconColor)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(CommunityMaterial.Icon2.cmd_projector_screen, iconSizeDp, iconColor)) .setOnClickAction(() -> { if (tryingToDevMode[0]) { if (getParentFragment() instanceof SettingsGeneralFragment) { @@ -1246,10 +1146,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_crash_text) .subText(R.string.settings_about_crash_subtext) - .icon(new IconicsDrawable(activity) - .icon(CommunityMaterial.Icon.cmd_bug_outline) - .color(IconicsColor.colorInt(primaryTextOnPrimaryBg)) - .size(IconicsSize.dp(iconSizeDp))) + .icon(icon(CommunityMaterial.Icon.cmd_bug_outline, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(() -> { throw new RuntimeException("MANUAL CRASH"); }) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableFragment.kt index 52441e25..2e3695cc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableFragment.kt @@ -18,8 +18,8 @@ import androidx.fragment.app.Fragment import androidx.viewpager.widget.ViewPager import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial.Icon2 -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont import com.wdullaer.materialdatetimepicker.date.DatePickerDialog +import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentAdapter.kt index 1975f39e..99abba4d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentAdapter.kt @@ -11,11 +11,10 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import com.google.android.material.chip.Chip import com.mikepenz.iconics.IconicsDrawable -import com.mikepenz.iconics.typeface.IIcon import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont import com.mikepenz.iconics.utils.paddingDp import com.mikepenz.iconics.utils.sizeDp +import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -60,7 +59,7 @@ class AttachmentAdapter( val fileName = item.name.substringBefore(":http") // create an icon for the attachment - val icon: IIcon = when (Utils.getExtensionFromFileName(fileName)) { + val attachmentIcon = when (Utils.getExtensionFromFileName(fileName)) { "doc", "docx", "odt", "rtf" -> SzkolnyFont.Icon.szf_file_word_outline "xls", "xlsx", "ods" -> SzkolnyFont.Icon.szf_file_excel_outline "ppt", "pptx", "odp" -> SzkolnyFont.Icon.szf_file_powerpoint_outline @@ -82,15 +81,17 @@ class AttachmentAdapter( } ?: fileName } - b.chip.chipIcon = IconicsDrawable(context) - .icon(icon) - .colorAttr(context, R.attr.colorOnSurface) - .sizeDp(24) - .paddingDp(2) - b.chip.closeIcon = IconicsDrawable(context) - .icon(CommunityMaterial.Icon.cmd_check) - .colorAttr(context, R.attr.colorOnSurface) - .sizeDp(18) + b.chip.chipIcon = IconicsDrawable(context).apply { + icon = attachmentIcon + colorAttr(context, R.attr.colorSurface) + sizeDp = 24 + paddingDp = 2 + } + b.chip.closeIcon = IconicsDrawable(context).apply { + icon = CommunityMaterial.Icon.cmd_check + colorAttr(context, R.attr.colorOnSurface) + sizeDp = 18 + } b.chip.isCloseIconVisible = item.isDownloaded && !item.isDownloading // prevent progress bar flickering diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/notifications/WidgetNotificationsProvider.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/notifications/WidgetNotificationsProvider.kt index aec64aef..3832b6c7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/notifications/WidgetNotificationsProvider.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/notifications/WidgetNotificationsProvider.kt @@ -48,10 +48,10 @@ class WidgetNotificationsProvider : AppWidgetProvider() { views.setImageViewBitmap( R.id.widgetNotificationsSync, - IconicsDrawable(context, CommunityMaterial.Icon.cmd_download_outline) - .colorInt(Color.WHITE) - .sizeDp(iconSize) - .toBitmap() + IconicsDrawable(context, CommunityMaterial.Icon.cmd_download_outline).apply { + colorInt = Color.WHITE + sizeDp = iconSize + }.toBitmap() ) views.setViewVisibility(R.id.widgetNotificationsLoading, View.GONE) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableFactory.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableFactory.java index 6f81bf2c..8a351b1f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableFactory.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableFactory.java @@ -24,13 +24,14 @@ import android.widget.RemoteViewsService; import androidx.annotation.DrawableRes; -import com.mikepenz.iconics.IconicsColor; import com.mikepenz.iconics.IconicsDrawable; -import com.mikepenz.iconics.IconicsSize; import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial; +import com.mikepenz.iconics.utils.IconicsConvertersKt; +import com.mikepenz.iconics.utils.IconicsDrawableExtensionsKt; import java.util.List; +import kotlin.Unit; import pl.szczodrzynski.edziennik.R; import pl.szczodrzynski.edziennik.utils.models.Date; import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel; @@ -126,6 +127,15 @@ public class WidgetTimetableFactory implements RemoteViewsService.RemoteViewsFac return resultBitmap; } + private Bitmap homeIconBitmap() { + return new IconicsDrawable(context).apply((drawable) -> { + IconicsConvertersKt.setColorRes(drawable, R.color.md_red_500); + IconicsConvertersKt.setSizeDp(drawable, 10); + IconicsDrawableExtensionsKt.icon(drawable, CommunityMaterial.Icon2.cmd_home); + return Unit.INSTANCE; + }).toBitmap(); + } + @Override public RemoteViews getViewAt(int i) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.row_widget_timetable_item); @@ -270,19 +280,19 @@ public class WidgetTimetableFactory implements RemoteViewsService.RemoteViewsFac if (lesson.eventColors.size() >= 1) { views.setViewVisibility(R.id.widgetTimetableEvent1, View.VISIBLE); if (lesson.eventColors.get(0) == -1) - views.setBitmap(R.id.widgetTimetableEvent1, "setImageBitmap", new IconicsDrawable(context).color(IconicsColor.colorRes(R.color.md_red_500)).size(IconicsSize.dp(10)).icon(CommunityMaterial.Icon2.cmd_home).toBitmap()); + views.setBitmap(R.id.widgetTimetableEvent1, "setImageBitmap", homeIconBitmap()); else views.setBitmap(R.id.widgetTimetableEvent1, "setImageBitmap", getColoredBitmap(context, R.drawable.event_color_circle, lesson.eventColors.get(0), eventIndicatorSize, eventIndicatorSize)); if (lesson.eventColors.size() >= 2) { views.setViewVisibility(R.id.widgetTimetableEvent2, View.VISIBLE); if (lesson.eventColors.get(1) == -1) - views.setBitmap(R.id.widgetTimetableEvent2, "setImageBitmap", new IconicsDrawable(context).color(IconicsColor.colorRes(R.color.md_red_500)).size(IconicsSize.dp(10)).icon(CommunityMaterial.Icon2.cmd_home).toBitmap()); + views.setBitmap(R.id.widgetTimetableEvent2, "setImageBitmap", homeIconBitmap()); else views.setBitmap(R.id.widgetTimetableEvent2, "setImageBitmap", getColoredBitmap(context, R.drawable.event_color_circle, lesson.eventColors.get(1), eventIndicatorSize, eventIndicatorSize)); if (lesson.eventColors.size() >= 3) { views.setViewVisibility(R.id.widgetTimetableEvent3, View.VISIBLE); if (lesson.eventColors.get(2) == -1) - views.setBitmap(R.id.widgetTimetableEvent3, "setImageBitmap", new IconicsDrawable(context).color(IconicsColor.colorRes(R.color.md_red_500)).size(IconicsSize.dp(10)).icon(CommunityMaterial.Icon2.cmd_home).toBitmap()); + views.setBitmap(R.id.widgetTimetableEvent3, "setImageBitmap", homeIconBitmap()); else views.setBitmap(R.id.widgetTimetableEvent3, "setImageBitmap", getColoredBitmap(context, R.drawable.event_color_circle, lesson.eventColors.get(2), eventIndicatorSize, eventIndicatorSize)); } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt index bc284ba2..07db9ea2 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt @@ -115,13 +115,21 @@ class WidgetTimetableProvider : AppWidgetProvider() { views.setOnClickPendingIntent(R.id.widgetTimetableSync, getPendingSelfIntent(context, ACTION_SYNC_DATA)) - views.setImageViewBitmap(R.id.widgetTimetableRefresh, IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh) - .colorInt(Color.WHITE) - .sizeDp(if (config.bigStyle) 24 else 16).toBitmap()) + views.setImageViewBitmap( + R.id.widgetTimetableRefresh, + IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh).apply { + colorInt = Color.WHITE + sizeDp = if (config.bigStyle) 24 else 16 + }.toBitmap() + ) - views.setImageViewBitmap(R.id.widgetTimetableSync, IconicsDrawable(context, CommunityMaterial.Icon.cmd_download_outline) - .colorInt(Color.WHITE) - .sizeDp(if (config.bigStyle) 24 else 16).toBitmap()) + views.setImageViewBitmap( + R.id.widgetTimetableSync, + IconicsDrawable(context, CommunityMaterial.Icon.cmd_download_outline).apply { + colorInt = Color.WHITE + sizeDp = if (config.bigStyle) 24 else 16 + }.toBitmap() + ) prepareAppWidget(app, appWidgetId, views, config, bellSyncDiffMillis) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/SwipeRefreshLayoutNoIndicator.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/SwipeRefreshLayoutNoIndicator.java new file mode 100644 index 00000000..75192eec --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/SwipeRefreshLayoutNoIndicator.java @@ -0,0 +1,208 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package pl.szczodrzynski.edziennik.utils; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +/** + * The SwipeRefreshLayout should be used whenever the user can refresh the + * contents of a view via a vertical swipe gesture. The activity that + * instantiates this view should add an OnRefreshListener to be notified + * whenever the swipe to refresh gesture is completed. The SwipeRefreshLayout + * will notify the listener each and every time the gesture is completed again; + * the listener is responsible for correctly determining when to actually + * initiate a refresh of its content. If the listener determines there should + * not be a refresh, it must call setRefreshing(false) to cancel any visual + * indication of a refresh. If an activity wishes to show just the progress + * animation, it should call setRefreshing(true). To disable the gesture and + * progress animation, call setEnabled(false) on the view. + *

+ * This layout should be made the parent of the view that will be refreshed as a + * result of the gesture and can only support one direct child. This view will + * also be made the target of the gesture and will be forced to match both the + * width and the height supplied in this layout. The SwipeRefreshLayout does not + * provide accessibility events; instead, a menu item must be provided to allow + * refresh of the content wherever this gesture is used. + *

+ */ +public class SwipeRefreshLayoutNoIndicator extends SwipeRefreshLayout { + + private SwipeRefreshLayoutNoTouch parent; + + @Override + public void setEnabled(boolean enabled) { + if (parent == null) + return; + parent.setEnabled(enabled); + super.setEnabled(enabled); + } + + public void setParent(SwipeRefreshLayoutNoTouch parent) { + this.parent = parent; + } + + /** + * Simple constructor to use when creating a SwipeRefreshLayout from code. + * + * @param context + */ + public SwipeRefreshLayoutNoIndicator(@NonNull Context context) { + this(context, null); + } + + /** + * Constructor that is called when inflating SwipeRefreshLayout from XML. + * + * @param context + * @param attrs + */ + public SwipeRefreshLayoutNoIndicator(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + ev.setSource(0x10000000); + boolean parentConsumed = parent.onInterceptTouchEvent(ev); + boolean superConsumed = super.onInterceptTouchEvent(ev); + return parentConsumed && superConsumed; + /*if (super.onInterceptTouchEvent(ev)) + return parent.onInterceptTouchEvent(ev); + return false;*/ + } + + @Override + public void requestDisallowInterceptTouchEvent(boolean b) { + parent.requestDisallowInterceptTouchEvent(b); + } + + // NestedScrollingParent + + @Override + public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { + parent.onStartNestedScroll(child, target, nestedScrollAxes); + return !parent.isRefreshing() && super.onStartNestedScroll(child, target, nestedScrollAxes); + } + + @Override + public void onNestedScrollAccepted(View child, View target, int axes) { + parent.onNestedScrollAccepted(child, target, axes); + } + + @Override + public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { + parent.onNestedPreScroll(target, dx, dy, consumed); + } + + @Override + public int getNestedScrollAxes() { + return parent.getNestedScrollAxes(); + } + + @Override + public void onStopNestedScroll(View target) { + parent.onStopNestedScroll(target); + } + + @Override + public void onNestedScroll(final View target, final int dxConsumed, final int dyConsumed, + final int dxUnconsumed, final int dyUnconsumed) { + parent.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); + } + + // NestedScrollingChild + + @Override + public void setNestedScrollingEnabled(boolean enabled) { + if (parent == null) + return; + //parent.setNestedScrollingEnabled(enabled); + super.setNestedScrollingEnabled(enabled); + } + + @Override + public boolean isNestedScrollingEnabled() { + return parent.isNestedScrollingEnabled(); + } + + @Override + public boolean startNestedScroll(int axes) { + return parent.startNestedScroll(axes); + } + + @Override + public void stopNestedScroll() { + parent.stopNestedScroll(); + } + + @Override + public boolean hasNestedScrollingParent() { + return parent.hasNestedScrollingParent(); + } + + @Override + public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, + int dyUnconsumed, int[] offsetInWindow) { + return super.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); + } + + @Override + public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { + return super.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); + } + + @Override + public boolean onNestedPreFling(View target, float velocityX, + float velocityY) { + return parent.onNestedPreFling(target, velocityX, velocityY); + } + + @Override + public boolean onNestedFling(View target, float velocityX, float velocityY, + boolean consumed) { + return parent.onNestedFling(target, velocityX, velocityY, consumed); + } + + @Override + public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { + return parent.dispatchNestedFling(velocityX, velocityY, consumed); + } + + @Override + public boolean dispatchNestedPreFling(float velocityX, float velocityY) { + return parent.dispatchNestedPreFling(velocityX, velocityY); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + ev.setSource(0x10000000); + /*boolean consumed = super.onTouchEvent(ev); + if (consumed) { + return false; + }*/ + return parent.onTouchEvent(ev); + } + + +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/SwipeRefreshLayoutNoTouch.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/SwipeRefreshLayoutNoTouch.java new file mode 100644 index 00000000..0b2daf51 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/SwipeRefreshLayoutNoTouch.java @@ -0,0 +1,51 @@ +package pl.szczodrzynski.edziennik.utils; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + + +public class SwipeRefreshLayoutNoTouch extends SwipeRefreshLayout { + public SwipeRefreshLayoutNoTouch(@NonNull Context context) { + super(context); + } + + public SwipeRefreshLayoutNoTouch(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { + return false; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (ev.getSource() == 0x10000000) { + // forward the event to super + return super.onInterceptTouchEvent(ev); + } + // discard all the other events + return false; + + /*if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) + return false; + super.onInterceptTouchEvent(ev); + return false;*/ + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (ev.getSource() == 0x10000000) { + // forward the event to super + return super.onTouchEvent(ev); + } + // discard all the other events + return false; + } +} diff --git a/build.gradle b/build.gradle index c0fb9910..fd64a16a 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ buildscript { materialdialogs : "0.9.6.0", materialdrawer : "817e45765c367034b03046aaea6e95eeabcb40e9", - iconics : "4.0.1", + iconics : "5.2.8", font_cmd : "3.5.95.1-kotlin", navlib : "28cdab341470dffa5f331379fe9702482681d7de", diff --git a/settings.gradle b/settings.gradle index 680b7d04..a1b55163 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,7 +3,7 @@ include ':wear' include ':codegen' include ':annotation' rootProject.name='Szkolny.eu' -include ':app', ':szkolny-font' +include ':app' /* include ':Navigation' project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/ diff --git a/szkolny-font/build.gradle b/szkolny-font/build.gradle deleted file mode 100644 index 70d20b0d..00000000 --- a/szkolny-font/build.gradle +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Mike Penz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'com.android.library' - -apply plugin: 'kotlin-android' - -android { - compileSdkVersion setup.compileSdk - - defaultConfig { - minSdkVersion setup.minSdk - targetSdkVersion setup.targetSdk - consumerProguardFiles 'consumer-proguard-rules.pro' - versionCode 11 - versionName "1.1" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - debugMinify { - debuggable = true - minifyEnabled = true - proguardFiles 'proguard-android.txt' - } - } -} -if (project.hasProperty('pushall') || project.hasProperty('SzkolnyFontonly')) { - apply from: '../gradle-mvn-push.gradle' -} - -dependencies { - implementation "com.mikepenz:iconics-core:${versions.iconics}" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}" -} diff --git a/szkolny-font/consumer-proguard-rules.pro b/szkolny-font/consumer-proguard-rules.pro deleted file mode 100644 index 61d1083d..00000000 --- a/szkolny-font/consumer-proguard-rules.pro +++ /dev/null @@ -1 +0,0 @@ --keep class com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont { *; } diff --git a/szkolny-font/gradle.properties b/szkolny-font/gradle.properties deleted file mode 100644 index 82ee377a..00000000 --- a/szkolny-font/gradle.properties +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright 2014 Mike Penz -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Settings specified in this file will override any Gradle settings -# configured through the IDE. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -VERSION_NAME=1.0 -VERSION_CODE=1 - -POM_NAME=Android-Iconics Szkolny.eu Icon Font Typeface Library -POM_ARTIFACT_ID=szkolny-font-typeface -POM_PACKAGING=aar diff --git a/szkolny-font/src/main/AndroidManifest.xml b/szkolny-font/src/main/AndroidManifest.xml deleted file mode 100644 index e4bf2179..00000000 --- a/szkolny-font/src/main/AndroidManifest.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/szkolny-font/src/main/java/com/mikepenz/iconics/typeface/library/szkolny/font/SzkolnyFont.kt b/szkolny-font/src/main/java/com/mikepenz/iconics/typeface/library/szkolny/font/SzkolnyFont.kt deleted file mode 100644 index 5e23dbd1..00000000 --- a/szkolny-font/src/main/java/com/mikepenz/iconics/typeface/library/szkolny/font/SzkolnyFont.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2019 Mike Penz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.mikepenz.iconics.typeface.library.szkolny.font - -import com.mikepenz.iconics.typeface.IIcon -import com.mikepenz.iconics.typeface.ITypeface -import com.mikepenz.iconics.typeface.library.szkolny.R -import java.util.* - -@Suppress("EnumEntryName") -object SzkolnyFont : ITypeface { - - override val fontRes: Int - get() = R.font.szkolny_font_font_v1_1 - - override val characters: Map by lazy { - Icon.values().associate { it.name to it.character } - } - - override val mappingPrefix: String - get() = "szf" - - override val fontName: String - get() = "Szkolny Font" - - override val version: String - get() = "1.1" - - override val iconCount: Int - get() = characters.size - - override val icons: List - get() = characters.keys.toCollection(LinkedList()) - - override val author: String - get() = "Kuba" - - override val url: String - get() = "" - - override val description: String - get() = "" - - override val license: String - get() = "" - - override val licenseUrl: String - get() = "" - - override fun getIcon(key: String): IIcon = Icon.valueOf(key) - - enum class Icon constructor(override val character: Char) : IIcon { - szf_alarm_bell_outline('\ue800'), - szf_calendar_plus_outline('\ue801'), - szf_calendar_today_outline('\ue802'), - szf_clipboard_list_outline('\ue803'), - szf_delete_empty_outline('\ue804'), - szf_discord_outline('\ue805'), - szf_file_code_outline('\ue806'), - szf_file_excel_outline('\ue807'), - szf_file_image_outline('\ue808'), - szf_file_music_outline('\ue809'), - szf_file_pdf_outline('\ue80a'), - szf_file_percent_outline('\ue80b'), - szf_file_powerpoint_outline('\ue80c'), - szf_file_video_outline('\ue80d'), - szf_file_word_outline('\ue80e'), - szf_message_processing_outline('\ue80f'), - szf_notebook_outline('\ue810'), - szf_zip_box_outline('\ue811'); - - override val typeface: ITypeface by lazy { SzkolnyFont } - } -} \ No newline at end of file diff --git a/szkolny-font/src/main/res/font/szkolny_font_font_v1_1.ttf b/szkolny-font/src/main/res/font/szkolny_font_font_v1_1.ttf deleted file mode 100644 index 33ad627f3fa830143956fc4b3e8e5d0bb8abaaf2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11232 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 diff --git a/szkolny-font/src/main/res/values/font_addon.xml b/szkolny-font/src/main/res/values/font_addon.xml deleted file mode 100644 index 3ea04e70..00000000 --- a/szkolny-font/src/main/res/values/font_addon.xml +++ /dev/null @@ -1,2 +0,0 @@ - - From ea3598bb6d9a6a6263629207458c90e377976d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 21 Mar 2021 18:21:14 +0100 Subject: [PATCH 07/15] [Gradle] Extract selective-dao dependency. --- annotation/.gitignore | 1 - annotation/build.gradle | 29 -- .../edziennik/annotation/SelectiveDao.kt | 14 - .../edziennik/annotation/UpdateSelective.kt | 13 - app/build.gradle | 5 +- .../edziennik/data/db/dao/AnnouncementDao.kt | 4 +- .../edziennik/data/db/dao/AttendanceDao.kt | 4 +- .../edziennik/data/db/dao/EventDao.kt | 4 +- .../edziennik/data/db/dao/GradeDao.kt | 4 +- .../edziennik/data/db/dao/LuckyNumberDao.kt | 4 +- .../edziennik/data/db/dao/MessageDao.kt | 4 +- .../edziennik/data/db/dao/NoticeDao.kt | 4 +- .../data/db/dao/TeacherAbsenceDao.kt | 4 +- .../edziennik/data/db/dao/TimetableDao.kt | 4 +- codegen/.gitignore | 1 - codegen/build.gradle | 39 -- .../edziennik/codegen/FileGenerator.kt | 342 ------------------ settings.gradle | 2 - 18 files changed, 20 insertions(+), 462 deletions(-) delete mode 100644 annotation/.gitignore delete mode 100644 annotation/build.gradle delete mode 100644 annotation/src/main/java/pl/szczodrzynski/edziennik/annotation/SelectiveDao.kt delete mode 100644 annotation/src/main/java/pl/szczodrzynski/edziennik/annotation/UpdateSelective.kt delete mode 100644 codegen/.gitignore delete mode 100644 codegen/build.gradle delete mode 100644 codegen/src/main/java/pl/szczodrzynski/edziennik/codegen/FileGenerator.kt diff --git a/annotation/.gitignore b/annotation/.gitignore deleted file mode 100644 index 796b96d1..00000000 --- a/annotation/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/annotation/build.gradle b/annotation/build.gradle deleted file mode 100644 index ee7f6d51..00000000 --- a/annotation/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-3-28. - */ - -apply plugin: 'java-library' -apply plugin: 'kotlin' -apply plugin: 'kotlin-kapt' - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} - -sourceCompatibility = "7" -targetCompatibility = "7" - -repositories { - mavenCentral() -} -compileKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} -compileTestKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} diff --git a/annotation/src/main/java/pl/szczodrzynski/edziennik/annotation/SelectiveDao.kt b/annotation/src/main/java/pl/szczodrzynski/edziennik/annotation/SelectiveDao.kt deleted file mode 100644 index d37e5b0a..00000000 --- a/annotation/src/main/java/pl/szczodrzynski/edziennik/annotation/SelectiveDao.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-3-28. - */ - -package pl.szczodrzynski.edziennik.annotation - -import kotlin.reflect.KClass - -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.SOURCE) -@MustBeDocumented -annotation class SelectiveDao( - val db: KClass<*> -) diff --git a/annotation/src/main/java/pl/szczodrzynski/edziennik/annotation/UpdateSelective.kt b/annotation/src/main/java/pl/szczodrzynski/edziennik/annotation/UpdateSelective.kt deleted file mode 100644 index 224fca1c..00000000 --- a/annotation/src/main/java/pl/szczodrzynski/edziennik/annotation/UpdateSelective.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-3-28. - */ - -package pl.szczodrzynski.edziennik.annotation - -@Target(AnnotationTarget.FUNCTION) -@Retention(AnnotationRetention.SOURCE) -@MustBeDocumented -annotation class UpdateSelective( - val primaryKeys: Array, - val skippedColumns: Array = [] -) diff --git a/app/build.gradle b/app/build.gradle index 4ad2fc5f..47d1b31b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -167,6 +167,8 @@ dependencies { implementation "eu.szkolny:nachos:0e5dfcaceb" //implementation project(":Navigation") implementation "eu.szkolny:szkolny-font:1dab7d64ed" + implementation "eu.szkolny.selective-dao:annotation:27f8f3f194" + kapt "eu.szkolny.selective-dao:codegen:27f8f3f194" implementation "com.github.ChuckerTeam.Chucker:library:3.0.1" //releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:3.0.1" @@ -195,9 +197,6 @@ dependencies { implementation 'com.github.kuba2k2:NumberSlidingPicker:2921225f76' - implementation project(":annotation") - kapt project(":codegen") - implementation 'com.google.android:flexbox:2.0.1' implementation 'com.qifan.powerpermission:powerpermission:1.3.0' diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.kt index 67e034c5..88b3ccd1 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.kt @@ -8,9 +8,9 @@ import androidx.room.Dao import androidx.room.Query import androidx.room.RawQuery import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.Announcement import pl.szczodrzynski.edziennik.data.db.entity.Metadata diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt index 97513689..3ffdc1b8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt @@ -8,9 +8,9 @@ import androidx.room.Dao import androidx.room.Query import androidx.room.RawQuery import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.Attendance import pl.szczodrzynski.edziennik.data.db.entity.Metadata diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.kt index a532602b..897d53ff 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.kt @@ -10,9 +10,9 @@ import androidx.room.RawQuery import androidx.room.Transaction import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.Event import pl.szczodrzynski.edziennik.data.db.entity.Metadata diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/GradeDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/GradeDao.kt index 4fcfc721..6254f80b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/GradeDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/GradeDao.kt @@ -9,9 +9,9 @@ import androidx.room.Query import androidx.room.RawQuery import androidx.room.Transaction import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.Grade import pl.szczodrzynski.edziennik.data.db.entity.Metadata diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.kt index ad44c0d3..3c752124 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.kt @@ -8,9 +8,9 @@ import androidx.room.Dao import androidx.room.Query import androidx.room.RawQuery import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber import pl.szczodrzynski.edziennik.data.db.entity.Metadata diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt index a0be36ab..51d56854 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt @@ -8,9 +8,9 @@ import androidx.room.Dao import androidx.room.Query import androidx.room.RawQuery import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.Message import pl.szczodrzynski.edziennik.data.db.entity.Metadata diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/NoticeDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/NoticeDao.kt index 79bae175..51f3e839 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/NoticeDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/NoticeDao.kt @@ -8,9 +8,9 @@ import androidx.room.Dao import androidx.room.Query import androidx.room.RawQuery import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.Notice diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TeacherAbsenceDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TeacherAbsenceDao.kt index 1528adf1..f12248b8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TeacherAbsenceDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TeacherAbsenceDao.kt @@ -8,9 +8,9 @@ import androidx.room.Dao import androidx.room.Query import androidx.room.RawQuery import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.data.db.entity.TeacherAbsence diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TimetableDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TimetableDao.kt index cc236dc6..c7cbee12 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TimetableDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/TimetableDao.kt @@ -8,9 +8,9 @@ import androidx.room.Dao import androidx.room.Query import androidx.room.RawQuery import androidx.sqlite.db.SupportSQLiteQuery +import eu.szkolny.selectivedao.annotation.SelectiveDao +import eu.szkolny.selectivedao.annotation.UpdateSelective import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective import pl.szczodrzynski.edziennik.data.db.AppDb import pl.szczodrzynski.edziennik.data.db.entity.Lesson import pl.szczodrzynski.edziennik.data.db.entity.Metadata diff --git a/codegen/.gitignore b/codegen/.gitignore deleted file mode 100644 index 796b96d1..00000000 --- a/codegen/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/codegen/build.gradle b/codegen/build.gradle deleted file mode 100644 index e2630bd0..00000000 --- a/codegen/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-3-28. - */ - -apply plugin: 'java-library' -apply plugin: 'kotlin' -apply plugin: 'kotlin-kapt' - -kapt { - generateStubs = true -} - -sourceSets { - main { - java { - srcDir "${buildDir.absolutePath}/tmp/kapt/main/kotlinGenerated/" - } - } -} - - -dependencies { - kapt project(":annotation") - compileOnly project(':annotation') - implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - - // configuration generator for service providers - implementation "com.google.auto.service:auto-service:1.0-rc4" - kapt "com.google.auto.service:auto-service:1.0-rc4" - kapt "androidx.room:room-compiler:${versions.room}" - implementation "androidx.room:room-runtime:${versions.room}" - implementation "com.squareup:kotlinpoet:1.5.0" - implementation "androidx.sqlite:sqlite:2.1.0@aar" - -} - -sourceCompatibility = "7" -targetCompatibility = "7" diff --git a/codegen/src/main/java/pl/szczodrzynski/edziennik/codegen/FileGenerator.kt b/codegen/src/main/java/pl/szczodrzynski/edziennik/codegen/FileGenerator.kt deleted file mode 100644 index 5b5b1f71..00000000 --- a/codegen/src/main/java/pl/szczodrzynski/edziennik/codegen/FileGenerator.kt +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) Kuba Szczodrzyński 2020-3-28. - */ - -package pl.szczodrzynski.edziennik.codegen - -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.Ignore -import androidx.room.TypeConverters -import com.google.auto.service.AutoService -import com.squareup.kotlinpoet.* -import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy -import pl.szczodrzynski.edziennik.annotation.SelectiveDao -import pl.szczodrzynski.edziennik.annotation.UpdateSelective -import java.io.File -import javax.annotation.processing.* -import javax.lang.model.SourceVersion -import javax.lang.model.element.* -import javax.lang.model.type.* -import javax.lang.model.util.ElementFilter -import javax.tools.Diagnostic -import kotlin.reflect.KClass - -@Suppress("unused") -@AutoService(Processor::class) -@SupportedSourceVersion(SourceVersion.RELEASE_8) -@SupportedOptions(FileGenerator.KAPT_KOTLIN_GENERATED_OPTION_NAME) -class FileGenerator : AbstractProcessor() { - companion object { - const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated" - } - - private data class TypeConverter(val dataType: TypeMirror, val converterType: TypeElement, val methodName: Name, val returnType: TypeMirror) - - private inline fun Element.getAnnotationClassValue(f: T.() -> KClass<*>) = try { - getAnnotation(T::class.java).f() - throw Exception("Expected to get a MirroredTypeException") - } catch (e: MirroredTypeException) { - e.typeMirror - } - private inline fun Element.getAnnotationClassValues(f: T.() -> Array>) = try { - getAnnotation(T::class.java).f() - throw Exception("Expected to get a MirroredTypesException") - } catch (e: MirroredTypesException) { - e.typeMirrors - } - - override fun process(set: MutableSet?, roundEnvironment: RoundEnvironment?): Boolean { - roundEnvironment?.getElementsAnnotatedWith(SelectiveDao::class.java)?.forEach { it -> - if (it.kind != ElementKind.CLASS) { - processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "Can only be applied to classes, element: $it") - return false - } - - val generatedSourcesRoot = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME] - if (generatedSourcesRoot?.isEmpty() != false) { - processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "Can't find the target directory for generated Kotlin files.") - return false - } - - val file = File(generatedSourcesRoot) - file.mkdirs() - - val dao = it as TypeElement - processClass(dao, file) - - //processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "package = $packageName, className = $className, methodName = $methodName, tableName = $tableName, paramName = $paramName, paramClass = $paramClass") - } - return true - } - - private fun processClass(dao: TypeElement, file: File) { - val daoName = dao.simpleName.toString() - val packageName = processingEnv.elementUtils.getPackageOf(dao).toString() - - val dbType = processingEnv.typeUtils.asElement(dao.getAnnotationClassValue { db }) as TypeElement - val typeConverters = dbType.getAnnotationClassValues { value }.map { - processingEnv.typeUtils.asElement(it) as TypeElement - }.map { type -> - processingEnv.elementUtils.getAllMembers(type).mapNotNull { element -> - if (element is ExecutableElement) { - if (element.returnType.toString() == "java.lang.String" - || element.returnType.toString() == "java.lang.Long" - || element.returnType.toString() == "java.lang.Integer" - || element.returnType.kind.isPrimitive) { - if (element.simpleName.startsWith("to") && element.parameters.isNotEmpty()) - return@mapNotNull TypeConverter(element.parameters.first().asType(), type, element.simpleName, element.returnType) - } - } - null - } - }.flatten() - - //processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "c = ${typeConverters.joinToString()}") - - val roomDatabase = ClassName("androidx.room", "RoomDatabase") - val selective = TypeSpec.classBuilder("${daoName}Selective") - .primaryConstructor(FunSpec.constructorBuilder() - .addParameter("__db", roomDatabase, KModifier.PRIVATE) - .build()) - .addProperty(PropertySpec.builder("__db", roomDatabase) - .initializer("__db") - .addModifiers(KModifier.PRIVATE) - .build()) - - val usedTypeConverters = mutableSetOf() - - processingEnv.elementUtils.getAllMembers(dao).forEach { element -> - if (element.kind != ElementKind.METHOD) - return@forEach - val method = element as ExecutableElement - val annotation = method.getAnnotation(UpdateSelective::class.java) ?: return@forEach - usedTypeConverters.addAll(processMethod(selective, method, annotation, typeConverters)) - } - - usedTypeConverters.forEach { converter -> - selective.addProperty(PropertySpec.builder("__${converter.converterType.simpleName}", converter.converterType.asType().asTypeName(), KModifier.PRIVATE) - .delegate(CodeBlock.builder() - .beginControlFlow("lazy") - .addStatement("%T()", converter.converterType.asType().asTypeName()) - .endControlFlow() - .build()) - .build()) - } - - FileSpec.builder(packageName, "${daoName}Selective") - .addType(selective.build()) - .build() - .writeTo(file) - } - - private fun VariableElement.name() = getAnnotation(ColumnInfo::class.java)?.name ?: simpleName.toString() - - private fun processMethod(cls: TypeSpec.Builder, method: ExecutableElement, annotation: UpdateSelective, typeConverters: List): List { - val methodName = method.simpleName.toString() - val parameter = method.parameters.first() - val paramName = parameter.simpleName.toString() - val paramTypeElement = processingEnv.typeUtils.asElement(parameter.asType()) as TypeElement - val paramTypeAnnotation = paramTypeElement.getAnnotation(Entity::class.java) - - val tableName = paramTypeAnnotation.tableName - val primaryKeys = annotation.primaryKeys - val skippedColumns = annotation.skippedColumns - - - var members = processingEnv.elementUtils.getAllMembers(paramTypeElement) - val allFields = ElementFilter.fieldsIn(members) - - // check all super classes - var superType = paramTypeElement.superclass - while (superType !is NoType) { - val superTypeElement = processingEnv.typeUtils.asElement(superType) as TypeElement - members = processingEnv.elementUtils.getAllMembers(superTypeElement) - allFields += ElementFilter.fieldsIn(members) - superType = superTypeElement.superclass - } - - allFields.removeAll { skippedColumns.contains(it.name()) } - allFields.removeAll { it.getAnnotation(Ignore::class.java) != null } - allFields.removeAll { field -> field.modifiers.any { it == Modifier.STATIC } } - val allFieldsDistinct = allFields.distinct() - - // dump fields - //processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, allFieldsDistinct.joinToString()) - - val fields = allFieldsDistinct.filterNot { primaryKeys.contains(it.name()) } - val primaryFields = allFieldsDistinct.filter { primaryKeys.contains(it.name()) } - val fieldNames = fields.map { it.name() } - val primaryFieldNames = primaryFields.map { it.name() } - - val fieldNamesQuery = fieldNames.joinToString { "$it = ?" } - val primaryFieldNamesQuery = primaryFieldNames.joinToString(" AND ") { "$it = ?" } - val query = "\"\"\"UPDATE $tableName SET $fieldNamesQuery WHERE $primaryFieldNamesQuery\"\"\"" - - val entityInsertionAdapter = ClassName("androidx.room", "EntityInsertionAdapter") - val supportSQLiteStatement = ClassName("androidx.sqlite.db", "SupportSQLiteStatement") - - val usedTypeConverters = mutableListOf() - - val bind = CodeBlock.builder() - (fields+primaryFields).forEachIndexed { i, field -> - val index = i+1 - val fieldName = field.simpleName.toString() - val name = "${paramName}_$fieldName" - val realName = "${paramName}.$fieldName" - val nullable = field.getAnnotation(org.jetbrains.annotations.Nullable::class.java) != null - - var param = when (field.asType().kind) { - TypeKind.BOOLEAN -> "if ($name) 1L else 0L" - TypeKind.BYTE, - TypeKind.SHORT, - TypeKind.INT -> "$name.toLong()" - TypeKind.CHAR -> "$name.toString()" - TypeKind.FLOAT -> "$name.toDouble()" - else -> when (field.asType().toString()) { - "java.lang.String" -> name - "java.lang.Boolean" -> "if ($name == true) 1L else 0L" - "java.lang.Byte", - "java.lang.Short", - "java.lang.Integer" -> "$name.toLong()" - "java.lang.Long" -> name - "java.lang.Char" -> "$name.toString()" - "java.lang.Float" -> "$name.toDouble()" - "java.lang.Double" -> name - else -> name - } - } - - var isConvert = false - val bindMethod = when (field.asType().kind) { - TypeKind.BOOLEAN -> "bindLong" - TypeKind.BYTE -> "bindLong" - TypeKind.SHORT -> "bindLong" - TypeKind.INT -> "bindLong" - TypeKind.LONG -> "bindLong" - TypeKind.CHAR -> "bindString" - TypeKind.FLOAT -> "bindDouble" - TypeKind.DOUBLE -> "bindDouble" - else -> when (field.asType().toString()) { - "java.lang.String" -> "bindString" - "java.lang.Boolean" -> "bindLong" - "java.lang.Byte" -> "bindLong" - "java.lang.Short" -> "bindLong" - "java.lang.Integer" -> "bindLong" - "java.lang.Long" -> "bindLong" - "java.lang.Char" -> "bindString" - "java.lang.Float" -> "bindDouble" - "java.lang.Double" -> "bindDouble" - else -> { - val converter = typeConverters.firstOrNull { - it.dataType.toString() == field.asType().toString() - } - if (converter != null) { - param = "__${converter.converterType.simpleName}.${converter.methodName}($realName)" - param = when (converter.returnType.toString()) { - "java.lang.Integer", "int", - "java.lang.Short", "short", - "java.lang.Byte", "byte" -> "$param.toLong()" - "java.lang.Boolean", "boolean" -> "if ($param) 1L else 0L" - "java.lang.Char", "char" -> "$param.toString()" - "java.lang.Float", "float" -> "$param.toDouble()" - else -> param - } - isConvert = true - usedTypeConverters += converter - when (converter.returnType.toString()) { - "java.lang.Integer", "int", - "java.lang.Short", "short", - "java.lang.Byte", "byte", - "java.lang.Boolean", "boolean" -> "bindLong" - "java.lang.Char", "char" -> "bindString" - "java.lang.Float", "float" -> "bindDouble" - else -> "bindString" - } - } - else "bind${field.asType()}" - } - } - } - - if (!isConvert) { - bind.addStatement("val $name = $realName") - } - else { - bind.addStatement("val $name = $param") - param = name - } - if (nullable) { - bind.beginControlFlow("if ($name == null)") - .addStatement("stmt.bindNull($index)") - .endControlFlow() - .beginControlFlow("else") - .addStatement("stmt.$bindMethod($index, $param)") - .endControlFlow() - } - else { - bind.addStatement("stmt.$bindMethod($index, $param)") - } - } - - val adapterName = "__insertionAdapterOf$methodName" - val delegate = CodeBlock.builder().add(""" - |lazy { - | object : EntityInsertionAdapter<%T>(__db) { - | override fun createQuery() = $query - | override fun bind(stmt: %T, $paramName: %T) { - |${bind.indent().indent().indent().build()} - | } - | } - |}""".trimMargin(), paramTypeElement.asClassName(), supportSQLiteStatement, paramTypeElement.asClassName()) - - cls.addProperty(PropertySpec.builder(adapterName, entityInsertionAdapter.parameterizedBy(paramTypeElement.asClassName()), KModifier.PRIVATE) - .delegate(delegate.build()) - .build()) - - val list = ClassName("kotlin.collections", "List") - val longArray = ClassName("kotlin", "LongArray") - - val function = FunSpec.builder(methodName) - .addModifiers(KModifier.INTERNAL) - .addParameter("item", parameter.asType().asTypeName()) - .returns(Long::class.java) - .addStatement("__db.assertNotSuspendingTransaction()") - .addStatement("__db.beginTransaction()") - .addCode(""" - |try { - | val _result = $adapterName.insertAndReturnId(item) - | __db.setTransactionSuccessful() - | return _result - |} finally { - | __db.endTransaction() - |} - """.trimMargin()) - .build() - - val functionAll = FunSpec.builder(methodName+"All") - .addModifiers(KModifier.INTERNAL) - .addParameter("items", list.parameterizedBy(parameter.asType().asTypeName())) - .returns(longArray) - .addStatement("__db.assertNotSuspendingTransaction()") - .addStatement("__db.beginTransaction()") - .addCode(""" - |try { - | val _result = $adapterName.insertAndReturnIdsArray(items) - | __db.setTransactionSuccessful() - | return _result - |} finally { - | __db.endTransaction() - |} - """.trimMargin()) - .build() - - cls.addFunction(function) - cls.addFunction(functionAll) - return usedTypeConverters - } - - override fun getSupportedAnnotationTypes(): MutableSet { - return mutableSetOf(SelectiveDao::class.java.canonicalName) - } -} diff --git a/settings.gradle b/settings.gradle index a1b55163..d7b33210 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,5 @@ include ':wear' include ':wear' -include ':codegen' -include ':annotation' rootProject.name='Szkolny.eu' include ':app' /* From 78333e0077c9f9241d8b0e14b357809ab242d0a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 21 Mar 2021 20:14:54 +0100 Subject: [PATCH 08/15] [Gradle] Remove wear module. --- settings.gradle | 5 - wear/.gitignore | 1 - wear/build.gradle | 53 ------ wear/proguard-rules.pro | 21 --- .../edziennik/ExampleInstrumentedTest.kt | 26 --- wear/src/main/AndroidManifest.xml | 43 ----- .../szczodrzynski/edziennik/MainActivity.kt | 47 ----- .../drawable-v24/ic_launcher_foreground.xml | 34 ---- .../res/drawable/ic_launcher_background.xml | 174 ------------------ wear/src/main/res/layout/activity_main.xml | 29 --- .../res/mipmap-anydpi-v26/ic_launcher.xml | 9 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 9 - wear/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3593 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 5339 -> 0 bytes wear/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2636 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 3388 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4926 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 7472 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7909 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 11873 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 10652 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 16570 -> 0 bytes wear/src/main/res/values-night/themes.xml | 20 -- wear/src/main/res/values-round/strings.xml | 7 - wear/src/main/res/values/colors.xml | 14 -- wear/src/main/res/values/dimens.xml | 19 -- wear/src/main/res/values/strings.xml | 12 -- wear/src/main/res/values/themes.xml | 20 -- .../edziennik/ExampleUnitTest.kt | 20 -- 29 files changed, 563 deletions(-) delete mode 100644 wear/.gitignore delete mode 100644 wear/build.gradle delete mode 100644 wear/proguard-rules.pro delete mode 100644 wear/src/androidTest/java/pl/szczodrzynski/edziennik/ExampleInstrumentedTest.kt delete mode 100644 wear/src/main/AndroidManifest.xml delete mode 100644 wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt delete mode 100644 wear/src/main/res/drawable-v24/ic_launcher_foreground.xml delete mode 100644 wear/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 wear/src/main/res/layout/activity_main.xml delete mode 100644 wear/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 wear/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 wear/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 wear/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 wear/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 wear/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 wear/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 wear/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 wear/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 wear/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 wear/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 wear/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 wear/src/main/res/values-night/themes.xml delete mode 100644 wear/src/main/res/values-round/strings.xml delete mode 100644 wear/src/main/res/values/colors.xml delete mode 100644 wear/src/main/res/values/dimens.xml delete mode 100644 wear/src/main/res/values/strings.xml delete mode 100644 wear/src/main/res/values/themes.xml delete mode 100644 wear/src/test/java/pl/szczodrzynski/edziennik/ExampleUnitTest.kt diff --git a/settings.gradle b/settings.gradle index d7b33210..02529180 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,2 @@ -include ':wear' -include ':wear' rootProject.name='Szkolny.eu' include ':app' -/* -include ':Navigation' -project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/ diff --git a/wear/.gitignore b/wear/.gitignore deleted file mode 100644 index 796b96d1..00000000 --- a/wear/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/wear/build.gradle b/wear/build.gradle deleted file mode 100644 index 5b531ae4..00000000 --- a/wear/build.gradle +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2020-9-17 - */ - -plugins { - id 'com.android.application' - id 'kotlin-android' -} - -android { - compileSdkVersion 29 - buildToolsVersion "29.0.3" - - defaultConfig { - applicationId "pl.szczodrzynski.edziennik" - minSdkVersion 23 - targetSdkVersion 29 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = '1.8' - } -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin}" - implementation 'androidx.core:core-ktx:1.3.1' - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'com.google.android.material:material:1.2.1' - testImplementation 'junit:junit:4.13' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - - implementation 'androidx.wear:wear:1.0.0' - implementation 'com.google.android.support:wearable:2.7.0' - compileOnly 'com.google.android.wearable:wearable:2.7.0' - - implementation "com.google.android.gms:play-services-wearable:${versions.play_services}" -} diff --git a/wear/proguard-rules.pro b/wear/proguard-rules.pro deleted file mode 100644 index f1b42451..00000000 --- a/wear/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/wear/src/androidTest/java/pl/szczodrzynski/edziennik/ExampleInstrumentedTest.kt b/wear/src/androidTest/java/pl/szczodrzynski/edziennik/ExampleInstrumentedTest.kt deleted file mode 100644 index 84289796..00000000 --- a/wear/src/androidTest/java/pl/szczodrzynski/edziennik/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2020-9-17 - */ - -package pl.szczodrzynski.edziennik - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("pl.szczodrzynski.edziennik", appContext.packageName) - } -} diff --git a/wear/src/main/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml deleted file mode 100644 index 803bc28d..00000000 --- a/wear/src/main/AndroidManifest.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt deleted file mode 100644 index ed694372..00000000 --- a/wear/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2020-9-17 - */ - -package pl.szczodrzynski.edziennik - -import android.os.Bundle -import android.support.wearable.activity.WearableActivity -import com.google.android.gms.wearable.* - -class MainActivity : WearableActivity(), DataClient.OnDataChangedListener { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - - // Enables Always-on - setAmbientEnabled() - } - - override fun onDataChanged(dataEvents: DataEventBuffer) { - dataEvents.forEach { event -> - if (event.type == DataEvent.TYPE_CHANGED) { - event.dataItem.also { item -> - if (item?.uri?.path?.compareTo("/test") == 0) { - DataMapItem.fromDataItem(item).dataMap.apply { - getInt("test") - } - } - } - } else if (event.type == DataEvent.TYPE_DELETED) { - // DataItem deleted - } - - } - } - - override fun onResume() { - super.onResume() - Wearable.getDataClient(this).addListener(this) - } - - override fun onPause() { - super.onPause() - Wearable.getDataClient(this).removeListener(this) - } -} diff --git a/wear/src/main/res/drawable-v24/ic_launcher_foreground.xml b/wear/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index d36dec1a..00000000 --- a/wear/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - diff --git a/wear/src/main/res/drawable/ic_launcher_background.xml b/wear/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index f14b2240..00000000 --- a/wear/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wear/src/main/res/layout/activity_main.xml b/wear/src/main/res/layout/activity_main.xml deleted file mode 100644 index 8d270149..00000000 --- a/wear/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - diff --git a/wear/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/wear/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 16e1857e..00000000 --- a/wear/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/wear/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/wear/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 16e1857e..00000000 --- a/wear/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/wear/src/main/res/mipmap-hdpi/ic_launcher.png b/wear/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a571e60098c92c2baca8a5df62f2929cbff01b52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3593 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 P00000NkvXXu0mjfP=x?Y diff --git a/wear/src/main/res/mipmap-hdpi/ic_launcher_round.png b/wear/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 61da551c5594a1f9d26193983d2cd69189014603..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5339 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 diff --git a/wear/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/wear/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index b216f2d313cc673d8b8c4da591c174ebed52795c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11873 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 diff --git a/wear/src/main/res/values-night/themes.xml b/wear/src/main/res/values-night/themes.xml deleted file mode 100644 index ad19c38e..00000000 --- a/wear/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/wear/src/main/res/values-round/strings.xml b/wear/src/main/res/values-round/strings.xml deleted file mode 100644 index 62eacd26..00000000 --- a/wear/src/main/res/values-round/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - Hello Round World! - diff --git a/wear/src/main/res/values/colors.xml b/wear/src/main/res/values/colors.xml deleted file mode 100644 index a7c719f0..00000000 --- a/wear/src/main/res/values/colors.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF - diff --git a/wear/src/main/res/values/dimens.xml b/wear/src/main/res/values/dimens.xml deleted file mode 100644 index 2e76f3e3..00000000 --- a/wear/src/main/res/values/dimens.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - 0dp - - - 5dp - diff --git a/wear/src/main/res/values/strings.xml b/wear/src/main/res/values/strings.xml deleted file mode 100644 index bbaabade..00000000 --- a/wear/src/main/res/values/strings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - Szkolny.eu - - Hello Square World! - diff --git a/wear/src/main/res/values/themes.xml b/wear/src/main/res/values/themes.xml deleted file mode 100644 index 58cc0c22..00000000 --- a/wear/src/main/res/values/themes.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/wear/src/test/java/pl/szczodrzynski/edziennik/ExampleUnitTest.kt b/wear/src/test/java/pl/szczodrzynski/edziennik/ExampleUnitTest.kt deleted file mode 100644 index affae81c..00000000 --- a/wear/src/test/java/pl/szczodrzynski/edziennik/ExampleUnitTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) Kacper Ziubryniewicz 2020-9-17 - */ - -package pl.szczodrzynski.edziennik - -import org.junit.Assert.assertEquals -import org.junit.Test - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} From b6d625a1fc50f819a06d6756787109ffa777d92d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 21 Mar 2021 21:01:28 +0100 Subject: [PATCH 09/15] [Gradle] Update most libraries. Rearrange dependencies. --- app/build.gradle | 216 +++++++----------- .../ui/dialogs/RegisterUnavailableDialog.kt | 2 +- .../edziennik/ui/dialogs/day/DayDialog.kt | 6 +- .../ui/dialogs/event/EventManualDialog.kt | 2 +- .../ui/modules/feedback/FeedbackFragment.kt | 20 +- .../home/cards/HomeAvailabilityCard.kt | 2 +- .../ui/modules/login/LoginPrizeFragment.kt | 2 +- .../login/viewholder/PlatformViewHolder.kt | 2 +- build.gradle | 50 +--- 9 files changed, 103 insertions(+), 199 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 47d1b31b..466d538a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,21 +1,21 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' -apply plugin: 'kotlin-android-extensions' apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.firebase.crashlytics' android { - signingConfigs { - } compileSdkVersion setup.compileSdk + defaultConfig { applicationId 'pl.szczodrzynski.edziennik' minSdkVersion setup.minSdk targetSdkVersion setup.targetSdk + versionCode release.versionCode versionName release.versionName - multiDexEnabled true + + multiDexEnabled = true externalNativeBuild { cmake { @@ -28,41 +28,35 @@ android { variant.outputs.all { if (variant.buildType.name == "release") { outputFileName = "Edziennik_" + defaultConfig.versionName + ".apk" - } else if (variant.buildType.name == "debugMinify") { - outputFileName = "Edziennik_" + defaultConfig.versionName + "_debugMinify.apk" } else { outputFileName = "Edziennik_" + defaultConfig.versionName + "_debug.apk" } } } debug { - minifyEnabled false + minifyEnabled = false } release { - minifyEnabled true - shrinkResources true + minifyEnabled = true + shrinkResources = true proguardFiles getDefaultProguardFile('proguard-android.txt') proguardFiles fileTree('proguard').asList().toArray() } } - dependencies { - implementation "com.google.firebase:firebase-core:${versions.firebase}" - } defaultConfig { vectorDrawables.useSupportLibrary = true } lintOptions { - checkReleaseBuilds false + checkReleaseBuilds = false } buildFeatures { dataBinding = true + viewBinding = true } compileOptions { - coreLibraryDesugaringEnabled true - sourceCompatibility '1.8' - targetCompatibility '1.8' - } - productFlavors { + coreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" @@ -76,137 +70,97 @@ android { version "3.10.2" } } - ndkVersion '21.3.6528147' } -/*task finalizeBundleDebug(type: Copy) { - from("debug/debug") - include "app.aab" - destinationDir file("debug/debug") - rename "app.aab", "Edziennik_debug.aab" -} - -// it finalizes :bundleRelease -task finalizeBundleRelease(type: Copy) { - from("release/release") - include "app.aab" - destinationDir file("release/release") - rename "app.aab", "Edziennik_${android.defaultConfig.versionCode}.aab" -}*/ -/* -// this adds the above two tasks -tasks.whenTaskAdded { task -> - if (task.name == "bundleDebug") { - task.finalizedBy finalizeBundleDebug - } else if (task.name == "bundleRelease") { - task.finalizedBy finalizeBundleRelease - } -}*/ - dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1' + // Language cores + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5" - kapt "androidx.room:room-compiler:${versions.room}" - debugImplementation "com.amitshekhar.android:debug-db:1.0.5" + // Android Jetpack + implementation "androidx.appcompat:appcompat:1.2.0" + implementation "androidx.cardview:cardview:1.0.0" + implementation "androidx.constraintlayout:constraintlayout:2.0.4" + implementation "androidx.core:core-ktx:1.3.2" + implementation "androidx.gridlayout:gridlayout:1.0.0" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.0" + implementation "androidx.navigation:navigation-fragment-ktx:2.3.4" + implementation "androidx.recyclerview:recyclerview:1.1.0" + implementation "androidx.room:room-runtime:2.2.6" + implementation "androidx.work:work-runtime-ktx:2.5.0" + kapt "androidx.room:room-compiler:2.2.6" - implementation "android.arch.navigation:navigation-fragment-ktx:${versions.navigationFragment}" - implementation "androidx.appcompat:appcompat:${versions.appcompat}" - implementation "androidx.cardview:cardview:${versions.cardView}" - implementation "androidx.constraintlayout:constraintlayout:${versions.constraintLayout}" - implementation "androidx.core:core-ktx:${versions.ktx}" - implementation "androidx.gridlayout:gridlayout:${versions.gridLayout}" - implementation "androidx.legacy:legacy-support-v4:${versions.legacy}" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:${versions.lifecycle}" - implementation "androidx.recyclerview:recyclerview:${versions.recyclerView}" - implementation "androidx.room:room-runtime:${versions.room}" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" + // Google design libs + implementation "com.google.android.material:material:1.3.0" + implementation "com.google.android:flexbox:2.0.1" - implementation "com.google.android.gms:play-services-wearable:${versions.play_services}" - implementation "com.google.android.material:material:${versions.material}" - implementation "com.google.firebase:firebase-messaging:${versions.firebasemessaging}" + // Play Services/Firebase + implementation "com.google.android.gms:play-services-wearable:17.0.0" + implementation "com.google.firebase:firebase-core:18.0.2" + implementation "com.google.firebase:firebase-crashlytics:17.4.0" + implementation "com.google.firebase:firebase-messaging:20.1.3" - implementation "pl.szczodrzynski:NavLib:v0.7.0" - implementation "com.mikepenz:iconics-views:${versions.iconics}" - implementation "com.mikepenz:community-material-typeface:${versions.font_cmd}@aar" - - implementation "com.afollestad.material-dialogs:commons:${versions.materialdialogs}" - implementation "com.afollestad.material-dialogs:core:${versions.materialdialogs}" - - implementation "cat.ereza:customactivityoncrash:2.2.0" - implementation "com.applandeo:material-calendar-view:1.5.0" - implementation 'com.google.firebase:firebase-crashlytics:17.3.1' - implementation "com.daimajia.swipelayout:library:1.2.0@aar" - implementation "com.evernote:android-job:1.2.6" - implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2" - implementation "com.github.bassaer:chatmessageview:2.0.1" - implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true} - implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update - implementation "com.jaredrummler:colorpicker:1.0.2" - implementation("com.squareup.okhttp3:okhttp") { - version { - strictly "3.12.13" - } - } - implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update - implementation "com.wdullaer:materialdatetimepicker:4.1.2" - implementation "com.yuyh.json:jsonviewer:1.0.6" - implementation "me.dm7.barcodescanner:zxing:1.9.8" - implementation "me.grantland:autofittextview:0.2.1" - implementation "me.leolin:ShortcutBadger:1.1.22@aar" - implementation "org.greenrobot:eventbus:3.1.1" - implementation "org.jsoup:jsoup:1.12.1" - implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.15" - implementation "uk.co.samuelwall:material-tap-target-prompt:2.14.0" + // OkHttp, Retrofit, Gson, Jsoup + implementation("com.squareup.okhttp3:okhttp") { version { strictly "3.12.13" } } + implementation "com.squareup.retrofit2:retrofit:2.9.0" + implementation "com.squareup.retrofit2:converter-gson:2.9.0" + implementation "com.squareup.retrofit2:converter-scalars:2.9.0" + implementation 'com.google.code.gson:gson:2.8.6' + implementation "org.jsoup:jsoup:1.13.1" + implementation "pl.droidsonroids:jspoon:1.3.2" + implementation "pl.droidsonroids.retrofit2:converter-jspoon:1.3.2" + // Szkolny.eu libraries/forks implementation "eu.szkolny:agendacalendarview:1799f8ef47" implementation "eu.szkolny:cafebar:5bf0c618de" implementation "eu.szkolny:material-about-library:0534abf316" implementation "eu.szkolny:mhttp:af4b62e6e9" implementation "eu.szkolny:nachos:0e5dfcaceb" - //implementation project(":Navigation") - implementation "eu.szkolny:szkolny-font:1dab7d64ed" implementation "eu.szkolny.selective-dao:annotation:27f8f3f194" + implementation "pl.szczodrzynski:NavLib:v0.7.0" + implementation "pl.szczodrzynski:NumberSlidingPicker:2921225f76" + implementation "pl.szczodrzynski:RecyclerTabLayout:700f980584" + implementation "pl.szczodrzynski:Tachyon:551943a6b5" + implementation "pl.szczodrzynski.FSLogin:lib:2.0.0" kapt "eu.szkolny.selective-dao:codegen:27f8f3f194" + // Iconics & related + implementation "com.mikepenz:iconics-core:5.2.8" + implementation "com.mikepenz:iconics-views:5.2.8" + implementation "com.mikepenz:community-material-typeface:3.5.95.1-kotlin@aar" + implementation "eu.szkolny:szkolny-font:1dab7d64ed" + + // Other dependencies + implementation "cat.ereza:customactivityoncrash:2.3.0" + implementation "com.afollestad.material-dialogs:commons:0.9.6.0" + implementation "com.afollestad.material-dialogs:core:0.9.6.0" + implementation "com.applandeo:material-calendar-view:1.5.0" + implementation "com.daimajia.swipelayout:library:1.2.0@aar" + implementation "com.evernote:android-job:1.4.2" + implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2" + implementation "com.github.bassaer:chatmessageview:2.0.1" implementation "com.github.ChuckerTeam.Chucker:library:3.0.1" - //releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:3.0.1" + implementation "com.github.jetradarmobile:android-snowfall:1.2.0" + implementation "com.github.wulkanowy.uonet-request-signer:hebe-jvm:a99ca50a31" + implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update + implementation "com.hypertrack:hyperlog:0.0.10" + implementation "com.jaredrummler:colorpicker:1.1.0" + implementation "com.qifan.powerpermission:powerpermission-coroutines:1.3.0" + implementation "com.qifan.powerpermission:powerpermission:1.3.0" + implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update + implementation "com.wdullaer:materialdatetimepicker:4.2.3" + implementation "com.yuyh.json:jsonviewer:1.0.6" + implementation "io.coil-kt:coil:1.1.1" + implementation "me.dm7.barcodescanner:zxing:1.9.8" + implementation "me.grantland:autofittextview:0.2.1" + implementation "me.leolin:ShortcutBadger:1.1.22@aar" + implementation "org.greenrobot:eventbus:3.2.0" + implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.15" + implementation "uk.co.samuelwall:material-tap-target-prompt:2.14.0" + implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true} - //implementation 'com.github.wulkanowy:uonet-request-signer:master-SNAPSHOT' - //implementation 'com.github.kuba2k2.uonet-request-signer:android:master-63f094b14a-1' - - //implementation "org.redundent:kotlin-xml-builder:1.5.3" - - implementation 'com.github.wulkanowy.uonet-request-signer:hebe-jvm:a99ca50a31' - - implementation "androidx.work:work-runtime-ktx:${versions.work}" - - implementation 'com.hypertrack:hyperlog:0.0.10' - - implementation 'com.github.kuba2k2:RecyclerTabLayout:700f980584' - - implementation 'com.github.kuba2k2:Tachyon:551943a6b5' - - implementation "com.squareup.retrofit2:retrofit:${versions.retrofit}" - implementation "com.squareup.retrofit2:converter-gson:${versions.retrofit}" - - implementation 'com.github.jetradarmobile:android-snowfall:1.2.0' - - implementation "io.coil-kt:coil:0.9.2" - - implementation 'com.github.kuba2k2:NumberSlidingPicker:2921225f76' - - implementation 'com.google.android:flexbox:2.0.1' - - implementation 'com.qifan.powerpermission:powerpermission:1.3.0' - implementation 'com.qifan.powerpermission:powerpermission-coroutines:1.3.0' - - implementation 'com.github.kuba2k2.FSLogin:lib:2.0.0' - implementation 'pl.droidsonroids:jspoon:1.3.2' - implementation "com.squareup.retrofit2:converter-scalars:2.8.1" - implementation "pl.droidsonroids.retrofit2:converter-jspoon:1.3.2" -} -repositories { - mavenCentral() + // Debug-only dependencies + debugImplementation "com.amitshekhar.android:debug-db:1.0.5" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/RegisterUnavailableDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/RegisterUnavailableDialog.kt index 6ecd494f..b9e733b8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/RegisterUnavailableDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/RegisterUnavailableDialog.kt @@ -8,7 +8,7 @@ import android.text.method.LinkMovementMethod import android.view.LayoutInflater import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import coil.api.load +import coil.load import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/day/DayDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/day/DayDialog.kt index c6a7b2f9..e5b7768d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/day/DayDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/day/DayDialog.kt @@ -10,8 +10,6 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.android.synthetic.main.row_lesson_change_item.view.* -import kotlinx.android.synthetic.main.row_teacher_absence_item.view.* import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.entity.Lesson @@ -111,7 +109,7 @@ class DayDialog( } lessonChanges.ifNotEmpty { - b.lessonChangeContainer.visibility = View.VISIBLE + b.lessonChangeContainer.root.visibility = View.VISIBLE b.lessonChangeContainer.lessonChangeCount.text = it.size.toString() b.lessonChangeLayout.onClick { @@ -130,7 +128,7 @@ class DayDialog( } teacherAbsences.ifNotEmpty { - b.teacherAbsenceContainer.visibility = View.VISIBLE + b.teacherAbsenceContainer.root.visibility = View.VISIBLE b.teacherAbsenceContainer.teacherAbsenceCount.text = it.size.toString() b.teacherAbsenceLayout.onClick { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt index 06b5f1a6..7240934b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualDialog.kt @@ -378,7 +378,7 @@ class EventManualDialog( customColor = color } }) - colorPickerDialog.show(activity.fragmentManager, "color-picker-dialog") + colorPickerDialog.show(activity.supportFragmentManager, "color-picker-dialog") } }} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/feedback/FeedbackFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/feedback/FeedbackFragment.kt index 63f7500f..3c33be8d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/feedback/FeedbackFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/feedback/FeedbackFragment.kt @@ -14,8 +14,8 @@ import android.widget.PopupMenu import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment -import coil.Coil -import coil.api.load +import coil.imageLoader +import coil.request.ImageRequest import com.github.bassaer.chatmessageview.model.IChatUser import com.github.bassaer.chatmessageview.model.Message import com.github.bassaer.chatmessageview.view.ChatView @@ -34,14 +34,6 @@ import pl.szczodrzynski.edziennik.onClick import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils.openUrl import java.util.* -import kotlin.collections.List -import kotlin.collections.any -import kotlin.collections.filter -import kotlin.collections.firstOrNull -import kotlin.collections.forEach -import kotlin.collections.forEachIndexed -import kotlin.collections.isNotEmpty -import kotlin.collections.mutableMapOf import kotlin.collections.set import kotlin.coroutines.CoroutineContext @@ -221,13 +213,15 @@ class FeedbackFragment : Fragment(), CoroutineScope { Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888).also { bmp -> launch { Log.d(TAG, "Created image for $userName") - Coil.load(activity, image) { - target { + val request = ImageRequest.Builder(activity) + .data(image) + .target { val canvas = Canvas(bmp) it.setBounds(0, 0, bmp.width, bmp.height) it.draw(canvas) } - } + .build() + activity.imageLoader.enqueue(request) } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeAvailabilityCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeAvailabilityCard.kt index 957dff0c..fd54748e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeAvailabilityCard.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeAvailabilityCard.kt @@ -12,7 +12,7 @@ import androidx.core.text.HtmlCompat import androidx.core.view.isVisible import androidx.core.view.plusAssign import androidx.core.view.setMargins -import coil.api.load +import coil.load import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt index b9fdf43a..1c9634fc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginPrizeFragment.kt @@ -10,7 +10,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import coil.api.load +import coil.load import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/PlatformViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/PlatformViewHolder.kt index ea8a063d..2c08c27e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/PlatformViewHolder.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/viewholder/PlatformViewHolder.kt @@ -9,7 +9,7 @@ import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView -import coil.api.load +import coil.load import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.databinding.LoginPlatformItemBinding import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder diff --git a/build.gradle b/build.gradle index fd64a16a..343e5fd5 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { - kotlin_version = '1.4.30' + kotlin_version = '1.4.31' release = [ versionName: "4.6.1", @@ -11,50 +11,9 @@ buildscript { setup = [ compileSdk: 30, - buildTools: "28.0.3", minSdk : 16, targetSdk : 30 ] - - versions = [ - gradleAndroid : '4.2.0-beta04', - - kotlin : ext.kotlin_version, - ktx : "1.3.2", - - androidX : '1.0.0', - annotation : '1.1.0', - recyclerView : '1.2.0-beta01', - material : '1.3.0', - appcompat : '1.3.0-beta01', - constraintLayout : '2.1.0-alpha2', - cardview : '1.0.0', - gridLayout : '1.0.0', - navigation : "2.0.0", - navigationFragment: "1.0.0", - legacy : "1.0.0", - - room : "2.2.6", - lifecycle : "2.3.0", - work : "2.5.0", - - firebase : '18.0.2', - firebasemessaging: "20.1.3", - play_services : "17.0.0", - - materialdialogs : "0.9.6.0", - materialdrawer : "817e45765c367034b03046aaea6e95eeabcb40e9", - iconics : "5.2.8", - font_cmd : "3.5.95.1-kotlin", - - navlib : "28cdab341470dffa5f331379fe9702482681d7de", - - gifdrawable : "1.2.15", - - retrofit : "2.6.4" - ] - versions.kotlin = '1.4.0' - versions.kotlin = '1.4.0' } repositories { @@ -62,11 +21,10 @@ buildscript { jcenter() } dependencies { - classpath "com.android.tools.build:gradle:${versions.gradleAndroid}" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" - classpath 'me.tatarka:gradle-retrolambda:3.7.0' + classpath "com.android.tools.build:gradle:4.2.0-beta06" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.gms:google-services:4.3.5' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.0' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.1' } } From cf4aa552e7681da912cccf0844b182ffc1dadc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 21 Mar 2021 22:30:19 +0100 Subject: [PATCH 10/15] [Gradle] Update NavLib to fix multiple item selection issue. --- app/build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 466d538a..8ad2fc81 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -115,15 +115,15 @@ dependencies { // Szkolny.eu libraries/forks implementation "eu.szkolny:agendacalendarview:1799f8ef47" implementation "eu.szkolny:cafebar:5bf0c618de" + implementation "eu.szkolny.fslogin:lib:2.0.0" implementation "eu.szkolny:material-about-library:0534abf316" implementation "eu.szkolny:mhttp:af4b62e6e9" implementation "eu.szkolny:nachos:0e5dfcaceb" implementation "eu.szkolny.selective-dao:annotation:27f8f3f194" - implementation "pl.szczodrzynski:NavLib:v0.7.0" - implementation "pl.szczodrzynski:NumberSlidingPicker:2921225f76" - implementation "pl.szczodrzynski:RecyclerTabLayout:700f980584" - implementation "pl.szczodrzynski:Tachyon:551943a6b5" - implementation "pl.szczodrzynski.FSLogin:lib:2.0.0" + implementation "pl.szczodrzynski:navlib:0.7.2" + implementation "pl.szczodrzynski:numberslidingpicker:2921225f76" + implementation "pl.szczodrzynski:recyclertablayout:700f980584" + implementation "pl.szczodrzynski:tachyon:551943a6b5" kapt "eu.szkolny.selective-dao:codegen:27f8f3f194" // Iconics & related From 85379b0bebbc2eeaf4386b33732d5a12584d13ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 21 Mar 2021 22:42:37 +0100 Subject: [PATCH 11/15] [Gradle] Remove unused dependencies. --- app/build.gradle | 4 ---- .../ui/modules/settings/SettingsLicenseActivity.kt | 12 ------------ app/src/main/res/xml/backup_descriptor.xml | 2 -- 3 files changed, 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8ad2fc81..9f915809 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -84,7 +84,6 @@ dependencies { implementation "androidx.cardview:cardview:1.0.0" implementation "androidx.constraintlayout:constraintlayout:2.0.4" implementation "androidx.core:core-ktx:1.3.2" - implementation "androidx.gridlayout:gridlayout:1.0.0" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.0" implementation "androidx.navigation:navigation-fragment-ktx:2.3.4" implementation "androidx.recyclerview:recyclerview:1.1.0" @@ -138,7 +137,6 @@ dependencies { implementation "com.afollestad.material-dialogs:core:0.9.6.0" implementation "com.applandeo:material-calendar-view:1.5.0" implementation "com.daimajia.swipelayout:library:1.2.0@aar" - implementation "com.evernote:android-job:1.4.2" implementation "com.github.antonKozyriatskyi:CircularProgressIndicator:1.2.2" implementation "com.github.bassaer:chatmessageview:2.0.1" implementation "com.github.ChuckerTeam.Chucker:library:3.0.1" @@ -158,8 +156,6 @@ dependencies { implementation "me.leolin:ShortcutBadger:1.1.22@aar" implementation "org.greenrobot:eventbus:3.2.0" implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.15" - implementation "uk.co.samuelwall:material-tap-target-prompt:2.14.0" - implementation("com.github.ozodrukh:CircularReveal:2.0.1@aar") {transitive = true} // Debug-only dependencies debugImplementation "com.amitshekhar.android:debug-db:1.0.5" diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsLicenseActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsLicenseActivity.kt index 192f1273..2e5aaf6f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsLicenseActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsLicenseActivity.kt @@ -79,12 +79,6 @@ class SettingsLicenseActivity : MaterialAboutActivity() { "Applandeo sp. z o.o.", OpenSourceLicense.APACHE_2, "https://github.com/Applandeo/Material-Calendar-View/"), - createLicenseCard(this, - "Android-Job", - "2007-2017", - "Evernote Corporation", - OpenSourceLicense.APACHE_2, - "https://github.com/evernote/android-job/"), createLicenseCard(this, "Custom Activity On Crash", "", @@ -151,12 +145,6 @@ class SettingsLicenseActivity : MaterialAboutActivity() { "Arthur Teplitzki, 2013 Edmodo, Inc.", OpenSourceLicense.APACHE_2, "https://github.com/ArthurHub/Android-Image-Cropper/"), - createLicenseCard(this, - "Material Tap Target Prompt", - "2016-2018", - "Samuel Wall", - OpenSourceLicense.APACHE_2, - "https://github.com/sjwall/MaterialTapTargetPrompt/"), createLicenseCard(this, "Android Swipe Layout", "2014", diff --git a/app/src/main/res/xml/backup_descriptor.xml b/app/src/main/res/xml/backup_descriptor.xml index 9b85b4b7..f5417ebb 100644 --- a/app/src/main/res/xml/backup_descriptor.xml +++ b/app/src/main/res/xml/backup_descriptor.xml @@ -2,6 +2,4 @@ - - From 177ffd92f7d7e685fbd8f7dfece17e029aa41a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 21 Mar 2021 22:49:43 +0100 Subject: [PATCH 12/15] [Proguard] Remove unneeded rules. Move app proguard rules. --- app/build.gradle | 2 +- app/{proguard/app.pro => proguard-rules.pro} | 0 app/proguard/android-job.pro | 14 ------ app/proguard/blurry.pro | 1 - app/proguard/cafebar.pro | 25 ---------- app/proguard/iconics.pro | 14 ------ app/proguard/mhttp.pro | 48 -------------------- app/proguard/szkolny-font.pro | 1 - app/proguard/wear.pro | 21 --------- 9 files changed, 1 insertion(+), 125 deletions(-) rename app/{proguard/app.pro => proguard-rules.pro} (100%) delete mode 100644 app/proguard/android-job.pro delete mode 100644 app/proguard/blurry.pro delete mode 100644 app/proguard/cafebar.pro delete mode 100644 app/proguard/iconics.pro delete mode 100644 app/proguard/mhttp.pro delete mode 100644 app/proguard/szkolny-font.pro delete mode 100644 app/proguard/wear.pro diff --git a/app/build.gradle b/app/build.gradle index 9f915809..f146d6c8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,7 +39,7 @@ android { release { minifyEnabled = true shrinkResources = true - proguardFiles getDefaultProguardFile('proguard-android.txt') + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles fileTree('proguard').asList().toArray() } } diff --git a/app/proguard/app.pro b/app/proguard-rules.pro similarity index 100% rename from app/proguard/app.pro rename to app/proguard-rules.pro diff --git a/app/proguard/android-job.pro b/app/proguard/android-job.pro deleted file mode 100644 index 3f1a67be..00000000 --- a/app/proguard/android-job.pro +++ /dev/null @@ -1,14 +0,0 @@ --dontwarn com.evernote.android.job.gcm.** --dontwarn com.evernote.android.job.GcmAvailableHelper --dontwarn com.evernote.android.job.work.** --dontwarn com.evernote.android.job.WorkManagerAvailableHelper - --keep public class com.evernote.android.job.v21.PlatformJobService --keep public class com.evernote.android.job.v14.PlatformAlarmService --keep public class com.evernote.android.job.v14.PlatformAlarmReceiver --keep public class com.evernote.android.job.JobBootReceiver --keep public class com.evernote.android.job.JobRescheduleService --keep public class com.evernote.android.job.gcm.PlatformGcmService --keep public class com.evernote.android.job.work.PlatformWorker - --keep class com.evernote.android.job.** { *; } \ No newline at end of file diff --git a/app/proguard/blurry.pro b/app/proguard/blurry.pro deleted file mode 100644 index 980f404e..00000000 --- a/app/proguard/blurry.pro +++ /dev/null @@ -1 +0,0 @@ --keep class android.support.v8.renderscript.** { *; } \ No newline at end of file diff --git a/app/proguard/cafebar.pro b/app/proguard/cafebar.pro deleted file mode 100644 index 6f8147fd..00000000 --- a/app/proguard/cafebar.pro +++ /dev/null @@ -1,25 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in D:\AndroidSDK/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - --keep class !android.support.v7.internal.view.menu.**,android.support.** {*;} --keep class android.support.v7.graphics.** { *; } --dontwarn android.support.v7.graphics.** - --keep class android.support.design.widget.** { *; } --keep interface android.support.design.widget.** { *; } --dontwarn android.support.design.** diff --git a/app/proguard/iconics.pro b/app/proguard/iconics.pro deleted file mode 100644 index 0aa62122..00000000 --- a/app/proguard/iconics.pro +++ /dev/null @@ -1,14 +0,0 @@ -# Android iconics library - https://github.com/mikepenz/Android-Iconics -# Warning: works ONLY with iconics > 1.0.0 -# -# Tested on gradle config: -# -# compile 'com.mikepenz:iconics-core:1.7.1@aar' -# - --keep class com.mikepenz.iconics.** { *; } --keep class com.mikepenz.community_material_typeface_library.CommunityMaterial --keep class com.mikepenz.fontawesome_typeface_library.FontAwesome --keep class com.mikepenz.google_material_typeface_library.GoogleMaterial --keep class com.mikepenz.meteocons_typeface_library.Meteoconcs --keep class com.mikepenz.octicons_typeface_library.Octicons \ No newline at end of file diff --git a/app/proguard/mhttp.pro b/app/proguard/mhttp.pro deleted file mode 100644 index 6d3e4e38..00000000 --- a/app/proguard/mhttp.pro +++ /dev/null @@ -1,48 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/wangchao/Work/android-sdk/sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} --dontwarn im.wangchao.** --dontwarn okio.** --dontwarn javax.annotation.Nullable --dontwarn javax.annotation.ParametersAreNonnullByDefault --keep class im.wangchao.** { *; } --keep class **_HttpBinder { *; } --keepclasseswithmembernames class * { - @im.wangchao.* ; -} --keepclasseswithmembernames class * { - @im.wangchao.* ; -} --keepclassmembers class * implements java.io.Serializable { - static final long serialVersionUID; - private static final java.io.ObjectStreamField[] serialPersistentFields; - !static !transient ; - private void writeObject(java.io.ObjectOutputStream); - private void readObject(java.io.ObjectInputStream); - java.lang.Object writeReplace(); - java.lang.Object readResolve(); -} -# okhttp --dontwarn okhttp3.** --dontwarn okio.** --dontwarn javax.annotation.** --dontwarn org.conscrypt.** -# A resource is loaded with a relative path so the package of this class must be preserved. --keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase - -# If you do not use Rx: --dontwarn rx.** \ No newline at end of file diff --git a/app/proguard/szkolny-font.pro b/app/proguard/szkolny-font.pro deleted file mode 100644 index 4e48be73..00000000 --- a/app/proguard/szkolny-font.pro +++ /dev/null @@ -1 +0,0 @@ --keep class com.mikepenz.szkolny_font_typeface_library.SzkolnyFont { *; } diff --git a/app/proguard/wear.pro b/app/proguard/wear.pro deleted file mode 100644 index f1b42451..00000000 --- a/app/proguard/wear.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile From da953c9b1c36e23cd6f3b5ee47ea8fe647765c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 21 Mar 2021 23:39:51 +0100 Subject: [PATCH 13/15] [Gradle] Update CommunityMaterial to v5.8.55. --- app/build.gradle | 2 +- .../szczodrzynski/edziennik/MainActivity.kt | 14 ++++----- .../ui/modules/agenda/AgendaFragment.kt | 5 ++-- .../modules/attendance/AttendanceFragment.kt | 2 +- .../ui/modules/behaviour/NoticesAdapter.kt | 2 +- .../ui/modules/grades/GradesListFragment.kt | 5 ++-- .../modules/home/cards/HomeTimetableCard.kt | 4 +-- .../ui/modules/homework/HomeworkFragment.kt | 2 +- .../edziennik/ui/modules/login/LoginInfo.kt | 8 ++--- .../ui/modules/messages/MessageFragment.kt | 4 +-- .../ui/modules/messages/MessagesFragment.kt | 2 +- .../compose/MessagesComposeFragment.kt | 2 +- .../modules/settings/SettingsNewFragment.java | 30 +++++++++---------- .../ui/modules/timetable/TimetableFragment.kt | 3 +- .../ui/modules/views/AttachmentAdapter.kt | 4 +-- .../timetable/WidgetTimetableProvider.kt | 2 +- .../main/res/layout/dialog_event_details.xml | 25 +++++++++------- app/src/main/res/layout/event_list_item.xml | 5 ++-- .../res/layout/login_chooser_fragment.xml | 2 +- .../main/res/layout/login_form_fragment.xml | 2 +- .../layout/login_platform_list_fragment.xml | 2 +- .../res/layout/login_summary_fragment.xml | 2 +- app/src/main/res/layout/message_fragment.xml | 2 +- 23 files changed, 67 insertions(+), 64 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f146d6c8..f9adae64 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -128,7 +128,7 @@ dependencies { // Iconics & related implementation "com.mikepenz:iconics-core:5.2.8" implementation "com.mikepenz:iconics-views:5.2.8" - implementation "com.mikepenz:community-material-typeface:3.5.95.1-kotlin@aar" + implementation "com.mikepenz:community-material-typeface:5.8.55.0-kotlin@aar" implementation "eu.szkolny:szkolny-font:1dab7d64ed" // Other dependencies diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index 099763d2..de9b5f85 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -152,7 +152,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { .withPopToHome(false) list += NavTarget(DRAWER_ITEM_TIMETABLE, R.string.menu_timetable, TimetableFragment::class) - .withIcon(CommunityMaterial.Icon2.cmd_timetable) + .withIcon(CommunityMaterial.Icon3.cmd_timetable) .withBadgeTypeId(TYPE_LESSON_CHANGE) .isInDrawer(true) @@ -162,7 +162,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { .isInDrawer(true) list += NavTarget(DRAWER_ITEM_GRADES, R.string.menu_grades, GradesListFragment::class) - .withIcon(CommunityMaterial.Icon2.cmd_numeric_5_box_outline) + .withIcon(CommunityMaterial.Icon3.cmd_numeric_5_box_outline) .withBadgeTypeId(TYPE_GRADE) .isInDrawer(true) @@ -200,7 +200,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { .isBelowSeparator(true) list += NavTarget(DRAWER_ITEM_SETTINGS, R.string.menu_settings, SettingsNewFragment::class) - .withIcon(CommunityMaterial.Icon2.cmd_settings_outline) + .withIcon(CommunityMaterial.Icon.cmd_cog_outline) .isInDrawer(true) .isStatic(true) .isBelowSeparator(true) @@ -208,7 +208,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { // profile settings items list += NavTarget(DRAWER_PROFILE_ADD_NEW, R.string.menu_add_new_profile, null) - .withIcon(CommunityMaterial.Icon2.cmd_plus) + .withIcon(CommunityMaterial.Icon3.cmd_plus) .withDescription(R.string.drawer_add_new_profile_desc) .isInProfileList(true) @@ -237,7 +237,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { if (App.devMode) { list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class) list += NavTarget(TARGET_LAB, R.string.menu_lab, LabFragment::class) - .withIcon(CommunityMaterial.Icon.cmd_flask_outline) + .withIcon(CommunityMaterial.Icon2.cmd_flask_outline) .isInDrawer(true) .isBelowSeparator(true) .isStatic(true) @@ -520,7 +520,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { CafeBar.builder(this) .content(R.string.rate_snackbar_text) .icon(IconicsDrawable(this).apply { - icon = CommunityMaterial.Icon2.cmd_star_outline + icon = CommunityMaterial.Icon3.cmd_star_outline sizeDp = 20 colorInt = Themes.getPrimaryTextColor(this@MainActivity) }) @@ -565,7 +565,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope { BottomSheetSeparatorItem(false), BottomSheetPrimaryItem(false) .withTitle(R.string.menu_settings) - .withIcon(CommunityMaterial.Icon2.cmd_settings_outline) + .withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withOnClickListener(View.OnClickListener { loadTarget(DRAWER_ITEM_SETTINGS) }), BottomSheetPrimaryItem(false) .withTitle(R.string.menu_feedback) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt index 35750f43..367b00da 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/agenda/AgendaFragment.kt @@ -18,7 +18,6 @@ import com.github.tibolte.agendacalendarview.models.CalendarEvent import com.github.tibolte.agendacalendarview.models.IDayItem import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial.Icon2 import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.sizeDp import eu.szkolny.font.SzkolnyFont @@ -89,7 +88,7 @@ class AgendaFragment : Fragment(), CoroutineScope { }), BottomSheetPrimaryItem(true) .withTitle(R.string.menu_agenda_change_view) - .withIcon(if (type == Profile.AGENDA_DEFAULT) CommunityMaterial.Icon.cmd_calendar_outline else CommunityMaterial.Icon.cmd_format_list_bulleted_square) + .withIcon(if (type == Profile.AGENDA_DEFAULT) CommunityMaterial.Icon.cmd_calendar_outline else CommunityMaterial.Icon2.cmd_format_list_bulleted_square) .withOnClickListener(View.OnClickListener { activity.bottomSheet.close() type = if (type == Profile.AGENDA_DEFAULT) Profile.AGENDA_CALENDAR else Profile.AGENDA_DEFAULT @@ -111,7 +110,7 @@ class AgendaFragment : Fragment(), CoroutineScope { activity.navView.bottomBar.fabEnable = true activity.navView.bottomBar.fabExtendedText = getString(R.string.add) - activity.navView.bottomBar.fabIcon = Icon2.cmd_plus + activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon3.cmd_plus activity.navView.setFabOnClickListener(View.OnClickListener { EventManualDialog(activity, app.profileId, defaultDate = actualDate) }) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceFragment.kt index 0af177f9..194f36d2 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceFragment.kt @@ -60,7 +60,7 @@ class AttendanceFragment : Fragment(), CoroutineScope { activity.bottomSheet.prependItems( BottomSheetPrimaryItem(true) .withTitle(R.string.menu_attendance_config) - .withIcon(CommunityMaterial.Icon2.cmd_settings_outline) + .withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withOnClickListener(View.OnClickListener { activity.bottomSheet.close() AttendanceConfigDialog(activity, true, null, null) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt index 93f21191..a3288da2 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/behaviour/NoticesAdapter.kt @@ -50,7 +50,7 @@ class NoticesAdapter//getting the context and product list with constructor if (notice.type == Notice.TYPE_POSITIVE) { holder.noticesItemType.setImageDrawable( - IconicsDrawable(context, CommunityMaterial.Icon2.cmd_plus_circle_outline).apply { + IconicsDrawable(context, CommunityMaterial.Icon3.cmd_plus_circle_outline).apply { colorRes = R.color.md_green_600 sizeDp = 36 } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt index 33d69c60..eb7fdcb1 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/grades/GradesListFragment.kt @@ -15,7 +15,6 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial.Icon2 import kotlinx.coroutines.* import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.MainActivity.Companion.TARGET_GRADES_EDITOR @@ -71,7 +70,7 @@ class GradesListFragment : Fragment(), CoroutineScope { val adapter = GradesAdapter(activity) var firstRun = true - app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(this@GradesListFragment, Observer { grades -> this@GradesListFragment.launch { + app.db.gradeDao().getAllOrderBy(App.profileId, app.gradesManager.getOrderByString()).observe(viewLifecycleOwner, Observer { grades -> this@GradesListFragment.launch { if (!isAdded) return@launch val items = when { @@ -135,7 +134,7 @@ class GradesListFragment : Fragment(), CoroutineScope { activity.bottomSheet.prependItems( BottomSheetPrimaryItem(true) .withTitle(R.string.menu_grades_config) - .withIcon(Icon2.cmd_settings_outline) + .withIcon(CommunityMaterial.Icon.cmd_cog_outline) .withOnClickListener(View.OnClickListener { activity.bottomSheet.close() GradesConfigDialog(activity, true, null, null) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt index a530eefc..a2e4f9d7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt @@ -88,7 +88,7 @@ class HomeTimetableCard( holder.root += b.root b.settings.setImageDrawable( - IconicsDrawable(activity, CommunityMaterial.Icon2.cmd_settings_outline).apply { + IconicsDrawable(activity, CommunityMaterial.Icon.cmd_cog_outline).apply { colorAttr(activity, R.attr.colorIcon) sizeDp = 20 } @@ -102,7 +102,7 @@ class HomeTimetableCard( ) b.showCounter.setImageDrawable( - IconicsDrawable(activity, CommunityMaterial.Icon.cmd_fullscreen).apply { + IconicsDrawable(activity, CommunityMaterial.Icon2.cmd_fullscreen).apply { colorAttr(activity, R.attr.colorIcon) sizeDp = 20 } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkFragment.kt index f757570a..c8a62def 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkFragment.kt @@ -100,7 +100,7 @@ class HomeworkFragment : Fragment(), CoroutineScope { bottomBar.apply { fabEnable = true fabExtendedText = getString(R.string.add) - fabIcon = CommunityMaterial.Icon2.cmd_plus + fabIcon = CommunityMaterial.Icon3.cmd_plus } setFabOnClickListener(View.OnClickListener { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt index 949848a5..77036f19 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/login/LoginInfo.kt @@ -110,7 +110,7 @@ object LoginInfo { FormField( keyName = "accountPin", name = R.string.login_hint_pin, - icon = CommunityMaterial.Icon2.cmd_lock, + icon = CommunityMaterial.Icon2.cmd_lock_outline, emptyText = R.string.login_error_no_pin, invalidText = R.string.login_error_incorrect_pin, errorCodes = mapOf(), @@ -157,7 +157,7 @@ object LoginInfo { FormField( keyName = "symbol", name = R.string.login_hint_symbol, - icon = CommunityMaterial.Icon2.cmd_school, + icon = CommunityMaterial.Icon3.cmd_school_outline, emptyText = R.string.login_error_no_symbol, invalidText = R.string.login_error_incorrect_symbol, errorCodes = mapOf( @@ -170,7 +170,7 @@ object LoginInfo { FormField( keyName = "devicePin", name = R.string.login_hint_pin, - icon = CommunityMaterial.Icon2.cmd_lock, + icon = CommunityMaterial.Icon2.cmd_lock_outline, emptyText = R.string.login_error_no_pin, invalidText = R.string.login_error_incorrect_pin, errorCodes = mapOf( @@ -252,7 +252,7 @@ object LoginInfo { FormField( keyName = "serverName", name = R.string.login_hint_address, - icon = CommunityMaterial.Icon2.cmd_web, + icon = CommunityMaterial.Icon3.cmd_web, emptyText = R.string.login_error_no_address, invalidText = R.string.login_error_incorrect_address, errorCodes = mapOf( diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt index 19106004..2fcadf55 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessageFragment.kt @@ -65,7 +65,7 @@ class MessageFragment : Fragment(), CoroutineScope { if (!isAdded) return b.closeButton.setImageDrawable( - IconicsDrawable(activity, CommunityMaterial.Icon2.cmd_window_close).apply { + IconicsDrawable(activity, CommunityMaterial.Icon3.cmd_window_close).apply { colorAttr(activity, android.R.attr.textColorSecondary) sizeDp = 12 } @@ -231,7 +231,7 @@ class MessageFragment : Fragment(), CoroutineScope { bottomBar.apply { fabEnable = true fabExtendedText = getString(R.string.messages_reply) - fabIcon = CommunityMaterial.Icon2.cmd_reply + fabIcon = CommunityMaterial.Icon3.cmd_reply_outline } setFabOnClickListener(View.OnClickListener { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt index 043cce7d..add36a3c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/MessagesFragment.kt @@ -97,7 +97,7 @@ class MessagesFragment : Fragment(), CoroutineScope { bottomBar.apply { fabEnable = true fabExtendedText = getString(R.string.compose) - fabIcon = CommunityMaterial.Icon2.cmd_pencil_outline + fabIcon = CommunityMaterial.Icon3.cmd_pencil_outline } setFabOnClickListener(View.OnClickListener { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeFragment.kt index 96898871..942876f2 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/messages/compose/MessagesComposeFragment.kt @@ -316,7 +316,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope { activity.navView.bottomBar.apply { fabEnable = true fabExtendedText = getString(R.string.messages_compose_send) - fabIcon = CommunityMaterial.Icon2.cmd_send + fabIcon = CommunityMaterial.Icon3.cmd_send_outline setFabOnClickListener(View.OnClickListener { sendMessage() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java index 3a6bffe4..d009cdf1 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/settings/SettingsNewFragment.java @@ -239,7 +239,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_profile_notifications_text), getString(R.string.settings_profile_notifications_subtext), - icon(CommunityMaterial.Icon.cmd_filter_outline, iconSizeDp, iconColor) + icon(CommunityMaterial.Icon2.cmd_filter_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { new NotificationFilterDialog(activity, null, null); @@ -295,7 +295,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutSwitchItem.Builder() .text(R.string.settings_theme_snowfall_text) .subText(R.string.settings_theme_snowfall_subtext) - .icon(icon(CommunityMaterial.Icon2.cmd_snowflake, iconSizeDp, iconColor)) + .icon(icon(CommunityMaterial.Icon3.cmd_snowflake, iconSizeDp, iconColor)) .setChecked(app.getConfig().getUi().getSnowfall()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getUi().setSnowfall(isChecked); @@ -310,7 +310,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_theme_theme_text), Themes.INSTANCE.getThemeName(activity), - icon(CommunityMaterial.Icon2.cmd_palette_outline, iconSizeDp, iconColor) + icon(CommunityMaterial.Icon3.cmd_palette_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { new MaterialDialog.Builder(activity) @@ -354,7 +354,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_theme_mini_drawer_buttons_text), null, - icon(CommunityMaterial.Icon.cmd_format_list_checks, iconSizeDp, iconColor) + icon(CommunityMaterial.Icon2.cmd_format_list_checks, iconSizeDp, iconColor) ) .setOnClickAction(() -> { List buttonIds = new ArrayList<>(); @@ -472,7 +472,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add( new MaterialAboutSwitchItem.Builder( ) .text(R.string.settings_theme_open_drawer_on_back_pressed_text) - .icon(icon(CommunityMaterial.Icon2.cmd_menu_open, iconSizeDp, iconColor)) + .icon(icon(CommunityMaterial.Icon3.cmd_menu_open, iconSizeDp, iconColor)) .setChecked(app.getConfig().getUi().getOpenDrawerOnBackPressed()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getUi().setOpenDrawerOnBackPressed(isChecked); @@ -521,7 +521,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { return new MaterialAboutSwitchItem.Builder() .text(R.string.settings_sync_wifi_text) .subText(R.string.settings_sync_wifi_subtext) - .icon(icon(CommunityMaterial.Icon2.cmd_wifi_strength_2, iconSizeDp, iconColor)) + .icon(icon(CommunityMaterial.Icon3.cmd_wifi_strength_2, iconSizeDp, iconColor)) .setChecked(app.getConfig().getSync().getOnlyWifi()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getSync().setOnlyWifi(isChecked); @@ -721,7 +721,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutActionItem( getString(R.string.settings_sync_notifications_settings_text), getString(R.string.settings_sync_notifications_settings_subtext), - icon(CommunityMaterial.Icon2.cmd_settings_outline, iconSizeDp, iconColor) + icon(CommunityMaterial.Icon.cmd_cog_outline, iconSizeDp, iconColor) ) .setOnClickAction(() -> { String channel = app.getNotificationChannelsManager().getData().getKey(); @@ -794,7 +794,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { return new MaterialAboutSwitchItem.Builder() .text(R.string.settings_register_shared_events_text) .subText(R.string.settings_register_shared_events_subtext) - .icon(icon(CommunityMaterial.Icon2.cmd_share_outline, iconSizeDp, iconColor)) + .icon(icon(CommunityMaterial.Icon3.cmd_share_outline, iconSizeDp, iconColor)) .setChecked(app.getProfile().getEnableSharedEvents()) .setOnCheckedChanged((item, isChecked) -> { app.getProfile().setEnableSharedEvents(isChecked); @@ -822,7 +822,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem( getString(R.string.menu_grades_config), null, - icon(CommunityMaterial.Icon2.cmd_numeric_5_box_outline, iconSizeDp, iconColor) + icon(CommunityMaterial.Icon3.cmd_numeric_5_box_outline, iconSizeDp, iconColor) ).setOnClickAction(() -> new GradesConfigDialog(activity, false, null, null))); items.add(new MaterialAboutActionItem( @@ -958,7 +958,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { new MaterialAboutSwitchItem.Builder() .text(R.string.settings_register_count_in_seconds_text) .subText(R.string.settings_register_count_in_seconds_subtext) - .icon(icon(CommunityMaterial.Icon2.cmd_timer, iconSizeDp, iconColor)) + .icon(icon(CommunityMaterial.Icon3.cmd_timer, iconSizeDp, iconColor)) .setChecked(app.getConfig().getTimetable().getCountInSeconds()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().getTimetable().setCountInSeconds(isChecked); @@ -986,7 +986,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add( new MaterialAboutSwitchItem.Builder() .text(R.string.settings_register_hide_sticks_from_old) - .icon(icon(CommunityMaterial.Icon2.cmd_numeric_1_box_outline, iconSizeDp, iconColor)) + .icon(icon(CommunityMaterial.Icon3.cmd_numeric_1_box_outline, iconSizeDp, iconColor)) .setChecked(app.getConfig().forProfile().getGrades().getHideSticksFromOld()) .setOnCheckedChanged((item, isChecked) -> { app.getConfig().forProfile().getGrades().setHideSticksFromOld(isChecked); @@ -1041,7 +1041,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_privacy_policy_text) - .icon(icon(CommunityMaterial.Icon2.cmd_shield_outline, iconSizeDp, primaryTextOnPrimaryBg)) + .icon(icon(CommunityMaterial.Icon3.cmd_shield_outline, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(ConvenienceBuilder.createWebsiteOnClickAction(activity, Uri.parse("https://szkolny.eu/privacy-policy"))) .build()); @@ -1055,7 +1055,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_language_text) .subText(R.string.settings_about_language_subtext) - .icon(icon(CommunityMaterial.Icon2.cmd_translate, iconSizeDp, primaryTextOnPrimaryBg)) + .icon(icon(CommunityMaterial.Icon3.cmd_translate, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(() -> { new MaterialDialog.Builder(activity) .title(getString(R.string.settings_about_language_dialog_title)) @@ -1090,7 +1090,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_update_text) .subText(R.string.settings_about_update_subtext) - .icon(icon(CommunityMaterial.Icon2.cmd_update, iconSizeDp, primaryTextOnPrimaryBg)) + .icon(icon(CommunityMaterial.Icon3.cmd_update, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(() -> { //open browser or intent here NetworkUtils net = new NetworkUtils(app); @@ -1110,7 +1110,7 @@ public class SettingsNewFragment extends MaterialAboutFragment { items.add(new MaterialAboutActionItem.Builder() .text(R.string.settings_about_changelog_text) - .icon(icon(CommunityMaterial.Icon2.cmd_radar, iconSizeDp, primaryTextOnPrimaryBg)) + .icon(icon(CommunityMaterial.Icon3.cmd_radar, iconSizeDp, primaryTextOnPrimaryBg)) .setOnClickAction(() -> new ChangelogDialog(activity, null, null)) .build()); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableFragment.kt index 2e3695cc..d7b1b9a7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/timetable/TimetableFragment.kt @@ -17,7 +17,6 @@ import android.widget.Toast import androidx.fragment.app.Fragment import androidx.viewpager.widget.ViewPager import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial -import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial.Icon2 import com.wdullaer.materialdatetimepicker.date.DatePickerDialog import eu.szkolny.font.SzkolnyFont import kotlinx.coroutines.* @@ -192,7 +191,7 @@ class TimetableFragment : Fragment(), CoroutineScope { BottomSheetPrimaryItem(true) .withTitle(R.string.menu_generate_block_timetable) .withDescription(R.string.menu_generate_block_timetable_desc) - .withIcon(Icon2.cmd_table_large) + .withIcon(CommunityMaterial.Icon3.cmd_table_large) .withOnClickListener(View.OnClickListener { activity.bottomSheet.close() GenerateBlockTimetableDialog(activity) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentAdapter.kt index 99abba4d..6f8bc4c7 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/views/AttachmentAdapter.kt @@ -69,7 +69,7 @@ class AttachmentAdapter( "jpg", "jpeg", "png", "bmp", "gif" -> SzkolnyFont.Icon.szf_file_image_outline "zip", "rar", "tar", "7z" -> SzkolnyFont.Icon.szf_zip_box_outline "html", "cpp", "c", "h", "css", "java", "py" -> SzkolnyFont.Icon.szf_file_code_outline - else -> CommunityMaterial.Icon.cmd_file_document_outline + else -> CommunityMaterial.Icon2.cmd_file_document_outline } b.chip.text = if (item.isDownloading) { @@ -83,7 +83,7 @@ class AttachmentAdapter( b.chip.chipIcon = IconicsDrawable(context).apply { icon = attachmentIcon - colorAttr(context, R.attr.colorSurface) + colorAttr(context, R.attr.colorOnSurface) sizeDp = 24 paddingDp = 2 } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt index 07db9ea2..daffae65 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt @@ -117,7 +117,7 @@ class WidgetTimetableProvider : AppWidgetProvider() { views.setImageViewBitmap( R.id.widgetTimetableRefresh, - IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh).apply { + IconicsDrawable(context, CommunityMaterial.Icon3.cmd_refresh).apply { colorInt = Color.WHITE sizeDp = if (config.bigStyle) 24 else 16 }.toBitmap() diff --git a/app/src/main/res/layout/dialog_event_details.xml b/app/src/main/res/layout/dialog_event_details.xml index 11f57902..dc883137 100644 --- a/app/src/main/res/layout/dialog_event_details.xml +++ b/app/src/main/res/layout/dialog_event_details.xml @@ -206,6 +206,7 @@ app:flexWrap="wrap" app:justifyContent="flex_end"> + + + + + diff --git a/app/src/main/res/layout/event_list_item.xml b/app/src/main/res/layout/event_list_item.xml index 295ffdc2..f8f42ef9 100644 --- a/app/src/main/res/layout/event_list_item.xml +++ b/app/src/main/res/layout/event_list_item.xml @@ -73,14 +73,15 @@ android:textAppearance="@style/NavView.TextView.Medium" tools:text="Rozdział II: Panowanie Piastów i Jagiellonów.Przeniesiony z 11 grudnia. Nie wiem co się dzieje w tym roku nie będzie już religii w szkołach podstawowych w Polsce i Europie zachodniej Afryki" /> + diff --git a/app/src/main/res/layout/login_chooser_fragment.xml b/app/src/main/res/layout/login_chooser_fragment.xml index 27e6f309..6e83c68c 100644 --- a/app/src/main/res/layout/login_chooser_fragment.xml +++ b/app/src/main/res/layout/login_chooser_fragment.xml @@ -18,7 +18,7 @@ android:layout_marginHorizontal="24dp" android:layout_marginTop="32dp" app:iiv_color="@color/colorPrimary" - app:iiv_icon="cmd-school" + app:iiv_icon="cmd-school-outline" app:iiv_size="32dp" tools:srcCompat="@tools:sample/avatars" /> diff --git a/app/src/main/res/layout/login_form_fragment.xml b/app/src/main/res/layout/login_form_fragment.xml index 6bfb817f..ac4afd93 100644 --- a/app/src/main/res/layout/login_form_fragment.xml +++ b/app/src/main/res/layout/login_form_fragment.xml @@ -29,7 +29,7 @@ android:layout_height="32dp" android:layout_marginTop="32dp" app:iiv_color="@color/colorPrimary" - app:iiv_icon="cmd-account-circle" + app:iiv_icon="cmd-account-circle-outline" app:iiv_size="32dp" tools:srcCompat="@tools:sample/avatars" /> diff --git a/app/src/main/res/layout/login_platform_list_fragment.xml b/app/src/main/res/layout/login_platform_list_fragment.xml index 699177ff..7604f1c7 100644 --- a/app/src/main/res/layout/login_platform_list_fragment.xml +++ b/app/src/main/res/layout/login_platform_list_fragment.xml @@ -18,7 +18,7 @@ android:layout_marginHorizontal="24dp" android:layout_marginTop="32dp" app:iiv_color="@color/colorPrimary" - app:iiv_icon="cmd-tooltip-account" + app:iiv_icon="cmd-comment-account-outline" app:iiv_size="32dp" tools:srcCompat="@tools:sample/avatars" /> diff --git a/app/src/main/res/layout/login_summary_fragment.xml b/app/src/main/res/layout/login_summary_fragment.xml index 1b7aac65..174087e8 100644 --- a/app/src/main/res/layout/login_summary_fragment.xml +++ b/app/src/main/res/layout/login_summary_fragment.xml @@ -28,7 +28,7 @@ android:layout_marginHorizontal="24dp" android:layout_marginTop="32dp" app:iiv_color="@color/colorPrimary" - app:iiv_icon="cmd-account-check" + app:iiv_icon="cmd-account-check-outline" app:iiv_size="32dp" tools:srcCompat="@tools:sample/avatars" /> diff --git a/app/src/main/res/layout/message_fragment.xml b/app/src/main/res/layout/message_fragment.xml index a58f610f..bb252b11 100644 --- a/app/src/main/res/layout/message_fragment.xml +++ b/app/src/main/res/layout/message_fragment.xml @@ -217,7 +217,7 @@ android:layout_height="24dp" android:padding="4dp" app:iiv_color="?android:textColorSecondary" - app:iiv_icon="cmd-reply" + app:iiv_icon="cmd-reply-outline" tools:srcCompat="@android:drawable/ic_menu_revert" /> Date: Sun, 21 Mar 2021 23:47:14 +0100 Subject: [PATCH 14/15] [Gradle] Assign strict versions where required. --- app/build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f9adae64..0e83e107 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -99,7 +99,7 @@ dependencies { implementation "com.google.android.gms:play-services-wearable:17.0.0" implementation "com.google.firebase:firebase-core:18.0.2" implementation "com.google.firebase:firebase-crashlytics:17.4.0" - implementation "com.google.firebase:firebase-messaging:20.1.3" + implementation("com.google.firebase:firebase-messaging") { version { strictly "20.1.3" } } // OkHttp, Retrofit, Gson, Jsoup implementation("com.squareup.okhttp3:okhttp") { version { strictly "3.12.13" } } @@ -142,12 +142,12 @@ dependencies { implementation "com.github.ChuckerTeam.Chucker:library:3.0.1" implementation "com.github.jetradarmobile:android-snowfall:1.2.0" implementation "com.github.wulkanowy.uonet-request-signer:hebe-jvm:a99ca50a31" - implementation "com.heinrichreimersoftware:material-intro:1.5.8" // do not update + implementation("com.heinrichreimersoftware:material-intro") { version { strictly "1.5.8" } } implementation "com.hypertrack:hyperlog:0.0.10" implementation "com.jaredrummler:colorpicker:1.1.0" implementation "com.qifan.powerpermission:powerpermission-coroutines:1.3.0" implementation "com.qifan.powerpermission:powerpermission:1.3.0" - implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" // do not update + implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0" implementation "com.wdullaer:materialdatetimepicker:4.2.3" implementation "com.yuyh.json:jsonviewer:1.0.6" implementation "io.coil-kt:coil:1.1.1" @@ -155,7 +155,7 @@ dependencies { implementation "me.grantland:autofittextview:0.2.1" implementation "me.leolin:ShortcutBadger:1.1.22@aar" implementation "org.greenrobot:eventbus:3.2.0" - implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.15" + implementation("pl.droidsonroids.gif:android-gif-drawable") { version { strictly "1.2.15" } } // Debug-only dependencies debugImplementation "com.amitshekhar.android:debug-db:1.0.5" From b4595446a3ce0a4e160ac67360ab444abb9d2dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Mon, 22 Mar 2021 17:07:17 +0100 Subject: [PATCH 15/15] [Gradle] Change wrapper distribution from bin to all. --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1a62f29e..9bd0ad16 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Feb 17 14:04:38 CET 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME