From f021a854dedbcde5e3f177e858c4fd848082f8cb Mon Sep 17 00:00:00 2001 From: Kosh Date: Mon, 24 Oct 2016 21:22:00 +0800 Subject: [PATCH] init repo --- .gitignore | 9 + app/.gitignore | 1 + app/build.gradle | 90 ++++ app/proguard-rules.pro | 17 + app/src/main/AndroidManifest.xml | 93 ++++ app/src/main/assets/fonts/app_font.ttf | Bin 0 -> 114624 bytes app/src/main/java/com/fastaccess/App.java | 68 +++ .../com/fastaccess/data/dao/AppsModel.java | 181 +++++++ .../data/dao/BackupRestoreModel.java | 98 ++++ .../data/dao/DeviceAppsEventModel.java | 10 + .../data/dao/FloatingEventModel.java | 30 ++ .../fastaccess/data/dao/FolderEventModel.java | 9 + .../com/fastaccess/data/dao/FolderModel.java | 119 +++++ .../data/dao/SelectedAppsEventModel.java | 10 + .../data/dao/ThemePackEventModel.java | 10 + .../com/fastaccess/helper/ActivityHelper.java | 92 ++++ .../com/fastaccess/helper/AnimHelper.java | 157 ++++++ .../java/com/fastaccess/helper/AppHelper.java | 276 +++++++++++ .../java/com/fastaccess/helper/Bundler.java | 195 ++++++++ .../com/fastaccess/helper/ColorHelper.java | 52 ++ .../com/fastaccess/helper/DatabaseHelper.java | 11 + .../com/fastaccess/helper/DateHelper.java | 293 +++++++++++ .../com/fastaccess/helper/FileHelper.java | 162 +++++++ .../com/fastaccess/helper/GsonHelper.java | 31 ++ .../com/fastaccess/helper/InputHelper.java | 87 ++++ .../java/com/fastaccess/helper/Logger.java | 96 ++++ .../fastaccess/helper/NotificationHelper.java | 145 ++++++ .../com/fastaccess/helper/PaletteHelper.java | 69 +++ .../helper/ParcelableBooleanParse.java | 58 +++ .../fastaccess/helper/PermissionsHelper.java | 34 ++ .../com/fastaccess/helper/PrefConstant.java | 88 ++++ .../com/fastaccess/helper/PrefHelper.java | 121 +++++ .../com/fastaccess/helper/TypeFaceHelper.java | 25 + .../com/fastaccess/helper/ViewHelper.java | 243 ++++++++++ .../provider/analytics/Analytics.java | 34 ++ .../fastaccess/provider/icon/IconCache.java | 415 ++++++++++++++++ .../provider/icon/IconPackAdapter.java | 99 ++++ .../provider/icon/IconPackHelper.java | 455 ++++++++++++++++++ .../provider/icon/model/IconPackInfo.java | 28 ++ .../provider/loader/DeviceAppsLoader.java | 110 +++++ .../provider/loader/FoldersLoader.java | 70 +++ .../provider/loader/SelectedAppsLoader.java | 104 ++++ .../provider/push/PushNotification.java | 19 + .../receiver/ApplicationsReceiver.java | 39 ++ .../provider/receiver/BootReceiver.java | 20 + .../provider/service/FloatingService.java | 71 +++ .../ui/adapter/DeviceAppsAdapter.java | 97 ++++ .../ui/adapter/FloatingAppsAdapter.java | 39 ++ .../ui/adapter/FloatingFoldersAdapter.java | 39 ++ .../fastaccess/ui/adapter/FoldersAdapter.java | 59 +++ .../ui/adapter/SelectFolderAppsAdapter.java | 64 +++ .../adapter/viewholder/AppDrawerHolder.java | 43 ++ .../viewholder/DeviceAppsViewHolder.java | 60 +++ .../viewholder/FloatingAppsViewHolder.java | 70 +++ .../viewholder/FloatingFoldersViewHolder.java | 63 +++ .../viewholder/FloatingWindowsViewHolder.java | 66 +++ .../adapter/viewholder/FoldersViewHolder.java | 62 +++ .../SelectFolderAppsViewHolder.java | 49 ++ .../com/fastaccess/ui/base/BaseActivity.java | 126 +++++ .../ui/base/BaseBottomSheetDialog.java | 123 +++++ .../com/fastaccess/ui/base/BaseFragment.java | 76 +++ .../com/fastaccess/ui/base/mvp/BaseMvp.java | 14 + .../ui/base/mvp/presenter/BasePresenter.java | 42 ++ .../ui/modules/apps/device/DeviceAppsMvp.java | 46 ++ .../apps/device/DeviceAppsPresenter.java | 104 ++++ .../modules/apps/device/DeviceAppsView.java | 167 +++++++ .../ui/modules/apps/folders/FoldersMvp.java | 41 ++ .../apps/folders/FoldersPresenter.java | 55 +++ .../ui/modules/apps/folders/FoldersView.java | 115 +++++ .../apps/folders/create/CreateFolderMvp.java | 18 + .../folders/create/CreateFolderPresenter.java | 20 + .../apps/folders/create/CreateFolderView.java | 159 ++++++ .../folders/select/SelectFolderAppsMvp.java | 29 ++ .../select/SelectFolderAppsPresenter.java | 49 ++ .../folders/select/SelectFolderAppsView.java | 170 +++++++ .../apps/selected/SelectedAppsMvp.java | 54 +++ .../apps/selected/SelectedAppsPresenter.java | 118 +++++ .../apps/selected/SelectedAppsView.java | 178 +++++++ .../ui/modules/cloud/auth/LoginMvp.java | 50 ++ .../ui/modules/cloud/auth/LoginPresenter.java | 117 +++++ .../ui/modules/cloud/auth/LoginView.java | 166 +++++++ .../ui/modules/cloud/backup/BackupMvp.java | 32 ++ .../modules/cloud/backup/BackupPresenter.java | 46 ++ .../ui/modules/cloud/backup/BackupView.java | 92 ++++ .../ui/modules/cloud/restore/RestoreMvp.java | 37 ++ .../cloud/restore/RestorePresenter.java | 74 +++ .../ui/modules/cloud/restore/RestoreView.java | 105 ++++ .../ui/modules/floating/BaseFloatingMvp.java | 71 +++ .../floating/BaseFloatingPresenter.java | 132 +++++ .../ui/modules/floating/BaseFloatingView.java | 176 +++++++ .../modules/floating/apps/FloatingHVMvp.java | 13 + .../floating/apps/FloatingVHPresenter.java | 41 ++ .../modules/floating/apps/FloatingVHView.java | 56 +++ .../floating/folders/FloatingFoldersMvp.java | 21 + .../folders/FloatingFoldersPresenter.java | 28 ++ .../floating/folders/FloatingFoldersView.java | 70 +++ .../folders/drawer/FloatingDrawPresenter.java | 50 ++ .../folders/drawer/FloatingDrawerMvp.java | 37 ++ .../folders/drawer/FloatingDrawerView.java | 145 ++++++ .../fastaccess/ui/modules/main/MainMvp.java | 87 ++++ .../ui/modules/main/MainPresenter.java | 212 ++++++++ .../fastaccess/ui/modules/main/MainView.java | 227 +++++++++ .../settings/SettingsFragmentView.java | 239 +++++++++ .../ui/modules/settings/SettingsView.java | 30 ++ .../dialogs/CropImageActivityDialog.java | 72 +++ .../dialogs/CustomIconChooserDialog.java | 54 +++ .../dialogs/IconSizeTransparencyDialog.java | 105 ++++ .../ui/widgets/AppbarRefreshLayout.java | 56 +++ .../ui/widgets/FastBitmapDrawable.java | 221 +++++++++ .../ui/widgets/FitWidthImageView.java | 60 +++ .../ui/widgets/FontAutoCompleteEditText.java | 48 ++ .../com/fastaccess/ui/widgets/FontButton.java | 50 ++ .../fastaccess/ui/widgets/FontCheckbox.java | 43 ++ .../fastaccess/ui/widgets/FontEditText.java | 46 ++ .../ui/widgets/FontFitTextView.java | 86 ++++ .../ui/widgets/FontRadioButton.java | 43 ++ .../fastaccess/ui/widgets/FontTextView.java | 45 ++ .../ui/widgets/ForegroundImageView.java | 115 +++++ .../ui/widgets/NestedCoordinatorLayout.java | 110 +++++ .../ui/widgets/ShadowTransformer.java | 115 +++++ .../com/fastaccess/ui/widgets/SwitchView.java | 35 ++ .../fastaccess/ui/widgets/ViewPagerView.java | 48 ++ .../ui/widgets/dialog/MessageDialogView.java | 94 ++++ .../ui/widgets/floating/FloatingLayout.java | 49 ++ .../floating/FloatingTouchCallback.java | 25 + .../ui/widgets/floating/FloatingView.java | 175 +++++++ .../recyclerview/BaseRecyclerAdapter.java | 129 +++++ .../widgets/recyclerview/BaseViewHolder.java | 54 +++ .../recyclerview/DynamicRecyclerView.java | 133 +++++ .../layout_manager/GridManager.java | 30 ++ .../layout_manager/LinearManager.java | 30 ++ .../layout_manager/StaggeredManager.java | 27 ++ .../touch/ItemTouchHelperAdapter.java | 9 + .../touch/ItemTouchHelperViewHolder.java | 7 + .../touch/SimpleItemTouchHelperCallback.java | 86 ++++ .../res/color/preference_primary_color.xml | 5 + .../res/color/preference_secondry_color.xml | 5 + .../res/drawable-hdpi/folder_background.9.png | Bin 0 -> 5873 bytes .../res/drawable-hdpi/ic_drawer_normal.png | Bin 0 -> 5764 bytes .../res/drawable-hdpi/ic_drawer_pressed.png | Bin 0 -> 5754 bytes .../res/drawable-mdpi/folder_background.9.png | Bin 0 -> 3390 bytes .../res/drawable-mdpi/ic_drawer_normal.png | Bin 0 -> 3433 bytes .../res/drawable-mdpi/ic_drawer_pressed.png | Bin 0 -> 3532 bytes .../res/drawable-nodpi/header_background.jpeg | Bin 0 -> 83414 bytes .../main/res/drawable-nodpi/ic_fa_splash.png | Bin 0 -> 6236 bytes .../drawable-xhdpi/folder_background.9.png | Bin 0 -> 7477 bytes .../res/drawable-xhdpi/ic_drawer_normal.png | Bin 0 -> 8402 bytes .../res/drawable-xhdpi/ic_drawer_pressed.png | Bin 0 -> 8708 bytes .../drawable-xxhdpi/folder_background.9.png | Bin 0 -> 15077 bytes .../res/drawable-xxhdpi/ic_drawer_normal.png | Bin 0 -> 13762 bytes .../res/drawable-xxhdpi/ic_drawer_pressed.png | Bin 0 -> 14014 bytes .../drawable-xxxhdpi/folder_background.9.png | Bin 0 -> 21489 bytes .../res/drawable-xxxhdpi/ic_drawer_normal.png | Bin 0 -> 20788 bytes .../drawable-xxxhdpi/ic_drawer_pressed.png | Bin 0 -> 20915 bytes app/src/main/res/drawable/bottom_border.xml | 14 + app/src/main/res/drawable/ic_add.xml | 9 + .../main/res/drawable/ic_app_drawer_icon.xml | 8 + app/src/main/res/drawable/ic_apps_drawer.xml | 9 + app/src/main/res/drawable/ic_arrow_right.xml | 9 + app/src/main/res/drawable/ic_back.xml | 9 + app/src/main/res/drawable/ic_back_pressed.xml | 9 + .../main/res/drawable/ic_back_selector.xml | 8 + app/src/main/res/drawable/ic_backup.xml | 9 + app/src/main/res/drawable/ic_clear.xml | 9 + app/src/main/res/drawable/ic_done.xml | 9 + app/src/main/res/drawable/ic_fa.xml | 66 +++ .../main/res/drawable/ic_fa_notification.xml | 66 +++ app/src/main/res/drawable/ic_folder.xml | 9 + app/src/main/res/drawable/ic_menu.xml | 9 + app/src/main/res/drawable/ic_nav_right.xml | 9 + app/src/main/res/drawable/ic_notification.png | Bin 0 -> 2819 bytes app/src/main/res/drawable/ic_play.xml | 9 + app/src/main/res/drawable/ic_restore.xml | 9 + app/src/main/res/drawable/ic_sad_face.xml | 9 + app/src/main/res/drawable/ic_search.xml | 9 + app/src/main/res/drawable/ic_select_all.xml | 10 + .../main/res/drawable/ic_selected_apps.xml | 9 + app/src/main/res/drawable/ic_settings.xml | 9 + app/src/main/res/drawable/ic_share.xml | 9 + app/src/main/res/drawable/ic_stop.xml | 9 + app/src/main/res/drawable/ic_trash.xml | 9 + app/src/main/res/drawable/left_border.xml | 17 + app/src/main/res/drawable/list_divider.xml | 8 + app/src/main/res/drawable/right_border.xml | 17 + .../res/drawable/splash_screen_drawable.xml | 12 + app/src/main/res/drawable/toolbar_shadow.xml | 8 + app/src/main/res/drawable/top_border.xml | 17 + app/src/main/res/drawable/top_shadow.xml | 8 + .../layout/floating_folder_layout.xml | 38 ++ .../layout/horizontal_layout.xml | 36 ++ .../layout/transparency_layout.xml | 75 +++ .../layout/vertical_layout.xml | 33 ++ .../main_layouts/layout/activity_main.xml | 65 +++ .../layout/app_details_layout.xml | 104 ++++ .../layout/create_edit_folder.xml | 72 +++ .../layout/select_folder_apps_layout.xml | 18 + .../main_layouts/layout/settings_layout.xml | 17 + .../main_layouts/layout/sign_in_layout.xml | 39 ++ .../other_layouts/layout/appbar_elevation.xml | 40 ++ .../layout/appbar_elevation_dark.xml | 42 ++ .../layout/appbar_search_elevation.xml | 85 ++++ .../layout/appbar_tabbed_elevation.xml | 44 ++ .../layout/crop_image_layout.xml | 53 ++ .../other_layouts/layout/drawer_header.xml | 41 ++ .../other_layouts/layout/empty_layout.xml | 30 ++ .../other_layouts/layout/grid_list.xml | 20 + .../layout/icon_chooser_layout.xml | 40 ++ .../other_layouts/layout/message_dialog.xml | 70 +++ .../other_layouts/layout/progress_layout.xml | 18 + .../other_layouts/layout/small_grid_list.xml | 19 + .../row_layouts/layout/app_details_header.xml | 101 ++++ .../row_layouts/layout/app_row_item.xml | 24 + .../layout/floating_apps_row_item.xml | 19 + .../row_layouts/layout/folder_row_item.xml | 111 +++++ .../row_layouts/layout/icon_pack_layout.xml | 41 ++ .../layout/permission_row_item.xml | 41 ++ .../layout/select_apps_folder_row.xml | 47 ++ app/src/main/res/menu/add_menu.xml | 17 + app/src/main/res/menu/bottom_nav_menu.xml | 25 + app/src/main/res/menu/drawer_menu.xml | 54 +++ app/src/main/res/menu/remove_menu.xml | 16 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 5125 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3191 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 7179 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 11010 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 15595 bytes app/src/main/res/values-land/dimens.xml | 6 + .../main/res/values-sw600dp-land/dimens.xml | 7 + app/src/main/res/values-sw600dp/dimens.xml | 7 + .../main/res/values-sw720dp-land/dimens.xml | 7 + app/src/main/res/values-sw720dp/dimens.xml | 11 + app/src/main/res/values-v21/styles.xml | 12 + .../main/res/values-w820dp-land/dimens.xml | 6 + app/src/main/res/values-w820dp/dimens.xml | 6 + app/src/main/res/values/arrays.xml | 43 ++ app/src/main/res/values/attrs.xml | 10 + app/src/main/res/values/colors.xml | 19 + app/src/main/res/values/dimens.xml | 21 + app/src/main/res/values/strings.xml | 136 ++++++ app/src/main/res/values/styles.xml | 84 ++++ app/src/main/res/xml/fa_settings.xml | 145 ++++++ app/src/main/res/xml/fa_shortcuts.xml | 32 ++ build.gradle | 24 + color-picker/.gitignore | 1 + color-picker/build.gradle | 28 ++ color-picker/proguard-rules.pro | 17 + color-picker/src/main/AndroidManifest.xml | 11 + .../preference/AppCompatColorPreference.java | 283 +++++++++++ .../xdty/preference/ColorCircleDrawable.java | 46 ++ .../org/xdty/preference/ColorPreference.java | 236 +++++++++ .../colorpicker/ColorPickerDialog.java | 244 ++++++++++ .../colorpicker/ColorPickerPalette.java | 195 ++++++++ .../colorpicker/ColorPickerSwatch.java | 77 +++ .../colorpicker/ColorStateDrawable.java | 72 +++ .../colorpicker/HsvColorComparator.java | 61 +++ .../ic_colorpicker_swatch_selected.png | Bin 0 -> 2414 bytes .../ic_colorpicker_swatch_selected.png | Bin 0 -> 1662 bytes .../ic_colorpicker_swatch_selected.png | Bin 0 -> 3241 bytes .../main/res/drawable/color_picker_swatch.xml | 16 + .../main/res/layout/color_picker_dialog.xml | 45 ++ .../main/res/layout/color_picker_swatch.xml | 32 ++ .../src/main/res/values-af/strings.xml | 22 + .../src/main/res/values-am/strings.xml | 22 + .../src/main/res/values-ar/strings.xml | 22 + .../src/main/res/values-bg/strings.xml | 22 + .../src/main/res/values-bn-rBD/strings.xml | 22 + .../src/main/res/values-ca/strings.xml | 22 + .../src/main/res/values-cs/strings.xml | 22 + .../src/main/res/values-da/strings.xml | 22 + .../src/main/res/values-de/strings.xml | 22 + .../src/main/res/values-el/strings.xml | 22 + .../src/main/res/values-en-rAU/strings.xml | 22 + .../src/main/res/values-en-rGB/strings.xml | 22 + .../src/main/res/values-en-rIN/strings.xml | 22 + .../src/main/res/values-es-rUS/strings.xml | 22 + .../src/main/res/values-es/strings.xml | 22 + .../src/main/res/values-et-rEE/strings.xml | 22 + .../src/main/res/values-eu-rES/strings.xml | 22 + .../src/main/res/values-fa/strings.xml | 22 + .../src/main/res/values-fi/strings.xml | 22 + .../src/main/res/values-fr-rCA/strings.xml | 22 + .../src/main/res/values-fr/strings.xml | 22 + .../src/main/res/values-gl-rES/strings.xml | 22 + .../src/main/res/values-gu-rIN/strings.xml | 22 + .../src/main/res/values-hi/strings.xml | 22 + .../src/main/res/values-hr/strings.xml | 22 + .../src/main/res/values-hu/strings.xml | 22 + .../src/main/res/values-hy-rAM/strings.xml | 22 + .../src/main/res/values-in/strings.xml | 22 + .../src/main/res/values-is-rIS/strings.xml | 22 + .../src/main/res/values-it/strings.xml | 22 + .../src/main/res/values-iw/strings.xml | 22 + .../src/main/res/values-ja/strings.xml | 22 + .../src/main/res/values-ka-rGE/strings.xml | 22 + .../src/main/res/values-kk-rKZ/strings.xml | 22 + .../src/main/res/values-km-rKH/strings.xml | 22 + .../src/main/res/values-kn-rIN/strings.xml | 22 + .../src/main/res/values-ko/strings.xml | 22 + .../src/main/res/values-ky-rKG/strings.xml | 22 + .../src/main/res/values-lo-rLA/strings.xml | 22 + .../src/main/res/values-lt/strings.xml | 22 + .../src/main/res/values-lv/strings.xml | 22 + .../src/main/res/values-mk-rMK/strings.xml | 22 + .../src/main/res/values-ml-rIN/strings.xml | 22 + .../src/main/res/values-mn-rMN/strings.xml | 22 + .../src/main/res/values-mr-rIN/strings.xml | 22 + .../src/main/res/values-ms-rMY/strings.xml | 22 + .../src/main/res/values-my-rMM/strings.xml | 22 + .../src/main/res/values-nb/strings.xml | 22 + .../src/main/res/values-ne-rNP/strings.xml | 22 + .../src/main/res/values-nl/strings.xml | 22 + .../src/main/res/values-pa-rIN/strings.xml | 22 + .../src/main/res/values-pl/strings.xml | 22 + .../src/main/res/values-pt-rPT/strings.xml | 22 + .../src/main/res/values-pt/strings.xml | 22 + .../src/main/res/values-ro/strings.xml | 22 + .../src/main/res/values-ru/strings.xml | 22 + .../src/main/res/values-si-rLK/strings.xml | 22 + .../src/main/res/values-sk/strings.xml | 22 + .../src/main/res/values-sl/strings.xml | 22 + .../src/main/res/values-sq-rAL/strings.xml | 22 + .../src/main/res/values-sr/strings.xml | 22 + .../src/main/res/values-sv/strings.xml | 22 + .../src/main/res/values-sw/strings.xml | 22 + .../src/main/res/values-ta-rIN/strings.xml | 22 + .../src/main/res/values-te-rIN/strings.xml | 22 + .../src/main/res/values-th/strings.xml | 22 + .../src/main/res/values-tl/strings.xml | 22 + .../src/main/res/values-tr/strings.xml | 22 + .../src/main/res/values-uk/strings.xml | 22 + .../src/main/res/values-ur-rPK/strings.xml | 22 + .../src/main/res/values-uz-rUZ/strings.xml | 22 + .../src/main/res/values-vi/strings.xml | 22 + .../src/main/res/values-zh-rCN/strings.xml | 35 ++ .../src/main/res/values-zh-rHK/strings.xml | 22 + .../src/main/res/values-zh-rTW/strings.xml | 22 + .../src/main/res/values-zu/strings.xml | 22 + color-picker/src/main/res/values/arrays.xml | 29 ++ color-picker/src/main/res/values/attrs.xml | 9 + color-picker/src/main/res/values/colors.xml | 30 ++ color-picker/src/main/res/values/dimens.xml | 21 + color-picker/src/main/res/values/strings.xml | 36 ++ gradle.properties | 17 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 160 ++++++ gradlew.bat | 90 ++++ settings.gradle | 1 + 348 files changed, 17381 insertions(+) create mode 100644 .gitignore create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/assets/fonts/app_font.ttf create mode 100644 app/src/main/java/com/fastaccess/App.java create mode 100644 app/src/main/java/com/fastaccess/data/dao/AppsModel.java create mode 100644 app/src/main/java/com/fastaccess/data/dao/BackupRestoreModel.java create mode 100644 app/src/main/java/com/fastaccess/data/dao/DeviceAppsEventModel.java create mode 100644 app/src/main/java/com/fastaccess/data/dao/FloatingEventModel.java create mode 100644 app/src/main/java/com/fastaccess/data/dao/FolderEventModel.java create mode 100644 app/src/main/java/com/fastaccess/data/dao/FolderModel.java create mode 100644 app/src/main/java/com/fastaccess/data/dao/SelectedAppsEventModel.java create mode 100644 app/src/main/java/com/fastaccess/data/dao/ThemePackEventModel.java create mode 100644 app/src/main/java/com/fastaccess/helper/ActivityHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/AnimHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/AppHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/Bundler.java create mode 100644 app/src/main/java/com/fastaccess/helper/ColorHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/DatabaseHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/DateHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/FileHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/GsonHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/InputHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/Logger.java create mode 100755 app/src/main/java/com/fastaccess/helper/NotificationHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/PaletteHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/ParcelableBooleanParse.java create mode 100644 app/src/main/java/com/fastaccess/helper/PermissionsHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/PrefConstant.java create mode 100644 app/src/main/java/com/fastaccess/helper/PrefHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/TypeFaceHelper.java create mode 100644 app/src/main/java/com/fastaccess/helper/ViewHelper.java create mode 100644 app/src/main/java/com/fastaccess/provider/analytics/Analytics.java create mode 100644 app/src/main/java/com/fastaccess/provider/icon/IconCache.java create mode 100644 app/src/main/java/com/fastaccess/provider/icon/IconPackAdapter.java create mode 100644 app/src/main/java/com/fastaccess/provider/icon/IconPackHelper.java create mode 100644 app/src/main/java/com/fastaccess/provider/icon/model/IconPackInfo.java create mode 100644 app/src/main/java/com/fastaccess/provider/loader/DeviceAppsLoader.java create mode 100644 app/src/main/java/com/fastaccess/provider/loader/FoldersLoader.java create mode 100644 app/src/main/java/com/fastaccess/provider/loader/SelectedAppsLoader.java create mode 100644 app/src/main/java/com/fastaccess/provider/push/PushNotification.java create mode 100644 app/src/main/java/com/fastaccess/provider/receiver/ApplicationsReceiver.java create mode 100644 app/src/main/java/com/fastaccess/provider/receiver/BootReceiver.java create mode 100644 app/src/main/java/com/fastaccess/provider/service/FloatingService.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/DeviceAppsAdapter.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/FloatingAppsAdapter.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/FloatingFoldersAdapter.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/FoldersAdapter.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/SelectFolderAppsAdapter.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/AppDrawerHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/DeviceAppsViewHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingAppsViewHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingFoldersViewHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingWindowsViewHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/FoldersViewHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/SelectFolderAppsViewHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/base/BaseActivity.java create mode 100644 app/src/main/java/com/fastaccess/ui/base/BaseBottomSheetDialog.java create mode 100644 app/src/main/java/com/fastaccess/ui/base/BaseFragment.java create mode 100644 app/src/main/java/com/fastaccess/ui/base/mvp/BaseMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/base/mvp/presenter/BasePresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestoreMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestorePresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestoreView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingHVMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingVHPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingVHView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawerMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawerView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/MainMvp.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/MainPresenter.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/MainView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/SettingsFragmentView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/SettingsView.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/CropImageActivityDialog.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/CustomIconChooserDialog.java create mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/IconSizeTransparencyDialog.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/AppbarRefreshLayout.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FastBitmapDrawable.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FitWidthImageView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontAutoCompleteEditText.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontButton.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontCheckbox.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontEditText.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontFitTextView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontRadioButton.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontTextView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/ForegroundImageView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/NestedCoordinatorLayout.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/ShadowTransformer.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/SwitchView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/ViewPagerView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingLayout.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingTouchCallback.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseViewHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/GridManager.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/LinearManager.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/StaggeredManager.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/ItemTouchHelperAdapter.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/ItemTouchHelperViewHolder.java create mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/SimpleItemTouchHelperCallback.java create mode 100644 app/src/main/res/color/preference_primary_color.xml create mode 100644 app/src/main/res/color/preference_secondry_color.xml create mode 100755 app/src/main/res/drawable-hdpi/folder_background.9.png create mode 100755 app/src/main/res/drawable-hdpi/ic_drawer_normal.png create mode 100755 app/src/main/res/drawable-hdpi/ic_drawer_pressed.png create mode 100755 app/src/main/res/drawable-mdpi/folder_background.9.png create mode 100755 app/src/main/res/drawable-mdpi/ic_drawer_normal.png create mode 100755 app/src/main/res/drawable-mdpi/ic_drawer_pressed.png create mode 100644 app/src/main/res/drawable-nodpi/header_background.jpeg create mode 100644 app/src/main/res/drawable-nodpi/ic_fa_splash.png create mode 100755 app/src/main/res/drawable-xhdpi/folder_background.9.png create mode 100755 app/src/main/res/drawable-xhdpi/ic_drawer_normal.png create mode 100755 app/src/main/res/drawable-xhdpi/ic_drawer_pressed.png create mode 100755 app/src/main/res/drawable-xxhdpi/folder_background.9.png create mode 100755 app/src/main/res/drawable-xxhdpi/ic_drawer_normal.png create mode 100755 app/src/main/res/drawable-xxhdpi/ic_drawer_pressed.png create mode 100755 app/src/main/res/drawable-xxxhdpi/folder_background.9.png create mode 100755 app/src/main/res/drawable-xxxhdpi/ic_drawer_normal.png create mode 100755 app/src/main/res/drawable-xxxhdpi/ic_drawer_pressed.png create mode 100644 app/src/main/res/drawable/bottom_border.xml create mode 100644 app/src/main/res/drawable/ic_add.xml create mode 100644 app/src/main/res/drawable/ic_app_drawer_icon.xml create mode 100644 app/src/main/res/drawable/ic_apps_drawer.xml create mode 100644 app/src/main/res/drawable/ic_arrow_right.xml create mode 100644 app/src/main/res/drawable/ic_back.xml create mode 100644 app/src/main/res/drawable/ic_back_pressed.xml create mode 100644 app/src/main/res/drawable/ic_back_selector.xml create mode 100644 app/src/main/res/drawable/ic_backup.xml create mode 100644 app/src/main/res/drawable/ic_clear.xml create mode 100644 app/src/main/res/drawable/ic_done.xml create mode 100644 app/src/main/res/drawable/ic_fa.xml create mode 100644 app/src/main/res/drawable/ic_fa_notification.xml create mode 100644 app/src/main/res/drawable/ic_folder.xml create mode 100644 app/src/main/res/drawable/ic_menu.xml create mode 100644 app/src/main/res/drawable/ic_nav_right.xml create mode 100644 app/src/main/res/drawable/ic_notification.png create mode 100644 app/src/main/res/drawable/ic_play.xml create mode 100644 app/src/main/res/drawable/ic_restore.xml create mode 100644 app/src/main/res/drawable/ic_sad_face.xml create mode 100644 app/src/main/res/drawable/ic_search.xml create mode 100644 app/src/main/res/drawable/ic_select_all.xml create mode 100644 app/src/main/res/drawable/ic_selected_apps.xml create mode 100644 app/src/main/res/drawable/ic_settings.xml create mode 100644 app/src/main/res/drawable/ic_share.xml create mode 100644 app/src/main/res/drawable/ic_stop.xml create mode 100644 app/src/main/res/drawable/ic_trash.xml create mode 100644 app/src/main/res/drawable/left_border.xml create mode 100644 app/src/main/res/drawable/list_divider.xml create mode 100644 app/src/main/res/drawable/right_border.xml create mode 100644 app/src/main/res/drawable/splash_screen_drawable.xml create mode 100644 app/src/main/res/drawable/toolbar_shadow.xml create mode 100644 app/src/main/res/drawable/top_border.xml create mode 100644 app/src/main/res/drawable/top_shadow.xml create mode 100644 app/src/main/res/layouts/floating_layouts/layout/floating_folder_layout.xml create mode 100644 app/src/main/res/layouts/floating_layouts/layout/horizontal_layout.xml create mode 100644 app/src/main/res/layouts/floating_layouts/layout/transparency_layout.xml create mode 100644 app/src/main/res/layouts/floating_layouts/layout/vertical_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/activity_main.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/app_details_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/create_edit_folder.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/select_folder_apps_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/settings_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/sign_in_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_elevation.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_elevation_dark.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_search_elevation.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_tabbed_elevation.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/crop_image_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/drawer_header.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/empty_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/grid_list.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/icon_chooser_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/message_dialog.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/progress_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/small_grid_list.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/app_details_header.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/app_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/floating_apps_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/folder_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/icon_pack_layout.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/permission_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/select_apps_folder_row.xml create mode 100644 app/src/main/res/menu/add_menu.xml create mode 100644 app/src/main/res/menu/bottom_nav_menu.xml create mode 100644 app/src/main/res/menu/drawer_menu.xml create mode 100644 app/src/main/res/menu/remove_menu.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100755 app/src/main/res/values-land/dimens.xml create mode 100644 app/src/main/res/values-sw600dp-land/dimens.xml create mode 100644 app/src/main/res/values-sw600dp/dimens.xml create mode 100644 app/src/main/res/values-sw720dp-land/dimens.xml create mode 100644 app/src/main/res/values-sw720dp/dimens.xml create mode 100644 app/src/main/res/values-v21/styles.xml create mode 100755 app/src/main/res/values-w820dp-land/dimens.xml create mode 100755 app/src/main/res/values-w820dp/dimens.xml create mode 100644 app/src/main/res/values/arrays.xml create mode 100644 app/src/main/res/values/attrs.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/main/res/xml/fa_settings.xml create mode 100644 app/src/main/res/xml/fa_shortcuts.xml create mode 100644 build.gradle create mode 100755 color-picker/.gitignore create mode 100755 color-picker/build.gradle create mode 100755 color-picker/proguard-rules.pro create mode 100755 color-picker/src/main/AndroidManifest.xml create mode 100755 color-picker/src/main/java/org/xdty/preference/AppCompatColorPreference.java create mode 100755 color-picker/src/main/java/org/xdty/preference/ColorCircleDrawable.java create mode 100755 color-picker/src/main/java/org/xdty/preference/ColorPreference.java create mode 100755 color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerDialog.java create mode 100755 color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerPalette.java create mode 100755 color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerSwatch.java create mode 100755 color-picker/src/main/java/org/xdty/preference/colorpicker/ColorStateDrawable.java create mode 100755 color-picker/src/main/java/org/xdty/preference/colorpicker/HsvColorComparator.java create mode 100755 color-picker/src/main/res/drawable-hdpi/ic_colorpicker_swatch_selected.png create mode 100755 color-picker/src/main/res/drawable-mdpi/ic_colorpicker_swatch_selected.png create mode 100755 color-picker/src/main/res/drawable-xhdpi/ic_colorpicker_swatch_selected.png create mode 100755 color-picker/src/main/res/drawable/color_picker_swatch.xml create mode 100755 color-picker/src/main/res/layout/color_picker_dialog.xml create mode 100755 color-picker/src/main/res/layout/color_picker_swatch.xml create mode 100755 color-picker/src/main/res/values-af/strings.xml create mode 100755 color-picker/src/main/res/values-am/strings.xml create mode 100755 color-picker/src/main/res/values-ar/strings.xml create mode 100755 color-picker/src/main/res/values-bg/strings.xml create mode 100755 color-picker/src/main/res/values-bn-rBD/strings.xml create mode 100755 color-picker/src/main/res/values-ca/strings.xml create mode 100755 color-picker/src/main/res/values-cs/strings.xml create mode 100755 color-picker/src/main/res/values-da/strings.xml create mode 100755 color-picker/src/main/res/values-de/strings.xml create mode 100755 color-picker/src/main/res/values-el/strings.xml create mode 100755 color-picker/src/main/res/values-en-rAU/strings.xml create mode 100755 color-picker/src/main/res/values-en-rGB/strings.xml create mode 100755 color-picker/src/main/res/values-en-rIN/strings.xml create mode 100755 color-picker/src/main/res/values-es-rUS/strings.xml create mode 100755 color-picker/src/main/res/values-es/strings.xml create mode 100755 color-picker/src/main/res/values-et-rEE/strings.xml create mode 100755 color-picker/src/main/res/values-eu-rES/strings.xml create mode 100755 color-picker/src/main/res/values-fa/strings.xml create mode 100755 color-picker/src/main/res/values-fi/strings.xml create mode 100755 color-picker/src/main/res/values-fr-rCA/strings.xml create mode 100755 color-picker/src/main/res/values-fr/strings.xml create mode 100755 color-picker/src/main/res/values-gl-rES/strings.xml create mode 100755 color-picker/src/main/res/values-gu-rIN/strings.xml create mode 100755 color-picker/src/main/res/values-hi/strings.xml create mode 100755 color-picker/src/main/res/values-hr/strings.xml create mode 100755 color-picker/src/main/res/values-hu/strings.xml create mode 100755 color-picker/src/main/res/values-hy-rAM/strings.xml create mode 100755 color-picker/src/main/res/values-in/strings.xml create mode 100755 color-picker/src/main/res/values-is-rIS/strings.xml create mode 100755 color-picker/src/main/res/values-it/strings.xml create mode 100755 color-picker/src/main/res/values-iw/strings.xml create mode 100755 color-picker/src/main/res/values-ja/strings.xml create mode 100755 color-picker/src/main/res/values-ka-rGE/strings.xml create mode 100755 color-picker/src/main/res/values-kk-rKZ/strings.xml create mode 100755 color-picker/src/main/res/values-km-rKH/strings.xml create mode 100755 color-picker/src/main/res/values-kn-rIN/strings.xml create mode 100755 color-picker/src/main/res/values-ko/strings.xml create mode 100755 color-picker/src/main/res/values-ky-rKG/strings.xml create mode 100755 color-picker/src/main/res/values-lo-rLA/strings.xml create mode 100755 color-picker/src/main/res/values-lt/strings.xml create mode 100755 color-picker/src/main/res/values-lv/strings.xml create mode 100755 color-picker/src/main/res/values-mk-rMK/strings.xml create mode 100755 color-picker/src/main/res/values-ml-rIN/strings.xml create mode 100755 color-picker/src/main/res/values-mn-rMN/strings.xml create mode 100755 color-picker/src/main/res/values-mr-rIN/strings.xml create mode 100755 color-picker/src/main/res/values-ms-rMY/strings.xml create mode 100755 color-picker/src/main/res/values-my-rMM/strings.xml create mode 100755 color-picker/src/main/res/values-nb/strings.xml create mode 100755 color-picker/src/main/res/values-ne-rNP/strings.xml create mode 100755 color-picker/src/main/res/values-nl/strings.xml create mode 100755 color-picker/src/main/res/values-pa-rIN/strings.xml create mode 100755 color-picker/src/main/res/values-pl/strings.xml create mode 100755 color-picker/src/main/res/values-pt-rPT/strings.xml create mode 100755 color-picker/src/main/res/values-pt/strings.xml create mode 100755 color-picker/src/main/res/values-ro/strings.xml create mode 100755 color-picker/src/main/res/values-ru/strings.xml create mode 100755 color-picker/src/main/res/values-si-rLK/strings.xml create mode 100755 color-picker/src/main/res/values-sk/strings.xml create mode 100755 color-picker/src/main/res/values-sl/strings.xml create mode 100755 color-picker/src/main/res/values-sq-rAL/strings.xml create mode 100755 color-picker/src/main/res/values-sr/strings.xml create mode 100755 color-picker/src/main/res/values-sv/strings.xml create mode 100755 color-picker/src/main/res/values-sw/strings.xml create mode 100755 color-picker/src/main/res/values-ta-rIN/strings.xml create mode 100755 color-picker/src/main/res/values-te-rIN/strings.xml create mode 100755 color-picker/src/main/res/values-th/strings.xml create mode 100755 color-picker/src/main/res/values-tl/strings.xml create mode 100755 color-picker/src/main/res/values-tr/strings.xml create mode 100755 color-picker/src/main/res/values-uk/strings.xml create mode 100755 color-picker/src/main/res/values-ur-rPK/strings.xml create mode 100755 color-picker/src/main/res/values-uz-rUZ/strings.xml create mode 100755 color-picker/src/main/res/values-vi/strings.xml create mode 100755 color-picker/src/main/res/values-zh-rCN/strings.xml create mode 100755 color-picker/src/main/res/values-zh-rHK/strings.xml create mode 100755 color-picker/src/main/res/values-zh-rTW/strings.xml create mode 100755 color-picker/src/main/res/values-zu/strings.xml create mode 100755 color-picker/src/main/res/values/arrays.xml create mode 100755 color-picker/src/main/res/values/attrs.xml create mode 100755 color-picker/src/main/res/values/colors.xml create mode 100755 color-picker/src/main/res/values/dimens.xml create mode 100755 color-picker/src/main/res/values/strings.xml create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6480dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +.DS_Store +/build +/captures +.externalNativeBuild +/app/google-services.json +/.idea/ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..58146b3 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,90 @@ +apply plugin: 'com.android.application' +apply plugin: "com.neenbedankt.android-apt" + +android { + compileSdkVersion 25 + buildToolsVersion "24.0.2" + defaultConfig { + applicationId "com.styleme.floating.toolbox.pro" + minSdkVersion 18 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + sourceSets { + main { + res.srcDirs = [ + "src/main/res/", + "src/main/res/layouts/main_layouts", + "src/main/res/layouts/row_layouts", + "src/main/res/layouts/other_layouts", + "src/main/res/layouts/floating_layouts", + "src/main/res" + ] + } + } + lintOptions { + quiet true + abortOnError true + htmlReport true + xmlReport true + fatal 'NewApi' + disable 'InvalidPackage' + } +} +repositories { + maven { url "https://clojars.org/repo/" } + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + maven { url "http://dl.bintray.com/amulyakhare/maven" } + maven { url "https://jitpack.io" } +} +dependencies { + ext { + supportVerion = "25.0.0" + firebase = "9.8.00" + } + compile fileTree(include: ['*.jar'], dir: 'libs') + compile "com.android.support:appcompat-v7:${supportVerion}" + compile "com.android.support:design:${supportVerion}" + compile "com.android.support:cardview-v7:${supportVerion}" + compile "com.android.support:recyclerview-v7:${supportVerion}" + compile "com.android.support:palette-v7:${supportVerion}" + compile "com.android.support:preference-v14:${supportVerion}" + compile "com.android.support:customtabs:${supportVerion}" + compile('com.github.ozodrukh:CircularReveal:2.0.1@aar') { + transitive = true; + } + compile('com.mikepenz:aboutlibraries:5.8.1@aar') { + transitive = true + } + compile project(':color-picker') + compile "com.google.firebase:firebase-messaging:${firebase}" + compile "com.google.firebase:firebase-analytics:${firebase}" + compile "com.google.firebase:firebase-database:${firebase}" + compile "com.google.firebase:firebase-auth:${firebase}" + compile "com.google.android.gms:play-services-auth:${firebase}" + compile 'com.google.code.gson:gson:2.7' + compile 'com.jakewharton:butterknife:8.4.0' + compile 'org.greenrobot:eventbus:3.0.0' + compile 'cat.ereza:customactivityoncrash:1.5.0' + compile 'frankiesardo:icepick:3.1.0' + compile 'com.mikhaellopez:circularfillableloaders:1.2.0' + compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' + compile 'com.github.pluscubed:recycler-fast-scroll:0.3.2@aar' + compile 'com.github.satyan:sugar:1.4' + compile 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:1.0.7' + compile 'com.github.vihtarb:tooltip:0.1.8' + compile 'com.github.nisrulz:sensey:1.5.0' + compile 'org.adw.library:discrete-seekbar:1.0.1' + compile 'com.theartofdev.edmodo:android-image-cropper:2.3.1' + compile 'pub.devrel:easypermissions:0.2.1' + apt 'frankiesardo:icepick-processor:3.1.0' + apt 'com.jakewharton:butterknife-compiler:8.4.0' +} +apply plugin: "com.google.gms.google-services" \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..65fe9b3 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/Kosh/Library/Android/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 *; +#} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8b4c9f7 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/fonts/app_font.ttf b/app/src/main/assets/fonts/app_font.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b158a334eb372a9ab2ecd4f2566e60d561e71a9f GIT binary patch literal 114624 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

WH`00`s@p7bm8Ow12>ck9v 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 getApps() { + return Select.from(AppsModel.class) + .where(Condition.prop(NamingHelper.toSQLNameDefault("folderId")).eq(0)) + .orderBy(NamingHelper.toSQLNameDefault("indexPosition") + " ASC") + .list(); + } + + public static List getApps(long folderId) { + return Select.from(AppsModel.class) + .where(Condition.prop(NamingHelper.toSQLNameDefault("folderId")).eq(folderId)) + .list(); + } + + public static int lastPosition() { + AppsModel appsModel = Select.from(AppsModel.class).orderBy(NamingHelper.toSQLNameDefault("indexPosition") + " DESC").first(); + if (appsModel != null) { + return appsModel.getIndexPosition(); + } + return 0; + } + + public static long countApps(long folderId) { + return count(AppsModel.class, NamingHelper.toSQLNameDefault("folderId") + " = ?", new String[]{String.valueOf(folderId)}); + } + + public static void deleteAllByFolder(@NonNull FolderModel folder) { + deleteAll(AppsModel.class, NamingHelper.toSQLNameDefault("folderId") + " = ?", String.valueOf(folder.getId())); + } + + public static void deleteAll() { + deleteAll(AppsModel.class); + } + + public static boolean exists(@NonNull String activityInfoName, @NonNull String packageName) { + return Select.from(AppsModel.class) + .where(Condition.prop(NamingHelper.toSQLNameDefault("activityInfoName")).eq(activityInfoName)) + .and(Condition.prop(NamingHelper.toSQLNameDefault("packageName")).eq(packageName)) + .and(Condition.prop(NamingHelper.toSQLNameDefault("folderId")).eq(0)) + .first() != null; + } + + public static Comparator sortApps() { + return new Comparator() { + @Override public int compare(AppsModel one, AppsModel two) { + return one.getAppName().compareTo(two.getAppName()); + } + }; + } + + @Override public int describeContents() { return 0; } + + @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(this.folderId); + dest.writeString(this.appName); + dest.writeString(this.packageName); + dest.writeString(this.iconPath); + dest.writeString(this.activityInfoName); + dest.writeInt(this.indexPosition); + dest.writeInt(this.countEntry); + dest.writeLong(this.getId()); + } + + protected AppsModel(Parcel in) { + this.folderId = in.readLong(); + this.appName = in.readString(); + this.packageName = in.readString(); + this.iconPath = in.readString(); + this.activityInfoName = in.readString(); + this.indexPosition = in.readInt(); + this.countEntry = in.readInt(); + this.setId((Long) in.readValue(Long.class.getClassLoader())); + } + + public static final Creator CREATOR = new Creator() { + @Override public AppsModel createFromParcel(Parcel source) {return new AppsModel(source);} + + @Override public AppsModel[] newArray(int size) {return new AppsModel[size];} + }; +} diff --git a/app/src/main/java/com/fastaccess/data/dao/BackupRestoreModel.java b/app/src/main/java/com/fastaccess/data/dao/BackupRestoreModel.java new file mode 100644 index 0000000..3b36f37 --- /dev/null +++ b/app/src/main/java/com/fastaccess/data/dao/BackupRestoreModel.java @@ -0,0 +1,98 @@ +package com.fastaccess.data.dao; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +import org.greenrobot.eventbus.EventBus; + +import java.util.List; +import java.util.Map; + +/** + * Created by Kosh on 23 Oct 2016, 8:51 PM + */ + +public class BackupRestoreModel { + + private String uid; + private List folders; + private List appsModels; + private Map settings; + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public List getFolders() { + return folders; + } + + public void setFolders(List folders) { + this.folders = folders; + } + + public List getAppsModels() { + return appsModels; + } + + public void setAppsModels(List appsModels) { + this.appsModels = appsModels; + } + + public Map getSettings() { + return settings; + } + + public void setSettings(Map settings) { + this.settings = settings; + } + + @Nullable public static BackupRestoreModel backup() { + BackupRestoreModel model = new BackupRestoreModel(); + FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); + if (firebaseUser == null) return null; + model.setUid(firebaseUser.getUid()); + model.setFolders(FolderModel.getFolders()); + model.setSettings(PrefHelper.getAll()); + model.setAppsModels(AppsModel.getApps()); + return model; + } + + public static void restore(@NonNull BackupRestoreModel model) { + if (model.getFolders() != null) { + FolderModel.saveInTx(model.getFolders()); + EventBus.getDefault().post(new FolderEventModel()); + } + if (model.getAppsModels() != null) { + AppsModel.saveInTx(model.getAppsModels()); + EventBus.getDefault().post(new FloatingEventModel()); + } + if (model.getSettings() != null) { + for (String key : model.getSettings().keySet()) { + if (key != null && !key.equalsIgnoreCase("null")) { + if (key.equalsIgnoreCase(PrefConstant.FA_BACKGROUND)) { + PrefHelper.set(key, Integer.valueOf(model.getSettings().get(key).toString())); + } else { + PrefHelper.set(key, model.getSettings().get(key)); + } + } + } + } + } + + @Override public String toString() { + return "BackupRestoreModel{" + + "uid='" + uid + '\'' + + ", settings='" + settings + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/fastaccess/data/dao/DeviceAppsEventModel.java b/app/src/main/java/com/fastaccess/data/dao/DeviceAppsEventModel.java new file mode 100644 index 0000000..3db99e8 --- /dev/null +++ b/app/src/main/java/com/fastaccess/data/dao/DeviceAppsEventModel.java @@ -0,0 +1,10 @@ +package com.fastaccess.data.dao; + +/** + * Created by Kosh on 16 Oct 2016, 7:30 PM + */ + +public class DeviceAppsEventModel { + + public DeviceAppsEventModel() {} +} diff --git a/app/src/main/java/com/fastaccess/data/dao/FloatingEventModel.java b/app/src/main/java/com/fastaccess/data/dao/FloatingEventModel.java new file mode 100644 index 0000000..942ae31 --- /dev/null +++ b/app/src/main/java/com/fastaccess/data/dao/FloatingEventModel.java @@ -0,0 +1,30 @@ +package com.fastaccess.data.dao; + +/** + * Created by Kosh on 15 Oct 2016, 8:57 PM + */ + +public class FloatingEventModel { + + private boolean settingsChanged; + private String key; + + public FloatingEventModel() {} + + public FloatingEventModel(boolean settingsChanged) { + this.settingsChanged = settingsChanged; + } + + public FloatingEventModel(boolean settingsChanged, String key) { + this.settingsChanged = settingsChanged; + this.key = key; + } + + public boolean isSettingsChanged() { + return settingsChanged; + } + + public String getKey() { + return key; + } +} diff --git a/app/src/main/java/com/fastaccess/data/dao/FolderEventModel.java b/app/src/main/java/com/fastaccess/data/dao/FolderEventModel.java new file mode 100644 index 0000000..85c9cb5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/data/dao/FolderEventModel.java @@ -0,0 +1,9 @@ +package com.fastaccess.data.dao; + +/** + * Created by Kosh on 22 Oct 2016, 11:28 AM + */ + +public class FolderEventModel { + public FolderEventModel() {} +} diff --git a/app/src/main/java/com/fastaccess/data/dao/FolderModel.java b/app/src/main/java/com/fastaccess/data/dao/FolderModel.java new file mode 100644 index 0000000..bc99cf4 --- /dev/null +++ b/app/src/main/java/com/fastaccess/data/dao/FolderModel.java @@ -0,0 +1,119 @@ +package com.fastaccess.data.dao; + +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.NonNull; + +import com.orm.SugarRecord; +import com.orm.dsl.Ignore; +import com.orm.dsl.Unique; +import com.orm.query.Select; +import com.orm.util.NamingHelper; + +import java.util.List; + +/** + * Created by Kosh on 10 Oct 2016, 10:21 PM + */ + +public class FolderModel extends SugarRecord implements Parcelable { + + @Unique private String folderName; + private long createdDate; + private int orderIndex; + private int color; + private int appsCount; + @Ignore private List folderApps; + + public String getFolderName() { + return folderName; + } + + public void setFolderName(String folderName) { + this.folderName = folderName; + } + + public long getCreatedDate() { + return createdDate; + } + + public void setCreatedDate(long createdDate) { + this.createdDate = createdDate; + } + + public int getOrderIndex() { + return orderIndex; + } + + public void setOrderIndex(int orderIndex) { + this.orderIndex = orderIndex; + } + + public int getColor() { + return color; + } + + public void setColor(int color) { + this.color = color; + } + + public int getAppsCount() { + appsCount = (int) AppsModel.countApps(getId()); + return appsCount; + } + + public static List getFolders() { + return Select.from(FolderModel.class) + .orderBy(NamingHelper.toSQLNameDefault("createdDate") + " DESC") + .list(); + } + + public static void deleteFolder(@NonNull FolderModel model) { + model.delete(); + AppsModel.deleteAll(AppsModel.class, NamingHelper.toSQLNameDefault("folderId") + " = ?", String.valueOf(model.getId())); + } + + public FolderModel() {} + + @Override public int describeContents() { return 0; } + + @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.folderName); + dest.writeLong(this.createdDate); + dest.writeInt(this.orderIndex); + dest.writeInt(this.color); + dest.writeInt(this.appsCount); + dest.writeValue(this.getId()); + } + + protected FolderModel(Parcel in) { + this.folderName = in.readString(); + this.createdDate = in.readLong(); + this.orderIndex = in.readInt(); + this.color = in.readInt(); + this.appsCount = in.readInt(); + this.setId((Long) in.readValue(Long.class.getClassLoader())); + } + + public static final Creator CREATOR = new Creator() { + @Override public FolderModel createFromParcel(Parcel source) {return new FolderModel(source);} + + @Override public FolderModel[] newArray(int size) {return new FolderModel[size];} + }; + + public List getFolderApps() { + return AppsModel.getApps(getId()); + } + + public void setFolderApps(List folderApps) { + this.folderApps = folderApps; + if (folderApps != null && !folderApps.isEmpty()) { + for (AppsModel app : folderApps) { + if (app.getFolderId() == 0) { + app.setFolderId(getId()); + } + if (app.getFolderId() != 0) app.save(); + } + } + } +} diff --git a/app/src/main/java/com/fastaccess/data/dao/SelectedAppsEventModel.java b/app/src/main/java/com/fastaccess/data/dao/SelectedAppsEventModel.java new file mode 100644 index 0000000..70ea086 --- /dev/null +++ b/app/src/main/java/com/fastaccess/data/dao/SelectedAppsEventModel.java @@ -0,0 +1,10 @@ +package com.fastaccess.data.dao; + +/** + * Created by Kosh on 12 Oct 2016, 7:24 PM + */ + +public class SelectedAppsEventModel { + + public SelectedAppsEventModel() {} +} diff --git a/app/src/main/java/com/fastaccess/data/dao/ThemePackEventModel.java b/app/src/main/java/com/fastaccess/data/dao/ThemePackEventModel.java new file mode 100644 index 0000000..9bb3cbb --- /dev/null +++ b/app/src/main/java/com/fastaccess/data/dao/ThemePackEventModel.java @@ -0,0 +1,10 @@ +package com.fastaccess.data.dao; + +/** + * Created by Kosh on 17 Oct 2016, 7:48 PM + */ + +public class ThemePackEventModel { + + public ThemePackEventModel() {} +} diff --git a/app/src/main/java/com/fastaccess/helper/ActivityHelper.java b/app/src/main/java/com/fastaccess/helper/ActivityHelper.java new file mode 100644 index 0000000..f2462fd --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/ActivityHelper.java @@ -0,0 +1,92 @@ +package com.fastaccess.helper; + +import android.app.Activity; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.net.Uri; +import android.provider.MediaStore; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.customtabs.CustomTabsIntent; +import android.support.v4.app.Fragment; + +import com.fastaccess.R; +import com.mikepenz.aboutlibraries.Libs; +import com.mikepenz.aboutlibraries.LibsBuilder; + +import java.io.File; + +/** + * Created by Kosh on 12/12/15 10:51 PM + */ +public class ActivityHelper { + + public static final int REQUEST_CODE = 100; + public static final int CAMERA_REQUEST_CODE = 101; + public static final int SELECT_PHOTO_REQUEST = 102; + + @Nullable public static Activity getActivity(@Nullable Context cont) { + if (cont == null) return null; + else if (cont instanceof Activity) return (Activity) cont; + else if (cont instanceof ContextWrapper) return getActivity(((ContextWrapper) cont).getBaseContext()); + return null; + } + + public static int getScreenOrientation(Context activity) { + return activity.getResources().getConfiguration().orientation; + } + + public static void startActivity(@NonNull Context context, Class className) { + Intent intent = new Intent(context, className); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + context.startActivity(intent); + } + + public static void startActivityWithFinish(@NonNull Activity context, Class className) { + Intent intent = new Intent(context, className); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + context.startActivity(intent); + } + + public static void startGalleryIntent(@NonNull Activity activity) { + Intent intent = new Intent(Intent.ACTION_PICK); + intent.setType("image/*"); + activity.startActivityForResult(intent, SELECT_PHOTO_REQUEST); + } + + public static void startGalleryIntent(@NonNull Fragment fragment) { + Intent intent = new Intent(Intent.ACTION_PICK); + intent.setType("image/*"); + fragment.startActivityForResult(intent, SELECT_PHOTO_REQUEST); + } + public static void startCameraIntent(@NonNull Activity activity, @NonNull File file) { + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) { + takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); + activity.startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE); + } + } + + public static void startCustomTab(@NonNull Activity context) { + CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); + builder.setToolbarColor(ViewHelper.getPrimaryColor(context)); + CustomTabsIntent tabsIntent = builder.build(); + tabsIntent.launchUrl(context, Uri.parse("https://github.com/k0shk0sh/NewKam"));//TODO change url + } + + public static void startLibs(@NonNull Activity activity) { + new LibsBuilder() + .withFields(R.string.class.getFields()) + .withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR) + .withActivityTheme(R.style.AppTheme) + .withAboutIconShown(true) + .withAboutVersionShown(true) + .withAutoDetect(true) + .withLicenseShown(true) + .withVersionShown(true) + .withActivityTitle(activity.getString(R.string.libs)) + .start(activity); + } + +} diff --git a/app/src/main/java/com/fastaccess/helper/AnimHelper.java b/app/src/main/java/com/fastaccess/helper/AnimHelper.java new file mode 100644 index 0000000..50a7124 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/AnimHelper.java @@ -0,0 +1,157 @@ +package com.fastaccess.helper; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.graphics.Rect; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.UiThread; +import android.support.v4.view.ViewCompat; +import android.view.View; +import android.view.ViewPropertyAnimator; +import android.view.ViewTreeObserver; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + +import java.util.Arrays; +import java.util.List; + +import io.codetail.animation.ViewAnimationUtils; + +/** + * Created by Kosh on 27 May 2016, 9:04 PM + */ + +public class AnimHelper { + + public interface AnimationCallback { + void onAnimationEnd(); + + void onAnimationStart(); + } + + private static final Interpolator interpolator = new LinearInterpolator(); + + @UiThread public static void animateVisibility(@Nullable final View view, final boolean show) { + animateVisibility(view, show, null); + } + + @UiThread public static void animateVisibility(@Nullable final View view, final boolean show, @Nullable final AnimationCallback callback) { + if (view == null) { + return; + } + if (!ViewCompat.isAttachedToWindow(view)) { + view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override public boolean onPreDraw() { + view.getViewTreeObserver().removeOnPreDrawListener(this); + animateSafeVisibility(show, view, callback); + return true; + } + }); + } else { + animateSafeVisibility(show, view, callback); + } + } + + @UiThread private static void animateSafeVisibility(final boolean show, @NonNull final View view, @Nullable final AnimationCallback callback) { + view.clearAnimation(); + if (view.getAnimation() != null) view.getAnimation().cancel(); + ViewPropertyAnimator animator = view.animate().alpha(show ? 1F : 0F).setInterpolator(new AccelerateInterpolator()) + .setListener(new AnimatorListenerAdapter() { + @Override public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + if (callback != null) callback.onAnimationStart(); + if (show) { + view.setScaleX(1); + view.setScaleY(1); + view.setVisibility(View.VISIBLE); + } + } + + @Override public void onAnimationEnd(@NonNull Animator animation) { + super.onAnimationEnd(animation); + if (!show) { + view.setVisibility(View.GONE); + view.setScaleX(0); + view.setScaleY(0); + } + if (callback != null) callback.onAnimationEnd(); + animation.removeListener(this); + view.clearAnimation(); + } + }); + animator.scaleX(show ? 1 : 0).scaleY(show ? 1 : 0); + } + + @UiThread @NonNull private static List getBeats(@NonNull View view) { + ObjectAnimator[] animator = new ObjectAnimator[]{ + ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1), + ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1) + }; + return Arrays.asList(animator); + } + + @UiThread public static void startBeatsAnimation(@NonNull View view) { + view.clearAnimation(); + if (view.getAnimation() != null) { + view.getAnimation().cancel(); + } + List animators = getBeats(view); + for (ObjectAnimator anim : animators) { + anim.setDuration(300).start(); + anim.setInterpolator(interpolator); + } + } + + @UiThread public static void circularReveal(final View mRevealView, final View from, final boolean show) { + if (ViewCompat.isAttachedToWindow(mRevealView)) { + if (show) { + if (mRevealView.isShown()) return; + } else { + if (!mRevealView.isShown()) { + return; + } + } + reveal(mRevealView, show, from); + } else { + mRevealView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override public boolean onPreDraw() { + mRevealView.getViewTreeObserver().removeOnPreDrawListener(this); + if (show) { + if (mRevealView.isShown()) return true; + } else { + if (!mRevealView.isShown()) { + return true; + } + } + reveal(mRevealView, show, from); + return true; + } + }); + } + } + + @UiThread private static void reveal(final View mRevealView, final boolean show, View from) { + Rect rect = ViewHelper.getLayoutPosition(from); + int x = (int) rect.exactCenterX(); + int y = (int) rect.exactCenterY(); + Animator animator = ViewAnimationUtils.createCircularReveal(mRevealView, x, y, 0, Math.max(rect.width(), rect.height())); + animator.setDuration(400L); + animator.setInterpolator(new AccelerateDecelerateInterpolator()); + mRevealView.setVisibility(View.VISIBLE); + if (!show) { + animator.addListener(new AnimatorListenerAdapter() { + @Override public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mRevealView.setVisibility(View.GONE); + animation.removeListener(this); + } + }); + animator.start(); + } + } + +} diff --git a/app/src/main/java/com/fastaccess/helper/AppHelper.java b/app/src/main/java/com/fastaccess/helper/AppHelper.java new file mode 100644 index 0000000..5713061 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/AppHelper.java @@ -0,0 +1,276 @@ +package com.fastaccess.helper; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.location.LocationManager; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkInfo; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; +import android.support.annotation.ColorRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; + +import com.fastaccess.BuildConfig; +import com.fastaccess.data.dao.AppsModel; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Created by kosh20111 on 18 Oct 2016, 9:29 PM + */ + +public class AppHelper { + + private static final int GPS_REQUEST_CODE = 2004; + + public static boolean isOnline(Context context) { + boolean haveConnectedWifi = false; + boolean haveConnectedMobile = false; + try { + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (isM()) { + Network networks = cm.getActiveNetwork(); + NetworkInfo netInfo = cm.getNetworkInfo(networks); + haveConnectedWifi = netInfo.getType() == ConnectivityManager.TYPE_WIFI && netInfo.getState().equals(NetworkInfo.State.CONNECTED); + haveConnectedMobile = netInfo.getType() == ConnectivityManager.TYPE_MOBILE && netInfo.getState().equals(NetworkInfo.State.CONNECTED); + } else { + NetworkInfo[] netInfo = cm.getAllNetworkInfo(); + for (NetworkInfo ni : netInfo) { + if (ni.getTypeName().equalsIgnoreCase("WIFI")) { + if (ni.isConnected()) + haveConnectedWifi = true; + } + if (ni.getTypeName().equalsIgnoreCase("MOBILE")) { + if (ni.isConnected()) + haveConnectedMobile = true; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return haveConnectedWifi || haveConnectedMobile; + } + + public static boolean isApplicationInstalled(Context context, String packageName) { + PackageInfo info = null; + try { + info = context.getPackageManager().getPackageInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return info != null; + } + + public static boolean isM() {return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;} + + public static boolean isLollipopOrHigher() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; + } + + public static boolean isBelowLollipop() { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP; + } + + public static boolean isGPSEnabled(Context context) { + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + } + + public static void turnGpsOn(Activity context) { + context.startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), GPS_REQUEST_CODE); + } + + public static void setStatusBarColor(Activity activity, @ColorRes int colorRes) { + if (isLollipopOrHigher()) { + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + activity.getWindow().setStatusBarColor(ActivityCompat.getColor(activity, colorRes)); + } + } + + public static String getTransitionName(@NonNull String defaultValue, @NonNull View view) { + if (isLollipopOrHigher()) { + return !InputHelper.isEmpty(view.getTransitionName()) ? view.getTransitionName() : defaultValue; + } + return defaultValue; + } + + public static boolean isLandscape(int orientation) { + return (orientation == Configuration.ORIENTATION_LANDSCAPE); + } + + public static boolean hasNavigationBar() { + return KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK) && KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME); + + } + + public static int getNavigationBarHeight(Context context) { + int orientation = context.getResources().getConfiguration().orientation; + Resources resources = context.getResources(); + int id = resources.getIdentifier( + orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); + if (id > 0) { + return resources.getDimensionPixelSize(id); + } + return 0; + } + + public static void shareApp(@NonNull Context context) { + final String appPackageName = context.getPackageName(); + try { + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName))); + } catch (Exception e) { + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName))); + } + } + + @NonNull public static List getInstalledPackages(@NonNull Context context) { + final PackageManager pm = context.getPackageManager(); + Process process; + List result = new ArrayList<>(); + BufferedReader bufferedReader = null; + try { + process = Runtime.getRuntime().exec("pm list packages"); + bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = bufferedReader.readLine()) != null) { + final String packageName = line.substring(line.indexOf(':') + 1); + PackageInfo packageInfo = pm.getPackageInfo(packageName, 0); + Intent mainIntent = pm.getLaunchIntentForPackage(packageInfo.applicationInfo.packageName); + if (mainIntent != null) { + ResolveInfo resolveInfo = pm.resolveActivity(mainIntent, 0); + if (resolveInfo != null) { + if (!packageName.equalsIgnoreCase(BuildConfig.APPLICATION_ID)) { + AppsModel model = new AppsModel(); + model.setPackageName(resolveInfo.activityInfo.applicationInfo.packageName); + model.setActivityInfoName(resolveInfo.activityInfo.name); + model.setAppName(resolveInfo.loadLabel(pm).toString()); + result.add(model); + } + } + } + } + process.waitFor(); + Collections.sort(result, AppsModel.sortApps()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (bufferedReader != null) + try { + bufferedReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return result; + } + + public static void showKeyboard(@NonNull View v) { + showKeyboard(v, v.getContext()); + } + + public static void hideKeyboard(@NonNull View view) { + hideKeyboard(view, view.getContext()); + } + + public static void showKeyboard(@NonNull View v, @NonNull Context activity) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(v, 0); + } + + public static void hideKeyboard(@NonNull View view, @NonNull Context activity) { + InputMethodManager inputManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + + @Nullable public static Fragment getFragmentByTag(@NonNull FragmentManager fragmentManager, @NonNull String tag) { + return fragmentManager.findFragmentByTag(tag); + } + + @Nullable public static Fragment getVisibleFragment(@NonNull FragmentManager manager) { + List fragments = manager.getFragments(); + if (fragments != null && !fragments.isEmpty()) { + for (Fragment fragment : fragments) { + if (fragment != null && fragment.isVisible()) { + Logger.e(fragment.getClass().getSimpleName(), fragment.isVisible()); + return fragment; + } + } + } + return null; + } + + @Nullable public static String saveBitmap(Bitmap image) { + try { + File file = FileHelper.generateFile("fa_image_icon"); + if (file.exists()) { + file.delete(); + } + OutputStream fOut = new FileOutputStream(file); + image.compress(Bitmap.CompressFormat.PNG, 70, fOut); + fOut.flush(); + fOut.close(); + return file.getAbsolutePath(); + } catch (Exception e) { + return null; + } + } + + @Nullable public static Bitmap getBitmapFromUri(@NonNull Uri uri, @NonNull Context context) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + options.inSampleSize = 5; + try { + BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri), null, options); + options.inSampleSize = calculateInSampleSize(options, 300, 300); + options.inJustDecodeBounds = false; + return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri), null, options); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + if (height > reqHeight || width > reqWidth) { + final int halfHeight = height / 2; + final int halfWidth = width / 2; + while ((halfHeight / inSampleSize) >= reqHeight + && (halfWidth / inSampleSize) >= reqWidth) { + inSampleSize *= 2; + } + } + return inSampleSize; + } +} diff --git a/app/src/main/java/com/fastaccess/helper/Bundler.java b/app/src/main/java/com/fastaccess/helper/Bundler.java new file mode 100644 index 0000000..9cbeddf --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/Bundler.java @@ -0,0 +1,195 @@ +package com.fastaccess.helper; + +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcelable; +import android.support.annotation.NonNull; +import android.util.SparseArray; + +import java.io.Serializable; +import java.util.ArrayList; + +/** + * Created by Kosh on 23 May 2016, 3:37 PM + */ + +public class Bundler { + + private Bundle bundle; + + private Bundler() { + bundle = new Bundle(); + } + + public static Bundler start() { + return new Bundler(); + } + + public Bundler put(@NonNull String key, boolean value) { + bundle.putBoolean(key, value); + return this; + } + + public Bundler put(@NonNull String key, boolean[] value) { + bundle.putBooleanArray(key, value); + return this; + } + + public Bundler put(@NonNull String key, IBinder value) { + // Uncommment this line if your minimum sdk version is API level 18 + //start.putBinder(key, value); + return this; + } + + public Bundler put(@NonNull String key, int value) { + bundle.putInt(key, value); + return this; + } + + public Bundler put(@NonNull String key, int[] value) { + bundle.putIntArray(key, value); + return this; + } + + public Bundler putIntegerArrayList(@NonNull String key, ArrayList value) { + bundle.putIntegerArrayList(key, value); + return this; + } + + public Bundler put(@NonNull String key, Bundle value) { + bundle.putBundle(key, value); + return this; + } + + public Bundler put(@NonNull String key, byte value) { + bundle.putByte(key, value); + return this; + } + + public Bundler put(@NonNull String key, byte[] value) { + bundle.putByteArray(key, value); + return this; + } + + public Bundler put(@NonNull String key, String value) { + bundle.putString(key, value); + return this; + } + + public Bundler put(@NonNull String key, String[] value) { + bundle.putStringArray(key, value); + return this; + } + + public Bundler putStringArrayList(@NonNull String key, ArrayList value) { + bundle.putStringArrayList(key, value); + return this; + } + + public Bundler put(@NonNull String key, long value) { + bundle.putLong(key, value); + return this; + } + + public Bundler put(@NonNull String key, long[] value) { + bundle.putLongArray(key, value); + return this; + } + + public Bundler put(@NonNull String key, float value) { + bundle.putFloat(key, value); + return this; + } + + public Bundler put(@NonNull String key, float[] value) { + bundle.putFloatArray(key, value); + return this; + } + + public Bundler put(@NonNull String key, char value) { + bundle.putChar(key, value); + return this; + } + + public Bundler put(@NonNull String key, char[] value) { + bundle.putCharArray(key, value); + return this; + } + + public Bundler put(@NonNull String key, CharSequence value) { + bundle.putCharSequence(key, value); + return this; + } + + public Bundler put(@NonNull String key, CharSequence[] value) { + bundle.putCharSequenceArray(key, value); + return this; + } + + public Bundler putCharSequenceArrayList(@NonNull String key, ArrayList value) { + bundle.putCharSequenceArrayList(key, value); + return this; + } + + public Bundler put(@NonNull String key, double value) { + bundle.putDouble(key, value); + return this; + } + + public Bundler put(@NonNull String key, double[] value) { + bundle.putDoubleArray(key, value); + return this; + } + + public Bundler put(@NonNull String key, Parcelable value) { + bundle.putParcelable(key, value); + return this; + } + + public Bundler put(@NonNull String key, Parcelable[] value) { + bundle.putParcelableArray(key, value); + return this; + } + + public Bundler putParcelableArrayList(@NonNull String key, ArrayList value) { + bundle.putParcelableArrayList(key, value); + return this; + } + + public Bundler putSparseParcelableArray(@NonNull String key, SparseArray value) { + bundle.putSparseParcelableArray(key, value); + return this; + } + + public Bundler put(@NonNull String key, short value) { + bundle.putShort(key, value); + return this; + } + + public Bundler put(@NonNull String key, short[] value) { + bundle.putShortArray(key, value); + return this; + } + + public Bundler put(@NonNull String key, Serializable value) { + bundle.putSerializable(key, value); + return this; + } + + public Bundler putAll(Bundle map) { + bundle.putAll(map); + return this; + } + + /** + * Get the underlying start. + */ + public Bundle get() { + return bundle; + } + + public Bundle end() { + return get(); + } + +} diff --git a/app/src/main/java/com/fastaccess/helper/ColorHelper.java b/app/src/main/java/com/fastaccess/helper/ColorHelper.java new file mode 100644 index 0000000..bb331a9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/ColorHelper.java @@ -0,0 +1,52 @@ +package com.fastaccess.helper; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +public class ColorHelper { + + public static ColorHelper MATERIAL; + + static { + MATERIAL = create(Arrays.asList( + 0xffe57373, + 0xfff06292, + 0xffba68c8, + 0xff9575cd, + 0xff7986cb, + 0xff64b5f6, + 0xff4fc3f7, + 0xff4dd0e1, + 0xff4db6ac, + 0xff81c784, + 0xffaed581, + 0xffff8a65, + 0xffd4e157, + 0xffffd54f, + 0xffffb74d, + 0xffa1887f, + 0xff90a4ae + )); + } + + private final List mColors; + private final Random mRandom; + + public static ColorHelper create(List colorList) { + return new ColorHelper(colorList); + } + + private ColorHelper(List colorList) { + mColors = colorList; + mRandom = new Random(System.currentTimeMillis()); + } + + public int getRandomColor() { + return mColors.get(mRandom.nextInt(mColors.size())); + } + + public int getColor(Object key) { + return mColors.get(Math.abs(key.hashCode()) % mColors.size()); + } +} diff --git a/app/src/main/java/com/fastaccess/helper/DatabaseHelper.java b/app/src/main/java/com/fastaccess/helper/DatabaseHelper.java new file mode 100644 index 0000000..9d7f716 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/DatabaseHelper.java @@ -0,0 +1,11 @@ +package com.fastaccess.helper; + +/** + * Created by Kosh on 09 Aug 2016, 10:25 PM + */ + +public class DatabaseHelper { + + private DatabaseHelper() {} + +} diff --git a/app/src/main/java/com/fastaccess/helper/DateHelper.java b/app/src/main/java/com/fastaccess/helper/DateHelper.java new file mode 100644 index 0000000..813b8e0 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/DateHelper.java @@ -0,0 +1,293 @@ +package com.fastaccess.helper; + +import android.text.format.DateUtils; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + +/** + * Created by kosh20111 on 10/7/2015. CopyRights @ Innov8tif + *

+ * Helper Class to deal with time and dates + */ +public class DateHelper { + + public enum DateFormats { + D_YYMMDD("yy-MM-dd"), D_DDMMyy("dd-MM-yy"), + D_YYMMDD_N("yy-MMM-dd"), D_DDMMyy_N("dd-MMM-yy"), + D_YYMMDDHHMMA_N("yy-MMM-dd, hh:mma"), D_DDMMyyHHMMA_N("dd-MMM-yy, hh:mma"), + S_YYMMDD("yy/MM/dd"), S_DDMMyy("dd/MM/yy"), + S_YYMMDDHHMMA("yy/MM/dd, hh:mma"), S_DDMMyyHHMMA("dd/MM/yy, hh:mma"), + S_YYMMDDHHMMA_N("yy/MMM/dd, hh:mma"), S_DDMMyyHHMMA_N("dd/MMM/yy, hh:mma"), + D_YYYYMMDD("yyyy-MM-dd"), D_DDMMYYYY("dd-MM-yyyy"), + D_YYYYMMDDHHMMA("yyyy-MM-dd, hh:mma"), D_DDMMYYYYHHMMA("dd-MM-yyyy, hh:mma"), + D_YYYYMMDD_N("yyyy-MMM-dd"), D_DDMMYYYY_N("dd-MMM-yyyy"), + D_YYYYMMDDHHMMA_N("yyyy-MMM-dd, hh:mma"), D_DDMMYYYYHHMMA_N("dd-MMM-yyyy, hh:mma"), + S_YYYYMMDD("yyyy/MM/dd"), S_DDMMYYYY("dd/MM/yyyy"), + S_YYYYMMDDHHMMA("yyyy/MM/dd, hh:mma"), S_DDMMYYYYHHMMA("dd/MM/yyyy, hh:mma"), + S_YYYYMMDDHHMMA_N("yyyy/MMM/dd, hh:mma"), S_DDMMYYYYHHMMA_N("dd/MMM/yyyy, hh:mma"), + D_YYMMDDHHMMSSA_N("yy-MMM-dd, hh:mm:ssa"), D_DDMMyyHHMMSSA_N("dd-MMM-yy, hh:mm:ssa"), + S_YYMMDDHHMMSSA("yy/MM/dd, hh:mm:ssa"), S_DDMMyyHHMMSSA("dd/MM/yy, hh:mm:ssa"), + S_YYMMDDHHMMSSA_N("yy/MMM/dd, hh:mm:ssa"), S_DDMMyyHHMMSSA_N("dd/MMM/yy, hh:mm:ssa"), + D_YYYYMMDDHHMMSSA("yyyy-MM-dd, hh:mm:ssa"), D_DDMMYYYYHHMMSSA("dd-MM-yyyy, hh:mm:ssa"), + D_YYYYMMDDHHMMSSA_N("yyyy-MMM-dd, hh:mm:ssa"), D_DDMMYYYYHHMMSSA_N("dd-MMM-yyyy, hh:mm:ssa"), + S_YYYYMMDDHHMMSSA("yyyy/MM/dd, hh:mm:ssa"), S_DDMMYYYYHHMMSSA("dd/MM/yyyy, hh:mm:ssa"), + S_YYYYMMDDHHMMSSA_N("yyyy/MMM/dd, hh:mm:ssa"), S_DDMMYYYYHHMMSSA_N("dd/MMM/yyyy, hh:mm:ssa"), + YYMMDDHHMMSS("yyMMddhhmmss"), YYMMDDHHMMSS_24("yyMMddkkmmss"), + HHMMA("hh:mma"), HHMM("hh:mm"), HHMMSSA("hh:mm:ssa"), HHMMSS("hh:mm:ss"), + DD("dd"), MM("MM"), MM_N("MMM"), DDMM("dd MM"), DDMM_N("dd MMM"), DDMMYYYY("ddMMyyyy"); + private String dateFormat; + + DateFormats(String dateFormat) {this.dateFormat = dateFormat;} + + public String getDateFormat() { + return dateFormat; + } + } + + /** + * @return hh:mm a || dd MMM hh:mm a + */ + public static String prettifyDate(long timestamp) { + SimpleDateFormat dateFormat; + if (DateUtils.isToday(timestamp)) { + dateFormat = new SimpleDateFormat("hh:mm a", Locale.getDefault()); + } else { + dateFormat = new SimpleDateFormat("dd MMM hh:mm a", Locale.getDefault()); + } + return dateFormat.format(timestamp); + } + + /** + * @return hh:mm a || dd MMM hh:mm a + */ + public static String prettifyDate(String timestamp, DateFormats dateFormats) { + SimpleDateFormat sample = new SimpleDateFormat(dateFormats.getDateFormat(), Locale.getDefault()); + + try { + long time = sample.parse(timestamp).getTime(); + if (DateUtils.isToday(time)) { + sample = new SimpleDateFormat("hh:mm a", Locale.getDefault()); + } else { + sample = new SimpleDateFormat("dd MMM hh:mm a", Locale.getDefault()); + } + return sample.format(time); + } catch (Exception e) { + e.printStackTrace(); + } + return timestamp; + } + + /** + * @return dd/MM/yyyy + */ + public static long getDateOnly(String date) { + SimpleDateFormat sample = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()); + try { + return sample.parse(date).getTime(); + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + /** + * @return dd/MM/yyyy + */ + public static String getDateOnly(long time) { + return new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(time); + } + + /** + * @return dd/MM/yyyy, hh:mm a + */ + public static String getDateAndTime(long time) { + SimpleDateFormat sample = new SimpleDateFormat("dd/MM/yyyy, hh:mm a", Locale.getDefault()); + return sample.format(new Date(time)); + } + + /** + * @return dd/MM/yyyy, hh:mm a + */ + public static String getDateAndTime(String time) { + SimpleDateFormat sample = new SimpleDateFormat("dd/MM/yyyy, hh:mm a", Locale.getDefault()); + return sample.format(time); + } + + /** + * @return hh:mm a + */ + public static String getTimeOnly(long time) { + SimpleDateFormat sample = new SimpleDateFormat("hh:mm a", Locale.getDefault()); + return sample.format(time); + } + + /** + * @return today's date in format (dd/MM/yyyy HH:mm:ss) + */ + public static String getTodayWithTime() { + SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault()); + return dateFormat.format(new Date()); + } + + /** + * @return today's date in format (dd/MM/yyyy) + */ + public static String getToday() { + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()); + return dateFormat.format(new Date()); + } + + public static String getYesterday() { + try { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).parse(getToday())); + calendar.add(Calendar.DATE, -1); + Date tomorrow = calendar.getTime(); + return new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(tomorrow); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * @return tomorrows's date in format (dd/MM/yyyy) + */ + public static String getTomorrow() { + try { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).parse(getToday())); + calendar.add(Calendar.DATE, 1); + Date tomorrow = calendar.getTime(); + return new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(tomorrow); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * new and old date must equal to {@link DateFormats} + * + * @return number of hours + */ + public static long getDaysBetweenTwoDate(String old, String newDate, DateFormats dateFormats) { + SimpleDateFormat myFormat = new SimpleDateFormat(dateFormats.getDateFormat(), Locale.getDefault()); + try { + Date date1 = myFormat.parse(old); + Date date2 = myFormat.parse(newDate); + long diff = date1.getTime() - date2.getTime(); + long seconds = diff / 1000; + long minutes = seconds / 60; + long hours = minutes / 60; + return hours / 24; + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + /** + * new and old date must equal to {@link DateFormats} + * + * @return number of hours + */ + public static long getHoursBetweenTwoDate(String old, String newDate, DateFormats dateFormats) { + SimpleDateFormat myFormat = new SimpleDateFormat(dateFormats.getDateFormat(), Locale.getDefault()); + try { + Date date1 = myFormat.parse(old); + Date date2 = myFormat.parse(newDate); + long diff = date1.getTime() - date2.getTime(); + long seconds = diff / 1000; + long minutes = seconds / 60; + long hours = minutes / 60; + long days = hours / 24; + return hours; + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + public static long getMinutesBetweenTwoDates(String old, String newDate, DateFormats dateFormats) { + SimpleDateFormat myFormat = new SimpleDateFormat(dateFormats.getDateFormat(), Locale.getDefault()); + try { + Date date1 = myFormat.parse(old); + Date date2 = myFormat.parse(newDate); + long diff = date1.getTime() - date2.getTime(); + long seconds = diff / 1000; + long minutes = seconds / 60; + long hours = minutes / 60; + long days = hours / 24; + return minutes; + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + public static long getMinutesBetweenTwoDates(long old, long newDate) { + long diff = old - newDate; + long seconds = diff / 1000; + long minutes = seconds / 60; + long hours = minutes / 60; + long days = hours / 24; + return minutes; + } + + public static boolean isInFuture(long timestamp) { + Date date = new Date(timestamp); + return date.getTime() - new Date().getTime() >= 0; + } + + /** + */ + public static long parseAnyDate(String date) { + long time = 0; + for (DateFormats formats : DateFormats.values()) { + try { + SimpleDateFormat format = new SimpleDateFormat(formats.getDateFormat(), Locale.getDefault()); + time = format.parse(date).getTime(); + } catch (Exception e) { + e.printStackTrace(); + } + } + return time; + } + + public static long parseDate(String date, DateFormats dateFormats) { + SimpleDateFormat format = new SimpleDateFormat(dateFormats.getDateFormat(), Locale.getDefault()); + try { + return format.parse(date).getTime(); + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + public static String getDate(String date, DateFormats orginalFormat, DateFormats newFormat) { + SimpleDateFormat sample = new SimpleDateFormat(orginalFormat.getDateFormat(), Locale.getDefault()); + try { + long time = sample.parse(date).getTime(); + sample = new SimpleDateFormat(newFormat.getDateFormat(), Locale.getDefault()); + return sample.format(time); + } catch (Exception e) { + e.printStackTrace(); + } + return date; + } + + public static String getDesiredFormat(DateFormats formats) { + SimpleDateFormat format = new SimpleDateFormat(formats.getDateFormat(), Locale.getDefault()); + return format.format(new Date()); + } + + public static String getDesiredFormat(DateFormats formats, long date) { + if (date == 0) return ""; + SimpleDateFormat format = new SimpleDateFormat(formats.getDateFormat(), Locale.getDefault()); + return format.format(date); + } +} diff --git a/app/src/main/java/com/fastaccess/helper/FileHelper.java b/app/src/main/java/com/fastaccess/helper/FileHelper.java new file mode 100644 index 0000000..dba4363 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/FileHelper.java @@ -0,0 +1,162 @@ +package com.fastaccess.helper; + +import android.content.Context; +import android.os.Environment; +import android.text.TextUtils; +import android.webkit.MimeTypeMap; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kosh20111 on 10/7/2015. CopyRights @ Innov8tif + */ +public class FileHelper { + + private static String folderName; + private String TAG = this.getClass().getSimpleName(); + + public static void initFolderName(String fName) { + folderName = Environment.getExternalStorageDirectory() + "/" + fName; + } + + public static File folderName() { + File file = new File(folderName); + if (!file.exists()) + file.mkdir(); + return file; + } + + public static String getBaseFolderName() { + return folderName; + } + + public static File getFile(String path) { + return new File(path); + } + + private static String getPng(String path) { + return path + ".png"; + } + + public static boolean deleteFile(String path) { + if (!TextUtils.isEmpty(path)) { + File file = new File(path); + if (file.exists()) { + return file.delete(); + } else { + file = new File(folderName(), path); + if (file.exists()) { + return file.delete(); + } + } + } + return false; + } + + public static void deleteFile(List paths) { + for (String path : paths) { + if (path != null) { + File file = new File(folderName(), path); + if (file.exists()) { + file.delete(); + } + } + } + } + + public static String generateFileName(String packageName) { + return getPng(packageName); + } + + public static File generateFile(String path) { + File file = new File(folderName, ".nomedia"); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + file.mkdir(); + } + } + return new File(folderName(), generateFileName(path)); + } + + private static void generateDefaultFile() { + File file = new File(folderName); + if (!file.exists()) { + file.mkdir(); + } + } + + public static File generateZipFile(String name) { + File file = new File(folderName, ".nomedia"); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + file.mkdir(); + } + } + return new File(folderName(), name + ".zip"); + } + + public static File generateFolder(String name) { + File file = new File(folderName); + if (!file.exists()) { + file.mkdir(); + } + File folderName = new File(file, name); + if (!folderName.exists()) { + folderName.mkdirs(); + } + return folderName; + } + + public static String getCacheFile(Context context, String packageName) { + return context.getCacheDir().getPath() + "/" + generateFileName(packageName); + } + + public static boolean exists(String path) { + return getFile(path).exists(); + } + + public static List getFiles(File dir) { + List files = new ArrayList<>(); + File listFile[] = dir.listFiles(); + if (listFile != null && listFile.length > 0) { + for (File aListFile : listFile) { + if (aListFile.isDirectory()) { + getFiles(aListFile); + } else { + if (aListFile.getName().endsWith(".png") || aListFile.getName().endsWith(".jpg") + || aListFile.getName().endsWith(".jpeg") || aListFile.getName().endsWith(".gif")) { + files.add(aListFile); + } + } + + } + } + return files; + } + + public static String getInternalDirectoryPath() { + return Environment.getExternalStorageDirectory().getAbsolutePath(); + } + + public static String getSDcardDirectoryPath() { + return System.getenv("SECONDARY_STORAGE"); + } + + public static String getMimeType(String file) { + return MimeTypeMap.getFileExtensionFromUrl(file); + } + + public static String extension(String file) { + return MimeTypeMap.getFileExtensionFromUrl(file); + } + +} diff --git a/app/src/main/java/com/fastaccess/helper/GsonHelper.java b/app/src/main/java/com/fastaccess/helper/GsonHelper.java new file mode 100644 index 0000000..5644fb5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/GsonHelper.java @@ -0,0 +1,31 @@ +package com.fastaccess.helper; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; + +/** + * Created by Kosh on 29 May 2016, 5:09 AM + */ + +public class GsonHelper { + + public static T getObject(String json, Class clazz) { + return gson().fromJson(json, clazz); + } + + public static List getList(String json, Class clazz) { + return Arrays.asList(gson().fromJson(json, clazz)); + } + + public static Gson gson() { + return new GsonBuilder() + .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) + .setPrettyPrinting() + .disableHtmlEscaping() + .create(); + } +} diff --git a/app/src/main/java/com/fastaccess/helper/InputHelper.java b/app/src/main/java/com/fastaccess/helper/InputHelper.java new file mode 100644 index 0000000..3b414fd --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/InputHelper.java @@ -0,0 +1,87 @@ +package com.fastaccess.helper; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.design.widget.TextInputLayout; +import android.text.TextUtils; +import android.text.format.Formatter; +import android.widget.EditText; +import android.widget.TextView; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; + +/** + * Created by kosh20111 on 3/11/2015. CopyRights @ Innov8tif + *

+ * Input Helper to validate stuff related to input fields. + */ +public class InputHelper { + + + private static boolean isWhiteSpaces(String s) { + return s != null && s.matches("\\s+"); + } + + public static boolean isEmpty(String text) { + return text == null || TextUtils.isEmpty(text) || isWhiteSpaces(text); + } + + public static boolean isEmpty(Object text) { + return text == null || TextUtils.isEmpty(text.toString()) || isWhiteSpaces(text.toString()); + } + + public static boolean isEmpty(EditText text) { + return text == null || isEmpty(text.getText().toString()); + } + + public static boolean isEmpty(TextView text) { + return text == null || isEmpty(text.getText().toString()); + } + + public static boolean isEmpty(TextInputLayout txt) { + return txt == null || isEmpty(txt.getEditText()); + } + + public static String toNA(String value) { + return isEmpty(value) ? "N/A" : value; + } + + public static String toString(EditText editText) { + return editText.getText().toString(); + } + + public static String toString(TextView editText) { + return editText.getText().toString(); + } + + public static String toString(TextInputLayout textInputLayout) { + return toString(textInputLayout.getEditText()); + } + + @NonNull public static String toString(@NonNull Object object) { + return !isEmpty(object) ? object.toString() : ""; + } + + public static String formatSize(Context context, long size) { + return Formatter.formatShortFileSize(context, size); + } + + public static String formatPrice(double doubleValue) { + NumberFormat nf = NumberFormat.getCurrencyInstance(); + DecimalFormatSymbols decimalFormatSymbols = ((DecimalFormat) nf).getDecimalFormatSymbols(); + decimalFormatSymbols.setCurrencySymbol(""); + ((DecimalFormat) nf).setDecimalFormatSymbols(decimalFormatSymbols); + return nf.format(doubleValue).trim(); + } + + public static String ordinal(int i) { + return i % 100 == 11 || i % 100 == 12 || i % 100 == 13 ? i + "th" : i + + new String[]{"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"}[i % 10]; + } + + @NonNull public static String getTwoLetters(@NonNull String value) { + return value.length() > 1 ? (String.valueOf(value.charAt(0)) + String.valueOf(value.charAt(1))) : String.valueOf(value.charAt(0)); + } +} diff --git a/app/src/main/java/com/fastaccess/helper/Logger.java b/app/src/main/java/com/fastaccess/helper/Logger.java new file mode 100644 index 0000000..b53a7b1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/Logger.java @@ -0,0 +1,96 @@ +package com.fastaccess.helper; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.Log; + +import java.util.Arrays; +import java.util.List; + +import static com.fastaccess.helper.GsonHelper.gson; + +/** + * Created by Kosh on 04/12/15 11:52 PM. copyrights @ Innov8tif + */ +public class Logger { + + private final static String TAG = "Logger"; + + private static void e(@NonNull String tag, @Nullable Object text) { + Log.e(tag, text != null ? text.toString() : "LOGGER IS NULL");//avoid null + } + + private static void d(@NonNull String tag, @Nullable Object text) { + Log.d(tag, text != null ? text.toString() : "LOGGER IS NULL");//avoid null + } + + private static void i(@NonNull String tag, @Nullable Object text) { + Log.i(tag, text != null ? text.toString() : "LOGGER IS NULL");//avoid null + } + + public static void e(@Nullable Object text) {e(getCurrentClassName() + " || " + getCurrentMethodName(), text);} + + public static void d(@Nullable Object text) { + d(getCurrentClassName() + " || " + getCurrentMethodName(), text);//avoid null + } + + public static void i(@Nullable Object text) { + i(getCurrentClassName() + " || " + getCurrentMethodName(), text);//avoid null + } + + public static void e(Object... objects) { + if (objects != null && objects.length > 0) { + e(getCurrentClassName() + " || " + getCurrentMethodName(), Arrays.toString(objects)); + } else { + e(getCurrentClassName() + " || " + getCurrentMethodName(), getCurrentMethodName()); + } + } + + public static void e(List objects) { + if (objects != null) { + e(getCurrentClassName() + " || " + getCurrentMethodName(), Arrays.toString(objects.toArray())); + } else { + e(TAG, null); + } + } + + public static void longE(@NonNull Object text) { + String veryLongString = text.toString(); + int maxLogSize = 4000; + for (int i = 0; i <= veryLongString.length() / maxLogSize; i++) { + int start = i * maxLogSize; + int end = (i + 1) * maxLogSize; + end = end > veryLongString.length() ? veryLongString.length() : end; + e(getCurrentClassName() + " || " + getCurrentMethodName(), veryLongString.substring(start, end)); + } + + } + + public static void eJson(Object object) { + e(getCurrentClassName() + " || " + getCurrentMethodName(), gson().toJson(object)); + } + + private static String getCurrentMethodName() { + try { + return Thread.currentThread().getStackTrace()[4].getMethodName() + "()"; + } catch (Exception ignored) {} + return TAG; + } + + private static String getCurrentLineNumber() { + try { + return " :" + Thread.currentThread().getStackTrace()[4].getLineNumber(); + } catch (Exception ignored) {} + return TAG; + } + + private static String getCurrentClassName() { + try { + String className = Thread.currentThread().getStackTrace()[4].getClassName(); + String[] temp = className.split("[\\.]"); + className = temp[temp.length - 1]; + return className; + } catch (Exception ignored) {} + return TAG; + } +} diff --git a/app/src/main/java/com/fastaccess/helper/NotificationHelper.java b/app/src/main/java/com/fastaccess/helper/NotificationHelper.java new file mode 100755 index 0000000..7be6b62 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/NotificationHelper.java @@ -0,0 +1,145 @@ +package com.fastaccess.helper; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.support.annotation.DrawableRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.NotificationCompat; + +import com.fastaccess.R; +import com.fastaccess.provider.service.FloatingService; + +/** + * Created by kosh20111 on 9/8/2015. CopyRights @ Innov8tif + */ +public class NotificationHelper { + + public static final int NOTIFICATION_ID = 20111; + + public static void notifyShort(@NonNull Context context, @NonNull String title, @NonNull String msg, @DrawableRes int iconId) { + notifyShort(context, title, msg, iconId, NOTIFICATION_ID, null); + } + + public static void notifyShort(@NonNull Context context, @NonNull String title, @NonNull String msg, @DrawableRes int iconId, + @NonNull PendingIntent pendingIntent) { + notifyShort(context, title, msg, iconId, NOTIFICATION_ID, pendingIntent); + } + + public static void notifyShort(@NonNull Context context, @NonNull String title, @NonNull String msg, @DrawableRes int iconId, int nId) { + notifyShort(context, title, msg, iconId, nId, null); + } + + public static void notifyShort(@NonNull Context context, @NonNull String title, @NonNull String msg, @DrawableRes int iconId, int nId, + @Nullable PendingIntent pendingIntent) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + Notification notification = new NotificationCompat.Builder(context) + .setAutoCancel(true) + .setDefaults(Notification.DEFAULT_ALL) + .setContentTitle(title) + .setContentText(msg) + .setSmallIcon(iconId) + .setContentIntent(pendingIntent) + .build(); + notificationManager.notify(nId, notification); + } + + public static void notifyShort(@NonNull Context context, @NonNull String title, String msg, @DrawableRes int iconId, + @NonNull NotificationCompat.Action action) { + notifyShort(context, title, msg, iconId, action, NOTIFICATION_ID); + } + + public static void notifyShort(@NonNull Context context, @NonNull String title, String msg, @DrawableRes int iconId, + @NonNull NotificationCompat.Action action, int nId) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + Notification notification = new NotificationCompat.Builder(context) + .setAutoCancel(true) + .setDefaults(Notification.DEFAULT_ALL) + .setContentTitle(title) + .setContentText(msg) + .setSmallIcon(iconId) + .addAction(action) + .setContentIntent(action.actionIntent) + .build(); + notificationManager.notify(nId, notification); + } + + public static void notifyBig(@NonNull Context context, @NonNull String title, @NonNull String msg, @DrawableRes int iconId) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + Notification notification = new NotificationCompat.Builder(context) + .setAutoCancel(true) + .setContentTitle(title) + .setDefaults(Notification.DEFAULT_ALL) + .setContentText(msg) + .setSmallIcon(iconId) + .setStyle(new NotificationCompat.BigTextStyle().setBigContentTitle(title).setSummaryText(msg).bigText(msg)) + .build(); + notificationManager.notify(NOTIFICATION_ID, notification); + } + + public static void notifyWithImage(@NonNull Context context, @NonNull String title, @NonNull String msg, @DrawableRes int iconId, + @NonNull Bitmap bitmap) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + Notification notification = new NotificationCompat.Builder(context) + .setAutoCancel(true) + .setDefaults(Notification.DEFAULT_ALL) + .setContentTitle(title) + .setContentText(msg) + .setSmallIcon(iconId) + .setStyle(new NotificationCompat.BigPictureStyle().setBigContentTitle(title).setSummaryText(msg).bigPicture(bitmap)) + .build(); + notificationManager.notify(NOTIFICATION_ID, notification); + } + + public static Notification getNonCancellableNotification(@NonNull Context content, @NonNull String title, @NonNull String msg, + @DrawableRes int iconId, @NonNull PendingIntent pendingIntent) { + return new NotificationCompat.Builder(content) + .setAutoCancel(false) + .setOngoing(true) + .setContentTitle(title) + .setContentText(msg) + .setSmallIcon(iconId) + .setContentIntent(pendingIntent) + .build(); + } + + public static void collapseFAService(Context context, int size) { + context.stopService(new Intent(context, FloatingService.class)); + Intent notificationIntent = new Intent(context, FloatingService.class); + notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + PendingIntent pendingIntent = PendingIntent.getService(context, 0, notificationIntent, 0); + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context); + int icon = R.drawable.ic_fa_notification; + long finalTime = System.currentTimeMillis(); + if (PrefHelper.getBoolean(PrefConstant.STATUS_BAR_HIDDEN)) { + icon = R.drawable.ic_notification; + } + notificationBuilder + .setPriority(Notification.PRIORITY_LOW) + .setWhen(finalTime) + .setSmallIcon(icon) + .setContentTitle(context.getString(R.string.app_name)) + .setContentText(context.getString(R.string.click_to_start_service)) + .setNumber(size) + .setAutoCancel(false) + .setOngoing(true); + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationBuilder.setContentIntent(pendingIntent); + notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); + } + + public static void cancelNotification(@NonNull Context context, int id) { + int finalId = id == 0 ? NOTIFICATION_ID : id; + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(finalId); + } + + public static void cancelAllNotifications(@NonNull Context context) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancelAll(); + } +} diff --git a/app/src/main/java/com/fastaccess/helper/PaletteHelper.java b/app/src/main/java/com/fastaccess/helper/PaletteHelper.java new file mode 100644 index 0000000..f08a0db --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/PaletteHelper.java @@ -0,0 +1,69 @@ +package com.fastaccess.helper; + +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.graphics.Palette; + +/** + * Created by Kosh on 11 May 2016, 8:42 PM + */ +public class PaletteHelper { + + public static final int PRIMARY_COLOR = Color.parseColor("#FF2A456B"); + + public interface OnColorExtraction { + void onColorExtracted(int color, int textColor); + } + + public static void extractColor(@Nullable Bitmap bitmap, @NonNull final OnColorExtraction onColorExtraction) { + if (bitmap == null) { + onColorExtraction.onColorExtracted(PRIMARY_COLOR, Color.WHITE); + return; + } + Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() { + @Override public void onGenerated(Palette palette) { + if (palette == null) { + onColorExtraction.onColorExtracted(PRIMARY_COLOR, Color.WHITE); + return; + } + int color = PRIMARY_COLOR; + int textColor = Color.WHITE; + if (palette.getVibrantSwatch() != null) { + Palette.Swatch muted = palette.getVibrantSwatch(); + textColor = muted.getTitleTextColor(); + color = muted.getRgb(); + } else if (palette.getLightVibrantSwatch() != null) { + Palette.Swatch muted = palette.getLightVibrantSwatch(); + color = muted.getRgb(); + textColor = muted.getTitleTextColor(); + } else if (palette.getDarkVibrantSwatch() != null) { + Palette.Swatch muted = palette.getDarkVibrantSwatch(); + color = muted.getRgb(); + textColor = muted.getTitleTextColor(); + } else if (palette.getLightMutedSwatch() != null) { + Palette.Swatch muted = palette.getLightMutedSwatch(); + color = muted.getRgb(); + textColor = muted.getTitleTextColor(); + } else if (palette.getMutedSwatch() != null) { + Palette.Swatch muted = palette.getMutedSwatch(); + color = muted.getRgb(); + textColor = muted.getTitleTextColor(); + } + onColorExtraction.onColorExtracted(color, textColor); + } + }); + } + + public static void extractColor(@Nullable Drawable drawable, @NonNull OnColorExtraction onColorExtraction) { + if (drawable == null) { + onColorExtraction.onColorExtracted(PRIMARY_COLOR, Color.WHITE); + return; + } + extractColor(((BitmapDrawable) drawable).getBitmap(), onColorExtraction); + } + +} diff --git a/app/src/main/java/com/fastaccess/helper/ParcelableBooleanParse.java b/app/src/main/java/com/fastaccess/helper/ParcelableBooleanParse.java new file mode 100644 index 0000000..67c0b00 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/ParcelableBooleanParse.java @@ -0,0 +1,58 @@ +package com.fastaccess.helper; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.SparseBooleanArray; + +/** + * Created by Kosh on 13/12/15 3:04 PM + */ +public class ParcelableBooleanParse extends SparseBooleanArray implements Parcelable { + + public static Creator CREATOR = new Creator() { + @Override public ParcelableBooleanParse createFromParcel(Parcel source) { + ParcelableBooleanParse read = new ParcelableBooleanParse(); + int size = source.readInt(); + int[] keys = new int[size]; + boolean[] values = new boolean[size]; + source.readIntArray(keys); + source.readBooleanArray(values); + for (int i = 0; i < size; i++) { + read.put(keys[i], values[i]); + } + return read; + } + + @Override public ParcelableBooleanParse[] newArray(int size) { + return new ParcelableBooleanParse[size]; + } + }; + + public ParcelableBooleanParse() { + + } + + public ParcelableBooleanParse(SparseBooleanArray sparseBooleanArray) { + for (int i = 0; i < sparseBooleanArray.size(); i++) { + this.put(sparseBooleanArray.keyAt(i), sparseBooleanArray.valueAt(i)); + } + } + + @Override public int describeContents() { + return 0; + } + + @Override public void writeToParcel(Parcel dest, int flags) { + int[] keys = new int[size()]; + boolean[] values = new boolean[size()]; + + for (int i = 0; i < size(); i++) { + keys[i] = keyAt(i); + values[i] = valueAt(i); + } + + dest.writeInt(size()); + dest.writeIntArray(keys); + dest.writeBooleanArray(values); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/helper/PermissionsHelper.java b/app/src/main/java/com/fastaccess/helper/PermissionsHelper.java new file mode 100644 index 0000000..6e6d08d --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/PermissionsHelper.java @@ -0,0 +1,34 @@ +package com.fastaccess.helper; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; + +/** + * Created by Kosh on 19 Oct 2016, 6:55 PM + */ + +public class PermissionsHelper { + + public static final int OVERLAY_PERMISSION_REQ_CODE = 1; + + @TargetApi(Build.VERSION_CODES.M) public static boolean isSystemAlertGranted(@NonNull Context context) { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context); + } + + @TargetApi(Build.VERSION_CODES.M) public static boolean systemAlertPermissionIsGranted(@NonNull AppCompatActivity context) { + if (!isSystemAlertGranted(context)) { + Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName())); + context.startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE); + return false; + } + return true; + } +} + + diff --git a/app/src/main/java/com/fastaccess/helper/PrefConstant.java b/app/src/main/java/com/fastaccess/helper/PrefConstant.java new file mode 100644 index 0000000..bb8aa7f --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/PrefConstant.java @@ -0,0 +1,88 @@ +package com.fastaccess.helper; + +import android.content.Context; +import android.content.res.Resources; +import android.support.annotation.NonNull; +import android.view.ViewGroup; + +import com.fastaccess.R; + +/** + * Created by Kosh on 16 Oct 2016, 4:48 AM + */ + +public class PrefConstant { + + public static final String FLOATING_MODE = "floating_mode"; + public static final String FA_AUTO_SAVE_POSITION = "fa_auto_save_position"; + public static final String FA_EDGES_STICKY = "fa_edges_sticky"; + public static final String FA_ALWAYS_SHOWING = "fa_always_showing"; + public static final String STATUS_BAR_HIDDEN = "status_bar_hidden"; + public static final String FA_BACKGROUND = "fa_background"; + public static final String FA_BACKGROUND_ALPHA = "fa_background_alpha"; + public static final String ICON_PADDING = "icon_padding"; + public static final String ICON_PACK = "icon_pack"; + public static final String CUSTOM_ICON = "custom_icon"; + public static final String AUTO_TRANS = "auto_trans"; + public static final String ICON_ALPHA = "icon_alpha"; + public static final String ICON_SIZE = "icon_size"; + public static final String MANUAL_SIZE = "manual_size"; + public static final String POSITION_X = "floating_position_x"; + public static final String POSITION_Y = "floating_position_y"; + public static final String FA_AUTO_START = "fa_auto_start"; + public static final String FA_IS_HORIZONTAL = "fa_is_horizontal"; + + public static void savePosition(int x, int y) { + boolean isAutoSavePosition = PrefHelper.getBoolean(PrefConstant.FA_AUTO_SAVE_POSITION); + if (isAutoSavePosition) { + Logger.e(x, y); + PrefHelper.set(POSITION_X, x); + PrefHelper.set(POSITION_Y, y); + } + } + + public static int getFinalSize(@NonNull Context context) { + int imageSize = ViewGroup.MarginLayoutParams.WRAP_CONTENT; + int iconSize = PrefHelper.getInt(PrefConstant.MANUAL_SIZE); + String size = PrefHelper.getString(PrefConstant.ICON_SIZE); + if (iconSize > 0) { + imageSize = ViewHelper.toPx(context, iconSize); + } else { + if (InputHelper.isEmpty(size)) size = "medium"; + if (size.equalsIgnoreCase("small")) { + imageSize = context.getResources().getDimensionPixelSize(R.dimen.fa_size_small); + } else if (size.equalsIgnoreCase("medium")) { + imageSize = context.getResources().getDimensionPixelSize(R.dimen.fa_size_medium); + } else if (size.equalsIgnoreCase("large")) { + imageSize = context.getResources().getDimensionPixelSize(R.dimen.fa_size_large); + } + } + return imageSize; + } + + public static int getGapSize(@NonNull Resources resources) { + String gap = PrefHelper.getString(ICON_PADDING); + int gapSize = resources.getDimensionPixelSize(R.dimen.spacing_normal); + if (!InputHelper.isEmpty(gap)) { + if (gap.equalsIgnoreCase("small")) { + gapSize = resources.getDimensionPixelSize(R.dimen.spacing_micro); + } else if (gap.equalsIgnoreCase("medium")) { + gapSize = resources.getDimensionPixelSize(R.dimen.spacing_normal); + + } else if (gap.equalsIgnoreCase("large")) { + gapSize = resources.getDimensionPixelSize(R.dimen.spacing_xs_large); + } else { + gapSize = resources.getDimensionPixelSize(R.dimen.spacing_normal); + } + } + return gapSize; + } + + public static boolean isAutoStart() { + return PrefHelper.getBoolean(FA_AUTO_START); + } + + public static boolean isHorizontal() { + return PrefHelper.getBoolean(FA_IS_HORIZONTAL); + } +} diff --git a/app/src/main/java/com/fastaccess/helper/PrefHelper.java b/app/src/main/java/com/fastaccess/helper/PrefHelper.java new file mode 100644 index 0000000..d8b4b80 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/PrefHelper.java @@ -0,0 +1,121 @@ +package com.fastaccess.helper; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.fastaccess.helper.GsonHelper.gson; + +/** + * Created by kosh20111 on 18 Oct 2016, 9:29 PM + */ +public class PrefHelper { + private static PrefHelper prefHelper; + private Context context; + + private PrefHelper(Context context) { + this.context = context; + } + + public static void init(@NonNull Context context) { + if (prefHelper == null) { + prefHelper = new PrefHelper(context.getApplicationContext()); + } + } + + /** + * @param key + * ( the Key to used to retrieve this data later ) + * @param value + * ( any kind of primitive values ) + *

+ * non can be null!!! + */ + public static void set(@NonNull String key, @NonNull Object value) { + if (InputHelper.isEmpty(key)) { + throw new NullPointerException("Key must not be null! (key = " + key + "), (value = " + value + ")"); + } + Logger.e(key, value); + SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(prefHelper.context).edit(); + if (value instanceof String) { + edit.putString(key, (String) value); + } else if (value instanceof Integer) { + edit.putInt(key, (int) value); + } else if (value instanceof Long) { + edit.putLong(key, (long) value); + } else if (value instanceof Boolean) { + edit.putBoolean(key, (boolean) value); + } else if (value instanceof Float) { + edit.putFloat(key, (float) value); + } else { + edit.putString(key, gson().toJson(value)); + } + edit.apply(); + } + + @Nullable public static T getJsonObject(@NonNull String key, @NonNull Class type) { + String value = getString(key); + if (!InputHelper.isEmpty(value)) { + return gson().fromJson(value, type); + } + return null; + } + + @Nullable public static List getJsonArray(@NonNull String key, final @NonNull Class type) { + String value = getString(key); + if (!InputHelper.isEmpty(value)) { + return Arrays.asList(gson().fromJson(value, type)); + } + return null; + } + + @Nullable public static String getString(@NonNull String key) { + return PreferenceManager.getDefaultSharedPreferences(prefHelper.context).getString(key, null); + } + + public static boolean getBoolean(@NonNull String key) { + return PreferenceManager.getDefaultSharedPreferences(prefHelper.context).getBoolean(key, false); + } + + public static int getInt(@NonNull String key) { + return PreferenceManager.getDefaultSharedPreferences(prefHelper.context).getInt(key, 0); + } + + public static long getLong(@NonNull String key) { + return PreferenceManager.getDefaultSharedPreferences(prefHelper.context).getLong(key, 0); + } + + public static float getFloat(@NonNull String key) { + return PreferenceManager.getDefaultSharedPreferences(prefHelper.context).getFloat(key, 0); + } + + public static void clearKey(@NonNull String key) { + PreferenceManager.getDefaultSharedPreferences(prefHelper.context).edit().remove(key).apply(); + } + + public static boolean isExist(@NonNull String key) { + return PreferenceManager.getDefaultSharedPreferences(prefHelper.context).contains(key); + } + + public static void clearPrefs() { + PreferenceManager.getDefaultSharedPreferences(prefHelper.context).edit().clear().apply(); + } + + public static Map getAll() { + Map toBackupMap = new HashMap<>(); + Map prefs = PreferenceManager.getDefaultSharedPreferences(prefHelper.context).getAll(); + for (String key : prefs.keySet()) { + if (!InputHelper.isEmpty(key) && !key.equalsIgnoreCase("null")) {// sometimes key is null, for no fucking reason. + toBackupMap.put(key, prefs.get(key)); + } + } + return toBackupMap; + } +} diff --git a/app/src/main/java/com/fastaccess/helper/TypeFaceHelper.java b/app/src/main/java/com/fastaccess/helper/TypeFaceHelper.java new file mode 100644 index 0000000..baf340f --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/TypeFaceHelper.java @@ -0,0 +1,25 @@ +package com.fastaccess.helper; + +import android.content.Context; +import android.graphics.Typeface; +import android.widget.TextView; + +/** + * Created by Kosh on 17/12/15 10:25 PM + */ +public class TypeFaceHelper { + + private static Typeface arabicTypeFace; + + public static void generateTypeface(Context context) { + arabicTypeFace = Typeface.createFromAsset(context.getAssets(), "fonts/app_font.ttf"); + } + + public static void applyTypeface(TextView textView) { + textView.setTypeface(arabicTypeFace); + } + + public static Typeface getTypeface() { + return arabicTypeFace; + } +} diff --git a/app/src/main/java/com/fastaccess/helper/ViewHelper.java b/app/src/main/java/com/fastaccess/helper/ViewHelper.java new file mode 100644 index 0000000..f8e4f98 --- /dev/null +++ b/app/src/main/java/com/fastaccess/helper/ViewHelper.java @@ -0,0 +1,243 @@ +package com.fastaccess.helper; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.StateListDrawable; +import android.graphics.drawable.shapes.RoundRectShape; +import android.support.annotation.ColorInt; +import android.support.annotation.IdRes; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; +import android.support.design.widget.NavigationView; +import android.support.v4.content.ContextCompat; +import android.support.v4.graphics.drawable.DrawableCompat; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.fastaccess.R; +import com.tooltip.OnDismissListener; +import com.tooltip.Tooltip; + +import java.util.Arrays; + + +/** + * Created by kosh20111 on 10/7/2015 10:42 PM + */ +public class ViewHelper { + + public static int getAccentColor(Context context) { + TypedValue typedValue = new TypedValue(); + TypedArray a = context.obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorAccent}); + int color = a.getColor(0, 0); + a.recycle(); + return color; + } + + public static int getPrimaryColor(Context context) { + TypedValue typedValue = new TypedValue(); + TypedArray a = context.obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorPrimary}); + int color = a.getColor(0, 0); + a.recycle(); + return color; + } + + public static int getPrimaryDarkColor(Context context) { + TypedValue typedValue = new TypedValue(); + TypedArray a = context.obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorPrimaryDark}); + int color = a.getColor(0, 0); + a.recycle(); + return color; + } + + public static int toPx(Context context, int dp) { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, dp, context.getResources().getDisplayMetrics()); + } + + public static int toDp(Context context, int px) { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, context.getResources().getDisplayMetrics()); + } + + public static Drawable tintDrawable(Drawable drawable, int color) { + drawable = DrawableCompat.wrap(drawable); + DrawableCompat.setTint(drawable, color); + return drawable; + } + + public static Drawable getDrawableSelector(int normalColor, int pressedColor) { + if (AppHelper.isLollipopOrHigher()) { + return new RippleDrawable(ColorStateList.valueOf(pressedColor), getRippleMask(normalColor), getRippleMask(normalColor)); + } else { + return getStateListDrawable(normalColor, pressedColor); + } + } + + private static Drawable getRippleMask(int color) { + float[] outerRadii = new float[8]; + Arrays.fill(outerRadii, 3); + RoundRectShape r = new RoundRectShape(outerRadii, null, null); + ShapeDrawable shapeDrawable = new ShapeDrawable(r); + shapeDrawable.getPaint().setColor(color); + return shapeDrawable; + } + + private static StateListDrawable getStateListDrawable(int normalColor, int pressedColor) { + StateListDrawable states = new StateListDrawable(); + states.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(pressedColor)); + states.addState(new int[]{android.R.attr.state_focused}, new ColorDrawable(pressedColor)); + states.addState(new int[]{android.R.attr.state_activated}, new ColorDrawable(pressedColor)); + states.addState(new int[]{android.R.attr.state_selected}, new ColorDrawable(pressedColor)); + states.addState(new int[]{}, new ColorDrawable(normalColor)); + return states; + } + + public static ColorStateList textSelector(int normalColor, int pressedColor) { + return new ColorStateList( + new int[][]{ + new int[]{android.R.attr.state_pressed}, + new int[]{android.R.attr.state_focused}, + new int[]{android.R.attr.state_activated}, + new int[]{android.R.attr.state_selected}, + new int[]{} + }, + new int[]{ + pressedColor, + pressedColor, + pressedColor, + pressedColor, + normalColor + } + ); + } + + public static int generateTextColor(int color) { + return Color.rgb(255 - Color.red(color), + 255 - Color.green(color), + 255 - Color.blue(color)); + } + + public static int getDarkColor(@ColorInt int color) { + if (color == 0) return color; + float cl = 0.9f; + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + hsv[2] *= cl; + return Color.HSVToColor(hsv); + } + + private static boolean isTablet(Resources resources) { + return (resources.getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; + } + + public static boolean isTablet(Context context) { + return isTablet(context.getResources()); + } + + public static void setMenuCount(@NonNull NavigationView navigationView, @IdRes int itemId, @IdRes int txtId, int count) { + if (navigationView.getMenu().findItem(itemId).getActionView() != null) { + if (navigationView.getMenu().findItem(itemId).getActionView() instanceof TextView) { + setTextViewMenuCounter(navigationView, itemId, count); + return; + } + LinearLayout view = (LinearLayout) navigationView.getMenu().findItem(itemId).getActionView(); + ((TextView) view.findViewById(txtId)).setText(String.format("%s", count)); + } + } + + private static void setTextViewMenuCounter(@NonNull NavigationView navigationView, @IdRes int itemId, int count) { + TextView view = (TextView) navigationView.getMenu().findItem(itemId).getActionView(); + view.setText(String.format("%s", count)); + } + + public static boolean isLandscape(Resources resources) { + return resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; + } + + public static void setFullSpan(@NonNull RecyclerView.ViewHolder holder) { + StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams(); + if (params == null) { + params = new StaggeredGridLayoutManager.LayoutParams(StaggeredGridLayoutManager.LayoutParams.MATCH_PARENT, + StaggeredGridLayoutManager.LayoutParams.WRAP_CONTENT); + } + params.setFullSpan(true); + holder.itemView.setLayoutParams(params); + } + + public static float getDeviceWidth(Context context) { + Point size = new Point(); + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + windowManager.getDefaultDisplay().getSize(size); + return size.x; + } + + public static float getDeviceHeight(Context context) { + Point size = new Point(); + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + windowManager.getDefaultDisplay().getSize(size); + return size.y; + } + + @SuppressWarnings("ConstantConditions") @SuppressLint("PrivateResource") + public static void showTooltip(@NonNull final View view, @StringRes int titleResId, @NonNull final String tag, int gravity) { + if (view != null && view.getContext() != null) { + if (!PrefHelper.getBoolean(tag)) { + new Tooltip.Builder(view) + .setText(titleResId) + .setTypeface(TypeFaceHelper.getTypeface()) + .setTextColor(Color.WHITE) + .setGravity(gravity) + .setPadding(R.dimen.spacing_xs_large) + .setBackgroundColor(ContextCompat.getColor(view.getContext(), R.color.primary)) + .setDismissOnClick(true) + .setCancelable(true) + .setTextStyle(android.support.v7.appcompat.R.style.Base_TextAppearance_AppCompat_Title_Inverse) + .setOnDismissListener(new OnDismissListener() { + @Override public void onDismiss() { + PrefHelper.set(tag, true); + } + }) + .show(); + } + } + } + + @SuppressLint("PrivateResource") public static void showTooltip(@NonNull final View view, @StringRes int titleResId, + @NonNull final String tag) { + showTooltip(view, titleResId, tag, Gravity.BOTTOM); + } + + public static Rect getLayoutPosition(@NonNull View view) { + Rect myViewRect = new Rect(); + view.getGlobalVisibleRect(myViewRect); + return myViewRect; + } + + public static int getWidthFromRecyclerView(@NonNull RecyclerView recyclerView, @NonNull WindowManager windowManager) { + int iconSize = PrefConstant.getFinalSize(recyclerView.getContext()); + int padding = PrefConstant.getGapSize(recyclerView.getResources()); + int count = recyclerView.getAdapter().getItemCount(); + int width = (count * (iconSize + padding)) + iconSize; + DisplayMetrics metrics = new DisplayMetrics(); + windowManager.getDefaultDisplay().getMetrics(metrics); + Logger.e(width <= metrics.widthPixels); + return width <= metrics.widthPixels ? width : metrics.widthPixels; + } +} diff --git a/app/src/main/java/com/fastaccess/provider/analytics/Analytics.java b/app/src/main/java/com/fastaccess/provider/analytics/Analytics.java new file mode 100644 index 0000000..dcd814c --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/analytics/Analytics.java @@ -0,0 +1,34 @@ +package com.fastaccess.provider.analytics; + +import android.os.Bundle; + +import com.fastaccess.App; +import com.google.firebase.analytics.FirebaseAnalytics; + +/** + * Created by Kosh on 29 May 2016, 1:25 AM + */ + +public class Analytics { + + public static void logEvent() { + Bundle bundle = new Bundle(); + bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, getFileName()); + bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, getCurrentMethodName()); + App.getInstance().getFirebaseAnalytics().logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, bundle); + } + + private static String getCurrentMethodName() { + try { + return Thread.currentThread().getStackTrace()[4].getMethodName() + "()"; + } catch (Exception ignored) {} + return Analytics.class.getSimpleName(); + } + + private static String getFileName() { + try { + return Thread.currentThread().getStackTrace()[4].getFileName(); + } catch (Exception ignored) {} + return Analytics.class.getSimpleName(); + } +} diff --git a/app/src/main/java/com/fastaccess/provider/icon/IconCache.java b/app/src/main/java/com/fastaccess/provider/icon/IconCache.java new file mode 100644 index 0000000..349e4fb --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/icon/IconCache.java @@ -0,0 +1,415 @@ +package com.fastaccess.provider.icon; + +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BlurMaskFilter; +import android.graphics.Canvas; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.PaintDrawable; +import android.support.v4.content.res.ResourcesCompat; +import android.text.TextUtils; +import android.util.DisplayMetrics; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; + +import java.util.HashMap; + +/** + * Cache of application icons. Icons can be made from any thread. + */ +public class IconCache { + private static final int INITIAL_ICON_CACHE_CAPACITY = 50; + + private static class CacheEntry { + public Bitmap icon; + public String title; + } + + private final Bitmap mDefaultIcon; + private final Context mContext; + private final PackageManager mPackageManager; + private final HashMap mCache = new HashMap<>(INITIAL_ICON_CACHE_CAPACITY); + private int mIconDpi; + private static int sIconWidth = -1; + private static int sIconHeight = -1; + public static int sIconTextureWidth = -1; + public static int sIconTextureHeight = -1; + private static final Paint sBlurPaint = new Paint(); + private static final Paint sGlowColorPressedPaint = new Paint(); + private static final Paint sGlowColorFocusedPaint = new Paint(); + private static final Paint sDisabledPaint = new Paint(); + private static final Rect sOldBounds = new Rect(); + private static final Canvas sCanvas = new Canvas(); + private IconPackHelper mIconPackHelper; + + static { + sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, Paint.FILTER_BITMAP_FLAG)); + } + + public IconCache(Context context) { + ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + mContext = context; + mPackageManager = context.getPackageManager(); + mIconDpi = activityManager.getLauncherLargeIconDensity(); + mDefaultIcon = makeDefaultIcon(); + mIconPackHelper = new IconPackHelper(context); + loadIconPack(); + + } + + public void getTitleAndIcon(AppsModel application, ResolveInfo info, HashMap labelCache) { + synchronized (mCache) { + CacheEntry entry = cacheLocked(application.getComponentName(), info, labelCache); + application.setAppName(entry.title); + application.setBitmap(entry.icon); + } + } + + private void loadIconPack() { + mIconPackHelper.unloadIconPack(); + String iconPack = PrefHelper.getString(PrefConstant.ICON_PACK); + if (!TextUtils.isEmpty(iconPack) && !mIconPackHelper.loadIconPack(iconPack)) { + PrefHelper.set(PrefConstant.ICON_PACK, ""); + } + } + + public Drawable getFullResDefaultActivityIcon() { + return getFullResIcon(Resources.getSystem(), + android.R.mipmap.sym_def_app_icon); + } + + public Drawable getFullResIcon(Resources resources, int iconId) { + Drawable d; + try { + d = ResourcesCompat.getDrawableForDensity(resources, iconId, mIconDpi, mContext.getTheme()); + } catch (Resources.NotFoundException e) { + d = null; + } + + return (d != null) ? d : getFullResDefaultActivityIcon(); + } + + public Drawable getFullResIcon(String packageName, int iconId) { + Resources resources; + try { + resources = mPackageManager.getResourcesForApplication(packageName); + } catch (PackageManager.NameNotFoundException e) { + resources = null; + } + if (resources != null) { + if (iconId != 0) { + return getFullResIcon(resources, iconId); + } + } + return getFullResDefaultActivityIcon(); + } + + public Drawable getFullResIcon(ResolveInfo info) { + return getFullResIcon(info.activityInfo); + } + + public Drawable getFullResIcon(ActivityInfo info) { + Resources resources; + try { + resources = mPackageManager.getResourcesForApplication(info.applicationInfo); + } catch (PackageManager.NameNotFoundException e) { + resources = null; + } + if (resources != null) { + int iconId = 0; + if (mIconPackHelper != null && mIconPackHelper.isIconPackLoaded()) { + iconId = mIconPackHelper.getResourceIdForActivityIcon(info); + if (iconId != 0) { + return getFullResIcon(mIconPackHelper.getIconPackResources(), iconId); + } + } + iconId = info.getIconResource(); + if (iconId != 0) { + return getFullResIcon(resources, iconId); + } + } + return getFullResDefaultActivityIcon(); + } + + private Bitmap makeDefaultIcon() { + Drawable d = getFullResDefaultActivityIcon(); + Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1), + Math.max(d.getIntrinsicHeight(), 1), + Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(b); + d.setBounds(0, 0, b.getWidth(), b.getHeight()); + d.draw(c); + c.setBitmap(null); + return b; + } + + public void remove(ComponentName componentName) { + synchronized (mCache) { + mCache.remove(componentName); + } + } + + public void flush() { + synchronized (mCache) { + mCache.clear(); + } + } + + public Bitmap getIcon(Intent intent) { + synchronized (mCache) { + final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0); + ComponentName component = intent.getComponent(); + + if (resolveInfo == null || component == null) { + return mDefaultIcon; + } + + CacheEntry entry = cacheLocked(component, resolveInfo, null); + return entry.icon; + } + } + + public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo, HashMap labelCache) { + synchronized (mCache) { + if (resolveInfo == null || component == null) { + return null; + } + CacheEntry entry = cacheLocked(component, resolveInfo, labelCache); + return entry.icon; + } + } + + public boolean isDefaultIcon(Bitmap icon) { + return mDefaultIcon == icon; + } + + private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info, HashMap labelCache) { + CacheEntry entry = mCache.get(componentName); + if (entry == null) { + entry = new CacheEntry(); + mCache.put(componentName, entry); + ComponentName key; + if (info.activityInfo != null) { + key = new ComponentName(info.activityInfo.packageName, info.activityInfo.name); + } else { + key = new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name); + } + if (labelCache != null && labelCache.containsKey(key)) { + entry.title = labelCache.get(key).toString(); + } else { + entry.title = info.loadLabel(mPackageManager).toString(); + if (labelCache != null) { + labelCache.put(key, entry.title); + } + } + if (entry.title == null) { + entry.title = info.activityInfo.name; + } + + Drawable icon = getFullResIcon(info); + if (mIconPackHelper.isIconPackLoaded() && (mIconPackHelper.getResourceIdForActivityIcon(info.activityInfo) == 0)) { + entry.icon = createIconBitmap(icon, mContext, mIconPackHelper.getIconBack(), mIconPackHelper.getIconMask(), mIconPackHelper + .getIconUpon(), mIconPackHelper.getIconScale()); + } else { + entry.icon = createIconBitmap(icon, mContext); + } + } + return entry; + } + + public Bitmap getIcon(String packageName, String activityInfoName) { + ComponentName componentName = new ComponentName(packageName, activityInfoName); + if (mCache.get(componentName) != null) { + return mCache.get(componentName).icon; + } else { + Intent intent = new Intent(); + intent.setComponent(new ComponentName(packageName, activityInfoName)); + return getIcon(intent); + } + } + + public HashMap getAllIcons() { + synchronized (mCache) { + HashMap set = new HashMap<>(); + for (ComponentName cn : mCache.keySet()) { + final CacheEntry e = mCache.get(cn); + set.put(cn, e.icon); + } + return set; + } + } + + public static Bitmap createIconBitmap(Bitmap icon, Context context) { + int textureWidth = sIconTextureWidth; + int textureHeight = sIconTextureHeight; + int sourceWidth = icon.getWidth(); + int sourceHeight = icon.getHeight(); + if (sourceWidth > textureWidth && sourceHeight > textureHeight) { + // Icon is bigger than it should be; clip it (solves the GB->ICS migration case) + return Bitmap.createBitmap(icon, + (sourceWidth - textureWidth) / 2, + (sourceHeight - textureHeight) / 2, + textureWidth, textureHeight); + } else if (sourceWidth == textureWidth && sourceHeight == textureHeight) { + // Icon is the right size, no need to change it + return icon; + } else { + // Icon is too small, render to a larger bitmap + final Resources resources = context.getResources(); + return createIconBitmap(new BitmapDrawable(resources, icon), context); + } + } + + public static Bitmap createIconBitmap(Drawable icon, Context context) { + synchronized (sCanvas) { // we share the statics :-( + if (sIconWidth == -1) { + initStatics(context); + } + + int width = sIconWidth; + int height = sIconHeight; + + if (icon instanceof PaintDrawable) { + PaintDrawable painter = (PaintDrawable) icon; + painter.setIntrinsicWidth(width); + painter.setIntrinsicHeight(height); + } else if (icon instanceof BitmapDrawable) { + // Ensure the bitmap has a density. + BitmapDrawable bitmapDrawable = (BitmapDrawable) icon; + Bitmap bitmap = bitmapDrawable.getBitmap(); + if (bitmap.getDensity() == Bitmap.DENSITY_NONE) { + bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics()); + } + } + int sourceWidth = icon.getIntrinsicWidth(); + int sourceHeight = icon.getIntrinsicHeight(); + if (sourceWidth > 0 && sourceHeight > 0) { + // Scale the icon proportionally to the icon dimensions + final float ratio = (float) sourceWidth / sourceHeight; + if (sourceWidth > sourceHeight) { + height = (int) (width / ratio); + } else if (sourceHeight > sourceWidth) { + width = (int) (height * ratio); + } + } + + // no intrinsic size --> use default size + int textureWidth = sIconTextureWidth; + int textureHeight = sIconTextureHeight; + final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight, Bitmap.Config.ARGB_8888); + final Canvas canvas = sCanvas; + canvas.setBitmap(bitmap); + final int left = (textureWidth - width) / 2; + final int top = (textureHeight - height) / 2; + sOldBounds.set(icon.getBounds()); + icon.setBounds(left, top, left + width, top + height); + icon.draw(canvas); + icon.setBounds(sOldBounds); + canvas.setBitmap(null); + return bitmap; + } + } + + public static Bitmap createIconBitmap(Drawable icon, Context context, Drawable iconBack, Drawable iconMask, Drawable iconUpon, float scale) { + synchronized (sCanvas) { // we share the statics :-( + if (sIconWidth == -1) { + initStatics(context); + } + int width = sIconWidth; + int height = sIconHeight; + if (icon instanceof PaintDrawable) { + PaintDrawable painter = (PaintDrawable) icon; + painter.setIntrinsicWidth(width); + painter.setIntrinsicHeight(height); + } else if (icon instanceof BitmapDrawable) { + // Ensure the bitmap has a density. + BitmapDrawable bitmapDrawable = (BitmapDrawable) icon; + Bitmap bitmap = bitmapDrawable.getBitmap(); + if (bitmap.getDensity() == Bitmap.DENSITY_NONE) { + bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics()); + } + } + int sourceWidth = icon.getIntrinsicWidth(); + int sourceHeight = icon.getIntrinsicHeight(); + if (sourceWidth > 0 && sourceHeight > 0) { + // Scale the icon proportionally to the icon dimensions + final float ratio = (float) sourceWidth / sourceHeight; + if (sourceWidth > sourceHeight) { + height = (int) (width / ratio); + } else if (sourceHeight > sourceWidth) { + width = (int) (height * ratio); + } + } + + // no intrinsic size --> use default size + int textureWidth = sIconTextureWidth; + int textureHeight = sIconTextureHeight; + + Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight, + Bitmap.Config.ARGB_8888); + final Canvas canvas = sCanvas; + canvas.setBitmap(bitmap); + final int left = (textureWidth - width) / 2; + final int top = (textureHeight - height) / 2; + sOldBounds.set(icon.getBounds()); + icon.setBounds(left, top, left + width, top + height); + canvas.save(); + canvas.scale(scale, scale, width / 2, height / 2); + icon.draw(canvas); + canvas.restore(); + if (iconMask != null) { + iconMask.setBounds(icon.getBounds()); + ((BitmapDrawable) iconMask).getPaint().setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + iconMask.draw(canvas); + } + if (iconBack != null) { + canvas.setBitmap(null); + Bitmap finalBitmap = Bitmap.createBitmap(textureWidth, textureHeight, Bitmap.Config.ARGB_8888); + canvas.setBitmap(finalBitmap); + iconBack.setBounds(icon.getBounds()); + iconBack.draw(canvas); + canvas.drawBitmap(bitmap, null, icon.getBounds(), null); + bitmap = finalBitmap; + } + if (iconUpon != null) { + iconUpon.draw(canvas); + } + icon.setBounds(sOldBounds); + canvas.setBitmap(null); + + return bitmap; + } + } + + private static void initStatics(Context context) { + final Resources resources = context.getResources(); + final DisplayMetrics metrics = resources.getDisplayMetrics(); + final float density = metrics.density; + sIconWidth = sIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size); + sIconTextureWidth = sIconTextureHeight = sIconWidth; + sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL)); + sGlowColorPressedPaint.setColor(0xffffc300); + sGlowColorFocusedPaint.setColor(0xffff8e00); + ColorMatrix cm = new ColorMatrix(); + cm.setSaturation(0.2f); + sDisabledPaint.setColorFilter(new ColorMatrixColorFilter(cm)); + sDisabledPaint.setAlpha(0x88); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/icon/IconPackAdapter.java b/app/src/main/java/com/fastaccess/provider/icon/IconPackAdapter.java new file mode 100644 index 0000000..743ee60 --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/icon/IconPackAdapter.java @@ -0,0 +1,99 @@ +package com.fastaccess.provider.icon; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.support.v4.content.ContextCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; + +import com.fastaccess.R; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.provider.icon.model.IconPackInfo; +import com.fastaccess.ui.widgets.FontRadioButton; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.ForegroundImageView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * Created by Kosh on 13/12/15 1:21 AM + */ +public class IconPackAdapter extends BaseAdapter { + + private ArrayList mSupportedPackages; + private String mCurrentIconPack; + private int mCurrentIconPackPosition = -1; + private boolean isPickIcon; + + public IconPackAdapter(Context ctx, Map supportedPackages, boolean isPickIcon) { + mSupportedPackages = new ArrayList<>(supportedPackages.values()); + this.isPickIcon = isPickIcon; + Collections.sort(mSupportedPackages, new Comparator() { + @Override public int compare(IconPackInfo lhs, IconPackInfo rhs) { + return lhs.label.toString().compareToIgnoreCase(rhs.label.toString()); + } + }); + String defaultLabel = ctx.getString(R.string.default_theme); + Drawable icon = ContextCompat.getDrawable(ctx, R.mipmap.ic_launcher); + mSupportedPackages.add(0, new IconPackInfo(defaultLabel, icon, "")); + mCurrentIconPack = PrefHelper.getString(PrefConstant.ICON_PACK); + } + + @Override public int getCount() { + return mSupportedPackages.size(); + } + + @Override public String getItem(int position) { + return mSupportedPackages.get(position).packageName; + } + + @Override public long getItemId(int position) { + return 0; + } + + public boolean isCurrentIconPack(int position) { + return mCurrentIconPackPosition == position; + } + + @Override public View getView(int position, View convertView, ViewGroup parent) { + View view = convertView; + ViewHolder viewHolder; + if (view == null) { + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.icon_pack_layout, parent, false); + viewHolder = new ViewHolder(view); + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + } + IconPackInfo info = mSupportedPackages.get(position); + viewHolder.title.setText(info.label); + viewHolder.icon.setImageDrawable(info.icon); + if (!isPickIcon) { + boolean isCurrentIconPack = info.packageName.equals(mCurrentIconPack); + viewHolder.radio.setChecked(isCurrentIconPack); + if (isCurrentIconPack) { + mCurrentIconPackPosition = position; + } + } else { + viewHolder.radio.setVisibility(View.GONE); + } + return view; + } + + static class ViewHolder { + @BindView(R.id.icon) ForegroundImageView icon; + @BindView(R.id.title) FontTextView title; + @BindView(R.id.radio) FontRadioButton radio; + + ViewHolder(View view) {ButterKnife.bind(this, view);} + } +} diff --git a/app/src/main/java/com/fastaccess/provider/icon/IconPackHelper.java b/app/src/main/java/com/fastaccess/provider/icon/IconPackHelper.java new file mode 100644 index 0000000..56fe5d2 --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/icon/IconPackHelper.java @@ -0,0 +1,455 @@ +package com.fastaccess.provider.icon; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.support.v4.app.Fragment; +import android.text.TextUtils; +import android.widget.Toast; + +import com.fastaccess.App; +import com.fastaccess.R; +import com.fastaccess.data.dao.ThemePackEventModel; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.provider.icon.model.IconPackInfo; + +import org.greenrobot.eventbus.EventBus; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class IconPackHelper { + public final static int PICK_ICON = 2001; + static final String ICON_MASK_TAG = "iconmask"; + static final String ICON_BACK_TAG = "iconback"; + static final String ICON_UPON_TAG = "iconupon"; + static final String ICON_SCALE_TAG = "scale"; + final static String PLAY_STORE_PACKAGENAME = "com.android.vending"; + final static String PLAY_STORE_SEARCH_URI = "market://search?q=icon+pack"; + + public final static String[] sSupportedActions = new String[]{ + "org.adw.launcher.THEMES", + "com.gau.go.launcherex.theme" + }; + + public static final String[] sSupportedCategories = new String[]{ + "com.fede.launcher.THEME_ICONPACK", + "com.anddoes.launcher.THEME", + "com.teslacoilsw.launcher.THEME" + }; + + private Map mIconPackResources; + private final Context mContext; + private String mLoadedIconPackName; + private Resources mLoadedIconPackResource; + private Drawable mIconBack, mIconUpon, mIconMask; + private float mIconScale; + + public Drawable getIconBack() { + return mIconBack; + } + + public Drawable getIconMask() { + return mIconMask; + } + + public Drawable getIconUpon() { + return mIconUpon; + } + + public float getIconScale() { + return mIconScale; + } + + public IconPackHelper(Context context) { + mContext = context; + mIconPackResources = new HashMap<>(); + } + + private Drawable getDrawableForName(String name) { + if (isIconPackLoaded()) { + String item = mIconPackResources.get(name); + if (!TextUtils.isEmpty(item)) { + int id = getResourceIdForDrawable(item); + if (id != 0) { + return mLoadedIconPackResource.getDrawable(id); + } + } + } + return null; + } + + public static Map getSupportedPackages(Context context) { + Intent i = new Intent(); + Map packages = new HashMap<>(); + PackageManager packageManager = context.getPackageManager(); + for (String action : sSupportedActions) { + i.setAction(action); + for (ResolveInfo r : packageManager.queryIntentActivities(i, 0)) { + IconPackInfo info = new IconPackInfo(r, packageManager); + packages.put(r.activityInfo.packageName, info); + } + } + i = new Intent(Intent.ACTION_MAIN); + for (String category : sSupportedCategories) { + i.addCategory(category); + for (ResolveInfo r : packageManager.queryIntentActivities(i, 0)) { + IconPackInfo info = new IconPackInfo(r, packageManager); + packages.put(r.activityInfo.packageName, info); + } + i.removeCategory(category); + } + return packages; + } + + private static void loadResourcesFromXmlParser(XmlPullParser parser, Map iconPackResources) throws XmlPullParserException, + IOException { + int eventType = parser.getEventType(); + do { + + if (eventType != XmlPullParser.START_TAG) { + continue; + } + if (parser.getName().equalsIgnoreCase(ICON_MASK_TAG) || + parser.getName().equalsIgnoreCase(ICON_BACK_TAG) || + parser.getName().equalsIgnoreCase(ICON_UPON_TAG)) { + List icons = new ArrayList<>(); + icons.add(parser.getAttributeValue(null, "img")); + for (int i = 0; i < 10; i++) { + icons.add(parser.getAttributeValue(null, "img" + i)); + } + for (String icon : icons) { + if (icon == null) { + if (parser.getAttributeCount() > 0) { + for (int count = 0; count < parser.getAttributeCount(); count++) { + icon = parser.getAttributeValue(count); + iconPackResources.put(parser.getName().toLowerCase(), icon); + } + } + } + } + continue; + } + if (parser.getName().equalsIgnoreCase(ICON_SCALE_TAG)) { + String factor = parser.getAttributeValue(null, "factor"); + if (factor == null) { + if (parser.getAttributeCount() == 1) { + factor = parser.getAttributeValue(0); + } + } + iconPackResources.put(parser.getName().toLowerCase(), factor); + continue; + } + + if (!parser.getName().equalsIgnoreCase("item")) { + continue; + } + + String component = parser.getAttributeValue(null, "component"); + String drawable = parser.getAttributeValue(null, "drawable"); + + // Validate component/drawable exist + if (TextUtils.isEmpty(component) || TextUtils.isEmpty(drawable)) { + continue; + } + + // Validate format/length of component + if (!component.startsWith("ComponentInfo{") || !component.endsWith("}") + || component.length() < 16) { + continue; + } + + // Sanitize stored value + component = component.substring(14, component.length() - 1).toLowerCase(); + + ComponentName name = null; + if (!component.contains("/")) { + // Package icon reference + iconPackResources.put(component, drawable); + } else { + name = ComponentName.unflattenFromString(component); + if (name != null) { + iconPackResources.put(name.getPackageName(), drawable); + iconPackResources.put(name.getPackageName() + "." + name.getClassName(), drawable); + } + } + } while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT); + } + + private static void loadApplicationResources(Context context, Map iconPackResources, String packageName) { + Field[] drawableItems = null; + try { + Context appContext = context.createPackageContext(packageName, + Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); + drawableItems = Class.forName(packageName + ".R$drawable", + true, appContext.getClassLoader()).getFields(); + } catch (Exception e) { + return; + } + for (Field f : drawableItems) { + String name = f.getName(); + + String icon = name.toLowerCase(); + name = name.replaceAll("_", "."); + + iconPackResources.put(name, icon); + + int activityIndex = name.lastIndexOf("."); + if (activityIndex <= 0 || activityIndex == name.length() - 1) { + continue; + } + + String iconPackage = name.substring(0, activityIndex); + if (TextUtils.isEmpty(iconPackage)) { + continue; + } + iconPackResources.put(iconPackage, icon); + + String iconActivity = name.substring(activityIndex + 1); + if (TextUtils.isEmpty(iconActivity)) { + continue; + } + iconPackResources.put(iconPackage + "." + iconActivity, icon); + } + } + + public boolean loadIconPack(String packageName) { + mIconPackResources = getIconPackResources(mContext, packageName); + Resources res; + try { + res = mContext.getPackageManager().getResourcesForApplication(packageName); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + return false; + } + mLoadedIconPackResource = res; + mLoadedIconPackName = packageName; + mIconBack = getDrawableForName(ICON_BACK_TAG); + mIconMask = getDrawableForName(ICON_MASK_TAG); + mIconUpon = getDrawableForName(ICON_UPON_TAG); + String scale = mIconPackResources.get(ICON_SCALE_TAG); + if (scale != null) { + try { + mIconScale = Float.valueOf(scale); + } catch (NumberFormatException ignored) {} + } + return true; + } + + public static Map getIconPackResources(Context context, String packageName) { + if (TextUtils.isEmpty(packageName)) { + return null; + } + + Resources res = null; + try { + res = context.getPackageManager().getResourcesForApplication(packageName); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + return null; + } + + XmlPullParser parser = null; + InputStream inputStream = null; + Map iconPackResources = new HashMap(); + + try { + inputStream = res.getAssets().open("appfilter.xml"); + XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + parser = factory.newPullParser(); + parser.setInput(inputStream, "UTF-8"); + } catch (Exception e) { + // Catch any exception since we want to fall back to parsing the xml/ + // resource in all cases + int resId = res.getIdentifier("appfilter", "xml", packageName); + if (resId != 0) { + parser = res.getXml(resId); + } + } + + if (parser != null) { + try { + loadResourcesFromXmlParser(parser, iconPackResources); + return iconPackResources; + } catch (XmlPullParserException | IOException e) { + e.printStackTrace(); + } finally { + // Cleanup resources + if (parser instanceof XmlResourceParser) { + ((XmlResourceParser) parser).close(); + } + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException ignored) {} + } + } + } + + // Application uses a different theme format (most likely launcher pro) + int arrayId = res.getIdentifier("theme_iconpack", "array", packageName); + if (arrayId == 0) { + arrayId = res.getIdentifier("icon_pack", "array", packageName); + } + + if (arrayId != 0) { + String[] iconPack = res.getStringArray(arrayId); + for (String entry : iconPack) { + + if (TextUtils.isEmpty(entry)) { + continue; + } + + String icon = entry.toLowerCase(); + entry = entry.replaceAll("_", "."); + + iconPackResources.put(entry, icon); + + int activityIndex = entry.lastIndexOf("."); + if (activityIndex <= 0 || activityIndex == entry.length() - 1) { + continue; + } + + String iconPackage = entry.substring(0, activityIndex); + if (TextUtils.isEmpty(iconPackage)) { + continue; + } + iconPackResources.put(iconPackage, icon); + + String iconActivity = entry.substring(activityIndex + 1); + if (TextUtils.isEmpty(iconActivity)) { + continue; + } + iconPackResources.put(iconPackage + "." + iconActivity, icon); + } + } else { + loadApplicationResources(context, iconPackResources, packageName); + } + return iconPackResources; + } + + public void unloadIconPack() { + mLoadedIconPackResource = null; + mLoadedIconPackName = null; + mIconPackResources = null; + mIconMask = null; + mIconBack = null; + mIconUpon = null; + mIconScale = 1f; + } + + public static void pickIconPack(final Fragment context, final boolean pickIcon) { + Map supportedPackages = getSupportedPackages(context.getContext()); + AlertDialog.Builder builder = new AlertDialog.Builder(context.getContext(), R.style.AlertDialogStyle); + if (supportedPackages.isEmpty()) { + builder.setTitle(context.getString(R.string.get_themes)); + builder.setMessage(R.string.no_icon_packs) + .setPositiveButton(R.string.get_themes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(PLAY_STORE_SEARCH_URI)); + context.startActivity(intent); + } + }).setNegativeButton(R.string.cancel, null) + .show(); + return; + } + final IconPackAdapter adapter = new IconPackAdapter(context.getContext(), supportedPackages, pickIcon); + if (!pickIcon) { + builder.setTitle(R.string.choose_theme_pack); + builder.setAdapter(adapter, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int position) { + if (adapter.isCurrentIconPack(position)) { + return; + } + String selectedPackage = adapter.getItem(position); + PrefHelper.set(PrefConstant.ICON_PACK, selectedPackage); + App.getInstance().flushIconPack(); + EventBus.getDefault().post(new ThemePackEventModel()); + } + }).setPositiveButton(context.getString(R.string.get_themes), new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int which) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(PLAY_STORE_SEARCH_URI)); + context.startActivity(intent); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } else { + builder.setTitle(R.string.choose_icon); + builder.setAdapter(adapter, new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int which) { + if (which == 0) { + Intent intent = new Intent(); + intent.putExtra("default", true); + context.onActivityResult(PICK_ICON, Activity.RESULT_CANCELED, intent); + } else { + String selectedPackage = adapter.getItem(which); + try { + Intent i = new Intent(); + i.setPackage(selectedPackage); + i.setAction("org.adw.launcher.icons.ACTION_PICK_ICON"); + i.putExtra("package", selectedPackage); + context.startActivityForResult(i, PICK_ICON); + } catch (Exception e) { + Toast.makeText(context.getContext(), context.getString(R.string.not_support_icon_theme), Toast.LENGTH_LONG).show(); + } + } + } + }); + } + builder.show(); + } + + boolean isIconPackLoaded() { + return mLoadedIconPackResource != null && + mLoadedIconPackName != null && + mIconPackResources != null; + } + + private int getResourceIdForDrawable(String resource) { + return mLoadedIconPackResource.getIdentifier(resource, "drawable", mLoadedIconPackName); + } + + public Resources getIconPackResources() { + return mLoadedIconPackResource; + } + + public int getResourceIdForActivityIcon(ActivityInfo info) { + String drawable = mIconPackResources.get(info.packageName.toLowerCase() + + "." + info.name.toLowerCase()); + if (drawable == null) { + // Icon pack doesn't have an icon for the activity, fallback to package icon + drawable = mIconPackResources.get(info.packageName.toLowerCase()); + if (drawable == null) { + return 0; + } + } + return getResourceIdForDrawable(drawable); + } + + +} diff --git a/app/src/main/java/com/fastaccess/provider/icon/model/IconPackInfo.java b/app/src/main/java/com/fastaccess/provider/icon/model/IconPackInfo.java new file mode 100644 index 0000000..e4e155b --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/icon/model/IconPackInfo.java @@ -0,0 +1,28 @@ +package com.fastaccess.provider.icon.model; + +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.graphics.drawable.Drawable; + +/** + * Created by Kosh on 13/12/15 1:21 AM + */ +public class IconPackInfo { + public String packageName; + public CharSequence label; + public Drawable icon; + + private IconPackInfo() {} + + public IconPackInfo(ResolveInfo r, PackageManager packageManager) { + packageName = r.activityInfo.packageName; + icon = r.loadIcon(packageManager); + label = r.loadLabel(packageManager); + } + + public IconPackInfo(String label, Drawable icon, String packageName) { + this.label = label; + this.icon = icon; + this.packageName = packageName; + } +} diff --git a/app/src/main/java/com/fastaccess/provider/loader/DeviceAppsLoader.java b/app/src/main/java/com/fastaccess/provider/loader/DeviceAppsLoader.java new file mode 100644 index 0000000..24f78bc --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/loader/DeviceAppsLoader.java @@ -0,0 +1,110 @@ +package com.fastaccess.provider.loader; + + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.support.v4.content.AsyncTaskLoader; + +import com.fastaccess.App; +import com.fastaccess.BuildConfig; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.helper.AppHelper; +import com.fastaccess.provider.icon.IconCache; +import com.fastaccess.provider.receiver.ApplicationsReceiver; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DeviceAppsLoader extends AsyncTaskLoader> { + private ApplicationsReceiver mAppsObserver; + private final PackageManager packageManager; + private List appsModelList; + + public DeviceAppsLoader(Context ctx) { + super(ctx); + packageManager = getContext().getPackageManager(); + } + + @Override public List loadInBackground() { + try { + List entries = new ArrayList<>(); + Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); + List list = packageManager.queryIntentActivities(mainIntent, 0); + if (list == null || list.isEmpty()) { + return entries; + } + Collections.sort(list, new ResolveInfo.DisplayNameComparator(packageManager)); + String appPackage = BuildConfig.APPLICATION_ID; + IconCache iconCache = App.getInstance().getIconCache(); + for (ResolveInfo resolveInfo : list) { + if (!resolveInfo.activityInfo.applicationInfo.packageName.equalsIgnoreCase(appPackage)) { + AppsModel model = new AppsModel(); + model.setPackageName(resolveInfo.activityInfo.applicationInfo.packageName); + model.setActivityInfoName(resolveInfo.activityInfo.name); + iconCache.getTitleAndIcon(model, resolveInfo, null); + entries.add(model); + } + } + return entries; + } catch (Exception e) {//catching TransactionTooLargeException, + e.printStackTrace(); + return AppHelper.getInstalledPackages(getContext()); + } + } + + @Override public void deliverResult(List apps) { + if (isReset()) { + if (apps != null) { + return; + } + } + appsModelList = apps; + if (isStarted()) { + super.deliverResult(apps); + } + } + + @Override protected void onStartLoading() { + if (appsModelList != null && !appsModelList.isEmpty()) { + deliverResult(appsModelList); + } + if (mAppsObserver == null) { + mAppsObserver = new ApplicationsReceiver(this); + } + if (takeContentChanged()) { + forceLoad(); + } else if (appsModelList == null) { + forceLoad(); + } + + + } + + @Override protected void onStopLoading() { + cancelLoad(); + } + + @Override protected void onReset() { + onStopLoading(); + if (appsModelList != null) { + appsModelList = null; + } + if (mAppsObserver != null) { + getContext().unregisterReceiver(mAppsObserver); + mAppsObserver = null; + } + } + + @Override public void onCanceled(List apps) { + super.onCanceled(apps); + } + + @Override public void forceLoad() { + if (appsModelList != null) appsModelList.clear(); + super.forceLoad(); + } +} diff --git a/app/src/main/java/com/fastaccess/provider/loader/FoldersLoader.java b/app/src/main/java/com/fastaccess/provider/loader/FoldersLoader.java new file mode 100644 index 0000000..04f807a --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/loader/FoldersLoader.java @@ -0,0 +1,70 @@ +package com.fastaccess.provider.loader; + +import android.content.Context; +import android.support.v4.content.AsyncTaskLoader; + +import com.fastaccess.data.dao.FolderModel; + +import java.util.List; + +/** + * Created by Kosh on 11 Oct 2016, 7:37 PM + */ + +public class FoldersLoader extends AsyncTaskLoader> { + + private List folderModels; + + public FoldersLoader(Context context) { + super(context); + } + + @Override public List loadInBackground() { + return FolderModel.getFolders(); + } + + @Override public void deliverResult(List folders) { + if (isReset()) { + if (folders != null) { + return; + } + } + folderModels = folders; + if (isStarted()) { + super.deliverResult(folders); + } + } + + @Override protected void onStartLoading() { + if (folderModels != null) { + deliverResult(folderModels); + } + if (takeContentChanged()) { + forceLoad(); + } else if (folderModels == null) { + forceLoad(); + } + + + } + + @Override protected void onStopLoading() { + cancelLoad(); + } + + @Override protected void onReset() { + onStopLoading(); + if (folderModels != null) { + + folderModels = null; + } + } + + @Override public void onCanceled(List apps) { + super.onCanceled(apps); + } + + @Override public void forceLoad() { + super.forceLoad(); + } +} diff --git a/app/src/main/java/com/fastaccess/provider/loader/SelectedAppsLoader.java b/app/src/main/java/com/fastaccess/provider/loader/SelectedAppsLoader.java new file mode 100644 index 0000000..2a0c971 --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/loader/SelectedAppsLoader.java @@ -0,0 +1,104 @@ +package com.fastaccess.provider.loader; + + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.support.v4.content.AsyncTaskLoader; + +import com.fastaccess.App; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.provider.icon.IconCache; +import com.fastaccess.provider.receiver.ApplicationsReceiver; + +import java.util.ArrayList; +import java.util.List; + +public class SelectedAppsLoader extends AsyncTaskLoader> { + private ApplicationsReceiver mAppsObserver; + private final PackageManager packageManager; + private List appsModelList; + private long folderId = -1; + + public SelectedAppsLoader(Context ctx) { + super(ctx); + packageManager = getContext().getPackageManager(); + } + + public SelectedAppsLoader(Context ctx, long folderId) { + super(ctx); + this.folderId = folderId; + packageManager = getContext().getPackageManager(); + } + + @Override public List loadInBackground() { + List savedApps = folderId == -1 ? AppsModel.getApps() : AppsModel.getApps(folderId); + if (savedApps == null || savedApps.isEmpty()) return new ArrayList<>(); + IconCache iconCache = App.getInstance().getIconCache(); + for (AppsModel model : savedApps) { + Intent intent = new Intent(); + intent.setComponent(new ComponentName(model.getPackageName(), model.getActivityInfoName())); + ResolveInfo resolveInfo = packageManager.resolveActivity(intent, 0); + if (resolveInfo != null) { + iconCache.getTitleAndIcon(model, resolveInfo, null); + } else { + model.delete();//app is uninstalled! + } + } + return savedApps; + } + + @Override public void deliverResult(List apps) { + if (isReset()) { + if (apps != null) { + return; + } + } + appsModelList = apps; + if (isStarted()) { + super.deliverResult(apps); + } + } + + @Override protected void onStartLoading() { + if (appsModelList != null && !appsModelList.isEmpty()) { + deliverResult(appsModelList); + } + if (mAppsObserver == null) { + mAppsObserver = new ApplicationsReceiver(this); + } + if (takeContentChanged()) { + forceLoad(); + } else if (appsModelList == null) { + forceLoad(); + } + + + } + + @Override protected void onStopLoading() { + cancelLoad(); + } + + @Override protected void onReset() { + onStopLoading(); + if (appsModelList != null) { + appsModelList = null; + } + if (mAppsObserver != null) { + getContext().unregisterReceiver(mAppsObserver); + mAppsObserver = null; + } + } + + @Override public void onCanceled(List apps) { + super.onCanceled(apps); + } + + @Override public void forceLoad() { + if (appsModelList != null) appsModelList.clear(); + super.forceLoad(); + } +} diff --git a/app/src/main/java/com/fastaccess/provider/push/PushNotification.java b/app/src/main/java/com/fastaccess/provider/push/PushNotification.java new file mode 100644 index 0000000..ca31c6d --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/push/PushNotification.java @@ -0,0 +1,19 @@ +package com.fastaccess.provider.push; + +import com.fastaccess.R; +import com.fastaccess.helper.NotificationHelper; +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; + +/** + * Created by Kosh on 24 May 2016, 6:56 PM + */ +public class PushNotification extends FirebaseMessagingService { + @Override public void onMessageReceived(RemoteMessage remoteMessage) { + super.onMessageReceived(remoteMessage); + if (remoteMessage.getNotification() != null) { + NotificationHelper.notifyShort(this, remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(), R.drawable + .ic_fa); + } + } +} diff --git a/app/src/main/java/com/fastaccess/provider/receiver/ApplicationsReceiver.java b/app/src/main/java/com/fastaccess/provider/receiver/ApplicationsReceiver.java new file mode 100644 index 0000000..3be3004 --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/receiver/ApplicationsReceiver.java @@ -0,0 +1,39 @@ +package com.fastaccess.provider.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.support.v4.content.Loader; + +import static android.content.Intent.ACTION_PACKAGE_REMOVED; +import static android.content.Intent.ACTION_UNINSTALL_PACKAGE; + +/** + * Created by kosh on 18 Oct 2016, 9:33 PM + */ +public class ApplicationsReceiver extends BroadcastReceiver { + + private final static IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); + + static { + filter.addAction(ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_INSTALL_PACKAGE); + filter.addAction(ACTION_UNINSTALL_PACKAGE); + filter.addDataScheme("package"); + } + + private Loader loader; + + public ApplicationsReceiver(Loader loader) { + this.loader = loader; + this.loader.getContext().registerReceiver(this, filter); + } + + @Override public void onReceive(Context context, Intent intent) { + boolean isReplacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + if (isReplacing) return; + if (loader != null) loader.onContentChanged(); + } +} diff --git a/app/src/main/java/com/fastaccess/provider/receiver/BootReceiver.java b/app/src/main/java/com/fastaccess/provider/receiver/BootReceiver.java new file mode 100644 index 0000000..8e46132 --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/receiver/BootReceiver.java @@ -0,0 +1,20 @@ +package com.fastaccess.provider.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.fastaccess.helper.PermissionsHelper; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.provider.service.FloatingService; + +public class BootReceiver extends BroadcastReceiver { + @Override public void onReceive(Context context, Intent intent) { + if (PrefConstant.isAutoStart() && PermissionsHelper.isSystemAlertGranted(context)) { + if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { + Intent serviceIntent = new Intent(context, FloatingService.class); + context.startService(serviceIntent); + } + } + } +} diff --git a/app/src/main/java/com/fastaccess/provider/service/FloatingService.java b/app/src/main/java/com/fastaccess/provider/service/FloatingService.java new file mode 100644 index 0000000..a046f7a --- /dev/null +++ b/app/src/main/java/com/fastaccess/provider/service/FloatingService.java @@ -0,0 +1,71 @@ +package com.fastaccess.provider.service; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.IBinder; +import android.support.annotation.Nullable; + +import com.fastaccess.R; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.helper.NotificationHelper; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.ui.modules.floating.apps.FloatingVHView; +import com.fastaccess.ui.modules.floating.folders.FloatingFoldersView; +import com.fastaccess.ui.modules.main.MainView; + +/** + * Created by Kosh on 13 Oct 2016, 7:32 PM + */ + +public class FloatingService extends Service { + private FloatingVHView floatingVHView; + private FloatingFoldersView floatingFoldersView; + + @Override public void onCreate() { + super.onCreate(); + String floatingMode = PrefHelper.getString(PrefConstant.FLOATING_MODE); + if (!InputHelper.isEmpty(floatingMode)) { + switch (floatingMode) { + case "Apps": + floatingVHView = FloatingVHView.with(this, PrefConstant.isHorizontal()); + break; + case "Folders": + floatingFoldersView = FloatingFoldersView.with(this, PrefConstant.isHorizontal()); + break; + } + } else { + floatingVHView = FloatingVHView.with(this, PrefConstant.isHorizontal()); + } + startForeground(NotificationHelper.NOTIFICATION_ID, NotificationHelper.getNonCancellableNotification(this, + getString(R.string.app_name), getString(R.string.click_to_open_fa), + PrefHelper.getBoolean(PrefConstant.STATUS_BAR_HIDDEN) ? R.drawable.ic_notification : R.drawable.ic_fa_notification, + PendingIntent.getActivity(this, 0, new Intent(this, MainView.class), PendingIntent.FLAG_UPDATE_CURRENT))); + } + + @Nullable @Override public IBinder onBind(Intent intent) { + return null; + } + + @Override public int onStartCommand(Intent intent, int flags, int startId) { + super.onStartCommand(intent, flags, startId); + return START_STICKY; + } + + @Override public void onTaskRemoved(Intent rootIntent) { + PendingIntent service = PendingIntent.getService(getApplicationContext(), 1001, + new Intent(getApplicationContext(), FloatingService.class), PendingIntent.FLAG_ONE_SHOT); + AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 3000, service); + super.onTaskRemoved(rootIntent); + } + + @Override public void onDestroy() { + super.onDestroy(); + if (floatingVHView != null) floatingVHView.onDestroy(); + if (floatingFoldersView != null) floatingFoldersView.onDestroy(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/DeviceAppsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/DeviceAppsAdapter.java new file mode 100644 index 0000000..3844896 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/DeviceAppsAdapter.java @@ -0,0 +1,97 @@ +package com.fastaccess.ui.adapter; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.ViewGroup; +import android.widget.Filter; +import android.widget.Filterable; + +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.ui.adapter.viewholder.DeviceAppsViewHolder; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by Kosh on 30 Aug 2016, 11:42 PM + */ + +public class DeviceAppsAdapter extends BaseRecyclerAdapter> implements Filterable { + private Map selection; + + public DeviceAppsAdapter(@NonNull List data, @Nullable DeviceAppsViewHolder.OnItemClickListener listener, + Map selection) { + super(data, listener); + this.selection = selection; + } + + @Override protected DeviceAppsViewHolder viewHolder(ViewGroup parent, int viewType) { + return new DeviceAppsViewHolder(BaseViewHolder.getView(parent, R.layout.app_row_item), this); + } + + @Override protected void onBindView(DeviceAppsViewHolder holder, int position) { + AppsModel model = getItem(position); + if (model != null) { + holder.bind(model, isSelected(model.getComponentName().toShortString())); + } + } + + public void select(String packageName, int position, boolean select) { + if (select) selection.put(packageName, getItem(position)); + else selection.remove(packageName); + notifyItemChanged(position); + } + + public boolean isSelected(@NonNull String packageName) { + return selection.get(packageName) != null; + } + + public boolean hasSelection() { + return selection != null && !selection.isEmpty(); + } + + public void clearSelection() { + if (hasSelection()) selection.clear(); + notifyDataSetChanged(); + } + + public int selectionSize() { + return selection != null ? selection.size() : 0; + } + + public List getSelections() { + return new ArrayList<>(selection.values()); + } + + @Override public Filter getFilter() { + return new Filter() { + @Override protected FilterResults performFiltering(CharSequence charSequence) { + final FilterResults oReturn = new FilterResults(); + final List results = new ArrayList<>(); + if (!InputHelper.isEmpty(charSequence)) { + if (!getData().isEmpty()) { + for (AppsModel appInfo : getData()) { + if (appInfo.getAppName().toLowerCase().contains(charSequence.toString())) { + results.add(appInfo); + } + } + } + oReturn.values = results; + oReturn.count = results.size(); + } + return oReturn; + } + + @Override protected void publishResults(CharSequence constraint, FilterResults results) { + insertItems((List) results.values); + } + }; + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/FloatingAppsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/FloatingAppsAdapter.java new file mode 100644 index 0000000..a05b123 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/FloatingAppsAdapter.java @@ -0,0 +1,39 @@ +package com.fastaccess.ui.adapter; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.ViewGroup; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.adapter.viewholder.FloatingAppsViewHolder; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; + +import java.util.List; + +/** + * Created by Kosh on 30 Aug 2016, 11:42 PM + */ + +public class FloatingAppsAdapter extends BaseRecyclerAdapter> { + + private boolean isHorizontal; + + public FloatingAppsAdapter(@NonNull List data, + @Nullable FloatingAppsViewHolder.OnItemClickListener listener, boolean isHorizontal) { + super(data, listener); + this.isHorizontal = isHorizontal; + } + + @Override protected FloatingAppsViewHolder viewHolder(ViewGroup parent, int viewType) { + return FloatingAppsViewHolder.newInstance(parent, this); + } + + @Override protected void onBindView(FloatingAppsViewHolder holder, int position) { + AppsModel model = getItem(position); + if (model != null) { + holder.bind(model, isHorizontal); + } + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/FloatingFoldersAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/FloatingFoldersAdapter.java new file mode 100644 index 0000000..17eefa3 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/FloatingFoldersAdapter.java @@ -0,0 +1,39 @@ +package com.fastaccess.ui.adapter; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.ViewGroup; + +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.ui.adapter.viewholder.FloatingFoldersViewHolder; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; + +import java.util.List; + +/** + * Created by Kosh on 30 Aug 2016, 11:42 PM + */ + +public class FloatingFoldersAdapter extends BaseRecyclerAdapter> { + + private boolean isHorizontal; + + public FloatingFoldersAdapter(@NonNull List data, @Nullable FloatingFoldersViewHolder.OnItemClickListener listener, + boolean isHorizontal) { + super(data, listener); + this.isHorizontal = isHorizontal; + } + + @Override protected FloatingFoldersViewHolder viewHolder(ViewGroup parent, int viewType) { + return FloatingFoldersViewHolder.newInstance(parent, this); + } + + @Override protected void onBindView(FloatingFoldersViewHolder holder, int position) { + FolderModel model = getItem(position); + if (model != null) { + holder.bind(model, isHorizontal); + } + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/FoldersAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/FoldersAdapter.java new file mode 100644 index 0000000..278393d --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/FoldersAdapter.java @@ -0,0 +1,59 @@ +package com.fastaccess.ui.adapter; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.ViewGroup; +import android.widget.Filter; +import android.widget.Filterable; + +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.ui.adapter.viewholder.FoldersViewHolder; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Kosh on 11 Oct 2016, 7:58 PM + */ + +public class FoldersAdapter extends BaseRecyclerAdapter> implements Filterable { + public FoldersAdapter(@NonNull List data, @Nullable FoldersViewHolder.OnItemClickListener listener) { + super(data, listener); + } + + @Override protected FoldersViewHolder viewHolder(ViewGroup parent, int viewType) { + return FoldersViewHolder.newInstance(parent, this); + } + + @Override protected void onBindView(FoldersViewHolder holder, int position) { + holder.bind(getItem(position)); + } + + @Override public Filter getFilter() { + return new Filter() { + @Override protected FilterResults performFiltering(CharSequence charSequence) { + final FilterResults oReturn = new FilterResults(); + final List results = new ArrayList<>(); + if (!InputHelper.isEmpty(charSequence)) { + if (!getData().isEmpty()) { + for (FolderModel folder : getData()) { + if (folder.getFolderName().toLowerCase().contains(charSequence.toString())) { + results.add(folder); + } + } + } + oReturn.values = results; + oReturn.count = results.size(); + } + return oReturn; + } + + @Override protected void publishResults(CharSequence constraint, FilterResults results) { + insertItems((List) results.values); + } + }; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/SelectFolderAppsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/SelectFolderAppsAdapter.java new file mode 100644 index 0000000..d5f666d --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/SelectFolderAppsAdapter.java @@ -0,0 +1,64 @@ +package com.fastaccess.ui.adapter; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.ViewGroup; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.adapter.viewholder.SelectFolderAppsViewHolder; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by Kosh on 30 Aug 2016, 11:42 PM + */ + +public class SelectFolderAppsAdapter extends BaseRecyclerAdapter> { + private Map selection; + + public SelectFolderAppsAdapter(@NonNull List data, @Nullable SelectFolderAppsViewHolder.OnItemClickListener listener, + Map selection) { + super(data, listener); + this.selection = selection; + } + + @Override protected SelectFolderAppsViewHolder viewHolder(ViewGroup parent, int viewType) { + return SelectFolderAppsViewHolder.newInstance(parent, this); + } + + @Override protected void onBindView(SelectFolderAppsViewHolder holder, int position) { + AppsModel model = getItem(position); + holder.bind(model, isSelected(model.getActivityInfoName())); + } + + public void select(String packageName, int position, boolean select) { + if (select) selection.put(packageName, getItem(position)); + else selection.remove(packageName); + notifyItemChanged(position); + } + + public boolean isSelected(@NonNull String packageName) { + return selection.get(packageName) != null; + } + + public boolean hasSelection() { + return selection != null && !selection.isEmpty(); + } + + public void clearSelection() { + if (hasSelection()) selection.clear(); + notifyDataSetChanged(); + } + + public int selectionSize() { + return selection != null ? selection.size() : 0; + } + + public List getSelections() { + return new ArrayList<>(selection.values()); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/AppDrawerHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/AppDrawerHolder.java new file mode 100644 index 0000000..ce621b7 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/AppDrawerHolder.java @@ -0,0 +1,43 @@ +package com.fastaccess.ui.adapter.viewholder; + +import android.view.MotionEvent; +import android.view.View; + +import com.fastaccess.R; +import com.fastaccess.ui.modules.floating.folders.drawer.FloatingDrawerMvp; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.floating.FloatingLayout; +import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnTouch; +import butterknife.Unbinder; + +public class AppDrawerHolder { + @BindView(R.id.appDrawer) public FloatingLayout appDrawer; + @BindView(R.id.recycler) public DynamicRecyclerView recycler; + @BindView(R.id.empty_text) public FontTextView emptyText; + private FloatingDrawerMvp.View viewCallback; + private Unbinder unbinder; + + @OnTouch(R.id.appDrawer) boolean onTouch(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { + if (viewCallback != null) viewCallback.onTouchedOutside(); + } + return false; + } + + public AppDrawerHolder(View view, FloatingDrawerMvp.View viewCallback) { + this.viewCallback = viewCallback; + unbinder = ButterKnife.bind(this, view); + appDrawer.setViewCallback(viewCallback); + } + + public void onDestroy() { + appDrawer.setViewCallback(null); + viewCallback = null; + if (unbinder != null) unbinder.unbind(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/DeviceAppsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/DeviceAppsViewHolder.java new file mode 100644 index 0000000..0e011c6 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/DeviceAppsViewHolder.java @@ -0,0 +1,60 @@ +package com.fastaccess.ui.adapter.viewholder; + +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; +import android.support.v7.widget.CardView; +import android.view.View; +import android.widget.ImageView; + +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.widgets.FastBitmapDrawable; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; +import com.fastaccess.ui.widgets.recyclerview.touch.ItemTouchHelperViewHolder; + +import butterknife.BindView; + +/** + * Created by Kosh on 30 Aug 2016, 11:42 PM + */ + +public class DeviceAppsViewHolder extends BaseViewHolder implements ItemTouchHelperViewHolder { + @BindView(R.id.appIcon) ImageView appIcon; + @BindView(R.id.cardView) CardView cardView; + @ColorInt private int selectedColor; + @ColorInt private int normalColor; + private boolean selected; + + public DeviceAppsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { + super(itemView, adapter); + selectedColor = ActivityCompat.getColor(itemView.getContext(), R.color.light_gray); + normalColor = ActivityCompat.getColor(itemView.getContext(), R.color.cardview_light_background); + appIcon.setOnClickListener(this); + appIcon.setOnLongClickListener(this); + } + + public void bind(@NonNull AppsModel model, boolean selected) { + this.selected = selected; + bind(model); + } + + @Override public void bind(@NonNull AppsModel model) { + FastBitmapDrawable drawable = new FastBitmapDrawable(model.getBitmap()); + appIcon.setImageDrawable(drawable); + appIcon.setContentDescription(model.getAppName()); + drawable.setGhostModeEnabled(selected); + drawable.setPressed(selected); + cardView.setCardBackgroundColor(selected ? selectedColor : normalColor); + } + + @Override public void onItemSelected() { + cardView.setAlpha(0.5f); + } + + @Override public void onItemClear() { + cardView.setAlpha(1); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingAppsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingAppsViewHolder.java new file mode 100644 index 0000000..bb3ffb9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingAppsViewHolder.java @@ -0,0 +1,70 @@ +package com.fastaccess.ui.adapter.viewholder; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.ui.widgets.FastBitmapDrawable; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import butterknife.BindView; +import butterknife.OnTouch; + +/** + * Created by Kosh on 30 Aug 2016, 11:42 PM + */ + +public class FloatingAppsViewHolder extends BaseViewHolder { + + @BindView(R.id.imageIcon) ImageView imageIcon; + @BindView(R.id.iconHolder) RelativeLayout iconHolder; + private boolean isHorizontal; + + @OnTouch(R.id.imageIcon) boolean onTouch(MotionEvent event) { + FastBitmapDrawable drawable = (FastBitmapDrawable) imageIcon.getDrawable(); + if (drawable != null) { + if (event.getAction() == MotionEvent.ACTION_UP || + event.getAction() == MotionEvent.ACTION_CANCEL) { + drawable.setPressed(false); + } else if (event.getAction() == MotionEvent.ACTION_DOWN) { + drawable.setPressed(true); + } + } + return false; + } + + public static FloatingAppsViewHolder newInstance(@NonNull ViewGroup parent, @NonNull BaseRecyclerAdapter adapter) { + return new FloatingAppsViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.floating_apps_row_item, parent, false), adapter); + } + + public FloatingAppsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { + super(itemView, adapter); + iconHolder.setOnClickListener(null); + iconHolder.setOnLongClickListener(null); + imageIcon.setOnClickListener(this); + imageIcon.setOnLongClickListener(this); + } + + public void bind(@NonNull AppsModel model, boolean isHorizontal) { + this.isHorizontal = isHorizontal; + bind(model); + } + + @Override public void bind(@NonNull AppsModel model) { + imageIcon.setImageDrawable(new FastBitmapDrawable(model.getBitmap())); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) imageIcon.getLayoutParams(); + int gap = PrefConstant.getGapSize(imageIcon.getResources()); + if (!isHorizontal) params.setMargins(0, 0, 0, gap); + else params.setMargins(0, 0, gap, 0); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingFoldersViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingFoldersViewHolder.java new file mode 100644 index 0000000..c444afd --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingFoldersViewHolder.java @@ -0,0 +1,63 @@ +package com.fastaccess.ui.adapter.viewholder; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import com.amulyakhare.textdrawable.TextDrawable; +import com.amulyakhare.textdrawable.util.ColorGenerator; +import com.fastaccess.R; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import butterknife.BindView; + +/** + * Created by Kosh on 11 Oct 2016, 7:47 PM + */ + +public class FloatingFoldersViewHolder extends BaseViewHolder { + + @BindView(R.id.imageIcon) ImageView imageIcon; + @BindView(R.id.iconHolder) RelativeLayout iconHolder; + private boolean isHorizontal; + + public static FloatingFoldersViewHolder newInstance(@NonNull ViewGroup parent, @NonNull BaseRecyclerAdapter adapter) { + return new FloatingFoldersViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.floating_apps_row_item, parent, false), + adapter); + } + + public FloatingFoldersViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { + super(itemView, adapter); + iconHolder.setOnClickListener(null); + iconHolder.setOnLongClickListener(null); + imageIcon.setOnClickListener(this); + imageIcon.setOnLongClickListener(this); + } + + public void bind(@NonNull FolderModel model, boolean isHorizontal) { + this.isHorizontal = isHorizontal; + bind((model)); + } + + @Override public void bind(@NonNull FolderModel folderModel) { + TextDrawable.IBuilder builder = TextDrawable.builder() + .beginConfig() + .endConfig() + .round(); + String letter = InputHelper.getTwoLetters(folderModel.getFolderName()); + int color = folderModel.getColor() == 0 ? ColorGenerator.MATERIAL.getRandomColor() : folderModel.getColor(); + imageIcon.setImageDrawable(builder.build(letter.toUpperCase(), color)); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) imageIcon.getLayoutParams(); + int gap = PrefConstant.getGapSize(imageIcon.getResources()); + if (!isHorizontal) params.setMargins(0, 0, 0, gap); + else params.setMargins(0, 0, gap, 0); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingWindowsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingWindowsViewHolder.java new file mode 100644 index 0000000..a6dbb76 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FloatingWindowsViewHolder.java @@ -0,0 +1,66 @@ +package com.fastaccess.ui.adapter.viewholder; + +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; + +import com.fastaccess.R; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.ui.modules.floating.BaseFloatingMvp; +import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import butterknife.OnTouch; +import butterknife.Unbinder; + +/** + * Created by Kosh on 15 Oct 2016, 2:43 AM + */ + +public class FloatingWindowsViewHolder { + + private BaseFloatingMvp.BaseView callback; + private Unbinder unbinder; + + @BindView(R.id.toggleTapBar) public ImageView toggleTapBar; + @BindView(R.id.recycler) public DynamicRecyclerView recycler; + @BindView(R.id.tabBar) public View tabBar; + + @OnTouch(R.id.tabBar) boolean onTouch(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { + if (callback != null) callback.onTouchedOutside(); + } + return false; + } + + @OnClick(R.id.toggleTapBar) void onToggle() { + if (callback != null) callback.onToggleVisibility(true); + } + + public FloatingWindowsViewHolder(@NonNull View view, @NonNull BaseFloatingMvp.BaseView callback) { + this.callback = callback; + unbinder = ButterKnife.bind(this, view); + onSetupBackground(); + } + + public void onSetupBackground() { + int bgColor = PrefHelper.getInt(PrefConstant.FA_BACKGROUND); + int bgAlpha = PrefHelper.getInt(PrefConstant.FA_BACKGROUND_ALPHA); + Drawable drawable = new ColorDrawable(bgColor == 0 ? Color.TRANSPARENT : bgColor); + drawable.setAlpha(bgAlpha == 0 ? 255 : bgAlpha); + tabBar.setBackground(drawable); + } + + public void onDestroy() { + callback = null; + callback = null; + if (unbinder != null) unbinder.unbind(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FoldersViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FoldersViewHolder.java new file mode 100644 index 0000000..db7e01c --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FoldersViewHolder.java @@ -0,0 +1,62 @@ +package com.fastaccess.ui.adapter.viewholder; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.amulyakhare.textdrawable.TextDrawable; +import com.amulyakhare.textdrawable.util.ColorGenerator; +import com.fastaccess.R; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import butterknife.BindView; + +/** + * Created by Kosh on 11 Oct 2016, 7:47 PM + */ + +public class FoldersViewHolder extends BaseViewHolder { + + @BindView(R.id.folderImage) ImageView folderImage; + @BindView(R.id.folderName) FontTextView folderName; + @BindView(R.id.appsCount) FontTextView appsCount; + @BindView(R.id.addApps) View addApps; + @BindView(R.id.delete) View delete; + @BindView(R.id.editFolder) View editFolder; + + public static FoldersViewHolder newInstance(@NonNull ViewGroup parent, @NonNull BaseRecyclerAdapter adapter) { + return new FoldersViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.folder_row_item, parent, false), adapter); + } + + public FoldersViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { + super(itemView, adapter); + folderImage.setOnClickListener(this); + folderImage.setOnLongClickListener(this); + addApps.setOnClickListener(this); + addApps.setOnLongClickListener(this); + editFolder.setOnClickListener(this); + editFolder.setOnLongClickListener(this); + delete.setOnClickListener(this); + delete.setOnLongClickListener(this); + } + + @Override public void bind(@NonNull FolderModel folderModel) { + folderName.setText(folderModel.getFolderName()); + appsCount.setText(String.valueOf(folderModel.getAppsCount())); + folderImage.setContentDescription(folderModel.getFolderName()); + TextDrawable.IBuilder builder = TextDrawable.builder() + .beginConfig() + .endConfig() + .round(); + String letter = InputHelper.getTwoLetters(folderModel.getFolderName()); + int color = folderModel.getColor() == 0 ? ColorGenerator.MATERIAL.getRandomColor() : folderModel.getColor(); + folderImage.setImageDrawable(builder.build(letter.toUpperCase(), color)); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SelectFolderAppsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SelectFolderAppsViewHolder.java new file mode 100644 index 0000000..5668f83 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SelectFolderAppsViewHolder.java @@ -0,0 +1,49 @@ +package com.fastaccess.ui.adapter.viewholder; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.widgets.FontCheckbox; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import butterknife.BindView; + +/** + * Created by Kosh on 30 Aug 2016, 11:42 PM + */ + +public class SelectFolderAppsViewHolder extends BaseViewHolder { + @BindView(R.id.appIcon) ImageView appIcon; + @BindView(R.id.appName) FontTextView appName; + @BindView(R.id.checkbox) FontCheckbox checkbox; + private boolean selected; + + public static SelectFolderAppsViewHolder newInstance(@NonNull ViewGroup parent, @NonNull BaseRecyclerAdapter adapter) { + return new SelectFolderAppsViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.select_apps_folder_row, parent, false), adapter); + } + + public SelectFolderAppsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { + super(itemView, adapter); + } + + public void bind(@NonNull AppsModel model, boolean selected) { + this.selected = selected; + bind(model); + } + + @Override public void bind(@NonNull AppsModel model) { + appName.setText(model.getAppName()); + appIcon.setImageBitmap(model.getBitmap()); + appIcon.setContentDescription(model.getAppName()); + checkbox.setChecked(selected); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java new file mode 100644 index 0000000..d519354 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java @@ -0,0 +1,126 @@ +package com.fastaccess.ui.base; + +import android.os.Bundle; +import android.support.annotation.DrawableRes; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.MenuItem; +import android.view.View; + +import com.fastaccess.BuildConfig; +import com.fastaccess.R; +import com.fastaccess.helper.AppHelper; +import com.fastaccess.helper.ViewHelper; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; +import com.fastaccess.ui.widgets.dialog.MessageDialogView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import icepick.Icepick; + +/** + * Created by Kosh on 24 May 2016, 8:48 PM + */ + +public abstract class BaseActivity> extends AppCompatActivity implements + MessageDialogView.MessageDialogViewActionCallback { + + @LayoutRes protected abstract int layout(); + + @Nullable @BindView(R.id.toolbar) Toolbar toolbar; + + @NonNull protected abstract P getPresenter(); + + protected abstract boolean isTransparent(); + + protected abstract boolean canBack(); + + @Override protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + Icepick.saveInstanceState(this, outState); + } + + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (layout() != 0) { + setContentView(layout()); + ButterKnife.bind(this); + } + Icepick.setDebug(BuildConfig.DEBUG); + if (savedInstanceState != null && !savedInstanceState.isEmpty()) { + Icepick.restoreInstanceState(this, savedInstanceState); + } + setupToolbarAndStatusBar(); +// if (PermissionHelper.declinedPermissions(this.getApplicationContext(), PermissionActivity.PERMISSIONS).length != 0) { +// startActivity(new Intent(this, PermissionActivity.class)); +// finish(); +// return; +// } + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { + if (canBack()) { + if (item.getItemId() == android.R.id.home) { + supportFinishAfterTransition(); + } + } + return super.onOptionsItemSelected(item); + } + + @Override protected void onDestroy() { + //noinspection ConstantConditions + if (getPresenter() != null) getPresenter().onDestroy(); + super.onDestroy(); + } + + @Override public void onDialogDismissed() { + + }//pass + + @Override public void onMessageDialogActionClicked(boolean isOk, int requestCode) { + + }//pass + + private void setupToolbarAndStatusBar() { + if (AppHelper.isLollipopOrHigher()) { + changeAppColor(); + } + if (toolbar != null) { + setSupportActionBar(toolbar); + if (canBack()) { + if (getSupportActionBar() != null) { + if (toolbar != null) { + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + supportFinishAfterTransition(); + } + }); + } + getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_back); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + } + } + } + + protected void setToolbarIcon(@DrawableRes int res) { + if (getSupportActionBar() != null) { + getSupportActionBar().setHomeAsUpIndicator(res); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + } + + private void changeAppColor() { + if (AppHelper.isLollipopOrHigher()) { + if (!isTransparent()) { + getWindow().setStatusBarColor(ViewHelper.getPrimaryDarkColor(this)); + } else { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + } + } + } +} diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseBottomSheetDialog.java b/app/src/main/java/com/fastaccess/ui/base/BaseBottomSheetDialog.java new file mode 100644 index 0000000..456a338 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/base/BaseBottomSheetDialog.java @@ -0,0 +1,123 @@ +package com.fastaccess.ui.base; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.BottomSheetDialogFragment; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; + +import com.fastaccess.helper.Logger; +import com.fastaccess.helper.ViewHelper; + +import butterknife.ButterKnife; +import butterknife.Unbinder; +import icepick.Icepick; + +/** + * Created by Kosh on 16 Sep 2016, 2:11 PM + */ + +public abstract class BaseBottomSheetDialog extends BottomSheetDialogFragment { + + protected BottomSheetBehavior bottomSheetBehavior; + protected boolean isAlreadyHidden; + @Nullable private Unbinder unbinder; + + @LayoutRes protected abstract int layoutRes(); + + protected abstract void onViewCreated(@NonNull View view); + + @Override public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + Icepick.saveInstanceState(this, outState); + } + + @Override public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null && !savedInstanceState.isEmpty()) { + Icepick.restoreInstanceState(this, savedInstanceState); + } + } + + @Override public void setupDialog(Dialog dialog, int style) { + super.setupDialog(dialog, style); + View contentView = View.inflate(getContext(), layoutRes(), null); + dialog.setContentView(contentView); + View parent = ((View) contentView.getParent()); + bottomSheetBehavior = BottomSheetBehavior.from(parent); + if (bottomSheetBehavior != null) { + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); + bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { + @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { + if (newState == BottomSheetBehavior.STATE_HIDDEN) { + isAlreadyHidden = true; + onHidden(); + } + } + + @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { + if (slideOffset == -1.0) { + isAlreadyHidden = true; + onDismissedByScrolling(); + } + } + }); + } + unbinder = ButterKnife.bind(this, contentView); + onViewCreated(contentView); + } + + @Override public void onDestroyView() { + super.onDestroyView(); + if (unbinder != null) unbinder.unbind(); + } + + @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + final Dialog dialog = super.onCreateDialog(savedInstanceState); + if (ViewHelper.isTablet(getContext())) { + dialog.setOnShowListener(new DialogInterface.OnShowListener() { + @Override public void onShow(DialogInterface dialogINterface) { + if (dialog.getWindow() != null) dialog.getWindow().setLayout( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.MATCH_PARENT); + } + }); + } + dialog.setOnKeyListener(new DialogInterface.OnKeyListener() { + @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + isAlreadyHidden = true; + onDismissedByScrolling(); + } + return false; + } + }); + + return dialog; + } + + @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + Logger.e(); + } + + @Override public void onDetach() { + if (!isAlreadyHidden) { + onDismissedByScrolling(); + } + super.onDetach(); + } + + protected void onHidden() { + dismiss(); + } + + protected void onDismissedByScrolling() {} + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseFragment.java b/app/src/main/java/com/fastaccess/ui/base/BaseFragment.java new file mode 100644 index 0000000..05454a9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/base/BaseFragment.java @@ -0,0 +1,76 @@ +package com.fastaccess.ui.base; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +import butterknife.ButterKnife; +import butterknife.Unbinder; +import icepick.Icepick; + +/** + * Created by Kosh on 27 May 2016, 7:54 PM + */ + +public abstract class BaseFragment> extends Fragment { + + @Nullable private Unbinder unbinder; + + @LayoutRes protected abstract int fragmentLayout(); + + @NonNull protected abstract P getPresenter(); + + protected abstract void onFragmentCreated(View view, @Nullable Bundle savedInstanceState); + + @Override public void onAttach(Context context) { + super.onAttach(context); + } + + @Override public void onDetach() { + super.onDetach(); + } + + @Override public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + Icepick.saveInstanceState(this, outState); + } + + @Override public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null && !savedInstanceState.isEmpty()) { + Icepick.restoreInstanceState(this, savedInstanceState); + } + } + + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (fragmentLayout() != 0) { + View view = inflater.inflate(fragmentLayout(), container, false); + unbinder = ButterKnife.bind(this, view); + return view; + } + return super.onCreateView(inflater, container, savedInstanceState); + } + + @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + onFragmentCreated(view, savedInstanceState); + } + + @Override public void onDestroyView() { + getPresenter().onDestroy(); + super.onDestroyView(); + if (unbinder != null) unbinder.unbind(); + } + + protected boolean isSafe() { + return getView() != null && getActivity() != null && !getActivity().isFinishing(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/base/mvp/BaseMvp.java b/app/src/main/java/com/fastaccess/ui/base/mvp/BaseMvp.java new file mode 100644 index 0000000..348534c --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/base/mvp/BaseMvp.java @@ -0,0 +1,14 @@ +package com.fastaccess.ui.base.mvp; + +/** + * Created by Kosh on 25 May 2016, 9:09 PM + */ + +public interface BaseMvp { + + interface FAPresenter { + void attachView(V view); + + void onDestroy(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/base/mvp/presenter/BasePresenter.java b/app/src/main/java/com/fastaccess/ui/base/mvp/presenter/BasePresenter.java new file mode 100644 index 0000000..6b331b8 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/base/mvp/presenter/BasePresenter.java @@ -0,0 +1,42 @@ +package com.fastaccess.ui.base.mvp.presenter; + +import android.support.annotation.NonNull; + +import com.fastaccess.ui.base.mvp.BaseMvp; + +/** + * Created by Kosh on 25 May 2016, 9:12 PM + */ + +public class BasePresenter implements BaseMvp.FAPresenter { + + private V view; + + private BasePresenter() {throw new RuntimeException("Cant not be initialized");} + + protected BasePresenter(@NonNull V view) { + attachView(view); + } + + @Override public void attachView(@NonNull V view) { + this.view = view; + } + + @Override public void onDestroy() { + view = null; + } + + protected boolean isAttached() { + return view != null; + } + + protected V getView() { + checkViewAttached(); + return view; + } + + private void checkViewAttached() { + if (!isAttached()) throw new NullPointerException("View is not injected to presenter"); + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsMvp.java new file mode 100644 index 0000000..fb3740a --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsMvp.java @@ -0,0 +1,46 @@ +package com.fastaccess.ui.modules.apps.device; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.LoaderManager; +import android.support.v7.view.ActionMode; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import java.util.List; + +/** + * Created by Kosh on 10 Oct 2016, 11:40 PM + */ + +public interface DeviceAppsMvp { + + interface View { + void onStartLoading(); + + void onAppsLoaded(@Nullable List data); + + void onLoaderReset(); + + void setSelection(@NonNull String componentName, int position); + + boolean hasSelection(); + + void onActionModeDestroyed(); + + void onOpenAppDetails(@NonNull android.view.View view, @NonNull AppsModel appsModel); + + void onAddSelectedApps(); + + void onFilter(@Nullable String text); + + void onSelectAll(); + } + + interface Presenter extends LoaderManager.LoaderCallbacks>, + BaseViewHolder.OnItemClickListener, + ActionMode.Callback { + void onAddSelectedApps(@Nullable List selections); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsPresenter.java new file mode 100644 index 0000000..aa2e0ca --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsPresenter.java @@ -0,0 +1,104 @@ +package com.fastaccess.ui.modules.apps.device; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.Loader; +import android.support.v7.view.ActionMode; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +import com.fastaccess.App; +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.data.dao.FloatingEventModel; +import com.fastaccess.data.dao.SelectedAppsEventModel; +import com.fastaccess.helper.Logger; +import com.fastaccess.provider.loader.DeviceAppsLoader; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +import org.greenrobot.eventbus.EventBus; + +import java.util.List; + +/** + * Created by Kosh on 10 Oct 2016, 11:45 PM + */ + +public class DeviceAppsPresenter extends BasePresenter implements DeviceAppsMvp.Presenter { + + protected DeviceAppsPresenter(@NonNull DeviceAppsMvp.View view) { + super(view); + } + + public static DeviceAppsPresenter with(@NonNull DeviceAppsMvp.View view) { + return new DeviceAppsPresenter(view); + } + + @Override public Loader> onCreateLoader(int id, Bundle args) { + if (isAttached()) getView().onStartLoading(); + return new DeviceAppsLoader(App.getInstance().getApplicationContext()); + } + + @Override public void onLoadFinished(Loader> loader, List data) { + getView().onAppsLoaded(data); + } + + @Override public void onLoaderReset(Loader> loader) { + if (isAttached()) getView().onLoaderReset(); + } + + @Override public void onItemClick(int position, View v, AppsModel item) { + if (getView().hasSelection()) { + onItemLongClick(position, v, item); + } else { + getView().onOpenAppDetails(v, item); + } + } + + @Override public void onItemLongClick(int position, View v, AppsModel item) { + getView().setSelection(item.getComponentName().toShortString(), position); + } + + @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mode.getMenuInflater().inflate(R.menu.add_menu, menu); + return true; + } + + @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + + @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + if (item.getItemId() == R.id.add) { + getView().onAddSelectedApps(); + return true; + } else if (item.getItemId() == R.id.selectAll) { + getView().onSelectAll(); + return true; + } + return false; + } + + @Override public void onDestroyActionMode(ActionMode mode) { + getView().onActionModeDestroyed(); + } + + @Override public void onAddSelectedApps(@Nullable List selections) { + if (selections != null && !selections.isEmpty()) { + for (int i = 0; i < selections.size(); i++) { + AppsModel model = selections.get(i); + if (AppsModel.exists(model.getActivityInfoName(), model.getPackageName())) { + continue; + } + int lastPosition = AppsModel.lastPosition() + 1; + Logger.e(lastPosition); + model.setIndexPosition(lastPosition); + model.save(); + } + EventBus.getDefault().post(new SelectedAppsEventModel()); + EventBus.getDefault().post(new FloatingEventModel()); + } + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsView.java b/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsView.java new file mode 100644 index 0000000..30829a9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/device/DeviceAppsView.java @@ -0,0 +1,167 @@ +package com.fastaccess.ui.modules.apps.device; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.Loader; +import android.support.v4.widget.NestedScrollView; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.view.ActionMode; +import android.view.View; + +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.data.dao.DeviceAppsEventModel; +import com.fastaccess.data.dao.ThemePackEventModel; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.ui.adapter.DeviceAppsAdapter; +import com.fastaccess.ui.base.BaseFragment; +import com.fastaccess.ui.modules.main.MainMvp; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; +import com.mikhaellopez.circularfillableloaders.CircularFillableLoaders; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +import butterknife.BindView; +import icepick.State; + +/** + * Created by Kosh on 10 Oct 2016, 11:47 PM + */ + +public class DeviceAppsView extends BaseFragment implements DeviceAppsMvp.View { + public static final String TAG = "DeviceAppsView"; + @BindView(R.id.recycler) DynamicRecyclerView recycler; + @BindView(R.id.empty_text) FontTextView emptyText; + @BindView(R.id.empty) NestedScrollView empty; + @BindView(R.id.progressBar) CircularFillableLoaders progressBar; + @State HashMap selection = new LinkedHashMap<>(); + private DeviceAppsPresenter presenter; + private DeviceAppsAdapter adapter; + private ActionMode actionMode; + private Loader loader; + private MainMvp.View mainCallback; + + public static DeviceAppsView newInstance() { + return new DeviceAppsView(); + } + + @Override public void onAttach(Context context) { + super.onAttach(context); + if (!(context instanceof MainMvp.View)) { + throw new RuntimeException(context.getClass().getSimpleName() + " is not implementing MainMvp.View"); + } + mainCallback = (MainMvp.View) context; + EventBus.getDefault().register(this); + } + + @Override public void onDetach() { + super.onDetach(); + EventBus.getDefault().unregister(this); + mainCallback = null; + } + + @Override protected int fragmentLayout() { + return R.layout.grid_list; + } + + @NonNull @Override protected DeviceAppsPresenter getPresenter() { + if (presenter == null) { + presenter = DeviceAppsPresenter.with(this); + } + return presenter; + } + + @Override protected void onFragmentCreated(View view, @Nullable Bundle savedInstanceState) { + recycler.setEmptyView(empty); + adapter = new DeviceAppsAdapter(new ArrayList(), getPresenter(), selection); + recycler.setAdapter(adapter); + loader = getLoaderManager().initLoader(0, null, getPresenter()); + if (!selection.isEmpty()) { + actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(getPresenter()); + actionMode.setTitle(getString(R.string.selected) + " ( " + adapter.selectionSize() + " )"); + } + } + + @Override public void onStartLoading() { + recycler.showProgress(progressBar); + } + + @Override public void onAppsLoaded(@Nullable List data) { + recycler.hideProgress(progressBar); + if (data != null) adapter.insertItems(data); + else adapter.clear(); + } + + @Override public void onLoaderReset() { + recycler.hideProgress(progressBar); + adapter.clear(); + } + + @Override public void setSelection(@NonNull String packageName, int position) { + adapter.select(packageName, position, !adapter.isSelected(packageName)); + if (hasSelection()) { + if (actionMode == null) { + actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(getPresenter()); + } + actionMode.setTitle(getString(R.string.selected) + " ( " + adapter.selectionSize() + " )"); + } else { + actionMode.finish(); + } + } + + @Override public boolean hasSelection() { + return adapter.hasSelection(); + } + + @Override public void onActionModeDestroyed() { + adapter.clearSelection(); + actionMode = null; + } + + @Override public void onOpenAppDetails(@NonNull View view, @NonNull AppsModel appsModel) { + + } + + @Override public void onAddSelectedApps() { + getPresenter().onAddSelectedApps(adapter.getSelections()); + if (actionMode != null) actionMode.finish(); + if (mainCallback != null) mainCallback.onShowBadge(R.id.selectedApps); + } + + @Override public void onFilter(@Nullable String text) { + if (progressBar.isShown()) { + return; + } + if (InputHelper.isEmpty(text)) { + loader.onContentChanged(); + } else { + adapter.getFilter().filter(text); + } + } + + @Override public void onSelectAll() { + adapter.clearSelection(); + for (int i = 0; i < adapter.getData().size(); i++) { + AppsModel model = adapter.getItem(i); + setSelection(model.getComponentName().toShortString(), i); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) public void onEvent(DeviceAppsEventModel model) { + if (loader != null) loader.onContentChanged(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) public void onEvent(ThemePackEventModel model) { + if (loader != null) loader.forceLoad(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersMvp.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersMvp.java new file mode 100644 index 0000000..c3ed652 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersMvp.java @@ -0,0 +1,41 @@ +package com.fastaccess.ui.modules.apps.folders; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.LoaderManager; + +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.ui.modules.apps.folders.create.CreateFolderMvp; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import java.util.List; + +/** + * Created by Kosh on 11 Oct 2016, 7:32 PM + */ + +public interface FoldersMvp { + + interface View extends CreateFolderMvp.OnNotifyFoldersAdapter { + void onStartLoading(); + + void onFoldersLoaded(@Nullable List models); + + void onLoaderReset(); + + void onEditFolder(@NonNull FolderModel folder); + + void onAddAppsToFolder(@NonNull FolderModel folder); + + void onCreateNewFolder(); + + void onDeleteFolder(@NonNull FolderModel folder, int position); + + void onFilter(@Nullable String text); + } + + interface Presenter extends LoaderManager.LoaderCallbacks>, + BaseViewHolder.OnItemClickListener { + + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersPresenter.java new file mode 100644 index 0000000..fc3d1d7 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersPresenter.java @@ -0,0 +1,55 @@ +package com.fastaccess.ui.modules.apps.folders; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.content.Loader; +import android.view.View; + +import com.fastaccess.App; +import com.fastaccess.R; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.provider.loader.FoldersLoader; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +import java.util.List; + +/** + * Created by Kosh on 11 Oct 2016, 7:34 PM + */ + +public class FoldersPresenter extends BasePresenter implements FoldersMvp.Presenter { + protected FoldersPresenter(@NonNull FoldersMvp.View view) { + super(view); + } + + public static FoldersPresenter with(@NonNull FoldersMvp.View view) { + return new FoldersPresenter(view); + } + + @Override public Loader> onCreateLoader(int id, Bundle args) { + if (isAttached()) getView().onStartLoading(); + return new FoldersLoader(App.getInstance().getApplicationContext()); + } + + @Override public void onLoadFinished(Loader> loader, List data) { + getView().onFoldersLoaded(data); + } + + @Override public void onLoaderReset(Loader> loader) { + if (isAttached()) getView().onLoaderReset(); + } + + @Override public void onItemClick(int position, View v, FolderModel item) { + if (v.getId() == R.id.folderImage || v.getId() == R.id.editFolder) { + getView().onEditFolder(item); + } else if (v.getId() == R.id.delete) { + getView().onDeleteFolder(item, position); + } else { + getView().onAddAppsToFolder(item); + } + } + + @Override public void onItemLongClick(int position, View v, FolderModel item) { + onItemClick(position, v, item); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersView.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersView.java new file mode 100644 index 0000000..f51190f --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/FoldersView.java @@ -0,0 +1,115 @@ +package com.fastaccess.ui.modules.apps.folders; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.Loader; +import android.support.v4.widget.NestedScrollView; +import android.view.View; + +import com.fastaccess.R; +import com.fastaccess.data.dao.FolderEventModel; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.ui.adapter.FoldersAdapter; +import com.fastaccess.ui.base.BaseFragment; +import com.fastaccess.ui.modules.apps.folders.create.CreateFolderView; +import com.fastaccess.ui.modules.apps.folders.select.SelectFolderAppsView; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; +import com.mikhaellopez.circularfillableloaders.CircularFillableLoaders; + +import org.greenrobot.eventbus.EventBus; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; + +/** + * Created by Kosh on 11 Oct 2016, 7:42 PM + */ + +public class FoldersView extends BaseFragment implements FoldersMvp.View { + public final static String TAG = "FoldersView"; + + @BindView(R.id.recycler) DynamicRecyclerView recycler; + @BindView(R.id.empty_text) FontTextView emptyText; + @BindView(R.id.empty) NestedScrollView empty; + @BindView(R.id.progressBar) CircularFillableLoaders progressBar; + private FoldersPresenter presenter; + private FoldersAdapter adapter; + private Loader loader; + + public static FoldersView newInstance() { + return new FoldersView(); + } + + @Override protected int fragmentLayout() { + return R.layout.small_grid_list; + } + + @NonNull @Override protected FoldersPresenter getPresenter() { + if (presenter == null) { + presenter = FoldersPresenter.with(this); + } + return presenter; + } + + @Override protected void onFragmentCreated(View view, @Nullable Bundle savedInstanceState) { + adapter = new FoldersAdapter(new ArrayList(), getPresenter()); + recycler.setEmptyView(empty); + emptyText.setText(R.string.no_folders); + recycler.setAdapter(adapter); + loader = getLoaderManager().initLoader(1, null, getPresenter()); + } + + @Override public void onStartLoading() { + recycler.showProgress(progressBar); + } + + @Override public void onFoldersLoaded(@Nullable List models) { + recycler.hideProgress(progressBar); + if (models == null) adapter.clear(); + else adapter.insertItems(models); + } + + @Override public void onLoaderReset() { + recycler.hideProgress(progressBar); + adapter.clear(); + } + + @Override public void onEditFolder(@NonNull FolderModel folder) { + CreateFolderView.newInstance(folder.getId()).show(getChildFragmentManager(), "CreateFolderView"); + } + + @Override public void onAddAppsToFolder(@NonNull FolderModel folder) { + SelectFolderAppsView.newInstance(folder.getId()).show(getChildFragmentManager(), "SelectFolderAppsView"); + } + + @Override public void onCreateNewFolder() { + CreateFolderView.newInstance(-1).show(getChildFragmentManager(), "CreateFolderView"); + } + + @Override public void onDeleteFolder(@NonNull FolderModel folder, int position) { + FolderModel.deleteFolder(folder); + adapter.removeItem(position); + onNotifyChanges(); + } + + @Override public void onFilter(@Nullable String text) { + if (progressBar.isShown()) { + return; + } + if (InputHelper.isEmpty(text)) { + loader.onContentChanged(); + } else { + adapter.getFilter().filter(text); + } + } + + @Override public void onNotifyChanges() { + if (loader != null) loader.onContentChanged(); + EventBus.getDefault().post(new FolderEventModel()); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderMvp.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderMvp.java new file mode 100644 index 0000000..7495a74 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderMvp.java @@ -0,0 +1,18 @@ +package com.fastaccess.ui.modules.apps.folders.create; + +import org.xdty.preference.colorpicker.ColorPickerSwatch; + +/** + * Created by Kosh on 11 Oct 2016, 8:26 PM + */ + +public interface CreateFolderMvp { + + interface View extends ColorPickerSwatch.OnColorSelectedListener {}//op-out + + interface Presenter {}//op-out + + interface OnNotifyFoldersAdapter { + void onNotifyChanges(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderPresenter.java new file mode 100644 index 0000000..4c20d8c --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderPresenter.java @@ -0,0 +1,20 @@ +package com.fastaccess.ui.modules.apps.folders.create; + +import android.support.annotation.NonNull; + +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +/** + * Created by Kosh on 11 Oct 2016, 8:26 PM + */ + +public class CreateFolderPresenter extends BasePresenter implements CreateFolderMvp.Presenter { + + protected CreateFolderPresenter(@NonNull CreateFolderMvp.View view) { + super(view); + } + + public static CreateFolderPresenter with(@NonNull CreateFolderMvp.View view) { + return new CreateFolderPresenter(view); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderView.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderView.java new file mode 100644 index 0000000..eee5f65 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/create/CreateFolderView.java @@ -0,0 +1,159 @@ +package com.fastaccess.ui.modules.apps.folders.create; + +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.TextInputLayout; +import android.support.v4.content.ContextCompat; +import android.text.Editable; +import android.view.Gravity; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; + +import com.amulyakhare.textdrawable.TextDrawable; +import com.fastaccess.R; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.helper.Bundler; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.helper.ViewHelper; +import com.fastaccess.ui.base.BaseBottomSheetDialog; +import com.fastaccess.ui.modules.apps.folders.create.CreateFolderMvp.OnNotifyFoldersAdapter; +import com.fastaccess.ui.widgets.FontButton; + +import org.xdty.preference.colorpicker.ColorPickerDialog; + +import java.util.Date; + +import butterknife.BindView; +import butterknife.OnClick; +import butterknife.OnTextChanged; +import icepick.State; + +/** + * Created by Kosh on 11 Oct 2016, 8:27 PM + */ + +public class CreateFolderView extends BaseBottomSheetDialog implements CreateFolderMvp.View { + private long folderId; + + @State int selectedColor = Color.parseColor("#FF2A456B"); + @State String fName; + + @BindView(R.id.folderImage) ImageView folderImage; + @BindView(R.id.folderName) TextInputLayout folderName; + @BindView(R.id.cancel) FontButton cancel; + @BindView(R.id.save) FontButton save; + @BindView(R.id.folderNameEditText) EditText folderNameEditText; + private FolderModel folderModel; + private OnNotifyFoldersAdapter callback; + + private CreateFolderPresenter presenter; + + public static CreateFolderView newInstance(long folderId) { + CreateFolderView view = new CreateFolderView(); + view.setArguments(Bundler.start().put("folderId", folderId).end()); + return view; + } + + @OnClick(R.id.cancel) void onCancel() { + dismiss(); + } + + @OnClick(R.id.save) void onSave() { + boolean isEmpty = InputHelper.isEmpty(folderName); + folderName.setError(isEmpty ? getString(R.string.required_field) : null); + if (!isEmpty) { + getFolderModel().setColor(selectedColor); + getFolderModel().setFolderName(fName); + if (getFolderModel().getCreatedDate() == 0) { + getFolderModel().setCreatedDate(new Date().getTime()); + } + getFolderModel().save(); + callback.onNotifyChanges(); + dismiss(); + } + } + + @OnClick(R.id.folderImage) void onChooseColor() { + ColorPickerDialog.newInstance(R.string.color_picker_default_title, + getResources().getIntArray(R.array.colors_primary), + selectedColor != 0 ? selectedColor : ContextCompat.getColor(getContext(), R.color.primary), + (getResources().getInteger(R.integer.num_columns) + 1), ColorPickerDialog.SIZE_SMALL) + .show(getChildFragmentManager(), "ColorPickerDialog"); + } + + @OnTextChanged(value = R.id.folderNameEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) void onTextChanged(Editable editable) { + boolean isEmpty = InputHelper.isEmpty(editable); + if (!isEmpty) { + setupDrawable(editable.toString()); + } + folderName.setError(isEmpty ? getString(R.string.required_field) : null); + fName = InputHelper.toString(editable); + } + + @Override public void onAttach(Context context) { + super.onAttach(context); + if (getPresenter() != null && getParentFragment() instanceof OnNotifyFoldersAdapter) { + callback = (OnNotifyFoldersAdapter) getParentFragment(); + } else if (context instanceof OnNotifyFoldersAdapter) { + callback = (OnNotifyFoldersAdapter) context; + } else { + throw new RuntimeException("Activity/Fragment must implement OnNotifyFoldersAdapter"); + } + } + + @Override public void onDetach() { + super.onDetach(); + } + + @Override protected int layoutRes() { + return R.layout.create_edit_folder; + } + + @Override public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + folderId = getArguments().getLong("folderId", -1); + if (savedInstanceState == null) { + selectedColor = getFolderModel().getColor() != 0 ? getFolderModel().getColor() : selectedColor; + fName = getFolderModel().getFolderName(); + } + } + + @Override protected void onViewCreated(@NonNull View view) { + folderNameEditText.setText(fName); + setupDrawable(fName); + ViewHelper.showTooltip(folderImage, R.string.color_picker_hint_folder, "color_picker_folder", Gravity.TOP); + } + + @Override public void onColorSelected(int color) { + selectedColor = color; + setupDrawable(InputHelper.toString(folderNameEditText)); + } + + @NonNull private FolderModel getFolderModel() { + if (folderModel == null) { + folderModel = FolderModel.findById(FolderModel.class, folderId); + if (folderModel == null) { + folderModel = new FolderModel(); + } + } + return folderModel; + } + + private CreateFolderPresenter getPresenter() { + if (presenter == null) presenter = CreateFolderPresenter.with(this); + return presenter; + } + + private void setupDrawable(@NonNull String upDrawable) { + TextDrawable.IBuilder builder = TextDrawable.builder() + .beginConfig() + .endConfig() + .round(); + String letter = InputHelper.isEmpty(upDrawable) ? "N/A" : InputHelper.getTwoLetters(upDrawable); + folderImage.setImageDrawable(builder.build(letter.toUpperCase(), selectedColor)); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsMvp.java new file mode 100644 index 0000000..e29643e --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsMvp.java @@ -0,0 +1,29 @@ +package com.fastaccess.ui.modules.apps.folders.select; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.LoaderManager; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import java.util.List; + +/** + * Created by Kosh on 11 Oct 2016, 8:26 PM + */ + +public interface SelectFolderAppsMvp { + + interface View { + void onStartLoading(); + + void onAppsLoaded(@Nullable List models); + + void onLoaderReset(); + + void onRowClicked(@NonNull AppsModel model, int position); + } + + interface Presenter extends BaseViewHolder.OnItemClickListener, LoaderManager.LoaderCallbacks> {} +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsPresenter.java new file mode 100644 index 0000000..9940e8b --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsPresenter.java @@ -0,0 +1,49 @@ +package com.fastaccess.ui.modules.apps.folders.select; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.content.Loader; +import android.view.View; + +import com.fastaccess.App; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.provider.loader.DeviceAppsLoader; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +import java.util.List; + +/** + * Created by Kosh on 11 Oct 2016, 8:26 PM + */ + +public class SelectFolderAppsPresenter extends BasePresenter implements SelectFolderAppsMvp.Presenter { + + protected SelectFolderAppsPresenter(@NonNull SelectFolderAppsMvp.View view) { + super(view); + } + + public static SelectFolderAppsPresenter with(@NonNull SelectFolderAppsMvp.View view) { + return new SelectFolderAppsPresenter(view); + } + + @Override public void onItemClick(int position, View v, AppsModel item) { + getView().onRowClicked(item, position); + } + + @Override public void onItemLongClick(int position, View v, AppsModel item) { + onItemClick(position, v, item); + } + + @Override public Loader> onCreateLoader(int id, Bundle args) { + getView().onStartLoading(); + return new DeviceAppsLoader(App.getInstance().getApplicationContext()); + } + + @Override public void onLoadFinished(Loader> loader, List data) { + if (isAttached()) getView().onAppsLoaded(data); + } + + @Override public void onLoaderReset(Loader> loader) { + if (isAttached()) getView().onLoaderReset(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsView.java b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsView.java new file mode 100644 index 0000000..254611b --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/folders/select/SelectFolderAppsView.java @@ -0,0 +1,170 @@ +package com.fastaccess.ui.modules.apps.folders.select; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.AppBarLayout; +import android.support.v4.widget.NestedScrollView; +import android.support.v7.widget.Toolbar; +import android.view.MenuItem; +import android.view.View; +import android.widget.ProgressBar; + +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.helper.Bundler; +import com.fastaccess.helper.Logger; +import com.fastaccess.ui.adapter.SelectFolderAppsAdapter; +import com.fastaccess.ui.base.BaseBottomSheetDialog; +import com.fastaccess.ui.modules.apps.folders.create.CreateFolderMvp; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; +import com.mikhaellopez.circularfillableloaders.CircularFillableLoaders; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +import butterknife.BindView; +import icepick.State; + +/** + * Created by Kosh on 11 Oct 2016, 10:24 PM + */ + +public class SelectFolderAppsView extends BaseBottomSheetDialog implements SelectFolderAppsMvp.View { + + @State HashMap selection = new LinkedHashMap<>(); + private long folderId; + + @BindView(R.id.recycler) DynamicRecyclerView recycler; + @BindView(R.id.empty_text) FontTextView emptyText; + @BindView(R.id.empty) NestedScrollView empty; + @BindView(R.id.progressBar) CircularFillableLoaders progressBar; + @BindView(R.id.toolbar) Toolbar toolbar; + @BindView(R.id.topProgress) ProgressBar topProgress; + @BindView(R.id.appbar) AppBarLayout appbar; + private SelectFolderAppsAdapter adapter; + private SelectFolderAppsPresenter presenter; + private FolderModel folderModel; + private CreateFolderMvp.OnNotifyFoldersAdapter callback; + + public static SelectFolderAppsView newInstance(long folderId) { + SelectFolderAppsView view = new SelectFolderAppsView(); + view.setArguments(Bundler.start().put("folderId", folderId).end()); + return view; + } + + @Override public void onAttach(Context context) { + super.onAttach(context); + if (getPresenter() != null && getParentFragment() instanceof CreateFolderMvp.OnNotifyFoldersAdapter) { + callback = (CreateFolderMvp.OnNotifyFoldersAdapter) getParentFragment(); + } else if (context instanceof CreateFolderMvp.OnNotifyFoldersAdapter) { + callback = (CreateFolderMvp.OnNotifyFoldersAdapter) context; + } else { + throw new RuntimeException("Activity/Fragment must implement OnNotifyFoldersAdapter"); + } + } + + @Override public void onDetach() { + super.onDetach(); + } + + @Override protected int layoutRes() { + return R.layout.select_folder_apps_layout; + } + + @Override public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + folderId = getArguments().getLong("folderId"); + if (savedInstanceState == null) { + List apps = AppsModel.getApps(getFolderModel().getId()); + if (!apps.isEmpty()) { + for (AppsModel m : apps) { + selection.put(m.getActivityInfoName(), m); + } + } + } + } + + @Override protected void onViewCreated(@NonNull View view) { + toolbar.setTitle(R.string.select_apps); + toolbar.setNavigationIcon(R.drawable.ic_back); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override public void onClick(View v) { + dismiss(); + } + }); + toolbar.inflateMenu(R.menu.add_menu); + toolbar.getMenu().findItem(R.id.add).setIcon(R.drawable.ic_done); + toolbar.getMenu().findItem(R.id.selectAll).setVisible(false); + toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { + @Override public boolean onMenuItemClick(MenuItem item) { + if (item.getItemId() == R.id.add) { + onAddApps(); + } + return false; + } + }); + adapter = new SelectFolderAppsAdapter(new ArrayList(), getPresenter(), selection); + recycler.setEmptyView(empty); + recycler.setAdapter(adapter); + getLoaderManager().initLoader(2, null, getPresenter()); + } + + @Override public void onStartLoading() { + recycler.showProgress(progressBar); + } + + @Override public void onAppsLoaded(@Nullable List models) { + recycler.hideProgress(progressBar); + if (models == null) { + adapter.clear(); + dismiss(); + return; + } + adapter.insertItems(models); + Logger.e(models.size()); + } + + @Override public void onLoaderReset() { + if (recycler == null) return; + recycler.hideProgress(progressBar); + adapter.clear(); + } + + @Override public void onRowClicked(@NonNull AppsModel model, int position) { + adapter.select(model.getActivityInfoName(), position, !adapter.isSelected(model.getActivityInfoName())); + } + + @NonNull private FolderModel getFolderModel() { + if (folderModel == null) { + folderModel = FolderModel.findById(FolderModel.class, folderId); + } + if (folderModel == null) { + throw new NullPointerException("folderModel is null, make sure passing the right id"); + } + return folderModel; + } + + private void onAddApps() { + List appsModels = adapter.getSelections(); + AppsModel.deleteAllByFolder(getFolderModel()); + if (appsModels != null && !appsModels.isEmpty()) { + for (AppsModel app : appsModels) { + app.setFolderId(getFolderModel().getId()); + app.save(); + } + } + callback.onNotifyChanges(); + dismiss(); + } + + public SelectFolderAppsPresenter getPresenter() { + if (presenter == null) presenter = SelectFolderAppsPresenter.with(this); + return presenter; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsMvp.java new file mode 100644 index 0000000..796639c --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsMvp.java @@ -0,0 +1,54 @@ +package com.fastaccess.ui.modules.apps.selected; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.LoaderManager; +import android.support.v7.view.ActionMode; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.adapter.DeviceAppsAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; +import com.fastaccess.ui.widgets.recyclerview.touch.ItemTouchHelperAdapter; + +import java.util.List; + +/** + * Created by Kosh on 10 Oct 2016, 11:40 PM + */ + +public interface SelectedAppsMvp { + + interface View { + void onStartLoading(); + + void onAppsLoaded(@Nullable List data); + + void onLoaderReset(); + + void setSelection(@NonNull String componentName, int position); + + boolean hasSelection(); + + void onActionModeDestroyed(); + + void onRemoveSelectedApps(); + + void onFilter(@Nullable String text); + + void onNotifyChanges(); + + void onNotifyItemMoved(int fromPosition, int toPosition); + + void onSwap(int fromPosition, int toPosition); + + void onSelectAll(); + } + + interface Presenter extends LoaderManager.LoaderCallbacks>, + BaseViewHolder.OnItemClickListener, + ActionMode.Callback, ItemTouchHelperAdapter { + void onRemoveSelectedApps(@Nullable List selections); + + void onSaveIndexChanges(@NonNull DeviceAppsAdapter adapter, int fromPosition, int toPosition); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsPresenter.java new file mode 100644 index 0000000..fbbf376 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsPresenter.java @@ -0,0 +1,118 @@ +package com.fastaccess.ui.modules.apps.selected; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.Loader; +import android.support.v7.view.ActionMode; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +import com.fastaccess.App; +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.provider.loader.SelectedAppsLoader; +import com.fastaccess.ui.adapter.DeviceAppsAdapter; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +import java.util.List; + +/** + * Created by Kosh on 10 Oct 2016, 11:45 PM + */ + +public class SelectedAppsPresenter extends BasePresenter implements SelectedAppsMvp.Presenter { + + protected SelectedAppsPresenter(@NonNull SelectedAppsMvp.View view) { + super(view); + } + + public static SelectedAppsPresenter with(@NonNull SelectedAppsMvp.View view) { + return new SelectedAppsPresenter(view); + } + + @Override public Loader> onCreateLoader(int id, Bundle args) { + if (isAttached()) getView().onStartLoading(); + return new SelectedAppsLoader(App.getInstance().getApplicationContext()); + } + + @Override public void onLoadFinished(Loader> loader, List data) { + getView().onAppsLoaded(data); + } + + @Override public void onLoaderReset(Loader> loader) { + if (isAttached()) getView().onLoaderReset(); + } + + @Override public void onItemClick(int position, View v, AppsModel item) { + getView().setSelection(item.getComponentName().toShortString(), position); + } + + @Override public void onItemLongClick(int position, View v, AppsModel item) { + //op-out for drag & drop + } + + @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mode.getMenuInflater().inflate(R.menu.remove_menu, menu); + return true; + } + + @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + + @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + if (item.getItemId() == R.id.remove) { + getView().onRemoveSelectedApps(); + return true; + } else if (item.getItemId() == R.id.selectAll) { + getView().onSelectAll(); + return true; + } + return false; + } + + @Override public void onDestroyActionMode(ActionMode mode) { + getView().onActionModeDestroyed(); + } + + @Override public void onRemoveSelectedApps(@Nullable List selections) { + if (selections != null && !selections.isEmpty()) { + for (AppsModel selection : selections) { + selection.delete(); + } + if (isAttached()) getView().onNotifyChanges(); + } + } + + @Override public void onSaveIndexChanges(@NonNull DeviceAppsAdapter adapter, int fromPosition, int toPosition) { + AppsModel fromTo = adapter.getItem(toPosition); + AppsModel toFrom = adapter.getItem(fromPosition); + int actualFrom = fromTo.getIndexPosition(); + int actualTo = toFrom.getIndexPosition(); + fromTo.setIndexPosition(actualTo); + fromTo.save(); + toFrom.setIndexPosition(actualFrom); + toFrom.save(); + } + + @Override public void onItemMove(int fromPosition, int toPosition) { + if (fromPosition < toPosition) { + for (int i = fromPosition; i < toPosition; i++) { + if (isAttached()) getView().onSwap(i, i + 1); + } + } else { + for (int i = fromPosition; i > toPosition; i--) { + if (isAttached()) getView().onSwap(i, i - 1); + } + } + if (isAttached()) getView().onNotifyItemMoved(fromPosition, toPosition); + } + + @Override public void onItemDismiss(int position) {} + + @Override public void onItemStoppedMoving() { + if (isAttached()) getView().onNotifyChanges(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsView.java b/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsView.java new file mode 100644 index 0000000..96e89ff --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/apps/selected/SelectedAppsView.java @@ -0,0 +1,178 @@ +package com.fastaccess.ui.modules.apps.selected; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.Loader; +import android.support.v4.widget.NestedScrollView; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.view.ActionMode; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.view.View; + +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.data.dao.FloatingEventModel; +import com.fastaccess.data.dao.SelectedAppsEventModel; +import com.fastaccess.data.dao.ThemePackEventModel; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.ui.adapter.DeviceAppsAdapter; +import com.fastaccess.ui.base.BaseFragment; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; +import com.fastaccess.ui.widgets.recyclerview.touch.SimpleItemTouchHelperCallback; +import com.mikhaellopez.circularfillableloaders.CircularFillableLoaders; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +import butterknife.BindView; +import icepick.State; + +/** + * Created by Kosh on 10 Oct 2016, 11:47 PM + */ + +public class SelectedAppsView extends BaseFragment implements SelectedAppsMvp.View { + public static final String TAG = "SelectedAppsView"; + + @BindView(R.id.recycler) DynamicRecyclerView recycler; + @BindView(R.id.empty_text) FontTextView emptyText; + @BindView(R.id.empty) NestedScrollView empty; + @BindView(R.id.progressBar) CircularFillableLoaders progressBar; + @State HashMap selection = new LinkedHashMap<>(); + private SelectedAppsPresenter presenter; + private DeviceAppsAdapter adapter; + private ActionMode actionMode; + private Loader loader; + + public static SelectedAppsView newInstance() { + return new SelectedAppsView(); + } + + @Override public void onAttach(Context context) { + super.onAttach(context); + EventBus.getDefault().register(this); + } + + @Override public void onDetach() { + super.onDetach(); + EventBus.getDefault().unregister(this); + } + + @Override protected int fragmentLayout() { + return R.layout.grid_list; + } + + @NonNull @Override protected SelectedAppsPresenter getPresenter() { + if (presenter == null) { + presenter = SelectedAppsPresenter.with(this); + } + return presenter; + } + + @Override protected void onFragmentCreated(View view, @Nullable Bundle savedInstanceState) { + recycler.setEmptyView(empty); + emptyText.setText(R.string.no_apps_selected); + adapter = new DeviceAppsAdapter(new ArrayList(), getPresenter(), selection); + recycler.setAdapter(adapter); + loader = getLoaderManager().initLoader(0, null, getPresenter()); + if (!selection.isEmpty()) { + actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(getPresenter()); + actionMode.setTitle(getString(R.string.selected) + " ( " + adapter.selectionSize() + " )"); + } + ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(getPresenter(), false); + ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(callback); + mItemTouchHelper.attachToRecyclerView(recycler); + } + + @Override public void onStartLoading() { + recycler.showProgress(progressBar); + } + + @Override public void onAppsLoaded(@Nullable List data) { + recycler.hideProgress(progressBar); + if (data != null) adapter.insertItems(data); + else adapter.clear(); + } + + @Override public void onLoaderReset() { + recycler.hideProgress(progressBar); + adapter.clear(); + } + + @Override public void setSelection(@NonNull String packageName, int position) { + adapter.select(packageName, position, !adapter.isSelected(packageName)); + if (hasSelection()) { + if (actionMode == null) { + actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(getPresenter()); + } + actionMode.setTitle(getString(R.string.selected) + " ( " + adapter.selectionSize() + " )"); + } else { + actionMode.finish(); + } + } + + @Override public boolean hasSelection() { + return adapter.hasSelection(); + } + + @Override public void onActionModeDestroyed() { + adapter.clearSelection(); + actionMode = null; + } + + @Override public void onRemoveSelectedApps() { + getPresenter().onRemoveSelectedApps(adapter.getSelections()); + if (actionMode != null) actionMode.finish(); + } + + @Override public void onFilter(@Nullable String text) { + if (progressBar.isShown()) { + return; + } + if (InputHelper.isEmpty(text)) { + loader.onContentChanged(); + } else { + adapter.getFilter().filter(text); + } + } + + @Override public void onNotifyChanges() { + if (loader != null) loader.onContentChanged();//notify changes + EventBus.getDefault().post(new FloatingEventModel()); + } + + @Override public void onNotifyItemMoved(int fromPosition, int toPosition) { + adapter.notifyItemMoved(fromPosition, toPosition); + } + + @Override public void onSwap(int fromPosition, int toPosition) { + getPresenter().onSaveIndexChanges(adapter, fromPosition, toPosition); + Collections.swap(adapter.getData(), fromPosition, toPosition); + } + + @Override public void onSelectAll() { + adapter.clearSelection(); + for (int i = 0; i < adapter.getData().size(); i++) { + AppsModel model = adapter.getItem(i); + setSelection(model.getComponentName().toShortString(), i); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) public void onEvent(SelectedAppsEventModel eventModel) { + onNotifyChanges(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) public void onEvent(ThemePackEventModel model) { + if (loader != null) loader.forceLoad(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginMvp.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginMvp.java new file mode 100644 index 0000000..4db8482 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginMvp.java @@ -0,0 +1,50 @@ +package com.fastaccess.ui.modules.cloud.auth; + +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; + +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +/** + * Created by Kosh on 23 Oct 2016, 7:33 PM + */ + +public interface LoginMvp { + + interface View { + void onShowProgress(); + + void onHideProgress(); + + void onShowMessage(@StringRes int resId); + + void onShowMessage(@NonNull String msg); + + void onConnected(); + + void onConnectionFailed(@NonNull ConnectionResult connectionResult); + + void onSignedIn(@NonNull GoogleSignInAccount account); + + + void onFirebaseUser(@NonNull FirebaseUser user); + } + + interface Presenter extends GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, + FirebaseAuth.AuthStateListener, OnCompleteListener { + void onSignIn(@NonNull LoginView loginView, @NonNull GoogleApiClient googleApiClient); + + void onActivityResult(int requestCode, int resultCode, Intent data); + + void onFirebaseSignIn(@NonNull GoogleSignInAccount account, @NonNull FirebaseAuth auth); + + void onStartBackOrRestore(int type, @NonNull LoginView loginView); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginPresenter.java new file mode 100644 index 0000000..a379bbb --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginPresenter.java @@ -0,0 +1,117 @@ +package com.fastaccess.ui.modules.cloud.auth; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.fastaccess.R; +import com.fastaccess.helper.Logger; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; +import com.fastaccess.ui.modules.cloud.backup.BackupView; +import com.fastaccess.ui.modules.cloud.restore.RestoreView; +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInResult; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthCredential; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.auth.GoogleAuthProvider; + +/** + * Created by Kosh on 23 Oct 2016, 7:49 PM + */ + +public class LoginPresenter extends BasePresenter implements LoginMvp.Presenter { + + private static final int SIGN_IN_REQUEST_CODE = 100; + + protected LoginPresenter(@NonNull LoginMvp.View view) { + super(view); + } + + public static LoginPresenter with(@NonNull LoginMvp.View view) { + return new LoginPresenter(view); + } + + @Override public void onSignIn(@NonNull LoginView loginView, @NonNull GoogleApiClient googleApiClient) { + Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient); + loginView.startActivityForResult(signInIntent, SIGN_IN_REQUEST_CODE); + loginView.onShowProgress(); + } + + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == SIGN_IN_REQUEST_CODE) { + if (isAttached()) { + GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); + if (result.isSuccess()) { + GoogleSignInAccount account = result.getSignInAccount(); + if (account != null) { + getView().onSignedIn(account); + } else { + getView().onShowMessage(R.string.failed_login); + } + } else { + getView().onShowMessage(R.string.failed_login); + } + } + } + + } + + @Override public void onFirebaseSignIn(@NonNull GoogleSignInAccount acct, @NonNull FirebaseAuth auth) { + AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null); + auth.signInWithCredential(credential).addOnCompleteListener(this); + } + + @Override public void onStartBackOrRestore(int type, @NonNull LoginView loginView) { + Intent intent = new Intent(loginView, type == LoginView.BACKUP_TYPE ? BackupView.class : RestoreView.class); + loginView.startActivity(intent); + loginView.finish(); + } + + @Override public void onConnected(@Nullable Bundle bundle) { + if (isAttached()) getView().onConnected(); + } + + @Override public void onConnectionSuspended(int i) { + //TODO + } + + @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { + if (isAttached()) { + if (connectionResult.getErrorMessage() != null) { + getView().onShowMessage(connectionResult.getErrorMessage()); + } + getView().onConnectionFailed(connectionResult); + } + } + + @Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { + if (isAttached()) { + FirebaseUser user = firebaseAuth.getCurrentUser(); + if (user != null) { + getView().onFirebaseUser(user); + } else { + Logger.e(); + } + } + } + + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") @Override public void onComplete(@NonNull Task task) { + Logger.e(task.isSuccessful(), task.isComplete()); + if (isAttached()) { + if (!task.isSuccessful()) { + if (task.getException() != null && task.getException().getMessage() != null) { + getView().onShowMessage(task.getException().getMessage()); + } else { + getView().onShowMessage(R.string.failed_login); + } + } + } + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginView.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginView.java new file mode 100644 index 0000000..6c03f4c --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/auth/LoginView.java @@ -0,0 +1,166 @@ +package com.fastaccess.ui.modules.cloud.auth; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; +import android.support.design.widget.Snackbar; +import android.view.View; +import android.widget.ProgressBar; + +import com.fastaccess.R; +import com.fastaccess.helper.Logger; +import com.fastaccess.ui.base.BaseActivity; +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.SignInButton; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +import butterknife.BindView; +import butterknife.OnClick; +import icepick.State; + +/** + * Created by Kosh on 23 Oct 2016, 7:56 PM + */ + +public class LoginView extends BaseActivity implements LoginMvp.View { + + public static final int BACKUP_TYPE = 0; + public static final int RESTORE_TYPE = 1; + public static final String TYPE = "type"; + + @BindView(R.id.topProgress) ProgressBar topProgress; + @BindView(R.id.signInBtn) SignInButton signInBtn; + @State int type; + + private GoogleApiClient mGoogleApiClient; + private GoogleSignInOptions signInOptions; + private ProgressDialog progressDialog; + private LoginPresenter presenter; + private FirebaseAuth firebaseAuth; + + + @OnClick(R.id.signInBtn) void onSignIn() { + getPresenter().onSignIn(this, getGoogleApiClient()); + } + + @Override protected int layout() { + return R.layout.sign_in_layout; + } + + @NonNull @Override protected LoginPresenter getPresenter() { + if (presenter == null) presenter = LoginPresenter.with(this); + return presenter; + } + + @Override protected boolean isTransparent() { + return false; + } + + @Override protected boolean canBack() { + return true; + } + + @Override public void onShowProgress() { + topProgress.setVisibility(View.VISIBLE); + if (!getProgressDialog().isShowing()) getProgressDialog().show(); + } + + @Override public void onHideProgress() { + topProgress.setVisibility(View.GONE); + if (getProgressDialog().isShowing()) getProgressDialog().dismiss(); + } + + @Override public void onShowMessage(@StringRes int resId) { + onShowMessage(getString(resId)); + } + + @Override public void onShowMessage(@NonNull String msg) { + onHideProgress(); + Snackbar.make(signInBtn, msg, Snackbar.LENGTH_LONG).show(); + } + + @Override public void onConnected() { + Logger.e(); + } + + @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { + Logger.e(); + } + + @Override public void onSignedIn(@NonNull GoogleSignInAccount account) { + getPresenter().onFirebaseSignIn(account, getFirebaseAuth()); + } + + @Override public void onFirebaseUser(@NonNull FirebaseUser user) { + onHideProgress(); + getPresenter().onStartBackOrRestore(type, this); + } + + @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState == null) { + type = getIntent().getExtras().getInt(TYPE); + } + setTitle(type == BACKUP_TYPE ? R.string.backup : R.string.restore); + signInBtn.setSize(SignInButton.SIZE_WIDE); + } + + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + getPresenter().onActivityResult(requestCode, resultCode, data); + } + + @Override protected void onStart() { + super.onStart(); + getFirebaseAuth().addAuthStateListener(getPresenter()); + } + + @Override protected void onStop() { + super.onStop(); + getFirebaseAuth().removeAuthStateListener(getPresenter()); + } + + private ProgressDialog getProgressDialog() { + if (progressDialog == null) { + progressDialog = new ProgressDialog(this); + progressDialog.setCancelable(false); + progressDialog.setMessage(getString(R.string.in_progress)); + } + return progressDialog; + } + + private GoogleApiClient getGoogleApiClient() { + if (mGoogleApiClient == null) { + mGoogleApiClient = new GoogleApiClient.Builder(this) + .enableAutoManage(this, getPresenter()) + .addApi(Auth.GOOGLE_SIGN_IN_API, getSignInOptions()) + .build(); + } + return mGoogleApiClient; + } + + private GoogleSignInOptions getSignInOptions() { + if (signInOptions == null) { + signInOptions = new GoogleSignInOptions + .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken(getString(R.string.default_web_client_id)) + .requestEmail() + .build(); + } + return signInOptions; + } + + public FirebaseAuth getFirebaseAuth() { + if (firebaseAuth == null) { + firebaseAuth = FirebaseAuth.getInstance(); + } + return firebaseAuth; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupMvp.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupMvp.java new file mode 100644 index 0000000..c386e63 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupMvp.java @@ -0,0 +1,32 @@ +package com.fastaccess.ui.modules.cloud.backup; + +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; + +import com.google.firebase.database.DatabaseReference; + +/** + * Created by Kosh on 23 Oct 2016, 8:56 PM + */ + +public interface BackupMvp { + + interface View { + void onShowProgress(); + + void onHideProgress(); + + void onShowMessage(@StringRes int resId); + + void onShowMessage(@NonNull String msg); + + void finishOnError(); + + void onBackupCompleted(); + } + + interface Presenter extends DatabaseReference.CompletionListener { + + void onBackup(DatabaseReference databaseReference); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupPresenter.java new file mode 100644 index 0000000..0d41a92 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupPresenter.java @@ -0,0 +1,46 @@ +package com.fastaccess.ui.modules.cloud.backup; + +import android.support.annotation.NonNull; + +import com.fastaccess.R; +import com.fastaccess.data.dao.BackupRestoreModel; +import com.fastaccess.helper.Logger; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; + +/** + * Created by Kosh on 23 Oct 2016, 9:04 PM + */ + +public class BackupPresenter extends BasePresenter implements BackupMvp.Presenter { + + protected BackupPresenter(@NonNull BackupMvp.View view) { + super(view); + } + + public static BackupPresenter with(@NonNull BackupMvp.View view) { + return new BackupPresenter(view); + } + + @Override public void onBackup(DatabaseReference databaseReference) { + BackupRestoreModel model = BackupRestoreModel.backup(); + if (model == null || model.getUid() == null) { + getView().onShowMessage(R.string.login_first_msg); + getView().finishOnError(); + } else { + getView().onShowProgress(); + Logger.e(model, model.getFolders(), model.getAppsModels()); + databaseReference.child(BackupView.BACKUP_DATABASE_NAME).child(model.getUid()).setValue(model, this); + } + } + + @Override public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) { + if (databaseError != null) { + getView().onShowMessage(databaseError.getDetails()); + getView().finishOnError(); + } else { + getView().onBackupCompleted(); + } + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupView.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupView.java new file mode 100644 index 0000000..7735ec9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/backup/BackupView.java @@ -0,0 +1,92 @@ +package com.fastaccess.ui.modules.cloud.backup; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.widget.Toast; + +import com.fastaccess.R; +import com.fastaccess.ui.base.BaseActivity; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; + +/** + * Created by Kosh on 23 Oct 2016, 9:05 PM + */ + +public class BackupView extends BaseActivity implements BackupMvp.View { + public static final String BACKUP_DATABASE_NAME = "backup_db"; + + private BackupPresenter presenter; + private ProgressDialog progressDialog; + private DatabaseReference database; + + @Override protected int layout() { + return 0; + } + + @NonNull @Override protected BackupPresenter getPresenter() { + if (presenter == null) { + presenter = BackupPresenter.with(this); + } + return presenter; + } + + @Override protected boolean isTransparent() { + return false; + } + + @Override protected boolean canBack() { + return false; + } + + @Override public void onShowProgress() { + if (!getProgressDialog().isShowing()) getProgressDialog().show(); + } + + @Override public void onHideProgress() { + if (getProgressDialog().isShowing()) getProgressDialog().dismiss(); + } + + @Override public void onShowMessage(@StringRes int resId) { + onShowMessage(getString(resId)); + } + + @Override public void onShowMessage(@NonNull String msg) { + onHideProgress(); + Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); + } + + @Override public void finishOnError() { + finish(); + } + + @Override public void onBackupCompleted() { + onHideProgress(); + onShowMessage(R.string.successfully_backup); + finish(); + } + + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getPresenter().onBackup(getDatabase()); + } + + private ProgressDialog getProgressDialog() { + if (progressDialog == null) { + progressDialog = new ProgressDialog(this); + progressDialog.setCancelable(false); + progressDialog.setMessage(getString(R.string.backup_in_progress)); + } + return progressDialog; + } + + private DatabaseReference getDatabase() { + if (database == null) { + database = FirebaseDatabase.getInstance().getReference(); + } + return database; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestoreMvp.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestoreMvp.java new file mode 100644 index 0000000..b8d91bd --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestoreMvp.java @@ -0,0 +1,37 @@ +package com.fastaccess.ui.modules.cloud.restore; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; + +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.ValueEventListener; + +/** + * Created by Kosh on 23 Oct 2016, 8:56 PM + */ + +public interface RestoreMvp { + + interface View { + void onShowProgress(); + + void onHideProgress(); + + void onShowMessage(@StringRes int resId); + + void onShowMessage(@NonNull String msg); + + void finishOnError(); + + void onRestoreCompleted(); + + @Nullable FirebaseUser user(); + } + + interface Presenter extends ValueEventListener { + + void onRestore(DatabaseReference databaseReference); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestorePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestorePresenter.java new file mode 100644 index 0000000..e54499c --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestorePresenter.java @@ -0,0 +1,74 @@ +package com.fastaccess.ui.modules.cloud.restore; + +import android.support.annotation.NonNull; + +import com.fastaccess.R; +import com.fastaccess.data.dao.BackupRestoreModel; +import com.fastaccess.helper.Logger; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; +import com.fastaccess.ui.modules.cloud.backup.BackupView; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.Query; + +/** + * Created by Kosh on 23 Oct 2016, 9:04 PM + */ + +public class RestorePresenter extends BasePresenter implements RestoreMvp.Presenter { + + protected RestorePresenter(@NonNull RestoreMvp.View view) { + super(view); + } + + public static RestorePresenter with(@NonNull RestoreMvp.View view) { + return new RestorePresenter(view); + } + + @Override public void onRestore(DatabaseReference databaseReference) { + FirebaseUser user = getView().user(); + if (user == null) { + getView().onShowMessage(R.string.login_first_msg); + } else { + getView().onShowProgress(); + Logger.e(user.getUid()); + Query query = databaseReference + .child(BackupView.BACKUP_DATABASE_NAME) + .child(user.getUid()) + .limitToFirst(1); + query.keepSynced(true); + query.addListenerForSingleValueEvent(this); + } + } + + @Override public void onDataChange(DataSnapshot dataSnapshot) { + if (!isAttached()) return; + if (dataSnapshot != null) { + Logger.e(dataSnapshot); + FirebaseUser user = getView().user(); + if (user == null) { + getView().onHideProgress(); + getView().onShowMessage(R.string.login_first_msg); + getView().finishOnError(); + return; + } + if (dataSnapshot.hasChildren()) { + BackupRestoreModel.restore(dataSnapshot.getValue(BackupRestoreModel.class)); + } + getView().onHideProgress(); + getView().onRestoreCompleted(); + } else { + getView().onHideProgress(); + getView().onShowMessage(R.string.no_data_to_restore); + getView().finishOnError(); + } + } + + @Override public void onCancelled(DatabaseError databaseError) { + Logger.e(databaseError.getMessage()); + getView().onHideProgress(); + getView().finishOnError(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestoreView.java b/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestoreView.java new file mode 100644 index 0000000..b214b78 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/cloud/restore/RestoreView.java @@ -0,0 +1,105 @@ +package com.fastaccess.ui.modules.cloud.restore; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.widget.Toast; + +import com.fastaccess.R; +import com.fastaccess.ui.base.BaseActivity; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; + +/** + * Created by Kosh on 23 Oct 2016, 9:05 PM + */ + +public class RestoreView extends BaseActivity implements RestoreMvp.View { + private RestorePresenter presenter; + private ProgressDialog progressDialog; + private DatabaseReference database; + private FirebaseUser user; + + @Override protected int layout() { + return 0; + } + + @NonNull @Override protected RestorePresenter getPresenter() { + if (presenter == null) { + presenter = RestorePresenter.with(this); + } + return presenter; + } + + @Override protected boolean isTransparent() { + return false; + } + + @Override protected boolean canBack() { + return false; + } + + @Override public void onShowProgress() { + if (!getProgressDialog().isShowing()) getProgressDialog().show(); + } + + @Override public void onHideProgress() { + if (getProgressDialog().isShowing()) getProgressDialog().dismiss(); + } + + @Override public void onShowMessage(@StringRes int resId) { + onShowMessage(getString(resId)); + } + + @Override public void onShowMessage(@NonNull String msg) { + onHideProgress(); + Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); + } + + @Override public void finishOnError() { + finish(); + } + + @Override public void onRestoreCompleted() { + onHideProgress(); + onShowMessage(R.string.successfully_restored); + finish(); + } + + @Nullable @Override public FirebaseUser user() { + if (user == null) user = FirebaseAuth.getInstance().getCurrentUser(); + return user; + } + + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getPresenter().onRestore(getDatabase()); + } + + @Override protected void onStop() { + super.onStop(); + try { + getDatabase().removeEventListener(getPresenter()); + } catch (Exception ignored) {} + } + + private ProgressDialog getProgressDialog() { + if (progressDialog == null) { + progressDialog = new ProgressDialog(this); + progressDialog.setCancelable(false); + progressDialog.setMessage(getString(R.string.restore_in_progress)); + } + return progressDialog; + } + + private DatabaseReference getDatabase() { + if (database == null) { + database = FirebaseDatabase.getInstance().getReference(); + } + return database; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingMvp.java b/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingMvp.java new file mode 100644 index 0000000..38733df --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingMvp.java @@ -0,0 +1,71 @@ +package com.fastaccess.ui.modules.floating; + +import android.graphics.Point; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.Loader; +import android.view.WindowManager; + +import com.fastaccess.ui.widgets.floating.FloatingTouchCallback; +import com.fastaccess.ui.widgets.floating.FloatingView; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import java.util.List; + +/** + * Created by Kosh on 23 Oct 2016, 12:14 AM + */ + +public interface BaseFloatingMvp { + + interface BaseView { + + Loader getLoader(); + + BaseRecyclerAdapter getAdapter(); + + BaseFloatingPresenter> getPresenter(); + + void onLoaderLoaded(@Nullable List data); + + void onViewMoving(int x, int y); + + void onStoppedMoving(); + + void onLongPressed(); + + void onDoubleTapped(); + + void onSingleTapped(); + + void onTouchedOutside(); + + void onBackPressed(); + + void onDestroy(); + + void onToggleVisibility(boolean showFloating); + + void onConfigChanged(int orientation); + + void onUpdateXY(); + + void setupParamsSize(); + } + + interface BasePresenter> extends BaseViewHolder.OnItemClickListener, + FloatingTouchCallback, Loader.OnLoadCompleteListener> { + void onUpdateWindowParams(@NonNull WindowManager windowManager, + @NonNull WindowManager.LayoutParams originalParams, + @NonNull FloatingView floatingView, + int x, int y); + + void onToggleVisibility(boolean showFloating, @NonNull WindowManager windowManager, + @NonNull WindowManager.LayoutParams originalParams, @NonNull android.view.View view, + @NonNull FloatingView floatingView, boolean isHorizontal); + + void onMoveToEdge(@NonNull WindowManager windowManager, @NonNull WindowManager.LayoutParams originalParams, + @NonNull FloatingView floatingView, @NonNull Point szWindow); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingPresenter.java new file mode 100644 index 0000000..7c21b15 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingPresenter.java @@ -0,0 +1,132 @@ +package com.fastaccess.ui.modules.floating; + +import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; +import android.graphics.Point; +import android.support.annotation.NonNull; +import android.support.v4.content.Loader; +import android.view.View; +import android.view.WindowManager; +import android.view.animation.AccelerateInterpolator; + +import com.fastaccess.R; +import com.fastaccess.helper.AnimHelper; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.helper.ViewHelper; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; +import com.fastaccess.ui.widgets.floating.FloatingView; +import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; + +import java.util.List; + +/** + * Created by Kosh on 23 Oct 2016, 12:18 AM + */ + +public class BaseFloatingPresenter> extends BasePresenter implements BaseFloatingMvp.BasePresenter { + + private final TimeInterpolator moveEdgeInterpolator = new AccelerateInterpolator(); + + protected BaseFloatingPresenter(@NonNull V view) { + super(view); + } + + @Override public void onViewMoving(int x, int y) { + if (isAttached()) getView().onViewMoving(x, y); + } + + @Override public void onSingleTapped() { + if (isAttached()) getView().onSingleTapped(); + } + + @Override public void onDoubleTapped() { + if (isAttached()) getView().onDoubleTapped(); + } + + @Override public void onLongPressed() { + if (isAttached()) getView().onLongPressed(); + } + + @Override public void onSwipe(int swipeDirection) {}//Op-out + + @Override public void onBackPressed() { + onTouchOutside(); + } + + @Override public void onTouchOutside() { + if (isAttached()) getView().onTouchedOutside(); + } + + @Override public void onStoppedMoving() { + if (isAttached()) getView().onStoppedMoving(); + } + + @Override public void onConfigChanged(int orientation) { + if (isAttached()) getView().onConfigChanged(orientation); + } + + @Override public void onItemClick(int position, View v, M item) { + if (isAttached()) getView().onTouchedOutside(); + } + + @Override public void onItemLongClick(int position, View v, M item) { + onItemClick(position, v, item); + } + + @Override public void onUpdateWindowParams(@NonNull WindowManager windowManager, + @NonNull WindowManager.LayoutParams originalParams, + @NonNull FloatingView floatingView, + int x, int y) { + originalParams.x = x; + originalParams.y = y; + windowManager.updateViewLayout(floatingView, originalParams); + } + + @Override public void onToggleVisibility(final boolean showFloating, @NonNull final WindowManager windowManager, + @NonNull final WindowManager.LayoutParams originalParams, @NonNull final View view, + @NonNull final FloatingView floatingView, boolean isHorizontal) { + AnimHelper.animateVisibility(floatingView, showFloating); + AnimHelper.animateVisibility(view, !showFloating, showFloating ? new AnimHelper.AnimationCallback() { + @Override public void onAnimationEnd() { + if (!isAttached()) return; + getView().setupParamsSize(); + } + + @Override public void onAnimationStart() {} + } : null); + if (!showFloating) { + if (!isAttached()) return; + if (isHorizontal) { + final DynamicRecyclerView recycler = (DynamicRecyclerView) view.findViewById(R.id.recycler); + originalParams.width = ViewHelper.getWidthFromRecyclerView(recycler, windowManager); + } + windowManager.updateViewLayout(view, originalParams); + } + } + + @Override public void onMoveToEdge(@NonNull final WindowManager windowManager, @NonNull final WindowManager.LayoutParams originalParams, + @NonNull final FloatingView floatingView, @NonNull Point szWindow) { + if (!PrefHelper.getBoolean(PrefConstant.FA_EDGES_STICKY)) return; + int w = originalParams.width; + final boolean isMoveRightEdge = originalParams.x + w / 2 <= szWindow.x / 2; + final int goalPositionX = isMoveRightEdge ? 0 : szWindow.x - w; + if (!isAttached() || !floatingView.isShown()) return; + ValueAnimator mMoveEdgeAnimator = ValueAnimator.ofInt(originalParams.x, goalPositionX); + mMoveEdgeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override public void onAnimationUpdate(ValueAnimator animation) { + if (!isAttached() || !floatingView.isShown()) return; + originalParams.x = (Integer) animation.getAnimatedValue(); + windowManager.updateViewLayout(floatingView, originalParams); + if (isAttached()) getView().onUpdateXY(); + } + }); + mMoveEdgeAnimator.setDuration(200L); + mMoveEdgeAnimator.setInterpolator(moveEdgeInterpolator); + mMoveEdgeAnimator.start(); + } + + @Override public void onLoadComplete(Loader> loader, List data) { + if (isAttached()) getView().onLoaderLoaded(data); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingView.java b/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingView.java new file mode 100644 index 0000000..fb36e84 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/BaseFloatingView.java @@ -0,0 +1,176 @@ +package com.fastaccess.ui.modules.floating; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.graphics.Point; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.GravityCompat; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.WindowManager; + +import com.fastaccess.R; +import com.fastaccess.data.dao.FloatingEventModel; +import com.fastaccess.data.dao.ThemePackEventModel; +import com.fastaccess.helper.NotificationHelper; +import com.fastaccess.helper.PermissionsHelper; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.provider.service.FloatingService; +import com.fastaccess.ui.adapter.viewholder.FloatingWindowsViewHolder; +import com.fastaccess.ui.widgets.floating.FloatingView; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.List; + +import static android.graphics.PixelFormat.TRANSLUCENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; +import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; +import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; + +/** + * Created by Kosh on 23 Oct 2016, 12:36 AM + */ + +public abstract class BaseFloatingView implements BaseFloatingMvp.BaseView { + private WindowManager.LayoutParams originalParams; + protected WindowManager windowManager; + protected Context context; + protected FloatingView floatingView; + private FloatingWindowsViewHolder layoutHolder; + private Point szWindow = new Point(); + protected boolean isHorizontal; + + @SuppressWarnings("unused") private BaseFloatingView() { + throw new RuntimeException("can't call me!"); + } + + @SuppressLint("InflateParams") protected BaseFloatingView(@NonNull Context context, boolean isHorizontal) { + EventBus.getDefault().register(this); + this.isHorizontal = isHorizontal; + this.context = context; + if (!PermissionsHelper.isSystemAlertGranted(context)) { + context.stopService(new Intent(context, FloatingService.class)); + return; + } + windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + windowManager.getDefaultDisplay().getSize(szWindow); + originalParams = new WindowManager.LayoutParams(TYPE_PRIORITY_PHONE, FLAG_NOT_TOUCH_MODAL | + FLAG_WATCH_OUTSIDE_TOUCH | FLAG_NOT_FOCUSABLE, TRANSLUCENT); + setupParamsSize(); + boolean isAutoSavePosition = PrefHelper.getBoolean(PrefConstant.FA_AUTO_SAVE_POSITION); + originalParams.x = isAutoSavePosition ? PrefHelper.getInt(PrefConstant.POSITION_X) : 0; + originalParams.y = isAutoSavePosition ? PrefHelper.getInt(PrefConstant.POSITION_Y) : 100; + originalParams.gravity = GravityCompat.START | Gravity.TOP; + floatingView = new FloatingView(context, getPresenter()); + onUpdateXY(); + windowManager.addView(floatingView, originalParams); + layoutHolder = new FloatingWindowsViewHolder(LayoutInflater.from(context).inflate(isHorizontal ? R.layout.horizontal_layout : R.layout + .vertical_layout, null, false), this); + layoutHolder.recycler.setAdapter(getAdapter()); + windowManager.addView(layoutHolder.tabBar, originalParams); + getLoader(); + moveToEdge(); + } + + @Override public void onLoaderLoaded(@Nullable List data) { + if (data == null || data.isEmpty()) { + getAdapter().clear(); + context.stopService(new Intent(context, FloatingService.class)); + } else { + getAdapter().insertItems(data); + } + } + + @Override public void onViewMoving(int x, int y) { + getPresenter().onUpdateWindowParams(windowManager, originalParams, floatingView, x, y); + } + + @Override public void onStoppedMoving() { + moveToEdge(); + onUpdateXY(); + PrefConstant.savePosition(originalParams.x, originalParams.y); + } + + @Override public void onLongPressed() { + NotificationHelper.collapseFAService(context, getAdapter().getItemCount()); + } + + @Override public void onDoubleTapped() { + Intent startMain = new Intent(Intent.ACTION_MAIN); + startMain.addCategory(Intent.CATEGORY_HOME); + startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(startMain); + } + + @Override public void onSingleTapped() { + onToggleVisibility(false); + } + + @Override public void onTouchedOutside() { + if (layoutHolder.tabBar.isShown() && !PrefHelper.getBoolean(PrefConstant.FA_ALWAYS_SHOWING)) { + onToggleVisibility(true); + } + } + + @Override public void onBackPressed() { + onTouchedOutside(); + } + + @Override public void onDestroy() { + if (windowManager != null) { + windowManager.removeView(floatingView); + windowManager.removeView(layoutHolder.tabBar); + } + if (getLoader() != null) getLoader().unregisterListener(getPresenter()); + if (getAdapter() != null) getAdapter().clear(); + if (layoutHolder != null) layoutHolder.onDestroy(); + if (getPresenter() != null) getPresenter().onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override public void onToggleVisibility(boolean showFloating) { + getPresenter().onToggleVisibility(showFloating, windowManager, originalParams, layoutHolder.tabBar, floatingView, isHorizontal); + } + + @Override public void onConfigChanged(int orientation) { + windowManager.getDefaultDisplay().getSize(szWindow); + moveToEdge(); + } + + @Override public void onUpdateXY() { + floatingView.setInitialX(originalParams.x); + floatingView.setInitialY(originalParams.y); + } + + @SuppressWarnings("unused") @Subscribe public void onEvent(FloatingEventModel model) { + if (!model.isSettingsChanged()) { + if (getLoader() != null) getLoader().onContentChanged(); + } else { + setupParamsSize(); + floatingView.setupImageView(); + layoutHolder.onSetupBackground(); + moveToEdge(); + } + } + + @SuppressWarnings("unused") @Subscribe public void onEvent(ThemePackEventModel model) { + if (getLoader() != null) getLoader().forceLoad(); + } + + @Override public void setupParamsSize() { + originalParams.width = PrefConstant.getFinalSize(context); + originalParams.height = isHorizontal ? PrefConstant.getFinalSize(context) : WRAP_CONTENT; + if (floatingView != null) windowManager.updateViewLayout(floatingView, originalParams); + } + + private void moveToEdge() { + getPresenter().onMoveToEdge(windowManager, originalParams, floatingView, szWindow); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingHVMvp.java b/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingHVMvp.java new file mode 100644 index 0000000..90769df --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingHVMvp.java @@ -0,0 +1,13 @@ +package com.fastaccess.ui.modules.floating.apps; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.modules.floating.BaseFloatingMvp; + +/** + * Created by Kosh on 14 Oct 2016, 8:54 PM + */ + +public interface FloatingHVMvp { + + interface Presenter extends BaseFloatingMvp.BasePresenter> {} +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingVHPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingVHPresenter.java new file mode 100644 index 0000000..d6de18f --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingVHPresenter.java @@ -0,0 +1,41 @@ +package com.fastaccess.ui.modules.floating.apps; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.support.annotation.NonNull; +import android.view.View; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.modules.floating.BaseFloatingMvp; +import com.fastaccess.ui.modules.floating.BaseFloatingPresenter; + +/** + * Created by Kosh on 14 Oct 2016, 9:00 PM + */ + +public class FloatingVHPresenter extends BaseFloatingPresenter> implements FloatingHVMvp.Presenter { + + + public FloatingVHPresenter(@NonNull BaseFloatingMvp.BaseView view) { + super(view); + } + + public static FloatingVHPresenter with(@NonNull BaseFloatingMvp.BaseView view) { + return new FloatingVHPresenter(view); + } + + @Override public void onItemClick(int position, View v, AppsModel item) { + try { + Context context = v.getContext(); + PackageManager manager = context.getPackageManager(); + Intent intent = manager.getLaunchIntentForPackage(item.getPackageName()); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + context.startActivity(intent); + } catch (Exception e) {// app uninstalled/not found + e.printStackTrace(); + item.delete(); + } + super.onItemClick(position, v, item); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingVHView.java b/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingVHView.java new file mode 100644 index 0000000..a5e5d44 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/apps/FloatingVHView.java @@ -0,0 +1,56 @@ +package com.fastaccess.ui.modules.floating.apps; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v4.content.Loader; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.provider.loader.SelectedAppsLoader; +import com.fastaccess.ui.adapter.FloatingAppsAdapter; +import com.fastaccess.ui.adapter.viewholder.FloatingAppsViewHolder; +import com.fastaccess.ui.modules.floating.BaseFloatingView; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import java.util.ArrayList; + +/** + * Created by Kosh on 14 Oct 2016, 9:12 PM + */ + + +public class FloatingVHView extends BaseFloatingView { + private FloatingAppsAdapter adapter; + private SelectedAppsLoader appsLoader; + private FloatingVHPresenter presenter; + + protected FloatingVHView(@NonNull Context context, boolean isHorizontal) { + super(context, isHorizontal); + } + + public static FloatingVHView with(@NonNull Context context, boolean isHorizontal) { + return new FloatingVHView(context, isHorizontal); + } + + @Override public Loader getLoader() { + if (appsLoader == null) { + appsLoader = new SelectedAppsLoader(context); + appsLoader.registerListener(10, getPresenter()); + appsLoader.startLoading(); + } + return appsLoader; + } + + @Override public BaseRecyclerAdapter> getAdapter() { + if (adapter == null) { + adapter = new FloatingAppsAdapter(new ArrayList(), getPresenter(), isHorizontal); + } + return adapter; + } + + @Override public FloatingVHPresenter getPresenter() { + if (presenter == null) presenter = new FloatingVHPresenter(this); + return presenter; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersMvp.java b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersMvp.java new file mode 100644 index 0000000..dc0c4fc --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersMvp.java @@ -0,0 +1,21 @@ +package com.fastaccess.ui.modules.floating.folders; + +import android.support.annotation.NonNull; + +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.ui.modules.floating.BaseFloatingMvp; + +/** + * Created by Kosh on 14 Oct 2016, 8:54 PM + */ + +public interface FloatingFoldersMvp { + + interface View extends BaseFloatingMvp.BaseView { + void onOpenFolder(@NonNull android.view.View v, @NonNull FolderModel item); + } + + interface Presenter extends BaseFloatingMvp.BasePresenter { + + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersPresenter.java new file mode 100644 index 0000000..999d265 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersPresenter.java @@ -0,0 +1,28 @@ +package com.fastaccess.ui.modules.floating.folders; + +import android.support.annotation.NonNull; +import android.view.View; + +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.ui.modules.floating.BaseFloatingPresenter; + +/** + * Created by Kosh on 14 Oct 2016, 9:00 PM + */ + +public class FloatingFoldersPresenter extends BaseFloatingPresenter implements FloatingFoldersMvp + .Presenter { + + private FloatingFoldersPresenter(@NonNull FloatingFoldersMvp.View view) { + super(view); + } + + public static FloatingFoldersPresenter with(@NonNull FloatingFoldersMvp.View view) { + return new FloatingFoldersPresenter(view); + } + + @Override public void onItemClick(int position, View v, FolderModel item) { + super.onItemClick(position, v, item); + if (isAttached()) getView().onOpenFolder(v, item); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersView.java b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersView.java new file mode 100644 index 0000000..0e9e068 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/FloatingFoldersView.java @@ -0,0 +1,70 @@ +package com.fastaccess.ui.modules.floating.folders; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v4.content.Loader; +import android.view.View; + +import com.fastaccess.data.dao.FolderEventModel; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.provider.loader.FoldersLoader; +import com.fastaccess.ui.adapter.FloatingFoldersAdapter; +import com.fastaccess.ui.modules.floating.BaseFloatingMvp; +import com.fastaccess.ui.modules.floating.BaseFloatingPresenter; +import com.fastaccess.ui.modules.floating.BaseFloatingView; +import com.fastaccess.ui.modules.floating.folders.drawer.FloatingDrawerView; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; + +import org.greenrobot.eventbus.Subscribe; + +import java.util.ArrayList; + +/** + * Created by Kosh on 14 Oct 2016, 9:12 PM + */ + + +public class FloatingFoldersView extends BaseFloatingView implements FloatingFoldersMvp.View { + private FloatingFoldersPresenter presenter; + private FoldersLoader foldersLoader; + private FloatingFoldersAdapter adapter; + + private FloatingFoldersView(@NonNull Context context, boolean isHorizontal) { + super(context, isHorizontal); + } + + public static FloatingFoldersView with(@NonNull Context context, boolean isHorizontal) { + return new FloatingFoldersView(context, isHorizontal); + } + + @SuppressWarnings("unused") @Subscribe public void onEvent(FolderEventModel model) { + if (foldersLoader != null) foldersLoader.onContentChanged(); + } + + @Override public void onOpenFolder(@NonNull View v, @NonNull FolderModel item) { + FloatingDrawerView.with(this).onShow(windowManager, floatingView, item); + } + + @Override public Loader getLoader() { + if (foldersLoader == null) { + foldersLoader = new FoldersLoader(context); + foldersLoader.registerListener(10, getPresenter()); + foldersLoader.startLoading(); + } + return foldersLoader; + } + + @Override public BaseRecyclerAdapter getAdapter() { + if (adapter == null) { + adapter = new FloatingFoldersAdapter(new ArrayList(), getPresenter(), isHorizontal); + } + return adapter; + } + + @Override public BaseFloatingPresenter> getPresenter() { + if (presenter == null) { + presenter = FloatingFoldersPresenter.with(this); + } + return presenter; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawPresenter.java new file mode 100644 index 0000000..2cee50d --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawPresenter.java @@ -0,0 +1,50 @@ +package com.fastaccess.ui.modules.floating.folders.drawer; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.support.annotation.NonNull; +import android.support.v4.content.Loader; +import android.view.View; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +import java.util.List; + +/** + * Created by Kosh on 22 Oct 2016, 3:13 PM + */ + +public class FloatingDrawPresenter extends BasePresenter implements FloatingDrawerMvp.Presenter { + + protected FloatingDrawPresenter(@NonNull FloatingDrawerMvp.View view) { + super(view); + } + + public static FloatingDrawPresenter with(@NonNull FloatingDrawerMvp.View view) { + return new FloatingDrawPresenter(view); + } + + @Override public void onLoadComplete(Loader> loader, List data) { + if (isAttached()) getView().onAppsLoaded(data); + } + + @Override public void onItemClick(int position, View v, AppsModel item) { + try { + Context context = v.getContext(); + PackageManager manager = context.getPackageManager(); + Intent intent = manager.getLaunchIntentForPackage(item.getPackageName()); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + context.startActivity(intent); + } catch (Exception e) {// app uninstalled/not found + e.printStackTrace(); + item.delete(); + } + if (isAttached()) getView().onTouchedOutside(); + } + + @Override public void onItemLongClick(int position, View v, AppsModel item) { + onItemClick(position, v, item); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawerMvp.java new file mode 100644 index 0000000..8c6eb60 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawerMvp.java @@ -0,0 +1,37 @@ +package com.fastaccess.ui.modules.floating.folders.drawer; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.Loader; +import android.view.WindowManager; + +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; + +import java.util.List; + +/** + * Created by Kosh on 22 Oct 2016, 3:11 PM + */ + +public interface FloatingDrawerMvp { + + interface View { + + void onShow(@NonNull WindowManager windowManager, @NonNull android.view.View view, @NonNull FolderModel folder); + + void onAppsLoaded(@Nullable List models); + + void onConfigChanged(int orientation); + + void onTouchedOutside(); + + void onBackPressed(); + + void onDestroy(); + } + + interface Presenter extends BaseViewHolder.OnItemClickListener, + Loader.OnLoadCompleteListener> {} +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawerView.java b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawerView.java new file mode 100644 index 0000000..b12779a --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/floating/folders/drawer/FloatingDrawerView.java @@ -0,0 +1,145 @@ +package com.fastaccess.ui.modules.floating.folders.drawer; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Point; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.NinePatchDrawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; + +import com.fastaccess.R; +import com.fastaccess.data.dao.AppsModel; +import com.fastaccess.data.dao.FolderModel; +import com.fastaccess.data.dao.ThemePackEventModel; +import com.fastaccess.helper.ViewHelper; +import com.fastaccess.provider.loader.SelectedAppsLoader; +import com.fastaccess.ui.adapter.FloatingAppsAdapter; +import com.fastaccess.ui.adapter.viewholder.AppDrawerHolder; +import com.fastaccess.ui.modules.floating.folders.FloatingFoldersMvp; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.ArrayList; +import java.util.List; + +import static android.graphics.PixelFormat.TRANSLUCENT; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; +import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; +import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; + +/** + * Created by Kosh on 22 Oct 2016, 11:45 AM + */ + +public class FloatingDrawerView implements FloatingDrawerMvp.View { + + private WindowManager.LayoutParams originalParams; + private final FloatingFoldersMvp.View view; + private AppDrawerHolder drawerHolder; + private SelectedAppsLoader appsLoader; + private FloatingAppsAdapter adapter; + private WindowManager windowManager; + private FloatingDrawPresenter presenter; + + + private FloatingDrawerView(@NonNull FloatingFoldersMvp.View view) { + this.view = view; + EventBus.getDefault().register(this); + } + + public static FloatingDrawerView with(@NonNull FloatingFoldersMvp.View view) { + return new FloatingDrawerView(view); + } + + private void setupParams(@NonNull WindowManager windowManager) { + this.windowManager = windowManager; + originalParams = new WindowManager.LayoutParams(TYPE_PRIORITY_PHONE, + FLAG_WATCH_OUTSIDE_TOUCH | FLAG_NOT_TOUCH_MODAL, TRANSLUCENT); + Point szWindow = new Point(); + windowManager.getDefaultDisplay().getSize(szWindow); + updateParams(ViewHelper.isLandscape(drawerHolder.appDrawer.getResources()) ? 2 : 1, false); + originalParams.gravity = Gravity.CENTER; + windowManager.addView(drawerHolder.appDrawer, originalParams); + drawerHolder.appDrawer.animate().scaleX(1f).scaleY(1f); + } + + private void updateParams(int orientation, boolean update) { + Point szWindow = new Point(); + windowManager.getDefaultDisplay().getSize(szWindow); +// originalParams.width = MATCH_PARENT; +// originalParams.height = WRAP_CONTENT; + originalParams.width = orientation == Configuration.ORIENTATION_PORTRAIT ? szWindow.x - 50 : (szWindow.x - 150); + originalParams.height = orientation == Configuration.ORIENTATION_PORTRAIT ? (int) (szWindow.y / 1.8) : (szWindow.y - 200); + if (update) windowManager.updateViewLayout(drawerHolder.appDrawer, originalParams); + } + + @SuppressLint("InflateParams") + @Override public void onShow(@NonNull WindowManager windowManager, @NonNull View view, @NonNull FolderModel folder) { + this.windowManager = windowManager; + Context context = view.getContext(); + drawerHolder = new AppDrawerHolder(LayoutInflater.from(view.getContext()).inflate(R.layout.floating_folder_layout, null, false), this); + adapter = new FloatingAppsAdapter(new ArrayList(), getPresenter(), false); + drawerHolder.recycler.setAdapter(adapter); + drawerHolder.emptyText.setText(R.string.no_apps); + drawerHolder.recycler.setEmptyView(drawerHolder.emptyText); + NinePatchDrawable drawable = (NinePatchDrawable) drawerHolder.appDrawer.getBackground(); + drawable.setColorFilter(new PorterDuffColorFilter(folder.getColor(), + PorterDuff.Mode.MULTIPLY)); + setupParams(windowManager); + appsLoader = new SelectedAppsLoader(context, folder.getId()); + appsLoader.registerListener(folder.hashCode(), getPresenter()); + appsLoader.startLoading(); + } + + @Override public void onAppsLoaded(@Nullable List models) { + if (models != null) adapter.insertItems(models); + else adapter.clear(); + } + + @Override public void onConfigChanged(int orientation) { + updateParams(orientation, true); + } + + @Override public void onTouchedOutside() { + onDestroy(); + } + + @Override public void onBackPressed() { + onTouchedOutside(); + } + + @Override public void onDestroy() { + if (windowManager != null) { + if (drawerHolder != null && drawerHolder.appDrawer.isShown()) { + drawerHolder.appDrawer.animate().scaleY(0).scaleX(0).withEndAction(new Runnable() { + @Override public void run() { + windowManager.removeView(drawerHolder.appDrawer); + drawerHolder.onDestroy(); + if (appsLoader != null) appsLoader.unregisterListener(getPresenter()); + EventBus.getDefault().unregister(this); + getPresenter().onDestroy(); + } + }); + } + } + } + + @SuppressWarnings("unused") @Subscribe public void onEvent(ThemePackEventModel model) { + if (appsLoader != null) appsLoader.forceLoad(); + } + + private FloatingDrawPresenter getPresenter() { + if (presenter == null) { + presenter = FloatingDrawPresenter.with(this); + } + return presenter; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/MainMvp.java b/app/src/main/java/com/fastaccess/ui/modules/main/MainMvp.java new file mode 100644 index 0000000..ca6e163 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/main/MainMvp.java @@ -0,0 +1,87 @@ +package com.fastaccess.ui.modules.main; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.IntDef; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.NavigationView; +import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.widget.DrawerLayout; + +import com.fastaccess.ui.base.mvp.BaseMvp; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import it.sephiroth.android.library.bottomnavigation.BottomNavigation; +import it.sephiroth.android.library.bottomnavigation.BottomNavigation.OnMenuItemSelectionListener; + +/** + * Created by Kosh on 10 Oct 2016, 10:56 PM + */ + +public interface MainMvp { + + int DEVICE_APPS = 0; + int FOLDERS = 1; + int SELECTED_APPS = 2; + + @IntDef({ + DEVICE_APPS, + FOLDERS, + SELECTED_APPS, + }) + @Retention(RetentionPolicy.SOURCE) @interface NavigationType {} + + interface View { + void onNavigationChanged(@NavigationType int navType); + + void onOpenDrawer(); + + void onCloseDrawer(); + + void onOpenSettings(); + + void onStartService(); + + void onStopService(); + + void onShowBadge(@IdRes int itemId); + + void onHideBadge(@IdRes int itemId); + + void onSelectMenuItem(@IdRes int itemId); + + void onBackup(); + + void onRestore(); + } + + interface Presenter extends BaseMvp.FAPresenter, OnNavigationItemSelectedListener, OnMenuItemSelectionListener { + void onActivityStarted(@Nullable Bundle savedInstance, @NonNull MainView mainView, + @NonNull BottomNavigation bottomNavigation, + @NonNull NavigationView navigationView); + + boolean canBackPress(@NonNull DrawerLayout drawerLayout); + + void onModuleChanged(@NonNull FragmentManager fragmentManager, @NavigationType int type); + + void onShowHideFragment(@NonNull FragmentManager fragmentManager, @NonNull Fragment toShow, @NonNull Fragment toHide); + + void onAddAndHide(@NonNull FragmentManager fragmentManager, @NonNull Fragment toAdd, @NonNull Fragment toHide); + + void onFilterResult(@NonNull FragmentManager supportFragmentManager, @Nullable String text); + + void onCreateNewFolder(@NonNull FragmentManager supportFragmentManager); + + void onActivityForResult(int requestCode, int resultCode); + + void onHandleShortcuts(@NonNull MainView mainView, @Nullable Intent intent); + + void onBackupRestore(int backupType, @NonNull MainView mainView); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/MainPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/main/MainPresenter.java new file mode 100644 index 0000000..10c9c34 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/main/MainPresenter.java @@ -0,0 +1,212 @@ +package com.fastaccess.ui.modules.main; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.NavigationView; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.view.MenuItem; + +import com.fastaccess.R; +import com.fastaccess.helper.Bundler; +import com.fastaccess.helper.Logger; +import com.fastaccess.helper.PermissionsHelper; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.helper.TypeFaceHelper; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; +import com.fastaccess.ui.modules.apps.device.DeviceAppsView; +import com.fastaccess.ui.modules.apps.folders.FoldersView; +import com.fastaccess.ui.modules.apps.selected.SelectedAppsView; +import com.fastaccess.ui.modules.cloud.auth.LoginView; + +import it.sephiroth.android.library.bottomnavigation.BottomNavigation; + +import static com.fastaccess.helper.AppHelper.getFragmentByTag; +import static com.fastaccess.helper.AppHelper.getVisibleFragment; + +/** + * Created by Kosh on 10 Oct 2016, 11:13 PM + */ + +public class MainPresenter extends BasePresenter implements MainMvp.Presenter { + + public static MainPresenter with(MainMvp.View view) { + return new MainPresenter(view); + } + + protected MainPresenter(@NonNull MainMvp.View view) { + super(view); + } + + @Override public void onActivityStarted(@Nullable Bundle savedInstance, + @NonNull MainView mainView, + @NonNull BottomNavigation bottomNavigation, + @NonNull NavigationView navigationView) { + navigationView.setNavigationItemSelectedListener(this); + Typeface myTypeface = TypeFaceHelper.getTypeface(); + bottomNavigation.setDefaultTypeface(myTypeface); + bottomNavigation.setOnMenuItemClickListener(this); + if (savedInstance == null) { + bottomNavigation.setDefaultSelectedIndex(0); + } + } + + @Override public boolean canBackPress(@NonNull DrawerLayout drawerLayout) { + return !drawerLayout.isDrawerOpen(GravityCompat.START); + } + + @SuppressWarnings("ConstantConditions") + @Override public void onModuleChanged(@NonNull FragmentManager fragmentManager, @MainMvp.NavigationType int type) { + Logger.e(type); + Fragment currentVisible = getVisibleFragment(fragmentManager); + DeviceAppsView deviceAppsView = (DeviceAppsView) getFragmentByTag(fragmentManager, DeviceAppsView.TAG); + FoldersView foldersView = (FoldersView) getFragmentByTag(fragmentManager, FoldersView.TAG); + SelectedAppsView selectedAppsView = (SelectedAppsView) getFragmentByTag(fragmentManager, SelectedAppsView.TAG); + switch (type) { + case MainMvp.DEVICE_APPS: + if (deviceAppsView == null) { + onAddAndHide(fragmentManager, DeviceAppsView.newInstance(), currentVisible); + } else { + onShowHideFragment(fragmentManager, deviceAppsView, currentVisible); + } + break; + case MainMvp.FOLDERS: + if (foldersView == null) { + onAddAndHide(fragmentManager, FoldersView.newInstance(), currentVisible); + } else { + onShowHideFragment(fragmentManager, foldersView, currentVisible); + } + break; + case MainMvp.SELECTED_APPS: + if (selectedAppsView == null) { + onAddAndHide(fragmentManager, SelectedAppsView.newInstance(), currentVisible); + } else { + onShowHideFragment(fragmentManager, selectedAppsView, currentVisible); + } + break; + } + } + + @Override public void onShowHideFragment(@NonNull FragmentManager fragmentManager, @NonNull Fragment toShow, @NonNull Fragment toHide) { + Logger.e("show", toShow.getClass().getSimpleName(), "hide", toHide.getClass().getSimpleName()); + fragmentManager + .beginTransaction() + .hide(toHide) + .show(toShow) + .commit(); + } + + @Override public void onAddAndHide(@NonNull FragmentManager fragmentManager, @NonNull Fragment toAdd, @NonNull Fragment toHide) { + Logger.e("add", toAdd.getClass().getSimpleName(), "hide", toHide.getClass().getSimpleName()); + fragmentManager + .beginTransaction() + .hide(toHide) + .add(R.id.container, toAdd, toAdd.getClass().getSimpleName()) + .commit(); + } + + @Override public void onFilterResult(@NonNull FragmentManager supportFragmentManager, @Nullable String text) { + Fragment fragment = getVisibleFragment(supportFragmentManager); + Logger.e(fragment); + if (fragment != null) { + if (fragment instanceof DeviceAppsView) { + ((DeviceAppsView) fragment).onFilter(text); + } else if (fragment instanceof FoldersView) { + ((FoldersView) fragment).onFilter(text); + } else if (fragment instanceof SelectedAppsView) { + ((SelectedAppsView) fragment).onFilter(text); + } + } + } + + @Override public void onCreateNewFolder(@NonNull FragmentManager supportFragmentManager) { + Fragment foldersView = getVisibleFragment(supportFragmentManager); + if (!(foldersView instanceof FoldersView)) { + throw new RuntimeException("Oops, Folders Fragment is not currently visible."); + } + ((FoldersView) foldersView).onCreateNewFolder(); + } + + @Override public void onActivityForResult(int requestCode, int resultCode) { + if (requestCode == PermissionsHelper.OVERLAY_PERMISSION_REQ_CODE) { + if (isAttached() && resultCode == Activity.RESULT_OK) getView().onStartService(); + } + } + + @Override public void onHandleShortcuts(@NonNull MainView mainView, @Nullable Intent intent) { + if (intent != null && intent.getAction() != null) { + String action = intent.getAction(); + switch (action) { + case "FOLDER_MODE": + PrefHelper.set(PrefConstant.FLOATING_MODE, "Folders"); + if (isAttached()) { + getView().onStopService(); + getView().onStartService(); + } + break; + case "APPS_MODE": + PrefHelper.set(PrefConstant.FLOATING_MODE, "Apps"); + if (isAttached()) { + getView().onStopService(); + getView().onStartService(); + } + break; + } + } + } + + @Override public void onBackupRestore(int backupType, @NonNull MainView mainView) { + Intent intent = new Intent(mainView, LoginView.class); + intent.putExtras(Bundler.start().put(LoginView.TYPE, backupType).end()); + mainView.startActivity(intent); + } + + @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { + getView().onCloseDrawer(); + switch (item.getItemId()) { + case R.id.settings: + getView().onOpenSettings(); + return true; + case R.id.start: + getView().onStartService(); + return true; + case R.id.stop: + getView().onStopService(); + return true; + case R.id.myApps: + onMenuItemSelect(R.id.myApps, 0); + return true; + case R.id.folders: + onMenuItemSelect(R.id.folders, 1); + return true; + case R.id.selectedApps: + onMenuItemSelect(R.id.selectedApps, 2); + return true; + case R.id.backup: + getView().onBackup(); + break; + case R.id.restore: + getView().onRestore(); + break; + } + return false; + } + + @Override public void onMenuItemSelect(@IdRes int id, int position) { + if (isAttached()) { + getView().onNavigationChanged(position); + getView().onHideBadge(id); + getView().onSelectMenuItem(id); + } + } + + @Override public void onMenuItemReselect(@IdRes int id, int position) {} +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/MainView.java b/app/src/main/java/com/fastaccess/ui/modules/main/MainView.java new file mode 100644 index 0000000..e7bac7d --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/main/MainView.java @@ -0,0 +1,227 @@ +package com.fastaccess.ui.modules.main; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.NonNull; +import android.support.design.widget.AppBarLayout; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.NavigationView; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.text.Editable; +import android.view.MenuItem; +import android.view.View; +import android.widget.Toast; + +import com.fastaccess.R; +import com.fastaccess.helper.AnimHelper; +import com.fastaccess.helper.AppHelper; +import com.fastaccess.helper.NotificationHelper; +import com.fastaccess.helper.PermissionsHelper; +import com.fastaccess.provider.service.FloatingService; +import com.fastaccess.ui.base.BaseActivity; +import com.fastaccess.ui.modules.apps.device.DeviceAppsView; +import com.fastaccess.ui.modules.cloud.auth.LoginView; +import com.fastaccess.ui.modules.settings.SettingsView; +import com.fastaccess.ui.widgets.FontEditText; +import com.fastaccess.ui.widgets.ForegroundImageView; +import com.fastaccess.ui.widgets.dialog.MessageDialogView; + +import butterknife.BindView; +import butterknife.OnClick; +import butterknife.OnTextChanged; +import butterknife.OnTouch; +import icepick.State; +import it.sephiroth.android.library.bottomnavigation.BadgeProvider; +import it.sephiroth.android.library.bottomnavigation.BottomNavigation; + +public class MainView extends BaseActivity implements MainMvp.View { + public final static int BACKUP_REQUEST_CODE = 1; + public final static int RESTORE_REQUEST_CODE = 2; + + @MainMvp.NavigationType @State int navType; + + @BindView(R.id.searchEditText) FontEditText searchEditText; + @BindView(R.id.clear) ForegroundImageView clear; + @BindView(R.id.appbar) AppBarLayout appbar; + @BindView(R.id.coordinatorLayout) CoordinatorLayout coordinatorLayout; + @BindView(R.id.navigation) NavigationView navigation; + @BindView(R.id.drawerLayout) DrawerLayout drawerLayout; + @BindView(R.id.bottomNavigation) BottomNavigation bottomNavigation; + @BindView(R.id.fab) FloatingActionButton fab; + private MainPresenter presenter; + private BadgeProvider badgeProvider; + + + @OnClick(R.id.fab) void onClick() { + if (navType == MainMvp.FOLDERS) { + getPresenter().onCreateNewFolder(getSupportFragmentManager()); + } + } + + @OnTouch(R.id.searchEditText) boolean onTouch() { + appbar.setExpanded(false, true); + return false; + } + + @OnTextChanged(value = R.id.searchEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) void onTextChange(Editable s) { + String text = s.toString(); + if (text.length() == 0) { + getPresenter().onFilterResult(getSupportFragmentManager(), text); + AnimHelper.animateVisibility(clear, false); + } else { + AnimHelper.animateVisibility(clear, true); + getPresenter().onFilterResult(getSupportFragmentManager(), text); + } + } + + @OnClick(value = {R.id.searchIcon, R.id.clear}) void onClick(View view) { + if (view.getId() == R.id.clear) { + AppHelper.hideKeyboard(searchEditText); + searchEditText.setText(""); + } + } + + @Override protected int layout() { + return R.layout.activity_main; + } + + @NonNull @Override protected MainPresenter getPresenter() { + if (presenter == null) { + presenter = MainPresenter.with(this); + } + return presenter; + } + + @Override protected boolean isTransparent() { + return true; + } + + @Override protected boolean canBack() { + return false; + } + + @Override protected void onCreate(Bundle savedInstanceState) { + setTheme(R.style.AppTheme); + super.onCreate(savedInstanceState); + if (savedInstanceState == null) { + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.container, DeviceAppsView.newInstance(), DeviceAppsView.TAG) + .commit(); + getPresenter().onHandleShortcuts(this, getIntent()); + } + setToolbarIcon(R.drawable.ic_menu); + getPresenter().onActivityStarted(savedInstanceState, this, bottomNavigation, navigation); + if (null != savedInstanceState) getBadgeProvider().restore(savedInstanceState); + if (navType == MainMvp.FOLDERS) { + fab.show(); + } else { + fab.hide(); + } + } + + @Override public void onNavigationChanged(@MainMvp.NavigationType int navType) { + //noinspection WrongConstant + if (bottomNavigation.getSelectedIndex() != navType) bottomNavigation.setSelectedIndex(navType, true); + this.navType = navType; + getPresenter().onModuleChanged(getSupportFragmentManager(), navType); + if (navType == MainMvp.FOLDERS) { + fab.show(); + } else { + fab.hide(); + } + } + + @Override public void onOpenDrawer() { + if (!drawerLayout.isDrawerOpen(GravityCompat.START)) drawerLayout.openDrawer(GravityCompat.START); + } + + @Override public void onCloseDrawer() { + if (drawerLayout.isDrawerOpen(GravityCompat.START)) drawerLayout.closeDrawer(GravityCompat.START); + } + + @Override public void onOpenSettings() { + startActivity(new Intent(this, SettingsView.class)); + } + + @Override public void onStartService() { + if (PermissionsHelper.systemAlertPermissionIsGranted(this)) { + startService(new Intent(this, FloatingService.class)); + } else { + Toast.makeText(this, R.string.floating_window_warning, Toast.LENGTH_LONG).show(); + } + } + + @Override public void onStopService() { + stopService(new Intent(this, FloatingService.class)); + NotificationHelper.cancelAllNotifications(this); + } + + @Override public void onShowBadge(@IdRes int itemId) { + if (!getBadgeProvider().hasBadge(itemId)) { + getBadgeProvider().show(itemId); + } + } + + @Override public void onHideBadge(@IdRes int itemId) { + if (getBadgeProvider().hasBadge(itemId)) { + getBadgeProvider().remove(itemId); + } + } + + @Override public void onSelectMenuItem(@IdRes int itemId) { + navigation.getMenu().findItem(itemId).setChecked(true); + } + + @Override public void onBackup() { + MessageDialogView.newInstance(R.string.backup, R.string.backup_warning, BACKUP_REQUEST_CODE) + .show(getSupportFragmentManager(), "MessageDialogView"); + } + + @Override public void onRestore() { + MessageDialogView.newInstance(R.string.restore, R.string.restore_warning, RESTORE_REQUEST_CODE) + .show(getSupportFragmentManager(), "MessageDialogView"); + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onOpenDrawer(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override public void onBackPressed() { + if (getPresenter().canBackPress(drawerLayout)) { + super.onBackPressed(); + } else { + drawerLayout.closeDrawer(GravityCompat.START); + } + } + + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + getPresenter().onActivityForResult(requestCode, resultCode); + } + + @Override protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + getPresenter().onHandleShortcuts(this, intent); + } + + @NonNull private BadgeProvider getBadgeProvider() { + if (badgeProvider == null) { + badgeProvider = bottomNavigation.getBadgeProvider(); + } + return badgeProvider; + } + + @Override public void onMessageDialogActionClicked(boolean isOk, int requestCode) { + if (isOk) { + getPresenter().onBackupRestore(requestCode == BACKUP_REQUEST_CODE ? LoginView.BACKUP_TYPE : LoginView.RESTORE_TYPE, this); + } + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsFragmentView.java b/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsFragmentView.java new file mode 100644 index 0000000..a344c17 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsFragmentView.java @@ -0,0 +1,239 @@ +package com.fastaccess.ui.modules.settings; + +import android.Manifest; +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; +import android.support.v14.preference.SwitchPreference; +import android.support.v4.app.ActivityCompat; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.support.v7.preference.PreferenceGroupAdapter; +import android.view.View; +import android.widget.Toast; + +import com.fastaccess.App; +import com.fastaccess.BuildConfig; +import com.fastaccess.R; +import com.fastaccess.data.dao.FloatingEventModel; +import com.fastaccess.helper.ActivityHelper; +import com.fastaccess.helper.AppHelper; +import com.fastaccess.helper.FileHelper; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.helper.Logger; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.provider.icon.IconPackHelper; +import com.fastaccess.ui.modules.settings.dialogs.CustomIconChooserDialog; +import com.fastaccess.ui.modules.settings.dialogs.IconSizeTransparencyDialog; +import com.google.common.io.Files; +import com.theartofdev.edmodo.cropper.CropImage; +import com.theartofdev.edmodo.cropper.CropImageView; + +import org.greenrobot.eventbus.EventBus; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import pub.devrel.easypermissions.AfterPermissionGranted; +import pub.devrel.easypermissions.EasyPermissions; + +import static android.app.Activity.RESULT_OK; + +/** + * Created by Kosh on 15 Oct 2016, 10:49 PM + */ + +public class SettingsFragmentView extends PreferenceFragmentCompat implements Preference.OnPreferenceClickListener, SharedPreferences + .OnSharedPreferenceChangeListener, CustomIconChooserDialog.OnCustomIconChooseCallback, EasyPermissions.PermissionCallbacks { + + private Toast toast; + + private final static String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}; + + private void showToast(@StringRes int resId) { + if (toast != null) toast.cancel(); + toast = Toast.makeText(App.getInstance(), resId, Toast.LENGTH_LONG);//getContext() might be null when onSharedPreferenceChanged, weird + // behavior + toast.show(); + } + + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.fa_settings); + } + + @Override public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + setDivider(ActivityCompat.getDrawable(getActivity(), R.drawable.list_divider)); + setDividerHeight(1); + PreferenceGroupAdapter adapter = (PreferenceGroupAdapter) getListView().getAdapter(); + for (int i = 0; i < getListView().getAdapter().getItemCount(); i++) {//lazy global setOnPreferenceClickListener + Preference preference = adapter.getItem(i); + if (preference != null && !InputHelper.isEmpty(preference.getKey())) { + if (preference.getKey().equalsIgnoreCase("version")) { + preference.setSummary(BuildConfig.VERSION_NAME); + } else if (!(preference instanceof SwitchPreference) && !(preference instanceof ListPreference)) { + preference.setOnPreferenceClickListener(this); + } + } + } + } + + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == IconPackHelper.PICK_ICON) { + Bitmap bitmap = data.getParcelableExtra("icon"); + if (bitmap == null) { + Uri uri = data.getData(); + if (uri != null) { + File file = FileHelper.generateFile("fa_image_icon"); + try { + Files.copy(new File(uri.getPath()), file); + } catch (IOException e) { + e.printStackTrace(); + showToast(R.string.error_retrieving_icon); + return; + } + PrefHelper.set(PrefConstant.CUSTOM_ICON, file.getPath()); + EventBus.getDefault().post(new FloatingEventModel(true, PrefConstant.CUSTOM_ICON)); + } else { + showToast(R.string.error_retrieving_icon); + } + } else { + String path = AppHelper.saveBitmap(bitmap); + if (path == null) { + showToast(R.string.write_sdcard_explanation); + return; + } + PrefHelper.set(PrefConstant.CUSTOM_ICON, path); + EventBus.getDefault().post(new FloatingEventModel(true, PrefConstant.CUSTOM_ICON)); + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + } else if (requestCode == ActivityHelper.SELECT_PHOTO_REQUEST) { + CropImage.activity(data.getData()) + .setCropShape(CropImageView.CropShape.OVAL) + .setOutputUri(Uri.fromFile(FileHelper.generateFile("fa_image_icon"))) + .setAspectRatio(5, 5) + .setFixAspectRatio(true) + .setOutputCompressFormat(Bitmap.CompressFormat.PNG) + .start(getContext(), this); + } else if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) { + CropImage.ActivityResult result = CropImage.getActivityResult(data); + Uri resultUri = result.getUri(); + PrefHelper.set(PrefConstant.CUSTOM_ICON, new File(resultUri.getPath()).getPath()); + EventBus.getDefault().post(new FloatingEventModel(true, PrefConstant.CUSTOM_ICON)); + } + } else if (resultCode == Activity.RESULT_CANCELED) { + if (requestCode == IconPackHelper.PICK_ICON) { + if (data != null) { + boolean defaultIcon = data.getBooleanExtra("default", false); + if (defaultIcon) { + PrefHelper.set(PrefConstant.CUSTOM_ICON, ""); + EventBus.getDefault().post(new FloatingEventModel(true, PrefConstant.CUSTOM_ICON)); + } + } + } + } + + } + + @Override public boolean onPreferenceClick(Preference preference) { + switch (preference.getKey()) { + case "fa_background_alpha": + IconSizeTransparencyDialog.newInstance(true).show(getChildFragmentManager(), "IconSizeTransparencyDialog"); + return true; + case "icon_pack": + IconPackHelper.pickIconPack(this, false); + return true; + case "custom_icon": + new CustomIconChooserDialog().show(getChildFragmentManager(), "CustomIconChooserDialog"); + return true; + case "icon_alpha": + IconSizeTransparencyDialog.newInstance(false).show(getChildFragmentManager(), "IconSizeTransparencyDialog"); + return true; + case "manual_size": + IconSizeTransparencyDialog.newInstance(false, true).show(getChildFragmentManager(), "IconSizeTransparencyDialog"); + return true; + case "version": + return true; + case "sourceCode": + ActivityHelper.startCustomTab(getActivity()); + return true; + case "libraries": + ActivityHelper.startLibs(getActivity()); + return true; + } + return false; + } + + @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key == null) return; + if (key.equalsIgnoreCase(PrefConstant.STATUS_BAR_HIDDEN) || key.equalsIgnoreCase(PrefConstant.FA_IS_HORIZONTAL)) { + showToast(R.string.required_restart); + } else if (key.equalsIgnoreCase(PrefConstant.ICON_SIZE)) { + sharedPreferences.edit().putInt(PrefConstant.MANUAL_SIZE, 0).apply(); + } + EventBus.getDefault().post(new FloatingEventModel(true, key)); + } + + @Override public void onResume() { + super.onResume(); + PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this); + } + + @Override public void onPause() { + super.onPause(); + PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this); + } + + @Override public void onUserChoose(boolean isFromGallery) { + if (!isFromGallery) { + pickIcon(); + } else { + pickImage(); + } + } + + @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); + } + + @Override public void onPermissionsGranted(int requestCode, List perms) { + Logger.e(); + } + + @Override public void onPermissionsDenied(int requestCode, List perms) { + Logger.e(); + } + + @AfterPermissionGranted(IconPackHelper.PICK_ICON) private void pickIcon() { + if (EasyPermissions.hasPermissions(getContext(), permissions)) { + IconPackHelper.pickIconPack(this, true); + } else { + EasyPermissions.requestPermissions(this, getString(R.string.write_sdcard_explanation), + IconPackHelper.PICK_ICON, permissions); + } + } + + @AfterPermissionGranted(ActivityHelper.SELECT_PHOTO_REQUEST) private void pickImage() { + if (EasyPermissions.hasPermissions(getContext(), permissions)) { + ActivityHelper.startGalleryIntent(this); + } else { + EasyPermissions.requestPermissions(this, getString(R.string.write_sdcard_explanation), + ActivityHelper.SELECT_PHOTO_REQUEST, permissions); + } + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsView.java b/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsView.java new file mode 100644 index 0000000..915023a --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsView.java @@ -0,0 +1,30 @@ +package com.fastaccess.ui.modules.settings; + +import android.support.annotation.NonNull; + +import com.fastaccess.R; +import com.fastaccess.ui.base.BaseActivity; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +/** + * Created by Kosh on 15 Oct 2016, 10:52 PM + */ + +public class SettingsView extends BaseActivity { + + @Override protected int layout() { + return R.layout.settings_layout; + } + + @NonNull @Override protected BasePresenter getPresenter() { + return null; + }//op-out + + @Override protected boolean isTransparent() { + return false; + } + + @Override protected boolean canBack() { + return true; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/CropImageActivityDialog.java b/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/CropImageActivityDialog.java new file mode 100644 index 0000000..addb4c9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/CropImageActivityDialog.java @@ -0,0 +1,72 @@ +package com.fastaccess.ui.modules.settings.dialogs; + +import android.support.annotation.NonNull; + +import com.fastaccess.R; +import com.fastaccess.ui.base.BaseActivity; +import com.fastaccess.ui.base.mvp.presenter.BasePresenter; + +/** + * Created by Kosh on 20 Oct 2016, 8:29 PM + */ + +public class CropImageActivityDialog extends BaseActivity { +// +// @BindView(R.id.done) ForegroundImageView done; +// @BindView(R.id.cutterImageView) CookieCutterImageView cutterImageView; +// @State Uri uri; +// +// @OnClick(R.id.done) void onDone() { +// Bitmap bitmap = cutterImageView.getCroppedBitmap(); +// if (bitmap != null) { +// Bitmap circularBitmap = ImageUtils.getCircularBitmap(bitmap); +// String path = AppHelper.saveBitmap(circularBitmap); +// if (path == null) { +// Toast.makeText(this, R.string.write_sdcard_explanation, Toast.LENGTH_SHORT).show(); +// return; +// } +// PrefHelper.set(PrefConstant.CUSTOM_ICON, path); +// EventBus.getDefault().post(new FloatingEventModel(true, PrefConstant.CUSTOM_ICON)); +// if (!bitmap.isRecycled() && !circularBitmap.isRecycled()) { +// bitmap.recycle(); +// circularBitmap.recycle(); +// } +// } +// finish(); +// } + + @Override protected int layout() { + return R.layout.crop_image_layout; + } + + @NonNull @Override protected BasePresenter getPresenter() { + return null; + } + + @Override protected boolean isTransparent() { + return false; + } + + @Override protected boolean canBack() { + return true; + } + +// @Override public void onCreate(@Nullable Bundle savedInstanceState) { +// super.onCreate(savedInstanceState); +// if (savedInstanceState == null) { +// uri = getIntent().getExtras().getParcelable("uri"); +// } +// if (uri == null) { +// finish(); +// return; +// } +// Bitmap bitmap = AppHelper.getBitmapFromUri(uri, this); +// if (bitmap != null) { +// cutterImageView.getParams().setShape(CookieCutterShape.CIRCLE); +// cutterImageView.invalidate(); +// cutterImageView.setImageBitmap(bitmap); +// } else { +// finish(); +// } +// } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/CustomIconChooserDialog.java b/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/CustomIconChooserDialog.java new file mode 100644 index 0000000..6d813c5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/CustomIconChooserDialog.java @@ -0,0 +1,54 @@ +package com.fastaccess.ui.modules.settings.dialogs; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.view.View; +import android.widget.FrameLayout; + +import com.fastaccess.R; +import com.fastaccess.ui.base.BaseBottomSheetDialog; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Created by Kosh on 19 Oct 2016, 8:08 PM + */ + +public class CustomIconChooserDialog extends BaseBottomSheetDialog { + + @BindView(R.id.fromIconPack) FrameLayout fromIconPack; + @BindView(R.id.fromGallery) FrameLayout fromGallery; + + public interface OnCustomIconChooseCallback { + void onUserChoose(boolean isFromGallery); + } + + private OnCustomIconChooseCallback callback; + + @OnClick(value = {R.id.fromIconPack, R.id.fromGallery}) void onClick(View view) { + callback.onUserChoose(view.getId() == R.id.fromGallery); + dismiss(); + } + + @Override public void onAttach(Context context) { + super.onAttach(context); + if (!(getParentFragment() instanceof OnCustomIconChooseCallback)) { + throw new RuntimeException("Parent Fragment must implement OnCustomIconChooseCallback"); + } + callback = (OnCustomIconChooseCallback) getParentFragment(); + } + + @Override public void onDetach() { + super.onDetach(); + callback = null; + } + + @Override protected int layoutRes() { + return R.layout.icon_chooser_layout; + } + + @Override protected void onViewCreated(@NonNull View view) { + + } +} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/IconSizeTransparencyDialog.java b/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/IconSizeTransparencyDialog.java new file mode 100644 index 0000000..c32117f --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/modules/settings/dialogs/IconSizeTransparencyDialog.java @@ -0,0 +1,105 @@ +package com.fastaccess.ui.modules.settings.dialogs; + +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.Toolbar; +import android.view.View; + +import com.fastaccess.R; +import com.fastaccess.helper.Bundler; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.fastaccess.helper.ViewHelper; +import com.fastaccess.ui.base.BaseBottomSheetDialog; +import com.fastaccess.ui.widgets.FontTextView; +import com.fastaccess.ui.widgets.ForegroundImageView; + +import org.adw.library.widgets.discreteseekbar.DiscreteSeekBar; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Created by Kosh on 16 Oct 2016, 6:46 PM + */ + +public class IconSizeTransparencyDialog extends BaseBottomSheetDialog implements DiscreteSeekBar.OnProgressChangeListener { + + @BindView(R.id.done) ForegroundImageView done; + @BindView(R.id.valueText) FontTextView valueText; + @BindView(R.id.seekBar) DiscreteSeekBar seekBar; + @BindView(R.id.toolbar) Toolbar toolbar; + private boolean isBackground; + private boolean isSize; + + public static IconSizeTransparencyDialog newInstance(boolean isBackground) { + IconSizeTransparencyDialog dialog = new IconSizeTransparencyDialog(); + dialog.setArguments(Bundler.start().put("isBackground", isBackground).end()); + return dialog; + } + + public static IconSizeTransparencyDialog newInstance(boolean isBackground, boolean isSize) { + IconSizeTransparencyDialog dialog = new IconSizeTransparencyDialog(); + dialog.setArguments(Bundler.start().put("isBackground", isBackground).put("isSize", isSize).end()); + return dialog; + } + + @OnClick(R.id.done) void onDone() { + if (!isSize) { + PrefHelper.set(isBackground ? PrefConstant.FA_BACKGROUND_ALPHA : PrefConstant.ICON_ALPHA, seekBar.getProgress()); + } else { + PrefHelper.set(PrefConstant.MANUAL_SIZE, seekBar.getProgress()); + } + dismiss(); + } + + @Override protected int layoutRes() { + return R.layout.transparency_layout; + } + + @Override public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + isSize = getArguments().getBoolean("isSize"); + isBackground = getArguments().getBoolean("isBackground"); + } + + @Override protected void onViewCreated(@NonNull View view) { + if (isSize) toolbar.setTitle(R.string.change_size); + seekBar.setOnProgressChangeListener(this); + if (isSize) { + seekBar.setMin(100); + seekBar.setMax(300); + seekBar.setProgress(PrefHelper.getInt(PrefConstant.MANUAL_SIZE)); + } else { + seekBar.setProgress(PrefHelper.getInt(isBackground ? PrefConstant.FA_BACKGROUND_ALPHA : PrefConstant.ICON_ALPHA)); + } + } + + @Override public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) { + changeIconAlpha(value); + } + + private void changeIconAlpha(int value) { + valueText.setText(String.format("%s: %s", getString(R.string.value), value)); + Drawable drawable = valueText.getCompoundDrawables()[2];//end drawable + if (!isSize) { + if (drawable != null) drawable.setAlpha(value); + } else { + if (drawable != null) { + int height = ViewHelper.toPx(getContext(), value); + drawable.setBounds(0, 0, height, height); + valueText.getLayoutParams().height = height; + } + } + } + + @Override public void onStartTrackingTouch(DiscreteSeekBar seekBar) { + + } + + @Override public void onStopTrackingTouch(DiscreteSeekBar seekBar) { + + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/AppbarRefreshLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/AppbarRefreshLayout.java new file mode 100644 index 0000000..962432f --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/AppbarRefreshLayout.java @@ -0,0 +1,56 @@ +package com.fastaccess.ui.widgets; + +import android.app.Activity; +import android.content.Context; +import android.support.design.widget.AppBarLayout; +import android.support.v4.widget.SwipeRefreshLayout; +import android.util.AttributeSet; + +import com.fastaccess.R; + + +/** + * Created by kosh on 7/30/2015. CopyRights @ Innov8tif + */ +public class AppbarRefreshLayout extends SwipeRefreshLayout implements AppBarLayout.OnOffsetChangedListener { + private AppBarLayout appBarLayout; + private boolean isReallyDisabled = false; + + public AppbarRefreshLayout(Context context) { + super(context, null); + } + + public AppbarRefreshLayout(Context context, AttributeSet attrs) { + super(context, attrs); + setColorSchemeResources(R.color.primary, R.color.primary_dark, R.color.primary_light, R.color.accent); + } + + public void setReallyDisable() { + this.setEnabled(false); + isReallyDisabled = true; + } + + @Override protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (getContext() instanceof Activity) { + appBarLayout = (AppBarLayout) ((Activity) getContext()).findViewById(R.id.appbar); + if (appBarLayout != null) { + appBarLayout.addOnOffsetChangedListener(this); + } + } + } + + @Override protected void onDetachedFromWindow() { + if (appBarLayout != null) { + appBarLayout.removeOnOffsetChangedListener(this); + appBarLayout = null; + } + super.onDetachedFromWindow(); + } + + @Override public void onOffsetChanged(AppBarLayout appBarLayout, int i) { + if (!isReallyDisabled) { + this.setEnabled(i == 0); + } + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FastBitmapDrawable.java b/app/src/main/java/com/fastaccess/ui/widgets/FastBitmapDrawable.java new file mode 100644 index 0000000..cea095f --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FastBitmapDrawable.java @@ -0,0 +1,221 @@ +package com.fastaccess.ui.widgets; + +import android.animation.ObjectAnimator; +import android.animation.TimeInterpolator; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.util.SparseArray; + +public class FastBitmapDrawable extends Drawable { + + private static final TimeInterpolator CLICK_FEEDBACK_INTERPOLATOR = new TimeInterpolator() { + @Override public float getInterpolation(float input) { + if (input < 0.05f) { + return input / 0.05f; + } else if (input < 0.3f) { + return 1; + } else { + return (1 - input) / 0.7f; + } + } + }; + private static final long CLICK_FEEDBACK_DURATION = 500; + private static final int PRESSED_BRIGHTNESS = 100; + private static ColorMatrix sGhostModeMatrix; + private static final ColorMatrix sTempMatrix = new ColorMatrix(); + /** + * Store the brightness colors filters to optimize animations during icon press. This only works for non-ghost-mode icons. + */ + private static final SparseArray sCachedBrightnessFilter = new SparseArray<>(); + + private static final int GHOST_MODE_MIN_COLOR_RANGE = 130; + + private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); + private final Bitmap mBitmap; + private int mAlpha; + + private int mBrightness = 0; + private boolean mGhostModeEnabled = false; + + private boolean mPressed = false; + private ObjectAnimator mPressedAnimator; + + public FastBitmapDrawable(Bitmap b) { + mAlpha = 255; + mBitmap = b; + setBounds(0, 0, b.getWidth(), b.getHeight()); + } + + @Override + public void draw(@NonNull Canvas canvas) { + final Rect r = getBounds(); + // Draw the bitmap into the bounding rect + canvas.drawBitmap(mBitmap, null, r, mPaint); + } + + @Override + public void setColorFilter(ColorFilter cf) { + // No op + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public void setAlpha(int alpha) { + mAlpha = alpha; + mPaint.setAlpha(alpha); + } + + @Override + public void setFilterBitmap(boolean filterBitmap) { + mPaint.setFilterBitmap(filterBitmap); + mPaint.setAntiAlias(filterBitmap); + } + + public int getAlpha() { + return mAlpha; + } + + @Override + public int getIntrinsicWidth() { + int width = getBounds().width(); + if (width == 0) { + width = mBitmap.getWidth(); + } + return width; + } + + @Override + public int getIntrinsicHeight() { + int height = getBounds().height(); + if (height == 0) { + height = mBitmap.getHeight(); + } + return height; + } + + @Override + public int getMinimumWidth() { + return getBounds().width(); + } + + @Override + public int getMinimumHeight() { + return getBounds().height(); + } + + public Bitmap getBitmap() { + return mBitmap; + } + + /** + * When enabled, the icon is grayed out and the contrast is increased to give it a 'ghost' appearance. + */ + public void setGhostModeEnabled(boolean enabled) { + if (mGhostModeEnabled != enabled) { + mGhostModeEnabled = enabled; + updateFilter(); + } + } + + public void setPressed(boolean pressed) { + if (mPressed != pressed) { + mPressed = pressed; + if (mPressed) { + mPressedAnimator = ObjectAnimator + .ofInt(this, "brightness", PRESSED_BRIGHTNESS) + .setDuration(CLICK_FEEDBACK_DURATION); + mPressedAnimator.setInterpolator(CLICK_FEEDBACK_INTERPOLATOR); + mPressedAnimator.start(); + } else if (mPressedAnimator != null) { + mPressedAnimator.cancel(); + setBrightness(0); + } + } + invalidateSelf(); + } + + public boolean isPressed() { + return mPressed; + } + + public boolean isGhostModeEnabled() { + return mGhostModeEnabled; + } + + public int getBrightness() { + return mBrightness; + } + + public void setBrightness(int brightness) { + if (mBrightness != brightness) { + mBrightness = brightness; + updateFilter(); + invalidateSelf(); + } + } + + private void updateFilter() { + if (mGhostModeEnabled) { + if (sGhostModeMatrix == null) { + sGhostModeMatrix = new ColorMatrix(); + sGhostModeMatrix.setSaturation(0); + + // For ghost mode, set the color range to [GHOST_MODE_MIN_COLOR_RANGE, 255] + float range = (255 - GHOST_MODE_MIN_COLOR_RANGE) / 255.0f; + sTempMatrix.set(new float[]{ + range, 0, 0, 0, GHOST_MODE_MIN_COLOR_RANGE, + 0, range, 0, 0, GHOST_MODE_MIN_COLOR_RANGE, + 0, 0, range, 0, GHOST_MODE_MIN_COLOR_RANGE, + 0, 0, 0, 1, 0}); + sGhostModeMatrix.preConcat(sTempMatrix); + } + + if (mBrightness == 0) { + mPaint.setColorFilter(new ColorMatrixColorFilter(sGhostModeMatrix)); + } else { + setBrightnessMatrix(sTempMatrix, mBrightness); + sTempMatrix.postConcat(sGhostModeMatrix); + mPaint.setColorFilter(new ColorMatrixColorFilter(sTempMatrix)); + } + } else if (mBrightness != 0) { + ColorFilter filter = sCachedBrightnessFilter.get(mBrightness); + if (filter == null) { + filter = new PorterDuffColorFilter(Color.argb(mBrightness, 255, 255, 255), + PorterDuff.Mode.SRC_ATOP); + sCachedBrightnessFilter.put(mBrightness, filter); + } + mPaint.setColorFilter(filter); + } else { + mPaint.setColorFilter(null); + } + } + + private static void setBrightnessMatrix(ColorMatrix matrix, int brightness) { + // Brightness: C-new = C-old*(1-amount) + amount + float scale = 1 - brightness / 255.0f; + matrix.setScale(scale, scale, scale, 1); + float[] array = matrix.getArray(); + + // Add the amount to RGB components of the matrix, as per the above formula. + // Fifth elements in the array correspond to the constant being added to + // red, blue, green, and alpha channel respectively. + array[4] = brightness; + array[9] = brightness; + array[14] = brightness; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FitWidthImageView.java b/app/src/main/java/com/fastaccess/ui/widgets/FitWidthImageView.java new file mode 100644 index 0000000..8d5092b --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FitWidthImageView.java @@ -0,0 +1,60 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.ImageView; + +/** + * Created by kosh on 12/7/2014. CopyRights @ innov8tif.com + */ +public class FitWidthImageView extends ImageView { + + /** + * Instantiates a new Fit width image. + * + * @param paramContext + * the param context + */ + public FitWidthImageView(Context paramContext) { + super(paramContext); + + } + + /** + * Instantiates a new Fit width image. + * + * @param paramContext + * the param context + * @param paramAttributeSet + * the param attribute set + */ + public FitWidthImageView(Context paramContext, AttributeSet paramAttributeSet) { + super(paramContext, paramAttributeSet); + } + + /** + * Instantiates a new Fit width image. + * + * @param paramContext + * the param context + * @param paramAttributeSet + * the param attribute set + * @param paramInt + * the param int + */ + public FitWidthImageView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) { + super(paramContext, paramAttributeSet, paramInt); + } + + @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { + final Drawable d = this.getDrawable(); + if (d != null) { + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = width * d.getIntrinsicHeight() / d.getIntrinsicWidth(); + setMeasuredDimension(width, height); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontAutoCompleteEditText.java b/app/src/main/java/com/fastaccess/ui/widgets/FontAutoCompleteEditText.java new file mode 100644 index 0000000..04da4d1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FontAutoCompleteEditText.java @@ -0,0 +1,48 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.support.annotation.ColorRes; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.AppCompatAutoCompleteTextView; +import android.util.AttributeSet; +import android.widget.AdapterView; + +import com.fastaccess.helper.TypeFaceHelper; +import com.fastaccess.helper.ViewHelper; + +/** + * Created by Kosh on 8/18/2015. copyrights are reserved + */ +public class FontAutoCompleteEditText extends AppCompatAutoCompleteTextView { + + public FontAutoCompleteEditText(Context context) { + super(context); + init(); + } + + public FontAutoCompleteEditText(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + + } + + public FontAutoCompleteEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + if (isInEditMode()) return; + TypeFaceHelper.applyTypeface(this); + } + + public void setTextColor(@ColorRes int normalColor, @ColorRes int pressedColor) { + int nColor = ContextCompat.getColor(getContext(), normalColor); + int pColor = ContextCompat.getColor(getContext(), pressedColor); + setTextColor(ViewHelper.textSelector(nColor, pColor)); + } + + @Override public void setOnItemClickListener(AdapterView.OnItemClickListener l) { + super.setOnItemClickListener(l); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontButton.java b/app/src/main/java/com/fastaccess/ui/widgets/FontButton.java new file mode 100644 index 0000000..da926d6 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FontButton.java @@ -0,0 +1,50 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.support.annotation.ColorRes; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.AppCompatButton; +import android.util.AttributeSet; + +import com.fastaccess.helper.TypeFaceHelper; +import com.fastaccess.helper.ViewHelper; + + +/** + * Created by Kosh on 8/18/2015. copyrights are reserved + */ +public class FontButton extends AppCompatButton { + + public FontButton(Context context) { + super(context); + init(); + } + + public FontButton(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public FontButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + if (isInEditMode()) return; + TypeFaceHelper.applyTypeface(this); + } + + public void setBackground(@ColorRes int normalColor, @ColorRes int pressedColor) { + int nColor = ContextCompat.getColor(getContext(), normalColor); + int pColor = ContextCompat.getColor(getContext(), pressedColor); + setBackgroundDrawable(ViewHelper.getDrawableSelector(nColor, pColor)); + } + + public void setTextColor(@ColorRes int normalColor, @ColorRes int pressedColor) { + int nColor = ContextCompat.getColor(getContext(), normalColor); + int pColor = ContextCompat.getColor(getContext(), pressedColor); + setTextColor(ViewHelper.textSelector(nColor, pColor)); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontCheckbox.java b/app/src/main/java/com/fastaccess/ui/widgets/FontCheckbox.java new file mode 100644 index 0000000..abe0560 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FontCheckbox.java @@ -0,0 +1,43 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.support.annotation.ColorRes; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.AppCompatCheckBox; +import android.util.AttributeSet; + +import com.fastaccess.helper.TypeFaceHelper; +import com.fastaccess.helper.ViewHelper; + + +/** + * Created by Kosh on 8/18/2015. copyrights are reserved + */ +public class FontCheckbox extends AppCompatCheckBox { + + public FontCheckbox(Context context) { + super(context); + init(); + } + + public FontCheckbox(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public FontCheckbox(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + if (isInEditMode()) return; + TypeFaceHelper.applyTypeface(this); + } + + public void setTextColor(@ColorRes int normalColor, @ColorRes int pressedColor) { + int nColor = ContextCompat.getColor(getContext(), normalColor); + int pColor = ContextCompat.getColor(getContext(), pressedColor); + setTextColor(ViewHelper.textSelector(nColor, pColor)); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontEditText.java b/app/src/main/java/com/fastaccess/ui/widgets/FontEditText.java new file mode 100644 index 0000000..c53a0ad --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FontEditText.java @@ -0,0 +1,46 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.support.annotation.ColorRes; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.AppCompatEditText; +import android.util.AttributeSet; +import android.view.inputmethod.EditorInfo; + +import com.fastaccess.helper.TypeFaceHelper; +import com.fastaccess.helper.ViewHelper; + +/** + * Created by Kosh on 8/18/2015. copyrights are reserved + */ +public class FontEditText extends AppCompatEditText { + + public FontEditText(Context context) { + super(context); + init(); + } + + public FontEditText(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + + } + + public FontEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + if (isInEditMode()) return; + setInputType(getInputType() | EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN); + setImeOptions(getImeOptions() | EditorInfo.IME_FLAG_NO_FULLSCREEN); + TypeFaceHelper.applyTypeface(this); + } + + public void setTextColor(@ColorRes int normalColor, @ColorRes int pressedColor) { + int nColor = ContextCompat.getColor(getContext(), normalColor); + int pColor = ContextCompat.getColor(getContext(), pressedColor); + setTextColor(ViewHelper.textSelector(nColor, pColor)); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontFitTextView.java b/app/src/main/java/com/fastaccess/ui/widgets/FontFitTextView.java new file mode 100644 index 0000000..0a8d05c --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FontFitTextView.java @@ -0,0 +1,86 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.util.DisplayMetrics; + +/** + * Created by Kosh on 29 Apr 2016, 5:47 PM + */ +public class FontFitTextView extends FontTextView { + private Paint paint; + + public FontFitTextView(Context var1) { + super(var1); + this.init(); + } + + public FontFitTextView(Context var1, AttributeSet var2) { + super(var1, var2); + this.init(); + } + + @Override protected void onMeasure(int var1, int var2) { + super.onMeasure(var1, var2); + var1 = MeasureSpec.getSize(var1); + var2 = this.getMeasuredHeight(); + this.resize(this.getText().toString(), var1); + this.setMeasuredDimension(var1, var2); + } + + @Override protected void onTextChanged(CharSequence var1, int var2, int var3, int var4) { + this.resize(var1.toString(), this.getWidth()); + } + + @Override protected void onSizeChanged(int var1, int var2, int var3, int var4) { + if (var1 != var3) { + this.resize(this.getText().toString(), var1); + } + + } + + private void init() { + this.paint = new Paint(); + this.paint.set(this.getPaint()); + } + + private void resize(String var1, int var2) { + if (var2 > 0) { + var2 = var2 - this.getPaddingLeft() - this.getPaddingRight(); + DisplayMetrics var3 = this.getResources().getDisplayMetrics(); + float var4 = 32.0F * var3.density; + float var11 = 6.0F * var3.density; + this.paint.set(this.getPaint()); + + while (var4 - var11 > 0.5F) { + float var5 = (var4 + var11) / 2.0F; + this.paint.setTextSize(var5); + FontFitTextView var6 = this; + float var7; + String[] var8; + if ((var8 = var1.split("\n")) != null && var8.length != 0) { + var7 = this.paint.measureText(var8[0]); + + for (int var9 = 1; var9 < var8.length; ++var9) { + float var10; + if ((var10 = var6.paint.measureText(var8[var9])) > var7) { + var7 = var10; + } + } + } else { + var7 = this.paint.measureText(var1); + } + + if (var7 >= (float) var2) { + var4 = var5; + } else { + var11 = var5; + } + } + + this.setTextSize(0, var11); + } + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontRadioButton.java b/app/src/main/java/com/fastaccess/ui/widgets/FontRadioButton.java new file mode 100644 index 0000000..2295227 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FontRadioButton.java @@ -0,0 +1,43 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.support.annotation.ColorRes; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.AppCompatRadioButton; +import android.util.AttributeSet; + +import com.fastaccess.helper.TypeFaceHelper; +import com.fastaccess.helper.ViewHelper; + + +/** + * Created by Kosh on 8/18/2015. copyrights are reserved + */ +public class FontRadioButton extends AppCompatRadioButton { + + public FontRadioButton(Context context) { + super(context); + init(); + } + + public FontRadioButton(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public FontRadioButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + if (isInEditMode()) return; + TypeFaceHelper.applyTypeface(this); + } + + public void setTextColor(@ColorRes int normalColor, @ColorRes int pressedColor) { + int nColor = ContextCompat.getColor(getContext(), normalColor); + int pColor = ContextCompat.getColor(getContext(), pressedColor); + setTextColor(ViewHelper.textSelector(nColor, pColor)); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontTextView.java b/app/src/main/java/com/fastaccess/ui/widgets/FontTextView.java new file mode 100644 index 0000000..fd0fe59 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/FontTextView.java @@ -0,0 +1,45 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.support.annotation.ColorRes; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.AppCompatTextView; +import android.util.AttributeSet; + +import com.fastaccess.helper.TypeFaceHelper; +import com.fastaccess.helper.ViewHelper; + + +/** + * Created by Kosh on 8/18/2015. copyrights are reserved + */ +public class FontTextView extends AppCompatTextView { + + public FontTextView(Context context) { + super(context); + init(); + } + + public FontTextView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + + } + + public FontTextView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + if (isInEditMode()) return; + TypeFaceHelper.applyTypeface(this); + } + + public void setTextColor(@ColorRes int normalColor, @ColorRes int pressedColor) { + int nColor = ContextCompat.getColor(getContext(), normalColor); + int pColor = ContextCompat.getColor(getContext(), pressedColor); + setTextColor(ViewHelper.textSelector(nColor, pColor)); + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/ForegroundImageView.java b/app/src/main/java/com/fastaccess/ui/widgets/ForegroundImageView.java new file mode 100644 index 0000000..5021b7a --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/ForegroundImageView.java @@ -0,0 +1,115 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.AppCompatImageView; +import android.util.AttributeSet; + +import com.fastaccess.R; + + +/** + * Created by Kosh on 22/11/15 2:29 PM. Fast Access + */ +public class ForegroundImageView extends AppCompatImageView { + private Drawable foreground; + + public ForegroundImageView(Context context) { + this(context, null); + } + + public ForegroundImageView(Context context, AttributeSet attrs) { + super(context, attrs, 0); + } + + public ForegroundImageView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ForegroundImageView); + Drawable foreground = a.getDrawable(R.styleable.ForegroundImageView_android_foreground); + if (foreground != null) { + setForeground(foreground); + } + a.recycle(); + } + + /** + * Supply a drawable resource that is to be rendered on top of all of the child views in the frame layout. + * + * @param drawableResId + * The drawable resource to be drawn on top of the children. + */ + public void setForegroundResource(int drawableResId) { + if (isInEditMode()) return; + setForeground(ContextCompat.getDrawable(getContext(), drawableResId)); + } + + /** + * Supply a Drawable that is to be rendered on top of all of the child views in the frame layout. + * + * @param drawable + * The Drawable to be drawn on top of the children. + */ + public void setForeground(Drawable drawable) { + if (foreground == drawable) { + return; + } + if (foreground != null) { + foreground.setCallback(null); + unscheduleDrawable(foreground); + } + + foreground = drawable; + + if (drawable != null) { + drawable.setCallback(this); + if (drawable.isStateful()) { + drawable.setState(getDrawableState()); + } + } + requestLayout(); + invalidate(); + } + + @Override protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == foreground; + } + + @Override public void jumpDrawablesToCurrentState() { + super.jumpDrawablesToCurrentState(); + if (foreground != null) foreground.jumpToCurrentState(); + } + + @Override protected void drawableStateChanged() { + super.drawableStateChanged(); + if (foreground != null && foreground.isStateful()) { + foreground.setState(getDrawableState()); + } + } + + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (foreground != null) { + foreground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + invalidate(); + } + } + + @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (foreground != null) { + foreground.setBounds(0, 0, w, h); + invalidate(); + } + } + + @Override public void draw(Canvas canvas) { + super.draw(canvas); + + if (foreground != null) { + foreground.draw(canvas); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/NestedCoordinatorLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/NestedCoordinatorLayout.java new file mode 100644 index 0000000..96b65b2 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/NestedCoordinatorLayout.java @@ -0,0 +1,110 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.support.design.widget.CoordinatorLayout; +import android.support.v4.view.NestedScrollingChild; +import android.support.v4.view.NestedScrollingChildHelper; +import android.util.AttributeSet; +import android.view.View; + +/** + * Created by Kosh on 13 Aug 2016, 1:11 PM + */ + +public class NestedCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild { + + private NestedScrollingChildHelper mChildHelper; + + public NestedCoordinatorLayout(Context context) { + super(context); + mChildHelper = new NestedScrollingChildHelper(this); + setNestedScrollingEnabled(true); + } + + public NestedCoordinatorLayout(Context context, AttributeSet attrs) { + super(context, attrs); + mChildHelper = new NestedScrollingChildHelper(this); + setNestedScrollingEnabled(true); + } + + public NestedCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mChildHelper = new NestedScrollingChildHelper(this); + setNestedScrollingEnabled(true); + } + + @Override public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { + /* Enable the scrolling behavior of our own children */ + boolean tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes); + /* Enable the scrolling behavior of the parent's other children */ + return startNestedScroll(nestedScrollAxes) || tHandled; + } + + @Override public void onStopNestedScroll(View target) { + /* Disable the scrolling behavior of our own children */ + super.onStopNestedScroll(target); + /* Disable the scrolling behavior of the parent's other children */ + stopNestedScroll(); + } + + @Override public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { + int[][] tConsumed = new int[2][2]; + super.onNestedPreScroll(target, dx, dy, tConsumed[0]); + dispatchNestedPreScroll(dx, dy, tConsumed[1], null); + consumed[0] = tConsumed[0][0] + tConsumed[1][0]; + consumed[1] = tConsumed[0][1] + tConsumed[1][1]; + } + + @Override public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { + super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); + dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null); + } + + @Override public boolean onNestedPreFling(View target, float velocityX, float velocityY) { + boolean tHandled = super.onNestedPreFling(target, velocityX, velocityY); + return dispatchNestedPreFling(velocityX, velocityY) || tHandled; + } + + @Override public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { + boolean tHandled = super.onNestedFling(target, velocityX, velocityY, consumed); + return dispatchNestedFling(velocityX, velocityY, consumed) || tHandled; + } + + @Override public void setNestedScrollingEnabled(boolean enabled) { + mChildHelper.setNestedScrollingEnabled(enabled); + } + + @Override public boolean isNestedScrollingEnabled() { + return mChildHelper.isNestedScrollingEnabled(); + } + + @Override public boolean startNestedScroll(int axes) { + return mChildHelper.startNestedScroll(axes); + } + + @Override public void stopNestedScroll() { + mChildHelper.stopNestedScroll(); + } + + @Override public boolean hasNestedScrollingParent() { + return mChildHelper.hasNestedScrollingParent(); + } + + @Override public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { + return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, + dyUnconsumed, offsetInWindow); + } + + @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { + return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); + } + + @Override public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { + return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); + } + + @Override public boolean dispatchNestedPreFling(float velocityX, float velocityY) { + return mChildHelper.dispatchNestedPreFling(velocityX, velocityY); + } +} + diff --git a/app/src/main/java/com/fastaccess/ui/widgets/ShadowTransformer.java b/app/src/main/java/com/fastaccess/ui/widgets/ShadowTransformer.java new file mode 100644 index 0000000..de75642 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/ShadowTransformer.java @@ -0,0 +1,115 @@ +package com.fastaccess.ui.widgets; + +import android.support.v4.view.ViewPager; +import android.support.v7.widget.CardView; +import android.view.View; + + +public class ShadowTransformer implements ViewPager.OnPageChangeListener, ViewPager.PageTransformer { + + public interface CardAdapter { + int MAX_ELEVATION_FACTOR = 8; + + float getBaseElevation(); + + CardView getCardViewAt(int position); + + int getCount(); + } + + private ViewPager mViewPager; + private CardAdapter mAdapter; + private float mLastOffset; + private boolean mScalingEnabled; + + public ShadowTransformer(ViewPager viewPager, CardAdapter adapter) { + mViewPager = viewPager; + viewPager.addOnPageChangeListener(this); + mAdapter = adapter; + } + + public void enableScaling(boolean enable) { + if (mScalingEnabled && !enable) { + // shrink main card + CardView currentCard = mAdapter.getCardViewAt(mViewPager.getCurrentItem()); + if (currentCard != null) { + currentCard.animate().scaleY(1); + currentCard.animate().scaleX(1); + } + } else if (!mScalingEnabled && enable) { + // grow main card + CardView currentCard = mAdapter.getCardViewAt(mViewPager.getCurrentItem()); + if (currentCard != null) { + currentCard.animate().scaleY(1.1f); + currentCard.animate().scaleX(1.1f); + } + } + + mScalingEnabled = enable; + } + + @Override public void transformPage(View page, float position) { + + } + + @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + int realCurrentPosition; + int nextPosition; + float baseElevation = mAdapter.getBaseElevation(); + float realOffset; + boolean goingLeft = mLastOffset > positionOffset; + + // If we're going backwards, onPageScrolled receives the last position + // instead of the current one + if (goingLeft) { + realCurrentPosition = position + 1; + nextPosition = position; + realOffset = 1 - positionOffset; + } else { + nextPosition = position + 1; + realCurrentPosition = position; + realOffset = positionOffset; + } + + // Avoid crash on overscroll + if (nextPosition > mAdapter.getCount() - 1 + || realCurrentPosition > mAdapter.getCount() - 1) { + return; + } + + CardView currentCard = mAdapter.getCardViewAt(realCurrentPosition); + + // This might be null if a fragment is being used + // and the views weren't created yet + if (currentCard != null) { + if (mScalingEnabled) { + currentCard.setScaleX((float) (1 + 0.1 * (1 - realOffset))); + currentCard.setScaleY((float) (1 + 0.1 * (1 - realOffset))); + } + currentCard.setCardElevation((baseElevation + baseElevation + * (CardAdapter.MAX_ELEVATION_FACTOR - 1) * (1 - realOffset))); + } + + CardView nextCard = mAdapter.getCardViewAt(nextPosition); + + // We might be scrolling fast enough so that the next (or previous) card + // was already destroyed or a fragment might not have been created yet + if (nextCard != null) { + if (mScalingEnabled) { + nextCard.setScaleX((float) (1 + 0.1 * (realOffset))); + nextCard.setScaleY((float) (1 + 0.1 * (realOffset))); + } + nextCard.setCardElevation((baseElevation + baseElevation * (CardAdapter.MAX_ELEVATION_FACTOR - 1) * (realOffset))); + } + + mLastOffset = positionOffset; + } + + @Override public void onPageSelected(int position) { + + } + + @Override public void onPageScrollStateChanged(int state) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/SwitchView.java b/app/src/main/java/com/fastaccess/ui/widgets/SwitchView.java new file mode 100644 index 0000000..f7c74ef --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/SwitchView.java @@ -0,0 +1,35 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.support.v7.widget.SwitchCompat; +import android.util.AttributeSet; + +import com.fastaccess.helper.TypeFaceHelper; + + +/** + * Created by Kosh on 8/18/2015. copyrights are reserved + */ +public class SwitchView extends SwitchCompat { + + public SwitchView(Context context) { + super(context); + init(); + } + + public SwitchView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + + } + + public SwitchView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + if (isInEditMode()) return; + TypeFaceHelper.applyTypeface(this); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/ViewPagerView.java b/app/src/main/java/com/fastaccess/ui/widgets/ViewPagerView.java new file mode 100644 index 0000000..a489c4d --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/ViewPagerView.java @@ -0,0 +1,48 @@ +package com.fastaccess.ui.widgets; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import com.fastaccess.R; + + +/** + * Created by kosh20111 on 10/8/2015. + *

+ * Viewpager that has scrolling animation by default + */ +public class ViewPagerView extends ViewPager { + + private boolean isEnabled; + + public ViewPagerView(Context context) { + super(context, null); + } + + public ViewPagerView(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerView); + isEnabled = a.getBoolean(R.styleable.ViewPagerView_isEnabled, true); + a.recycle(); + } + + @Override public boolean isEnabled() { + return isEnabled; + } + + @Override public void setEnabled(boolean enabled) { + this.isEnabled = enabled; + requestLayout(); + } + + @Override public boolean onTouchEvent(MotionEvent event) { + return !isEnabled() || super.onTouchEvent(event); + } + + @Override public boolean onInterceptTouchEvent(MotionEvent event) { + return isEnabled() && super.onInterceptTouchEvent(event); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java b/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java new file mode 100644 index 0000000..6d28c5d --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java @@ -0,0 +1,94 @@ +package com.fastaccess.ui.widgets.dialog; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.view.View; + +import com.fastaccess.R; +import com.fastaccess.helper.Bundler; +import com.fastaccess.ui.base.BaseBottomSheetDialog; +import com.fastaccess.ui.widgets.FontTextView; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Created by Kosh on 16 Sep 2016, 2:15 PM + */ + +public class MessageDialogView extends BaseBottomSheetDialog { + + public interface MessageDialogViewActionCallback { + void onMessageDialogActionClicked(boolean isOk, int requestCode); + + void onDialogDismissed(); + } + + @BindView(R.id.title) FontTextView title; + + @BindView(R.id.message) FontTextView message; + + @Nullable private MessageDialogViewActionCallback callback; + + @Override public void onAttach(Context context) { + super.onAttach(context); + if (getParentFragment() != null) { + if (getParentFragment() instanceof MessageDialogViewActionCallback) { + callback = (MessageDialogViewActionCallback) getParentFragment(); + } + } else if (context instanceof MessageDialogViewActionCallback) { + callback = (MessageDialogViewActionCallback) context; + } + } + + @Override public void onDetach() { + super.onDetach(); + callback = null; + } + + @OnClick({R.id.cancel, R.id.ok}) public void onClick(View view) { + if (callback != null) { + isAlreadyHidden = true; + callback.onMessageDialogActionClicked(view.getId() == R.id.ok, getArguments().getInt("requestCode")); + } + dismiss(); + } + + @Override protected int layoutRes() { + return R.layout.message_dialog; + } + + @Override protected void onViewCreated(@NonNull View view) { + Bundle bundle = getArguments(); + title.setText(bundle.getInt("bundleTitle")); + message.setText(bundle.getInt("bundleMsg")); + } + + @Override protected void onDismissedByScrolling() { + super.onDismissedByScrolling(); + if (callback != null) callback.onDialogDismissed(); + } + + @Override protected void onHidden() { + if (callback != null) callback.onDialogDismissed(); + super.onHidden(); + } + + @NonNull public static MessageDialogView newInstance(@StringRes int bundleTitle, @StringRes int bundleMsg) { + return newInstance(bundleTitle, bundleMsg, 0); + } + + @NonNull public static MessageDialogView newInstance(@StringRes int bundleTitle, @StringRes int bundleMsg, int requestCode) { + MessageDialogView messageDialogView = new MessageDialogView(); + messageDialogView.setArguments(Bundler + .start() + .put("bundleTitle", bundleTitle) + .put("bundleMsg", bundleMsg) + .put("requestCode", requestCode) + .end()); + return messageDialogView; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingLayout.java new file mode 100644 index 0000000..c959036 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingLayout.java @@ -0,0 +1,49 @@ +package com.fastaccess.ui.widgets.floating; + +import android.content.Context; +import android.content.res.Configuration; +import android.util.AttributeSet; +import android.view.KeyEvent; + +import com.fastaccess.ui.modules.floating.folders.drawer.FloatingDrawerMvp; + +import io.codetail.widget.RevealFrameLayout; + +/** + * Created by Kosh on 22 Oct 2016, 12:30 PM + */ + +public class FloatingLayout extends RevealFrameLayout { + + private FloatingDrawerMvp.View viewCallback; + + public FloatingLayout(Context context) { + this(context, null); + } + + public FloatingLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public FloatingLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { + if (viewCallback != null && isShown()) { + viewCallback.onBackPressed(); + } + } + return super.dispatchKeyEvent(event); + } + + @Override protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (viewCallback != null) viewCallback.onConfigChanged(newConfig.orientation); + } + + public void setViewCallback(FloatingDrawerMvp.View viewCallback) { + this.viewCallback = viewCallback; + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingTouchCallback.java b/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingTouchCallback.java new file mode 100644 index 0000000..e1a83b5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingTouchCallback.java @@ -0,0 +1,25 @@ +package com.fastaccess.ui.widgets.floating; + +/** + * Created by Kosh on 14 Oct 2016, 7:31 PM + */ + +public interface FloatingTouchCallback { + void onViewMoving(int x, int y); + + void onSingleTapped(); + + void onDoubleTapped(); + + void onLongPressed(); + + void onSwipe(int swipeDirection); + + void onBackPressed(); + + void onTouchOutside(); + + void onStoppedMoving(); + + void onConfigChanged(int orientation); +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingView.java b/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingView.java new file mode 100644 index 0000000..88585da --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/floating/FloatingView.java @@ -0,0 +1,175 @@ +package com.fastaccess.ui.widgets.floating; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.support.v4.graphics.drawable.RoundedBitmapDrawable; +import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.widget.ImageView; + +import com.fastaccess.R; +import com.fastaccess.helper.InputHelper; +import com.fastaccess.helper.Logger; +import com.fastaccess.helper.PrefConstant; +import com.fastaccess.helper.PrefHelper; +import com.github.nisrulz.sensey.Sensey; +import com.github.nisrulz.sensey.TouchTypeDetector; + +import java.io.File; + +import io.codetail.widget.RevealFrameLayout; + +/** + * Created by Kosh on 14 Oct 2016, 7:11 PM + */ + +@SuppressLint("ViewConstructor") +public class FloatingView extends RevealFrameLayout implements TouchTypeDetector.TouchTypListener { + + private int initialX; + private int initialY; + private float initialTouchX; + private float initialTouchY; + private ImageView imageView; + private FloatingTouchCallback callback; + + public FloatingView(Context context, FloatingTouchCallback callback) { + super(context); + this.callback = callback; + imageView = new ImageView(context); + imageView.setAdjustViewBounds(true); + setupImageView(); + addView(imageView); + } + + @Override protected void onAttachedToWindow() { + super.onAttachedToWindow(); + Sensey.getInstance().init(getContext().getApplicationContext()); + Sensey.getInstance().startTouchTypeDetection(this); + } + + @Override protected void onDetachedFromWindow() { + Sensey.getInstance().stopTouchTypeDetection(); + callback = null; + removeAllViews(); + super.onDetachedFromWindow(); + } + + @Override public void onTwoFingerSingleTap() {}//op-out + + @Override public void onThreeFingerSingleTap() {}//op-out + + @Override public void onDoubleTap() { + callback.onDoubleTapped(); + } + + @Override public void onScroll(int scrollDirection) {}//op-out + + @Override public void onSingleTap() { + callback.onSingleTapped(); + } + + @Override public void onSwipe(int swipeDirection) { + callback.onSwipe(swipeDirection); + } + + @Override public void onLongPress() { + callback.onLongPressed(); + } + + @Override public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + initialTouchX = event.getRawX(); + initialTouchY = event.getRawY(); + imageView.setPressed(true); + break; + case MotionEvent.ACTION_UP: + callback.onStoppedMoving(); + onMoving(false); + imageView.setPressed(false); + break; + case MotionEvent.ACTION_MOVE: + onMoving(true); + callback.onViewMoving(initialX + (int) (event.getRawX() - initialTouchX), initialY + (int) (event.getRawY() - initialTouchY)); + break; + case MotionEvent.ACTION_OUTSIDE: + callback.onTouchOutside(); + imageView.setPressed(false); + break; + } + return super.onTouchEvent(event); + } + + @Override public boolean dispatchTouchEvent(MotionEvent event) { + Sensey.getInstance().setupDispatchTouchEvent(event); + return super.dispatchTouchEvent(event); + } + + @Override public boolean dispatchKeyEvent(KeyEvent event) { + Logger.e(); + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { + callback.onBackPressed(); + } + return super.dispatchKeyEvent(event); + } + + @Override protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + callback.onConfigChanged(newConfig.orientation); + } + + public void setupImageView() { + if (imageView != null) { + String path = PrefHelper.getString(PrefConstant.CUSTOM_ICON); + if (!InputHelper.isEmpty(path)) { + path = Uri.decode(PrefHelper.getString(PrefConstant.CUSTOM_ICON)); + boolean fileExists = new File(path).exists(); + if (fileExists) { + imageView.setImageDrawable(null); + Bitmap src = BitmapFactory.decodeFile(path); + if (src == null) { + imageView.setImageResource(R.drawable.ic_app_drawer_icon); + onMoving(false); + return; + } + RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(getResources(), src); + dr.setCornerRadius(Math.max(src.getWidth(), src.getHeight()) / 2.0f); + imageView.setImageDrawable(dr); + return; + } + } + imageView.setImageResource(R.drawable.ic_app_drawer_icon); + onMoving(false); + } + } + + private void onMoving(boolean isMoving) { + if (imageView == null) return; + if (isMoving) { + imageView.setImageAlpha(255); + } else { + boolean isAutoTransparent = PrefHelper.getBoolean(PrefConstant.AUTO_TRANS); + int alpha = PrefHelper.getInt(PrefConstant.ICON_ALPHA); + if (isAutoTransparent) { + imageView.setImageAlpha(alpha == 0 ? 100 : alpha); + } else { + imageView.setImageAlpha(255); + } + } + } + + public void setInitialY(int initialY) { + this.initialY = initialY; + } + + public void setInitialX(int initialX) { + this.initialX = initialX; + + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java new file mode 100644 index 0000000..bbbfab1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java @@ -0,0 +1,129 @@ +package com.fastaccess.ui.widgets.recyclerview; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.ViewGroup; + +import com.fastaccess.helper.AnimHelper; + +import java.util.List; + +/** + * Created by Kosh on 17 May 2016, 7:10 PM + */ +public abstract class BaseRecyclerAdapter> extends RecyclerView.Adapter { + + @NonNull private List data; + @Nullable public P listener; + private int lastKnowingPosition = -1; + private boolean enableAnimation = true; + + public BaseRecyclerAdapter(@NonNull List data) { + this(data, null); + } + + public BaseRecyclerAdapter(@NonNull List data, @Nullable P listener) { + this.data = data; + this.listener = listener; + } + + protected abstract VH viewHolder(ViewGroup parent, int viewType); + + protected abstract void onBindView(VH holder, int position); + + @NonNull public List getData() { + return data; + } + + public M getItem(int position) { + return data.get(position); + } + + public int getItem(M t) { + return data.indexOf(t); + } + + @Override public VH onCreateViewHolder(ViewGroup parent, int viewType) { + return viewHolder(parent, viewType); + } + + @Override public void onBindViewHolder(VH holder, int position) { + animate(holder); + onBindView(holder, position); + } + + @Override public int getItemCount() { + return data.size(); + } + + private void animate(VH holder) { + int position = holder.getLayoutPosition(); + if (isEnableAnimation() /*&& position > lastKnowingPosition*/) { + AnimHelper.startBeatsAnimation(holder.itemView); + lastKnowingPosition = position; + } + } + + public void insertItems(List items) { + data.clear(); + addItems(items); + } + + public void addItem(M item) { + addItem(item, getItemCount()); + } + + public void addItem(M item, int position) { + data.add(position, item); + notifyItemInserted(position); + } + + public void addItems(List items) { + data.addAll(items); + notifyDataSetChanged(); + } + + public void removeItem(int position) { + data.remove(position); + notifyItemRemoved(position); + } + + public void removeItem(M item) { + int position = data.indexOf(item); + removeItem(position); + } + + public void removeItems(List items) { +// int prevSize = data.size(); + data.removeAll(items); + notifyDataSetChanged(); +// notifyItemRangeRemoved(prevSize, Math.abs(data.size() - prevSize)); + } + + public void swapItem(M model) { + int index = getItem(model); + swapItem(model, index); + } + + public void swapItem(M model, int position) { + data.set(position, model); + notifyDataSetChanged(); + } + + public void clear() { + data.clear(); + notifyItemRangeRemoved(0, getItemCount()); + } + + public void setEnableAnimation(boolean enableAnimation) { + this.enableAnimation = enableAnimation; + notifyDataSetChanged(); + } + + public boolean isEnableAnimation() { + return enableAnimation; + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseViewHolder.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseViewHolder.java new file mode 100644 index 0000000..aeaa925 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseViewHolder.java @@ -0,0 +1,54 @@ +package com.fastaccess.ui.widgets.recyclerview; + +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import butterknife.ButterKnife; + +/** + * Created by Kosh on 17 May 2016, 7:13 PM + */ +public abstract class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { + + public interface OnItemClickListener { + void onItemClick(int position, View v, T item); + + void onItemLongClick(int position, View v, T item); + } + + protected BaseRecyclerAdapter adapter; + + public static View getView(ViewGroup parent, @LayoutRes int layoutRes) { + return LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false); + } + + public BaseViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { + super(itemView); + ButterKnife.bind(this, itemView); + itemView.setOnClickListener(this); + itemView.setOnLongClickListener(this); + this.adapter = adapter; + } + + @SuppressWarnings("unchecked") @Override public void onClick(View v) { + int position = getAdapterPosition(); + if (adapter != null && adapter.listener != null) { + adapter.listener.onItemClick(position, v, adapter.getItem(position)); + } + } + + @SuppressWarnings("unchecked") @Override public boolean onLongClick(View v) { + int position = getAdapterPosition(); + if (adapter != null && adapter.listener != null) { + adapter.listener.onItemLongClick(position, v, adapter.getItem(position)); + } + return true; + } + + public abstract void bind(@NonNull T t); +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java new file mode 100644 index 0000000..441a46c --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java @@ -0,0 +1,133 @@ +package com.fastaccess.ui.widgets.recyclerview; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; + +import com.fastaccess.R; + +import static android.R.attr.columnWidth; + + +/** + * Created by Kosh on 9/24/2015. copyrights are reserved + *

+ * recyclerview which will showParentOrSelf/showParentOrSelf itself base on adapter + */ +public class DynamicRecyclerView extends RecyclerView { + + private View emptyView; + private int iconSize; + @Nullable private View parentView; + + @NonNull private AdapterDataObserver observer = new AdapterDataObserver() { + @Override public void onChanged() { + showEmptyView(); + } + + @Override public void onItemRangeInserted(int positionStart, int itemCount) { + super.onItemRangeInserted(positionStart, itemCount); + showEmptyView(); + } + + @Override public void onItemRangeRemoved(int positionStart, int itemCount) { + super.onItemRangeRemoved(positionStart, itemCount); + showEmptyView(); + } + }; + + public DynamicRecyclerView(Context context) { + this(context, null); + } + + public DynamicRecyclerView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DynamicRecyclerView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + if (attrs != null) { + int[] attrsArray = {columnWidth}; + TypedArray array = context.obtainStyledAttributes(attrs, attrsArray); + iconSize = array.getDimensionPixelSize(0, -1); + if (iconSize > 0) { + iconSize += getResources().getDimensionPixelSize(R.dimen.spacing_micro); + } + array.recycle(); + } + } + + public void showEmptyView() { + Adapter adapter = getAdapter(); + if (adapter != null) { + if (emptyView != null) { + if (adapter.getItemCount() == 0) { + showParentOrSelf(false); + } else { + showParentOrSelf(true); + } + } + } else { + if (emptyView != null) { + showParentOrSelf(false); + } + } + } + + @Override public void setAdapter(@Nullable Adapter adapter) { + super.setAdapter(adapter); + if (adapter != null) { + adapter.registerAdapterDataObserver(observer); + observer.onChanged(); + } + } + + @Override protected void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + int width = MeasureSpec.getSize(widthSpec); + if (iconSize > 0 && width != 0) { + int spanCount = Math.max(1, width / iconSize); + if (getLayoutManager() instanceof GridLayoutManager) { + ((GridLayoutManager) getLayoutManager()).setSpanCount(spanCount); + getLayoutManager().requestLayout(); + } + } + } + + private void showParentOrSelf(boolean show) { + if (parentView == null) { + setVisibility(show ? VISIBLE : GONE); + } else { + parentView.setVisibility(show ? VISIBLE : GONE); + } + emptyView.setVisibility(!show ? VISIBLE : GONE); + } + + public void setEmptyView(@NonNull View emptyView, @Nullable View parentView) { + this.emptyView = emptyView; + this.parentView = parentView; + showEmptyView(); + } + + public void setEmptyView(@NonNull View emptyView) { + setEmptyView(emptyView, null); + } + + public void hideProgress(@NonNull View view) { + view.setVisibility(GONE); + } + + public void showProgress(@NonNull View view) { + view.setVisibility(VISIBLE); + } + + public void setIconSize(int iconSize) { + this.iconSize = iconSize; + invalidate(); + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/GridManager.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/GridManager.java new file mode 100644 index 0000000..246a506 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/GridManager.java @@ -0,0 +1,30 @@ +package com.fastaccess.ui.widgets.recyclerview.layout_manager; + +import android.content.Context; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +/** + * Created by Kosh on 17 May 2016, 10:02 PM + */ +public class GridManager extends GridLayoutManager { + + public GridManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public GridManager(Context context, int spanCount) { + super(context, spanCount); + } + + public GridManager(Context context, int spanCount, int orientation, boolean reverseLayout) { + super(context, spanCount, orientation, reverseLayout); + } + + @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + try { + super.onLayoutChildren(recycler, state); + } catch (Exception ignored) {} + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/LinearManager.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/LinearManager.java new file mode 100644 index 0000000..9a78780 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/LinearManager.java @@ -0,0 +1,30 @@ +package com.fastaccess.ui.widgets.recyclerview.layout_manager; + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +/** + * Created by Kosh on 17 May 2016, 10:02 PM + */ +public class LinearManager extends LinearLayoutManager { + + public LinearManager(Context context) { + super(context); + } + + public LinearManager(Context context, int orientation, boolean reverseLayout) { + super(context, orientation, reverseLayout); + } + + public LinearManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + try { + super.onLayoutChildren(recycler, state); + } catch (IndexOutOfBoundsException ignored) {} + } +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/StaggeredManager.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/StaggeredManager.java new file mode 100644 index 0000000..659fba2 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/StaggeredManager.java @@ -0,0 +1,27 @@ +package com.fastaccess.ui.widgets.recyclerview.layout_manager; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.util.AttributeSet; + +/** + * Created by Kosh on 17 May 2016, 10:02 PM + */ +public class StaggeredManager extends StaggeredGridLayoutManager { + + public StaggeredManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public StaggeredManager(int spanCount, int orientation) { + super(spanCount, orientation); + } + + @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + try { + super.onLayoutChildren(recycler, state); + } catch (IndexOutOfBoundsException ignored) {} + } + +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/ItemTouchHelperAdapter.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/ItemTouchHelperAdapter.java new file mode 100644 index 0000000..3a7333d --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/ItemTouchHelperAdapter.java @@ -0,0 +1,9 @@ +package com.fastaccess.ui.widgets.recyclerview.touch; + +public interface ItemTouchHelperAdapter { + void onItemMove(int fromPosition, int toPosition); + + void onItemDismiss(int position); + + void onItemStoppedMoving(); +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/ItemTouchHelperViewHolder.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/ItemTouchHelperViewHolder.java new file mode 100644 index 0000000..2348cba --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/ItemTouchHelperViewHolder.java @@ -0,0 +1,7 @@ +package com.fastaccess.ui.widgets.recyclerview.touch; + +public interface ItemTouchHelperViewHolder { + void onItemSelected(); + + void onItemClear(); +} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/SimpleItemTouchHelperCallback.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/SimpleItemTouchHelperCallback.java new file mode 100644 index 0000000..77ce7e3 --- /dev/null +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/touch/SimpleItemTouchHelperCallback.java @@ -0,0 +1,86 @@ +package com.fastaccess.ui.widgets.recyclerview.touch; + +import android.graphics.Canvas; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.view.View; + +public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { + + public static final float ALPHA_FULL = 1.0f; + + private final ItemTouchHelperAdapter adapter; + private boolean isSwipeable; + + public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter, boolean isSwipeable) { + this.adapter = adapter; + this.isSwipeable = isSwipeable; + } + + @Override public boolean isLongPressDragEnabled() { + return true; + } + + @Override public boolean isItemViewSwipeEnabled() { + return isSwipeable; + } + + @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + if (recyclerView.getLayoutManager() instanceof GridLayoutManager) { + final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; + final int swipeFlags = 0; + return makeMovementFlags(dragFlags, swipeFlags); + } else { + final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; + final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; + return makeMovementFlags(dragFlags, swipeFlags); + } + } + + @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { + if (source.getItemViewType() != target.getItemViewType()) { + return false; + } + adapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition()); + return true; + } + + @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) { + if (viewHolder instanceof ItemTouchHelperViewHolder) { + adapter.onItemDismiss(viewHolder.getAdapterPosition()); + } + } + + @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, + float dX, float dY, int actionState, boolean isCurrentlyActive) { + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { + if (viewHolder instanceof ItemTouchHelperViewHolder) { + View itemView = viewHolder.itemView; + final float alpha = ALPHA_FULL - Math.abs(dX) / (float) itemView.getWidth(); + itemView.setAlpha(alpha); + } + } + } + + @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { + if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { + if (viewHolder instanceof ItemTouchHelperViewHolder) { + ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder; + itemViewHolder.onItemSelected(); + } + } + super.onSelectedChanged(viewHolder, actionState); + } + + @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + super.clearView(recyclerView, viewHolder); + if (viewHolder instanceof ItemTouchHelperViewHolder) { + viewHolder.itemView.setAlpha(ALPHA_FULL); + ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder; + itemViewHolder.onItemClear(); + } + adapter.onItemStoppedMoving(); + } +} diff --git a/app/src/main/res/color/preference_primary_color.xml b/app/src/main/res/color/preference_primary_color.xml new file mode 100644 index 0000000..4f97614 --- /dev/null +++ b/app/src/main/res/color/preference_primary_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/color/preference_secondry_color.xml b/app/src/main/res/color/preference_secondry_color.xml new file mode 100644 index 0000000..4bf3325 --- /dev/null +++ b/app/src/main/res/color/preference_secondry_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable-hdpi/folder_background.9.png b/app/src/main/res/drawable-hdpi/folder_background.9.png new file mode 100755 index 0000000000000000000000000000000000000000..9db01bfec156cd88302fd161cd147be3f8e4fee4 GIT binary patch literal 5873 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 N!WfxfDn{Ro`hQxS|A_zq literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_drawer_normal.png b/app/src/main/res/drawable-hdpi/ic_drawer_normal.png new file mode 100755 index 0000000000000000000000000000000000000000..732dadae17e9ba118b3ee15be037a07c39e6d5b2 GIT binary patch literal 5764 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�Cv& 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-nodpi/ic_fa_splash.png b/app/src/main/res/drawable-nodpi/ic_fa_splash.png new file mode 100644 index 0000000000000000000000000000000000000000..5ff210d1125c1dafbd2b359c1f7952a420f5581d GIT binary patch literal 6236 zcmaiYc|4Tg_xPPLV_zmkG_qtT4JAUO$xWYa(My*_V>+%93b^vW2&G zL}L=!vXh zEhqwjgI`_cs(!$?g$#@<+sMf;S;iIc`#4?{tx~`eo8JAx!T`Dp{erXz_VDv%WxvGU3V}Ic6E{iB7FSc5jQVy(8)x zCc(YPl1ej?-`>cN#C=}0V16ROa#c2pWxis!hO_P@e0z2%u__ikVsx_`o%Y$DE9I_x zXDhz_wYmxezc(_}`30~0K!=x5RqmM7-4U2k9Ab||Ebm;hitQWZiectGGda#l=8P_` zen?fk{MkE2WIAe?I==Me$oW}@U)wT~R8V23l(_;Ik$IP!fBigIQtY*L85k5o3 zj`3kOVLKz8JxRX9+-M|dCGqJvb7q@@gF#fU`gE|De1>)sTlb%4OSbA;E`U#|b=xxO zojei=5WFgFsI8b$P5?u}l@ME!y!H{t9VCJL561_&9;ZRIGv`6?CIJF3m!1(@)kky`5%W=s3G}i|+fN zg42_(aY6nCa5gW&+ro_<9#~)Pe-h3@FU_iL8%74a{I7(>giM@X1;c2fw z&ngW_hG`P4ufE=J_tj|uW}3;bg-0%*C_gooyr=lS!e;ID`B`!L(o=~^WfL0c&sXLd zS^27~RuwSA;T&5Who+W~X{DAwk=C)c?s14Bt^G#75ngKf&%#z&qx_meDqB;S6j+=T z3K7QfGZU3$%Zoy6*|-kUd=<$E7a+3ORiTpn%23EHo31ooco>J-BWt^J4G5d{>FtH{ z)>4@_GkM$l1mx^oPd_k!K^4X^+8}cshQux_DBDn77Fv>>aLwbczt`G&J=w7EdjmXF zEF~m7=6(mh<>5)B=Gb-72=O}i{t{s)?Nd&D!q*57Ug-K=e;!{oI#ZigJFHWvba7%G zOLc714Cr?#UL>rOFXg7`>6LIxkj3cdxW6r2AYda@42T$wtP8Kbc*w~@KN4dtJLW1l z;%Q{AoL!Vr5nCH8YhbhS{@I@%nh;j&z&&)bsdg%&;ov;YEib>*=aYHm9^dXQ=gRuM zP=vmJL$l!;p+Oqi+_Ip1qdYxoNhXoY-z;2uV*T~Ybw)XU=|2@@f$N@?(_wFJ-W`*W zGn%&;bWGP8-En@k#5ZVvrcpa>rq)bv@wVt$Q@?W?Z6(JzuPIYw`$njrbb6iK+OC{( z+051&yCa@p^Wcn~-ha&mI1R~cYkyU$hN|iGg1ArjzT`61gT#7K)_N9{Yd)3z^t0cW zTGaB0O$bEZZ)O3s;<$D{TVB~Xrv0$??6^tBxlOlrrbILqtk$?S{ZFv4Znmv(QqbLq z#fqg)DRvdKr)OKLrICH-e&>r>D?OZb7f<=a-j2$X)1wOdaaX_OHZF!Y_9_Cd%f7cm zwmk^?T)(8W6||S1mPpRIhUT?$J`u$L&nSPnQVB~!1LLl8f}*{6tp2MHfY;Zg9Wb)Xu-Wp8d)!bEY)Q^auoUL`o6Pt z8QmTCK;Wm~lDoDQD{%=2GM!ysHIuc)>E@@hrqKV{e$U)S#_u@|aU^SNEp} z4S*A~L^1AP|F{=^4-nm|ZzhP-1GZm#Fro|0S#a5l@C|$ICPHP5q5t?~hZV!gP<1#G zF9?&=Fbec`oU`JN%Tvzk!Hm49P63{hY;qY^G~);7x|i2u-aLvP&9l8(dq19Y{M2n8 zOoS(a<{Sa_>~ZqA3{RS_QSXQyn$51yDomAhLSAsDke0OO6`ID}a zx2#hsr{D6z-lj)EU6Afv%uvd+DC@)fN(}p+G9|?aztWbswlb{x|08BjPszx47<})| zY-4|!THKBQA;E8FqcAfcZqwKw;$mVACd>q3_SuhYHS-8oD! zHF*bECv|_Li$WS+knC++s(!Ti(P}2e-GQ}2!JV^KZ#$Q#^Kq&Ku`ttFwwBbOAV{}k z-8(Jf%iCm@B`T%yrr`Lo>SvqR2P#Jqrwfa;v3^;BE)R?0`yyQDUm8%%aZN0na&J!x zyis^L=?oYfM*btgNVB|7KLZ5RuY|KUXVI-7VZ{GnYPwxHnH6a_5PDoP__CB;s2#Ab zA#7fjs&2xrDv$5%SDMal>y)hk;xU+W@sDGpl$;P=wx3w?fn$$Ss2uQ=286xKeLm!i zZ|Osvr**i%j-r(8Zb;bfh1y0yFjaT#CNJbmCcG=G4?XYBeoItmJYxubc%bH ziZ}COD&1%r^@Y1(TM-j=uJ>Ts!eAgQj=z;NM851T$@a9riY8{{7rM-(regl zF`)9Q6kMdi<+_%BN$W3K9h|?9r4=g@y)Aiy1<+7Yj0Qo%%cWOCn1N7cXVLwe76x9T zXnQX@X0S_>y|=_olD8r}PR!FyoDp z;?~?)b|A835H_Bzcw79nT>RqU#$nKwnvW>v&O4Yv*QaZf?o>pmUepU_WhT3O)-IsF zU0?>Q#3B_Z|2Jl$DvL-^Jn^ZY-|eBBhShU-tek?e6@7zKnuSK7iF#CNX^Sb=`wl>X z%tcq_g>9?GT!w-xC4;W98edXFz8^)M%{x^Tbwl&(x?JB>mm$X>YNJ&mriMGciv9|? z)W&`(l&!aVMQ7flB1pKlQoy$ph5{U)>(T~x)@&;`a?a$8{tD?b(Qg{Q5Q>DdX^ERT zsFTu}GW59pb3#%hnvea47ZuS4JnI(II?b6Iqp>3`k{t;nvKTOCh8_isCI?SW_ek9eqM@t?l@Db|NNuAy@1t-{LBla}sU3#P!eob*F*AHm1zXXubpIqiaoX%BM zHy`2pI=o=d^*5okfI=ke)mw1=;B>JVJe8Fy8?qGy$0>sWb6Vg0Gr2yqf=@oSd!D~r zxBmiL9}U3l=<=?gR}>eKCppTecV_U+)d$aIziH!lW?sTtK)GF`sc?XPZcL(usH z`p>RSD8eDIZ{IR-D1Tq<%2Q+xJ5}0a;-dSg|GC;<3cdkdcg@KjD=AV*cYDTpp4D>z zfmby8%3X0X+!1h_W+a9xx!JD#9-GnmNN>8<)qZ>PtTi5WoZ6b^Jc z08ix6D=pB3_Xc55faHIw>$)cbJVg8G-Q$6_vVxrurx8-=1-c!jpH>af62SFyH`~$= z|M}ZbXo2|C+1x_#^zp$L-=iKDYET*;q(nm@M@>gm1~V)`JeCYuheH5-wBdn0YeeFK zq^CzJjA#L7_&_I1I)FCG8#lTEEPDw_1$Y4h4^hK$;8LO5BkH5~=MqF1fE{f_5&}W9`a7XhZqW-TC$rLU-br5l}-Rpwm?qMOJVbjl6#qFd&P0D6rLC zJURlBci_bStu&gsGUy$F2RgdUl=@Xbn$@5Ne<2$5eD*yWV{i-^{!f2ZGfHp)*1o+4 z_HT_9C$^^baj&)xjo*VGDFw@Bw>tVxT70B2#tjhAnW?eov>HAAgUpH#yrYT|!>J9wV#KL*Y!Ab(BMO9nH7hUX_bA&DdE;9cBCD^EQD zE=x$Y?rSmR3&x;g^(iDUe)8N)UgBy5PfE*Oxt|J)A%m%h_jrnG>zSaWFF!^(#Ll<@ zXWr~%9ANZ|>~}>DDr29dQIh#s+3&0Vh9{xJcaX%rrJA3r$K65U8(R2%sEp787GNy` zx-1QA;WuAFMp#GT$010GqS&2*L%W3;s&`8HUjT3zOQL?=bPXS{eOaU?QUBUz8kRMOma<0{{*?Q zai6PVFy!f77pNP6vV~ZI9Q1xU5R#yB#1Mf`-fy&6JTN?DeXz)B9?$LssjR=V>j!_~ zVRmsm31gC~L~WfM-3XDI!n4a;u7K*kH9n)5zv-6JzpZJkx2DTCjesBNbHijmv~XKY zPMGQ+E7VfbCQTD5^e-|ThuJ-dV@~dqSHX4x zMXUPl86^poZAq^NU`+^vydgE~K*uB%eh{v+h765|1qj3zh8OE} z!(rKhM>nwHJ;xq6?8rF92NBp$L8|xQN9Ltyzw)?aC?Kb}9e*$vSa_g#R03MR3V_1m z@yHs%vIsJLu%#p$*rCI12g7h~gM(F07w?EQw$ua3E?DWsL>^GIrX}eg7I}$by(ZE# z+@CF!gJSxH3rwE180qYgp&enlOk{x^zzFd37w4bHRLy6?m*1#V6*#83MxqnyC0e9ls^?(wTDs!8U_2}2Ps`hw4SSoS2v=#n8b?S@_2AiCsb(zQ;l|QzM+PDd?lvXY zp9*9nktblx5P~v|bu#CPqABGtG~^h`E;0G!d8l!uEAf_wR0hjV1x^<>L$A|DorSJ& z2pwU)bE0`e=V;W_$8sVHKvkF(R57KEqDspQtmVI-i>FdM5*mh&^!|Vxp$?4RF}=;* zHa;6XvBv8z8<{$8*9OYc!H7THIhb>19%Mr2_EW zYwsRglQ0=}SA74p46&)fIA69pKm{lq3`-r69N@iXNe|!N!p&DXdL{`!G&5^A6(ZLv z4H)XScRAL$cGdky5}i8Qiu`U|Fw&cPmY3V{`E`oIr+~_Haaa6yRt5a&GOm~%V9nUD zkqdoc;>WDeqo-oMmRj+MMBaEIT0QksKfTW(RYp!n<@pG1J%`1t2y`|(#PdC|{X0lt z`x%||$n1e+hrtOw3mc+smqh??loWLswNK+@b(=gDhaJU<^Fc8J0=Y&?eI~Nd+Qw>& z-`SvdLC`ii{w7NirG$Fo?Qh4fV1`HM)csB>klqye_ zJ{c5{ZFRR|V>3&i(3EpMXzKTik+>k$D7rXG?*}ue@;v)d_>rPkx6dY-ITJWOHT2M@ z%T=0G2j#CV+@>t?Mc!}DDo&x|HF5*Hr3!Mft(*hXgab z&c~m51hx8%im5ApiMy!;{%3FWP*;9*MmpEA*+$jCeC(sqfoW|UqpAZ!ts4p-rsFK) z%Q^Y(38Yw!VQ7qc3Ejd*p4nw83C9TryL25)XnbJlEiY=UcPLGD@*~)VoR(}8JkU` zya;^-L1*Ek?7X^+wmgFpm4;ZzKwhiawt%UP!OXCXk>Tpt7|!`7f&SxmQSYGLCMR*G zr29;bjPU}W^wq({@Ym3+$o_G0vzfQu!%BTx120RCf+|)6M1)}0{8Vq^43;0oCn5gH z+3Tf9GcI9hCD*xiV=9@8TJ?P~rqQD&T}Kl0 zfY&6tJJ$NP4<@4J*GV`L9rg32prWB*ehfDvOZ#ErT6$xuK_%B|RGn(uAF-8?;AE0I z(UNY4Yeh#dGC%19QR~6AvClZ#je6hAgt2O^fm^(NrM6Xhp1bb_o%}NV3TFEqlfEb1 z<*Tlw&52g?9{nyL{~(3ll%DODs@v^CwUsi}lgI*5uP zXiY&yOAW0nVxCIcn&lQ1!+Y-g;a%^?_xt-lYn^k}S$nPh+xywSy?@X1oJV$-FABkq zz(637kd@_m2jIQ*?=8RwJnsxzi-SPYyH@AVIz@Rb7hHKL{VBIo=lDUy)$G4@X@OxP z>Uqj#hHb0s2WdfD&NGWaS(-ZbSs5%w5aVPKNL-063{8mUm87UWVR|B*+; z(*p9C1RlzW$(&ccu?^}8%%D6Z%8h=+u3<o)6&w|%UxfOa}u0zS7FjJGMB)0RaIUdTX)Y4VvA582~mj2?1%|A7{4(x zk~wVn8mgD>QzuXjhJic$LvRma6I!z5{cV$Hxx zMZ6E^)-jZdid>GDY(;F^o`O}@vY4i(>RPwN!(xBP4}aZL+;Hh;@-Gs_wJz8zeAU%Ey7>os^ULV)ygF;k zBieTx>O|)>X$f92d!q2@wC_|$(2`GwNfBRDG&u-Pb+G2~sAWd@wYg8%y)=(OQ2p9} zMw1_uKj{W~=O_ZnCF_xvU}A_o-{u$9(!QT!n(C@+r7F|h7O=7aWUwqC z&u6NR%nmSvW58P2-6AL@%%iDpdX|H)kM;2Hzu(am+C@=LsHpMI$J!qM)RiG?V-|SU z-PM)DpFm8VWAP6VXkl0>UT~iZSaI{qPD|*hc}~sFKcy#AJkLX`)pd#>ZlzA?h%VTl zdYf}-eS$a7p8$Y*&n}%gl173`(r<)>AQqb@1&7f>(y1DA*vLWlG1WPgC$KdiHA&y>`k^2GR9`B<7FG zpJ#5xCZenk^Sogi)=Xcpzn&pg-&<`fS<^jw`9iPl`QF6HKd867I&&oY4B_RgT(DeX zN%2z$K7x1%5E4^C%ZQ~vjy1!QdLi6bWR9^x$m!Ejt39@e*78Xhs5^I2Q_`H}V?lcs zbnmkD>**YqER`i5=OrGer4ph0W)kVogp$ue!$KYj`ui1Zs{3Do*45rS;pZij(Y3#` z^S-d`HP}($k0Ri+tTU)00%Havgpc=g?l~w*t{n+mmj%JAe4kfro&4~<-v%sbu|CnS z(K~)Ws2jUTF&6*{U~2pvwfQD>`#FMiMtCrmYbbaw;@&;VEZUhFfT~4@YV*<#%<{uV zbchxzP4C{Rq&$HXrET2S98Q$NuBI~q>VzID@h#sTnWVSnu z_36B0^f-)472@NO^>HS(;W4Eodr@AmEc{=h$5nB9D1t@GCw;WKenZ6>C22&dCh?>$ zyMkVviR`K{NZ6jFF=S8GW$_Tf}CZwx($uFkh98V@sCS&&-vB_5NKoh>r3Lb z9O+0HrlDM>zTKrn8FnO%kMSn#63=lQN-nLckR6>m%py7bMLL|GG7K)V2(s}p0$+_B zDHfbz{c5V5JQ8pEJs*|aLx(t_mAY}YIWa?69!tu4&LshD4Kta!2&qvy0l|hVg(iCQ zRWkkL`RZH5PF4idJwzqdMS;{9E}a~Z2VoqdG#olFP?dxjuvVGt$<}NQUmm3`E=O`b zhlhs`=GznDp}c1YUaiyU12PWNYinx<=@}UZBa6TG!w>fNxEaUJ?3f3g;iEL)lHod|NRmGK6?xfct{R^ltN+PyCwKAfa^%s)H)Y~CbdNAxz=4?x_Q<60 zEPRkdx1QP0Xb+wNkJh-osg~cpp>eBUOKlEj?Bb9x3G`K>X3O^MlPe~_zg^*SxfwA3 z(XS1|i(VI83TLZ1#EFrSzdD8Xe8;ho!*T+43&rB; zCCaKDfo8p&rsz3FTBs)wiTfEP@u~!3{krXCVcbsZoz=;`6n6Bv28yWnE1Ld*qLsI_ zB;D5~NqfaDyE$g-ZLZ#?ap2E;31z%aEH7@-b0xFW z>ZjtkMh|G|*(yHdtJ9OsF|7yROEUHaF<=dSxCY^=!x8_PYO747zk$B~XNAA-S8u=Q zz~Yv#i*?UZwyuz#akHV}$){BJVJ34{_mch2 zk!w&2Ys1)c^|s-JO}0jC!lz=0({wHbC}f4>?{2YUIv2PmqxQ&RoQzaodQD(j?MqSlWyul1gHd?(KLBFwp;!>n|Bw=r~QD)vss zBcNLxmMCJfUBp?N>1d51-$@msXW97Jnt@qLSI94F@avz^k#7_b97d%Vk}n`H&nTPH z*zS^2nj1lXL%Y$;=`)&&<@6eaYPmQOV76*&BYuT@GaVwPyCtOR(C59?!2)60>4`nX z>cZzJq_Po}Io5A_U%IDjg)>@O_yn9HQv-2U!Ncj1jT5q=AtA8^|4tPcQ@`oKy@S32 zqt;)>t11K(y_2#|&+1IOaN@@n_lMLR>k#$Uu;(0FSS!v#C3Rhm@ir%TBX%m)1x#T_ zOKup4Hg8SF7ywr*r`lqJ`=Z#rr#81dMt0#a)R&IcrV=ruRM+n4PCusD-JBKl7!js7|uek zESS~qUWm|PbRm02U6ECaDf0yt6&1mKAH*&j%VJ_2O$eP2#Jas2^L>c4d8)(D`=pK8 zm6a8)EduC;Bk?`5(R2W7x*jV_z09ZvF*R0;)EOVd2q;rgySsP&w5d7rj0a-J3e++@ z?S&;vsVd1SncK6Ilarx2>Z)eY1+{@6x8sx_L^-7T^kNW4yJt7h2oYYA5*f5&j`PdD zy(Fk@?OhR(dQ`Dmy`#`v_sJy$vshtY?}-KU72O;c@5G1Dc*g!6F3OASN!M~s&5W9~ z4G#$L8};%dc8;p?Q86(Ex$=Az!lw5pulUY?p`?nk3NbkQBV!}88@Aev>V`^WQ1yIi zfg=%RdH}=q*cf6LlN?}o^l4f;z-9u@S7gUV*&&Y#Cmaznaig9G2Mz*jtlT?Q)49D! z$E46~j6ij}_m&*!qcIPG4WfF%D)ppHObIVm{sD1_W1Q-BCl>|G6=4`W%rWK(BD2MS zbHzL0Wt1q+I25&+NTlg}Kz6|7r>pr`-dWq({|znN?@@f<1dYH<^#ZH=KE4K73PbB| ziTYUa3kMN@#ZHY+T<`HRYpk!|f-9!L?1+iNTu;zYRwpLos&($X3|yT&e)jaZzwXx! zMdfRf|9QgFTd20#C$%iWOd&U-^-~|*tWl zatQBcM6V#%0{WfW#P`aKCQ;PkY!tr~+bb?d)w4l&RMbIu>qdY3tOk{Vh!rmFQa5N4 za@3(d*%(h9s6cS<;l8l)3ZNx&pT*5nF~bFAg(bO$04+35*W|D*7~)#bMl z5U)a>#gLVrPxbYskB^U&!lip68<$0rJG6SL?Sf=t$dVWB|Nh9i=N>eX=}=e8l;jw< zDwj4jG&XWMdGmxB2VyCZnl?6_A`V2(H3FR+FU;amrPe}tBLiMUQ|MQ=Ooem(9EL+TP&NZfzF5XI zlaFL{?X0cYO*O|{lbm{MQROpQP$2UT5JGe4tmVitS>a?rm^^11ZW?Q*7r*)o?=rZx zm&JU4vQ(FPn3Zj#7(W&Z?WPA-6oQ;folFJpw{-(W$`n!?O*Sy@cU7XUc;ZsSXfSmM zlhfoQ|3P%+4awT0+bgEoV<3=bUh3q==PXdA@xb5ZPU0XyFZOTJx)z;PVWrrx2<~dk5s1-Hix~du* z8)M3a{_-nJg<^?uy`_4BH&*(ZRZ z%hLJIihhee#>3LRH2i{eX^~18>JwjGUf%1LiIzGffvJELTxKhkO3gm%2&~}uLZ*WN z@}G});llysoWzdaX-nY${krA@9tX(Gue#7$->;vx_Vhj<_7Q|<)2PK0V`JQ3f#<%B zydoIEZW|WJy5N?pg&EYGlg`$;ndqKs1;Gy8OM}5GIKYa+j}IBD1N@(_P9dpdr)BEH zHjSl0lHN40v^hD{(SAatb7L6|3 z;zWdnKWuK+iQr0<+qLvF9WEeyusH3k#74xN3+Y4at&1KP%%RRN&9d+%&kREMm8@sH zeUSsgOPRuqx7bDAlR&OY5da^}ZftBUj5#Q?2_V%zxh&olKFu}hp0!j-oIUd7av6{x z_Z$#DjBS86Hv)P4n>LjANyi>+AdWUR-W^*WtB)7PC5pzP)qRugg#i}zoNFVuY~zgD@xkw$b2kbp%9k12LfL1p-)I_3q1Q)vJsi zRhf)t7p%7YUU+8UEUDOk9y)F}UDI#E?MRl5+r9`8#v(v%U?^?rRWDAI+Om5^3t{Tt z+IT>CT-RJx#v>)lr_pfrZtqmQJtC+gZP4T0&H3`x7OqApIc)BTkGPuCbb^SXw0P>Pl_`7z81OH4>exUw?-j$?AH{L!!-Vk=v?>RN@8eEh(*z$|%dMz?CGR`?5aU@!mdK^k}=*TeL-)`O7 z+LEucGrU9tprKbycfOaH^4Jjqy=bLj;T`dY(!!4F?9W*pI&;JSN;Dt) zVGC&xOPQ=|3(;Y6P`OnB#)Sn!@K8^@l?6l{%5TCnX3qaXUX=9^BemnP>%l zHSX7T*7IS?30$zs%;6^4!+e${R$v%=;jw2YeOKf?+zyviam*%7SOwqcL)MqrT-=#cH@MH*T<9%+`1nCDCs|n)ZHWuE+8?3 zx-u8-AGnH&f#7%2iY)QuA=n=X4eH#Zl*dAB)!yfyw{ zvgBe$%K-K$f9F)d{l?G<< zc)PijsVk|J_i3-$T;M7D^vdsE!0nmId%em%M6V5Nw?a`mO-y`z6T?dm247y007T-! zd%AlXfm4(NsavWBea>QFeyUje(EW;p?t>O-c(a+N92Z880WSqa0}UHXJP-m(j1b_i zy*8PNqB-Qelkbt$RmYz)v&_t=_PTh1?+R0_%`RIa$4+^!F*LBqW?4GeC^yis}`D5Cdep|L||ND znh?a40X*cFCeH;s3+VLQ8hjO$`5r~5(c1%R)Exl?q-t70qoiK{e_hF1RO0fJ)16_r zPkquYA1l6j>*jbLvP74h=v*9jMQa4V@?c{Q&0sM#!6~J3Xl=$@!bGa;3{^P-90FDv zXZl#Vb@q%_m}uT)9k&*G2v##uD%I`Lg1!iINwolL<^NrKR&-kAz7GNo{0o5LwJx86 zFXlV2P$PXS@oS=J0JMlPO4LtrN>n^?o=nI6iw3=B`<3hM}M`SM_2!2toXcjpxKE`BbMYj$w&PPp3 z;HinfC=OAukB+s4s%d`DX=3&lFJ26@%&CwTPWEk8zN17f3s5aqK1KC)QEb-|uj`Di zGF_zVy;DRk1W^bPnB8@|+hVsYS@kH8?P1F7H$y?~{=obpI^6PTTGDC4URs*a+^Za% zA(Z*9bgi0BR!(D|O*t%eBdASAkdJTFS1ca)1znDDbrt*9sRM@|!ac;{Pz17dVeG12 zpGxDxpAfA|f6c1EQ5B!_S)s6+^C z=Phej+!+K{&aa(XWfN+L0_Oo3ejm4k-}rpmI(~oN$uIU;vb#XYNJv$N%eUilI*UQ> zl54XxD3VKHk&#;292ixN>=!u&hE9{_wLqn@Lg=bcaA%y<*Y-a@A1GF1s)?U+pB-Ny zycefz4{+{>&vH_v>%YJHZJa+0apTpGI0mofIqfSTtOk-)~Fu8YFWI$O8uQY6!-ckY%M7=Han9vKwuF234k)$`|Q ze?O_UANtd6&BJam@vZCa{SVyEy-zl=?o$7h#t~(UA)3$4q?&3j`?RUY_Zh0B_k#aP zltUFBMBB^`dSjyAy6}_FJc{^M!#m4$nl_eD?m$<{!a+3IGuqtU<5iTytZTnS+EPAr zP65V80z{4YPXu`J>YmTKp~BDng)&imNvw@i$3n2?+qYmv!gE!xUpn%W3DO#DmbO zIMQ>Fs161c_xga}G@C(bnd!T}z5lCyE2U6a`b*QfGP1+7Y$H?984qgfw?7>n z-(8Fcy~u`a>Xj1y^}QdUC~XoK&eT>GUpV2zhO4B)Bx$T!xR$oa43HC{slmeIade1uI#1_40OD@b7! zs8{P>&j~PT9N#}bnH7Wstb&3yGtYh<%eO9)r=afnf1!0bWyULuYr+SI9H29%#3$J~ z&(GEXlOV$AAE^vV62Jl`fcdeP9`@@v_E1pLdo>GcA3*L zCs57`&^=b)p2Y-Oe-A(=_scry=6R*w*0NkAe3CrQNJWih(IWsS4wCM7%I}ukSdsv$ zS5JDt!uY1&@T3?6-M^cLowP<}vQwO-rjzKwP@3S+O9$yEDirm=$I z+?<@8?2?jKQF(c5Mja_gSs?SO4*8;}-E$usTYUntFf+dohabD^8wPEiogF}Lv3vy-^bhY*(P$UN?`IgUqyNW zB1U(??9a%K9`=Vz=4%DUkmoGzZZf@+ThOvZU$X;Z?OLLHk@~3#YX&i$KF+6 z&pkUa5kDL>w;D zmGpss&Q>Xj@~nSpk%o2SjN}eVbOJgw?Y1QEUhfGT!)LHS(IZz{xO#9QrT$M|sU|Hg zjc;@D&|jH|kB={9x!Lu-bU;8r5nqu5CLj!#r{6gD2`V%hk4T!Ws;!-$_aL(~MB3;H zLyNsVL>JM7xd>9u5VvP$X6De+($-GZv<-B=iUGKOmFrYMZESYgk{CJ^llniGWghgA zVq;^kaM+`V4-O7GxuZeA>=At%{D`*_k&tL)a9K!yQdY(w`Rcv%agG2eduX(4^ux`Y z2)eUylkndvf#pZn7w^&#Lq77(+VN?yrkv1-2i%fpW{fqpr=tXOQ>&?|Nzo-jJiBiC zc0Reo>imNoKp`0tAEBvbRKi>qLyis(4((pYOUb3Veibk=u^a)%r5{c(10;an)I>pH zh&V*DE+@|CnA|1My#@(~Y9g$uNgaxTayERb&{xZJ=Ut@y{=JApf^k^I0sp!idSuoC zZkAars3p51?GTN4Ra{sblp$azRmw=q)r~D4aH_w4Fp8WE<~OiPaXj03xRF|{K-DJ^ zuksbg&%IX*Ho@C)5fn~Q9$?|*T*D(HYne@A-$Mnyp8o#*+m%Ah@5(b2CNI=`nbES& z_E8v{<04&)Zs9^(R)EBPe4tk{iCbqCa&*$>Vcu$jJxbZR< zDl^U7$IMw){u@}J@m>xI#dkd9?N+0cd%IpT0 zYn2on=56!B7U3=N3t5keUT(qLj6$tC$}R$Av5|Q=S-`&_n}|ju{+Bl-(}ojTXZ?HI z4gH%o`pxN@nW*h_F~N>Q2p&*XmbSOIC)m4t`E~NP(Ai#~GoK{0Wu5Y)K{!0>D!7_6 zezFo{u+6Z6BTQRj6nZ9fHut&+mYoX7H^LNDo&(k*>)f{n>aG?gpPcc)Eyg%mO)pq- zR;cKa5Tf33_NjaO7+E_16{k|Y%I%c2w9+pT5fTal1sk4Mh0Yj2iZVM3%Q+?n#_%hM z^bzw`)GIWa+*({x^aoy`_=`(1gg%xhPN+lWa*~#wzS$iyc%QRRm`(TacPM-JtyyT?RYdJC8D zV`pW(XJBQuL#gof(nzER2Bn7v2F^K*n_WH+ZHe(f0hrXNTr;6}U2!O=hq~V;EML?7 zb(uxFQCA*JQ`Oke&{srI&<8{Ocb}e&1HgRB#L3A?M@P4bp_H^|Eoh9CZX|$s`LIN& zIY%oW%1GwB_Y(>x6Ty=N%}+o`12STzxWFXgP&I1zaaH&86HY@PZUw=<{@%I0zvnsG z4c2QXg_26=t7MohBdz7ue(7z{JG=NVY;p{Ju9g%>+FM2$V^?5!)@8?%-MHfp;9`!! zAnAP>jG+|-u-jafSCc0p((dlxd7o|5b(^*3Ld$S{DpXEyZ znr9h#^%D^d6>nL2b=!%QQwTTSim~t6eXAlVkp+wrp8#3%D%A~>5K2uK9=-@#Ki;+_ z2EVPl2ax8_6=S1MS34g5^+yq`efSH)08(Ej9BpkEPY(|6L&XZssy^h1>!ZZSUWY1J z#$MjU%vnpSIi>~03kV5(g0STZ#41;DquzAjV$!}Y_17Z^x@_AG-Pk9SDO(G2Zz7NT zWa5;{#}t40WsEb93+eC==g9hB%vqfc)S*$chrXrVKIYnpM6fL!qqxB&u8O1HO$^4HUMU zl9H0VtSs0ou9CDg0vl-g@Ed<#CIZLm!l%9d-$#}pi94HLxBBd=k>}x!6BPOlB@-IF z)1x6WCL5edAH|GlAsTGL&UnE?uW-I#zwWaIPI{lD4}{vB-Y;nCFWh*M)QuWED-*wY z5(M73rkY+BL1LwpUu*cg4LP{yBb@ zrK9D7y$A9e^3ZUpuS}X87Ku30C_*hmS#whBdgYR)Nzqo zi_YmDT3wwiu?uM$MNF7d;08EZUM?kaS*YrZ?^#-lG0?EgRTBO?y0v|-^NVt&eKGc9 zrxeyg%E@6!v5> z*JeDte`x3>1_lXe9dP0(6Ove4oF!;*(hW5(0IBxFu?UdxQys4=td0>h3ewRbbCV(^ zABE!vGhSlbfjV+E)Kii0^(uLNL}eb0&HujETHiV@E;Z8kMnk`eNj}T3M;4U}V8!m) z(u!v!nQi-9p`JfzN-Ic@Zr_!E;V z^%4QFoWTC6Q%Hg`%Ku0QWx4e)Sd==Ar~QSOOgEItk6uz- zXU&5xFco}97CLzx0kqKlfY&fhU}k=PB%Vg%ISZSDf7x1;wh5eIGm%Rr=Dstk3P^U1 zIpKFN|0vI!c=bh$-q?O0MJ3z8R-y!E@NR9ED87M9B;8!~|JrY8zSb;$%uz=<6dTAE z^XDH<1lH${atsdHxgUh{Kt1Hm#FAVnKo(^g(*+#3J*cdeAI}mvRZu8{{e$1Us{dkR z_qg?7*PK-g&~P#h)AvY@F8})N_=SeYDu4C><`qk#`jS#>c>4LSn$I$mx4F9d%Rx3H zvLhcjRIX25w1xSj zu5J;M+;>#b@Bj#5TV^B6jt>5TA8L5+ObI%K5J0FiPlO)fZE{}AwI>eNHw*Oq_3!xa z%kQo8qn$7Bw4;+&ey+=_Q|}~}rlzKywtq^<%FD~Yv9PcNcSs*eVigt@$?4acs(E{PQNNED zT%ROCaoO}hmksxkycjQ+f3Wfs%)srFUbfghEQ0F{9*q6WKLO?T%>=5FAEE>q3nXQB z9rgv>>U-Ukus;&D7Cx-;f(-?Ou6NkVQpq+klRM*A1N-;rXsB31+kD*&G6-?DcK){Iu!0`1S*#dsV4 zs9D2RG8*sqUKuSw%YH)IL(oq$qtIKgOmE7vJ{kx5B8*kd$Vw6F7U+qOT z8zz}klGRE0U-;ScGt#hn9hw*S(Gq#lOIe2rCMP02lGl1T>%%t3;6=24#jZUaYP0BQ z@oCcPP6V+SH^F>e*l4OISz8ym;_t)qwaH3VNhSAMxyYU9Uca`t2?!9K)*H+2w8Q{T zOY=TuidYR39$EBUA8RMn&lK4%)m!_0Cq>!)k9Ga<2W$5d@DHp;zKepngB3>G`6Yt$ z%-a57Y2!bE?S!wT!LM4#<->iuADNKNHwB$5!a~I;@vaJLY$Ul1^H_hG6Lfp81^%?W zyVxF@{_{tKUAJG*|Kz zoDcW^ca+iQyw+*IzrQc+4&+nG3tc%lIjJLlw#?6NCt$r~0mdaTa$?{Pwh_*}RGUX+ z1V2hhp~a_9pT=*`x9W+5I|S2nOLSrrT}q0JA@~FYE3B-ntJn~T!FFT~#N94p-+3-jriHS+I^{*~AcX&r&DS2EDYsByYKLiuMx1k>v3AsF+t1p>KaJe{L z@LC1vXlaN?(Zdxixh(llJS4*ckM-ySo=h0u{QL-Wisod?rjR8vRz*X#$O|+?Wh7FD zP#&O8NRTLhqrV@yE18#ip~-59j)|#!Ig5}O6%TrT42+VUwy5XBBT-aTgcg^S`045B z9O1Y`Y_J{<<*4uC5)J6>Wu*p4N=DmoD+0Rw! zB9h=@W=5yue%~7TEG%B)Ilaqnmi4D|*OS-3uNvY}Hny8XUivbwmw#fhCe1mS1e@Dl z&~c^A>3E-%x4q*gSIgh;Lo>w7@z~DSCf-K>@xzSV@jh+v z77cl+^1|hV<=ga5&8m=WVNbg;70wP1I!4BC@aj*aNRpMbHWCsNUG44d&IlVJ|CgTg zgL3!~!Guid91NsIUpGILfN3c__w1Js<*C`!nluTU*zNvXEB}^pltcYgn|p!ieDI_# z-}?GVLQDp$QuUxmFlZ&!fw}rkF-Na-c%65aD|vW}sad4PORDxtOH0e$`T4m!IXO8i z!tyjRlFOy65HSD_3w1qK6S-o&hx4_yG!ma4?XS>Tyd0;6ujIr(JnCS3A~=6$4MmUf zb8i`BOH?9MlQ9tR$0g~VXmMkGmqR1~#6t zTk-Qt5cIzIukPiNuB=8kq&A+Q%774uV9+ZlwYj#xv?Wi6nJ_zsg!9?)d~@Iw5sXv| zLNYi}p<09TXA?#W(e~WMv%A^%~@Z z7bQ!Vpvd5aa7&aK+1ZcqhzPV?hZAVp%p9?6GT7cc1AmWpw3H`LPEPJROTbxO)O|-) zU0PbYvi#<~8WOX7OiYaX$gf{#?E!Ze_ex)1ITAv^IEhH@>DBC;s^4`qDtguJiuJSO zza~ETistHZq`6Pzh@`bUEH+TNy1HJ(#$vHCWQp+&6oS`7U+dTWMqSzKIP@#td5msFCHmJT(tv#Z#fERb<0W-~aWZL$&E>~XY~ z*^z8cHbkQdc&F&uOtmZq@;fk4@jGW_PPQ}XvILL%jGnFkEFuU@Z{2lk$ z7_2t>`H75#q;xOpfd%QWxtMQANJwvVG)66jfYVWITwLy{qV5M)bVb1<({2wiv1Q3r z^{Z6jIcU}91+jr3Q{9kqs@N=H&1a>bb8~u5*48^2Lhd_NxL8;YRb^$}JJZx=F_xGB zGs-wKik6mE-}LmfdgQ?7hKJnH$pr3q#-2=2W8?cV{I7;aYs6vd{#HI87*EG@M65dp{#^CuL}XK%d?F>d+*~VPY!;5y+p)A3Yunb@)qepqpNpYgYe6C&%;z^gt8lm zCF3<6$cED&gG?6?crg;5J1X~rvIWFqUU#a#3j6WnM@OZ8?Xx+eEEtVYp%x_*g&TZs zSPpfd`#>}_G?Cf)`IvV`MrhwkOS{M@C?2vknP+Sp7kVr=lnzaeyQg)GjQSn-4ZcS# z6-33`NUigFX43>co*(x2_g6bPIjL1wSKltbZt`EaN@`wJ1gz{4rAK2t@DWXi+xD;- zLf6rFdwLEKd^qPWU9GX<6>VyY{5xGgXEsmhF6KiC*Dn9hlK$_};`j3bSzN?W!t3j6 z((|RqFYr!iECo6FfvL8(bchS$ljG^==}U3mKvD%4=i>O5eBONkR1SIjhje7Ty#6&B zez$(2j-nwauV7{=$V{&~c3@+P&=H;pLTxjE&6>J%|)H>#d0p zsTYV%GFO8yEY;5$okq^xk#e~?A&`5#kB|^rMN@BLDTTB%($XR-hOWN3>oK--;&=Ds zwns)nw4|g!uXe~SH}uXqQbPrE``A42=KlInVl;zy zSJ&YxGBQ$=n2->5ew~A(S3aIOsSl7sZ!Ih=3JVMAz&&E@?8ny&3kxWnot=ABTAlSp zQhT<6;2!OvOd&eMcbM;~aU%LEtE)ecj*h-XtZu7u8DHz_xU96a@bGEGsIy|71iYIC zK4xUZ02c$6^_r|HmV5(G2>LPP54^wfL|AGfb4v`Gfr3hhr*@s2yuX$%{(A#wO&t*~8s^ zo&EIsiR}PoBm2lpWj_;`PW*N<0ii@h%P8|ch8!IoISV)~-+r>PvXVjYzLBjhOYU<7 z%a>0CYo_?!|KcVeTyY?fv#N@UUU`Z%$G=T#L7P!bdJ*B_vE6?#_kXHu*0TS!Sq_F7 zT*j$NneP4xPc)BRoG^xeNE z&`vQ(3VQqSfO&qc$CEL-I4~fWo}JzPp*I};G6IL{Ab!B>2(FNq;+xYV7Tbsb2N+zT zK+~3{MXI@isQb_VUo&Q1AI=BWXqRU`Jw7g-2lh2KHkO^%mk#Z~Mu=BdX*kPDuUXoH zr(wh~a@ys|erS&~XZ{-4Q+E=_w^mjntpT7=lwL-=3;91VQ}^-0GFHtLtmPA@K! z;W8-H>=wN1w=*^|F>zE^AHREgxXEjF+r|(-p5h>m(bX;|?4bP5udOUQBmsDv(ocf% z*=cokwYQ;xN0hglg`a;e==xw*1CGGBfMvZPMu=ou;ww=YP3=KC~`5V4U)ZX@j+BOzK zC&22mdVjC1tau{$pf@xWDPRXJkIHkk!D=KqihyYl1qB6ub9sr`d&N_Mo{Tj&8P@x$ zR#YW|!uQRsuL9cj?bps2Wc0W^3#dNgFn#yV?-Jo_$xhoZ$90#=D(LCx-ptO<4kO5S zbax%8BhJB5OC;_r)S-o=f`kFGgr-kILNY%+tqqpy-o5m-toPB>)}C%oPfvI4`+`le zeSA#Cj33nwMgr->pqjym&RvzL;n9Yy3l~vn5TZ||12?SJdp~`IXr$n>7Hiu&A?COG zE0e}*lJYk-ayaU2v@ipMY_)dzlAV1yL9ylp{l;;{Av@kLE&hBaNmAG?qFx_0vD^0X z4LQ?i=@9d?y8v(k>$%>;;d z$rMeM5n`aYiBx2Q=tYgh7J574()&nFX81lbWs8c68aEr)V3x577pZfTQCj$#z9n`bwu_G|I_g~#<5IS%Lh7{E>Zz77i zZuMtd2M5DeIOH=iJW>gcj*jW|Gl<@VdFs9P{XO3;lbOj(GLsBJ_y0eSh|ZjQ?m6H4_3yiP82tZnT`9m^ z*SmXtbCE&fE7D#Q(tFjr=cJgEqO@${LJ?r(|NaAyKPCW)iEMnzD3<6J5m6u}CEa0d z3=I#kdVR)M$h$TyQz%BrKvLe$94AWJF*a1K*03iT^z(5NTl9Ygf4I)ecDgcxM_?-cB8KQX3#)u~Y zoGRq2&Zj5cL35NLGV$>#TvH^>AChrh0EmxI=3Ngy{MLVw3)Nq`bOk*S)KAT<1#nl!tr?!!Y>(cCjKhm~58qshg&j z)90@H^M#O&o!cw`xE^f8?OURGk-1+KaTkCaT!^k3T-uxZr?Kaw>j)6_5BZ9JZ(~>N`hL=RT7*=kt9@!{abLf`W&p^WmkB>&@|I9u%RVbY zd=h|BA-t+uRKokZcYn+$FlZk{2TlQ^lmYX;#bkSH&kuhot_9-S*oSKXfXKwoNaNF1 z4m3-fpT6a>9(pJWjr266s zG`Knc0+5)SiBdsj|uE^j{neaBVqGn{*@sB%ffTW%@48sz+*Ksz>Gdnj; z%_mzXMcRH0===tNv^gbWjl2D)NsP_*34r#ZCWbk=NZbLCHrt$WZ9X!H%$Cd zHPVfZ&Rvi17XTdfef+c^UKSZFcHnx&(EWKR@32$FL0~n~XEt&E?oCrjor;cUZpz7; z41l^3l7QbWL7xM--+}n@#{cv~B=xD0OqVFG*}ZYi-+?5nKR{>_0J32kXr_RQV>L+( zBi<~EHZ|e(N7wbfvW0Rkh80C|TW;QkJI)<=x=f{kuZyYk8x4Spe*CoWLPSRU6M!M2 zXd}IOJ>AO2(!ty76t|V(AzJqr7haike9z;>O_78~0bnP7LUOQZsooBVLq*Z5h^e<{ z`7_TWmBeanHp~9J{H&Wv5*iDF&j6_2j-vCo0J!DW%R`r2LP5)uFY;gbQ)s81xQpL>**m$d@`peWUcit!EoE&K64G2B~pduVM zealM>m?etAZI1knH)pvXbELATC|X%_O-17Vt@pg*s}y(*fNJgIr*FJP1pkwgRv^#d zf6d$R6-cVAu{N6t7E|%m{aYW}hmG*Gr&j6FcG72_3OwRXTn!7*8#|wJM7+&Xb-AE8f5@5Cr*gbC%3c5< zDsvc&nzrRjFw9-eZFD!T9*-8m8XP})6_3r`0gcY+kx)CeLvoFXKf9s{^VVQ0H{dDP5u5(hShwnLsFTPzF!@v4vh|OA~>va`B}36Km!gsW*_>(ZG)+3ATz4H;!`0I-dmx+#%mxdn>LdEK&_W>Z-muCEUS*TXdj2n@qoY*sU0 zQ(d(D;Eun)kdUyRtuJ%x5dgc(Ib~B6!*hp4Q4EvwvW{e1~E9XRbH*J8s??1o;S_^n4u< z7zVs1*f-RDp3PW9n}x5bF8KK1jz=Dkk59JO#a)+j3xM72oV1~nMyE>?MTGm4`&$^a zSU6_@`t%A#Wt9cX-aUpx#|otKyzA)PAsC6z-H5iW15s2`gIC@>f>RkKkU?Ju1tSq^)JgwuwTk%st8}bMIt5-6)=skT`9*s zk8PFi?Z_!*+a^}>j4MR#UeqZ7)PgDm0Rrima^37D15BTm{`2E}0-Qq+ji&ezZ zxA$ZF&lhE29Q^#9NfYgoLSGdX3z)qi1?MlyZYhC4DyC!m7Wnv$u`mQ{?ciR_D#LwG z%0!h3D}yj0zBA@MJtL9vnSU;4-&~Ac(MtuG`!qKlsAlkJxprEh{ zyZ2?IT97?D$ITN6I!z7YhPFdkh#psRDv)|O7iP1g_a|RLDkeD4f>A@;BREKdQyE1# zmVOmhtMlUn1P;dsHihjZm((N_=jL79H}t}(4=yRmOZ$zS08p}cmSI!Y-KOD#zquCb zM?H-_vQWbXY5AS^Jk%WZxQsbJP@9aCXS90R{xT&-Ef#C*TYXIop?jqY-YI(=`_W26e zI(j?}OC;-7x4cSkqdOrh4e|STXvEx1wVyM!%>d;@` z6m{tNTK6ExTWb-lMZaDx5ge>TajAf_nZ+nBrZczHKip5IY&lk9DU;$kjSY)Sseg|PW)=BR&P|@&t|K5 zxl1olp!D9-F=*e;0E*ej3(Co@#DdrNBJ*O2gP<@{0Jdb_aD<1-K^p~E$4_0wyd|lU zm($Q75UdurkCxSmxP1h{#xN{P?r2%@xqFYNzVMZ!J8B0&)&Il)vhI0~4_XRHO`Y_8 zy&2Pn4(9HAN-w-RZy;K?3V_LE!w)+zTv@0ED; zx&O+Npm6>NuZ=;Q$hvOhg{(3>K6jUsB=9_kad91xFr^!eEp#|^G#{(}a{^_RtQ!#A zAKwQMs7@eKR9snhamkUCISU=_fU>&X|K~#YFH~1sFn7^z9C7f&M+|CDpGNTaJQ0*kU^-%x|I{rCNdCPle4gN#UZzgdj|qzq4t&P%KVf=J077t zOtngLM*zgg$O(bnhdjOq4A;M@E#*%<*b{L>BJs`Uv-oO*a~bicuWp83S8LlTs$KNP zekAX$<_O0KYV$_>)ABHP(H><61z-VqAR!7jkM4wbJ~;yV-qY{`1Su~hR27^!xP8$`K+2;K z?QIeOYW6d#_cN_JbQ!x33=^e1q|hV}$Ws|{d|W%+dwVq6wFyR5wHf;k=VJMLhfrgx zjc_}4Xn_xwkA=}to7+(dP*!fjtoc79BU5^U2sieP#2X7oIuTTzOSz+&b9XtZkf1;< z<~|XN!LhBO({WNNWbxYvaqa>ccE3DSR zV31r^%9`dERJpB35O;e7!6o9Z2Lv@G@%xpmoujkT|8>e80AlaB#ofcg2BgBzF+hEO zz9ZYXGq>&A8gT2)UC<>e1jPB@|8x$Nxs)5joUiEHt0l(8bwr1@!N@D9#=7s%;Ns=l zIquw8Y`0Dl~5Uh2haN>N|;R1py0EZJ2)=O^;aFhV_8Z^I0%XWi* z@wW(Hr8EotQW#3gKaTT*kJv~(8E-?@62E+Qr4fS-O*uE`se?l~(I<}Bf1Uq+M#%Et1m#SFOU>HP3 z1mfK#@sg|RI!eoG@YwUolKV)bYg7nUERK@^bsblW1UxclCkl&e-AS#M$BcV>W7M#A z2ngVD{z3^}|KL|i!rTrwYLFzsX7wap&MJxJG?E)CROeqhm9}bJS;4*wKmxtCL{>pc zR0gB5qp{DZ70E2C>DSaa;P%N;c<`^?@Za4zSg}eDnAEZ5KNFld)oixmC;Jwj0nJv-Puy0M#EL@ID_EPov;ETS5=w+^RK&}n6A83N_uHXEdU93ut-V@ z7&ht4_js-GZ%qZ@)|)$G^0@Z+`rFgk{xg+AYrEH|-P{nQu@jfPQ+Wr zbjAx$4|3{=aHR0ZtB>Q$4X34#=FGei(wBv0t8l7zqj0 zNLnwwGR?IfpdCE^vuAZdk&9|8_>E6Td+Jgi&^sJ=P4A5UF%c*#5s)zc0(PcdJ=B!hUt@{ zL0x)Bj$f7XJ@$-e1Acy8m?;3$dH_MH3&Uy=n9`y%%hUHKE{cy&HmPrtaRq=M5dX$B zLrBlH$^!;XF31oFu7YVVo=Ybph($*<3Yxl=nb2%ejyTvf;)mGfQq$#NP|6m1OI!J^!~Po6#c z(Q3pbn&1flB_Pv5pdK^3!!>&jfO}6-Yumx2YE>8XNsiWQ+GqJ;}P4pl@tk+r<9phCfOBl z(hEM=6f4K+xXQ9iIT^=3n^Jl;?GylV$K1CjN(;xtXpx>CGUVpf?`Q+U?uID(y*YQ> z$hLUwfgUgzw6I!4{C4UpURbgRHq-@S(%2|G`A}cz^*ktI-ncarpR73nn@jG9Ivr*{ z&<9f{M1kiSrEqf$+mhuN#Bl@!Xt3+RC7wgBMJRXftq)VkZ2mhPJM~*(nVm z*MtusWnZ?`IP0j6zW!vQQ$C2inmG%8!KG}+2lg1WZySscUyDbG^3Vkl=n}e0zq$v|GAh)}wu$QV}_nikP|G4FHWHzO;<&{gh>$ zNlTeO6)2~U0}4o-TCm-&-oAZ8Kz4SLVZi8jW*LlKUH}-sHfgPSZxq_M39`pv6kI)* zxEm)<7upG+g7DTWaTwG;(mpriLMi4gPL*2K9i6zAVF7sSl@U^gl?J63emRhXmzV8x z&?542`^U7z(iewHt?4wVFKGS7^Z4lB$6WwuEb%4o7cJ&Wwz%NPKTjWe^VRn46Uwu* zlj;N|ZttL|p@8t#BYX55^z=rS3ux_6m$YqUAnu;t31j0rO5y*ztBy$NfI50z6NEOc zILw|gKnk$VUn-SS1{s+pbqeU@8O3xD!>k$o(V?9|>i74QUf@_3gKvz);}7O00I4L;}S^JweP+k5GR8cH@Bf74r?o z=$T+xDWlh*@$qs(LvE+)YC3kR`H48vGJf`U98OKiH_mD`3taKl-`1Quxb%g{$O)zS z`P)fk>$qedWh^EpL7SeQ6cpBORF5759{-N#gChMY1+-&NAh`PZ&LA{aEjYqg-x^I` z-^wx^S5=-}aPH)P?kLIIe+-DJ1f0DebvO0yBqAavsGuM{r0V+OF;{Q}`Dq_zq`kc~A|j@wpdg*1Ot%3^{cy*| zYLJ#@fHthnkTEO1(dt8cT#L9sm4t>O+uaa;6=9=3PljV_gd!ANPJTA?SeVETuEX2mh}CLXTfMJLTM>+f4xtKcmn{_zWq>rcJ@A_ zCa^Lg7cU!8jTmagZ0XgLN*ZaDAZvdeCvp}=~ z$TW72d2n>wPUAo2wJmsmdqvKY(D2rLX&0B3-Rx4-h5 zK$|F1e^I^NuRfi(Rua4b!N+z%@64XVc0F>woNh3i%GuJZCpMfs^xDfnP%%(RDOE~2 zd-Y2jzDR(gia^iq(`ySu2aJ02?VuJ><2hbu6-67{>>xC763|Q5%DSF_4+3heFZ?We?Vw3P%MKmdc}u9!5xM*I|xl|7ih4+ogpr?kHx+Q4 zup0LJC1%qAJ{sY*92Y@ zY4F^e?|dw;KyXKVk+l%l(>orjDsnROucW-5dw%mC==GHl1mb!!xQ$XfO*O*q08>B+ z3()Izp@NVb$OlA(_vrt`v%$vbY4j34mZkiW6c|cB8R(DU9)!AU*9(FZ@g+vKvh))% zqLtosh4SKao6a8p^i7LUa8<8wQzZzw^l&l-C`~55za&7VC7qnSA3YEr0u)lb5YV~j zePhBRV`u6EBfC>mF2m3ZjL1`x)KZg?a0bEia&AGe-<~SSlDeUkGDi;+R#)YnDb7E% z>eA`;J7j`~R{@0-;i`r8Mys7`ApwqS5(ru#*r3;Q20F>@RUAYD@m+AFJ zK@hCvKn3Z0DjItoWO*ay4e#2URqD=B?SdW%GXh1_U#<@__Gr`LhADRi8=`K}>O)&o z=L5rX)WSe-7gQxkYH9Lycz!^_aV3%Z_(hw|Y-7Mu@s=mGNP6BPl;o9_Wp2BY@zdJM zveWc5hX90C14X3oiR=BMa{TQD)ki0lpw#;jq}R7L2tpn`MW+igc5U50dgA0jWAs>^ zK0JniAm3f7h>_>y&^#jMx)_H&KTOJHf7t+0005MNklgo@mYrKRUDlwUoTuhD2sX8BF7X6W@M2y6{dMchx^PO7Ha2=C}R z`YJX4ny=ajdMZZ&gW?E{RuJ-u)#-Ek!)i1d)@(Ktu{rPtole(MuhjTkxdem*r`xT4 zLxj3k-~SN+s1Fd;Zm5JOfLI{d-7mI^K!vJ8)V~P~$N#?W1aD3^)L%^F%I)sB-_aFP iT_V@N{k0#zuJeDH%+WI}B;*4C000098QIseX3Y{JgR#Vnn4%&g*_X0rYwSs~ z?>pI&EhO7}`~BYI{qP>|$M-n?Uw$7r9-iY_?(4qp^S-Y0JfG-0y6TMQ*w0Z=P%vs> zPzDqfls2b7bZ5bTGEO*#C@6R+G*Gt<{Vmttn0a#=kt(h-`-&wy*o=tY4*zwQL#v{R zTHxPP8*6;)4+RBp>NL5zKJHEN&FE=I&SrCoiR;%TxznOE#3i_CD(ov6)tC-DqHOI= z^Sq55LpI$P^CpE&G_vi4?-nD3rLL|LMY#rRs4V07G+#ccu{3iSyO`NA6M za61BwE}yAaAEdpcxd92YJfW_$@xbXj+PH2X-(cGX6yAv(@AmdE%v5tq*7EB|Q zCXk2aWz~?`Q-wF{f0p|c>hv1p6B5Lij}(09rc|hqEL2o>c6M5ci_3jEkAt5SubW9` z?nfQM%2WPx&x+XOrKQUUhstb+52;{0VFP>;^77+GiB>_IXjfihC4Eg4 zT|gJEc64^-Z}3DfeT`3BYirtH*Uwn1ko|?>iO+s7CVnn2FFQPWwBvp`{*g%T}B4)`f71QnqQ1AnTwnI;TyZK57lOJq>1`n7b_j19T96{aTYDhOa=YkOjA_r z@Gv&NZi42PghWZ|P|0xJmmv_98}Kl2^LUkhw4$OS*I143YVF?bZ}^v+g8JTqm&954 zi(~L6s@4__stKWT=sJX@MHOOfWW;o*j*pK|a-?nBw)AiF{?`7Xvw7Ru&*j6MV2CYr z-@boW9`>ejCGo=Yy{C=6=4*&OHy}?AZ?YO_+aP?Z?3YEd&ySZ|F zj0qx_A5x{Ta&cybC}w|Ezp&ky#;nkIV83_yPwn=gbGcvoNEuV*S-sm-$P!B$ zE``7gS_04Y+N+MR*#`RS8rcTU^!lq_YJUnkFA>Y|)n-1mB!p!V?(?}Sg*Be7fp?bk zp8Q`Ue0Z%eY>j0j1sU`v$XA-#ae;M{x5Rf3{{1sNS#8^tPtg|Js~KDknGL{%(vWVy zHO}vP?tviQ>0bQ#)3z*Oak$txe?=N|kIg&R(4Y+}soI*@8;a*|C{S<1$GsrD$9g&2 z-YmOk*oaYD+G;t&x0QVRQ*N%%-2{JL%Pb}yTT~4}qB*sD(T-3;$7Tj~f7ip})Mn4U z=yc;1z2)=cNr!RjLpqR9?C0@qbM!IaD%J*9{U3s7i6(a6ZuG~$;VPlmAyBeRV(L*ap#kj>OTb@dHud(;gi@XX5)ENLJ{!hyTD&^TYS zzW%&??b%J0RxsAmi@d5|M_dOZ2o^)W{03yHM3I)CN*K))jq6^h)dWh2s`p(p}n0K0+a8VhGPW zvgl`8Z6(?CrFQ$4KbeWJS|~`VrDirXOzmh*o6pBOOuO?!{jS)U88+8p{zmWdz}(qN z43(4{r8Y>N3wLN4*7KB5bs^tPI*e%wxSt1OSPuxU?|SZ-Vc5xQ0yDb$rQ>W{qwG_H zhk*bgj1W9t0}Zf>7%Oy6 z_7*0sv)*lN1$$8UV|iG3Li~{Z^x4SiSf5FmS?tG==D!A7&h^@x>lWyGe;uUj*bONL z&Bh<7gTd=M!__;f?QGm-Zf11?Pu`%$MG=;H_!mfkGhUs;OgWLNToQ@)0#&jh61darc}@g8TgX?3O{hGvkc zEC^Yp8jN7*VUNtnwBl^@?kr0R_1&+~svL2>MRE`tnU$_JNmC{JE6T~`gZhG4dUQ#( zQTXAEdW(M%x^2~eY{L*Brwh8#^R+R}FM1Pn13@h9ATmg$9v}It>wU~q-g{8bcRiuz zulz0Z2aS<%>{->R&rqJcp8+V~}z3B}o|?lP2@AqBIOWijT6KI_tT2 zW=}3Axo*-z4sKd!iS>I1alu$A`7}unu=Wg;vHs;(E?pkn9G$Oo@%^~*80C?=3B3Fn^woWZjkOzJkHa?lkR^jOx3Uq3C!dWF;r2(A zH_MqvV&eGQ=!If&`tFYKvugi{why9*wrd6A_j@F9V<;p8RJC!qcxV-azK$keyLL@; z>4V^RdnqQwY;uf$2F5=PN2G22*YMeI{YDmyNG z!WLTWl$xMEb;v0(f0as2kqy>*;>vffl{%Ho+Kav(S6IKU{?$JLR_e-Y)d2-3tly-| zw1)Dgv-L>qmPQ0Q#0K|W*OwoMc?&{K@{QCHcDZTF zBkYJ-X`;tt9SIuz4iC$jPD6W)%!|(42hu6p2+=S$BPJ|cNjr#tm4m4#0GW1u<>qCd zTi0Y|hbw~*c5}A&gA`M=9iMmD3llN+i5>RrQwsrUWkmu;!B)O6)4W2H_SHeLXGwMZ z%f^>7Fi#~mG5Z!(7>QxfM$@a>T#U`7{9d_1Zc@QGzo%jU?1{Q(8dCd+lMfNCX z{gTzCK3J2A#Gj8woe%fTHOw;w%LJE`lVjveb#0Z$E;=%U$JDn_l>PSwh*A-9X(K1z z@9UWy1EGtQ;p!Q88jqHjly|nR}{c+Pd;1 zT3rYp0?(a{g)e3aOY|->F)`)!(;#M@%U8rCFhgRq@vz^rJe9ty#&?~cs;jAKe~Wn@ zXpJIcR1JkMa)f&zX8h&3_Gm|DyBx3Cj8z2wrk4#HSWFA~w;aZ1=|7Wl`l}I)8A&5Gy4HXi)5JN7TQO*9 z_l{6$6>cZ`5}fe-bph8IGg3CfT0?cIN4%My@<89i<+DR4=~t1(=SVem^*ts=#%Djh zs&mdqH&^(}r^W6Te#z&fgwZ7`zw7Zg6njCRZLs{kzrWw=;ds^N&?}jTljs!{EsZOb zs?98AX;;+@MVugQo;8$>>JLzRJ(XH@~!)(Yp;MsFh-C=UWA zWxW~^R!tHxd?=9~Kt%Oo+GF=NE%7>^jgkB5N4`&id^=HRR_Sh06S%YDHx+WQmep>8`W0IlpG0FXa&va~fh-a8fpZf^yTtmU z#FC>R2a$zP@%n;~MArw>#2t!-Y~_x)3iK`e1Rm_J9TnH@ju!j<9^c>F4+_CiG5s^1 z-`BAAKJUSqBPA#Icsq(a(=s~>!>7yE*h9#$0DHWt!TF5>Jl3nJ#a7=) zyPe`q7P6+FL0l9@Du1efk=Mb=fFmx3t{uxJu{G3At=fzaQRvoco%1a3THH2c;*$TH zuNuX4$Mfo!7^2^bFkXFQV;hNTG@uu$wr;4^?ilKZ2=Y$5-Wcul@j_%llDh1k&n2!VaBVQP5L<+j}A9*N%bFzA89L+6-l2-__F z5|vjc`CZ$2NHNP=I^NhMv$5Tpu|Xtb-E|#-2Nz<|(%1N&cVNA}y$ho+;h&<(HU7M| zba16SNhztaqsB1mcTr52{|y-mmj^cy?yH`Tzftf`p)t34ebD|?{lV|g(H$Kfv_-3f z+Igi0CReASiuGA}NyMl;(sLpT#Fl2^`~CBg_J$xCF#UV+Ev-6j(@Kd;vx ztSl`pDedm;9QBro;8ULbXS^A7Z_U?0*Iy|hAaJ}om!NbUyIP}3CX^~FM}cB)GVih) z@^$Aze;{nx=ibqE*n5c=n*4sNgN2qaguV%@kF(>?!vc}xVm2b<@fd9STS^GP(XYKc zHu5ZIRLLwQn7?&jw(A>je5Y|-i1#=1Hwm9q;hM=Sf*3}1Pv)Y-`u zZu~a#$aC&DUOD0aF7>>N+WR%K&18&jvX%ek3F83>`GDr|cE!l*Q1O%982}^ha5c06 z3?D<}P}9sDam_oF5b*f47;(f|%Km!Q=5llke}P^v;r2~D{Jdt_h=^BHVNeO`OCo(F z$bEg7qVGz7!>^H#i+dc5x5iYdKnztH)4z^ag&h48TKB5W~mA;?$- zN47z3^oTc03B>2`9TvOjR(Y-=(B*T&XQPGR}u4(|X9)h(=_9B{32#aV#4mc%?u0 zNyugk+mp860O5JUo@rAc>cRcFyIf(=IHYc+?OvOt*J$JR}d*6 z1PVHBZS5eh-CrXl9Fg>cc8L&AsIdvw=ML^Y>-fD~{O3nkh+WJUU|sU!ehkGBwyvkV z&7dC^*U^f_>!r!>>pkB49UNt$eHsdmH;v^kL&rWpzojVgoQn)CP4>YVYATc4nN`VG z?mkBcAEwKDy?_7ST-(9Y3pwt@Xk$UnHh?sQ7H}bEb`5dHsiaN5nf~bWf+6aVhkwix z*1#4^L5cYbBL3t8Whceuvx}p5VF;W4b92NlMgxXW20of_k1-PRSgYR$vGVl zJF*Rg3K9qJeNq=je1fnGGlpdgOUn9f&38=2$H&)qiTyXKy4JR~vwhd@e-E-9doP^ zI+*rCrEXIrc84JD3%CSsB_;^>wep!r4Pr61)}43k+lRIF)}ptXrS-T#h%oxuirY!A9J=3G zu4kea%|0L7!Cr$C?bQ5Sl)ptLYzz+%o7pT;R1g8n;e8&?&3*C_Gkm>E>ispXTU6(7 z+_@Z9*ne&{wl)?g>B5xlRF*ng1}2AJgn0h<`g$d|LSVn9dV4B#)4!JAI*X6T+EC3u zEe9EN_;<5XXr?RJZhJ+8M}&rF#(VL5@QR80hbwRdNlKcos^`H6DQQzxD*X+Ts2Mxh zPz%vPe+K#oQRHJJV{*K*uuA#|%1zA+aY@a9kkf-iEil>3X;?o$ABqzh;4slA=R4>TIjpc|O1k4!g!eOmV>C!`a%r_WR(PZ@muHeTf$43n#^TC~+ zf}l*J47+Ml6m%j{wrGX4 z0$!M!6MM+YgD#}JoLua})d73P;0e0i_zgjqJLK9F(95c5yfuNmdY?O(K!}*w-meul zGLwPWSy=aU#>Md;0 z1?Mn97wqx-@8(<-pn+eWpX{%^A)ZD8bhv#Q`uEIVm#Mu&0@y=*0bN~Hc^_44B5sGm;!!eN2(W3AHA7)cF5RUQ0DFi$$`JKT zjsPe)w&7QXM3pZNyMtH8u)M|b^*pPk``_#TFZ%yWp8qY~|3k=weF%A6iv4y0s~*oO zNgwgF^zoiMU$SNjH8r(bDfW|B^=qR-W6{3rYd}c>oK=N`X*8fr{48XgQXRi~zD}}% zugnBkwr>Jd$?z;fj2^9R_9)lh)lm?uD(9)&noR(vhnlJZG&q2Tm z7!!-49@sI!8%eC6o`cbWi#U0L(o#<^yJ9m*4bCB1z(umkf90i5F9W+PEjWka0T+3M zZUi`=UiKCjzzoh2lurjuF|*x&dYLk0n+u%d2|K-rlDwD;#t5GIQ{nX7|6cU}$B15k zT`569!T$Et3-G__{x4tu&msVVcLpm$dSoFJUg(s%yf^jajv03(9<5KhWf=&0TU$3?VU0Bw zd+{-EAkQK7y@H$^N2N$-g~(NCLfc%?s(?7-5erDlLnLh>6$+A5^wMsm0JURq``6Y9WZGfA|E-l?m)6TaZ7(GivYj zW83C5$?u(R0FQ-tmlqj`^?hiGj|h?InzL@ zt~)w9rm~c**8I*hR`*Gi5auJqEB}d2!WpVp6}>7G$xmihLxG0YQ`0|Sk6P(emH+Mcemw~YS6|xFTOG)uu*{P9}lA6`k(Fy2GE$Go8FZ+x- z-*_b~7>B8{EEYV~3iKt;E)wEd_BHD^Hs{)&XhDkSESm2Ewn*d^U>|;uSLU)R~KP}sWKNE%QY1KEz6WS zU4_BYjB`Qc;-4!9Y$1_{yJfi>;ip@3i7pLbAr%$8e|{6JaC>(HtMh~4g9D_iD_pIq ztU#^&o}0Z?3gBO~t+?Ru4FU;}7i~8N`#vq`!nnA&Zd^@{F%nLeurO7)BN*p{(;g(O z&^;+Ti?Efp;bV=>)_pCz`T3NH{HV(i02F>o81_ckDgC&7N-y<)?M=c%&m5?b3~2;h zuiKXamS)72HQO1eI!T{JAnA(1qu_ZmqkJ|*4`5g*Crg=9n?>V@iOLti!%$695&QEU z&reVg@q@H!+S8OKf?%CeVM{w-2*rl#7)1~;VhO{ymO0OyS2z%&+P)mUeEjgqV=u~d zT^NwR3I?2=q1?n0JRGLxOG6V^&gTPNb-}!r^_<-UliXmT9xs3KKe-*-*xcMKc)vUC zh&i~6&Z6-{{08k(5)R!6e+j6?r}v~%d{VpK=jZSlBW-feSJ>G1eaaumd(-7;geoZJ z&d?iHMu|{+=jguqx5x%8W`3OrGV>`N*mw)NA>aM^|E3%J5=-c+6fTCr0DogBY_qRv zbU92ZrJ&RnqNk&iyCA~-cyBZAX7Gv>GENhsJxq8oTvm{k#YaeNe9KvJdh-_wk9QA4 z-pFoU|IY;5Q?W>(&Oy?Zo*XkDkA5li#qrv;dEV2PIM;j!N(rgdGi{9n#J$UD+CPTB zH1k3-K;CIH8o{u4u_?pX-4yu4&Oz|pFp>|hpFy?0%ki$p|3mufB8ctmkv5_!OiKSL zjbGJ)!Q2P>(ad6*Pqt-hq&y%^@lV~xS{ZIgYp5DPkLy#*;_~SF>BLRR zRk{q{-6m=Vg8pt~0EV%PNF)Y){F&H+WDPJ`rW5(?KK96^7ifyXVScFAbwF(^0rhvU zOIzR?Zm(EUD@5Txlamsc2Ny?sBrJ#DL9+6A8B z!Dhx>lKpVei+>v`9z}o`_eEwIW4Fj} zyqXAGKp(K;;^27fJ67R#FuUphNR@cs?my)=Yb@9nXMq&k@CrOFy<6$z&`d~cdx8Fv zU0_)v(4H{QO5DaiM81@{GL*(Vh_Dg5yJ|t+GV_*_%~_0)^u2WVrDsS#!<^oGNv-nc ztHrfjWT1jDuZ>r4?*LTk<^tp$V8GShS{8R7{+&yBQDk22wVz*HUn4ZYg8f9hOh*St z=n6bvp;a8){_@BIN0N!eYyGMr@71Q+4)uR zjrep0&G@)DS0#_>#-$9^sAK75O}D8B8zWq&$ne29pZQe$dpH%mH_;3fX6ku7k(nf4 zg2855V}`lEdH?(OFO}eNaEoklcA-X{oJcyA+ft=-OfcFyIw_m}kHfa78P!b!wdge75a47*`KKcMpVfhsC`pyZEb>D*}a^- zEK)r8O-V6Nvu~VQRCd17Y4Eda6DCvraF_H$pGwYAm^Ev?JE9n5fz_ zTsml|$*2HoW9OG}+9$qCKQg8O`#3kyHL+HE>iK%6OhL6PU+lR)S=VqX0iMJqB%DZq z=+N)qU}xmFiGIq@7#37gZ;UH=9chSSetw-KFr$)T{cE!Bv$PYngL8z+7hDjLgvmA_ z9d6_tjz%{8`23Zbk3GJ{HrnxHigr%l^4eJCUc>IFOT#26sHPUT_n}WFW}f|EbEO6d zD1Zzt`*cbnKLIkAc*EgVXEB$&zr@|Jepe1?iKY?{Bd@+hFEhgWTVlR(zH=d6!6ivq z*$=%ei7|wT@iE7*qB`WI^TBB8;B!D9P0H&A}`I|2%J{I9Xf^+w<= zux*49O>JAn`q97~OjC2t^>DK*qqZvDVL7!sz6ZZ)fL?f4B~ z@Bx_4cdDwY@2bszFB=N)T*w!=(bGUQpX9E%#H)!6*<_ zibBExT;{feWkc9BH#lDkQW}Wq%!ex`4gVHm#q0g2b92&07jgveScLIQmHtS$r6

Gk4Nu&>ytclBHT3>yFZTip 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 F{}+c#fad&rj=iST9B{Rv~ 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 CG9jS= literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_drawer_pressed.png b/app/src/main/res/drawable-xxhdpi/ic_drawer_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..aa600e3f39975b3cfd690966eb30e6934bd702ae GIT binary patch literal 14014 zcmV;vHbKdWP)PCW@%07YSj&6;tfUEpCb961UiKzBulR6PGw{u~Wb;j%{3! z3(XjtCOU{}KolW?Kn?Y_yV^eAxo>yG?rNKaq?Iu5932UEW_ISi-`w`@yN|=AcBuz0 zpa-}MIQP=2mwEt~0J;Rh1@*usfLQm59J2q+`XVcTgx5aFNjoaCQ?j2I0nYaK&$#`J z0J1?sfK*qiR94O!#95&!@!Gt3uiX#^?+{s%J~{^;ALek69}x_%+1z| z8K{d4Ae%&>L3amCde)j4m@ESXaH-(A!6MLK6vciVxM% zfEEBv02)MyH5|v4aKIT@#X<|j0?38aTXU|dc7>IIvfbB(NW7k>D=z|oJV2A3&1W7S zpK7%VlK^ol2aE+U5J0T!Fo&l70&COfuLxDhg=tnRcO`%f0BHbJ(&rAKSOHNQP^k}Ge|vh}CE8qn z^8hDFEI5Fr2ape73(t!`7)_QP+gC1VmM)%|xk+YIbLRo;d2+_{9rZGR+DaQ50BdAR z1`qLi5x5G#AQxaP0249vtd2ijF;4V7jz1j02`*Bqhy&J&ocJ|Yr`{^P0KHWz^%{Vv zgB|UM%dh{gzXjYcA&R#E80i2F4In{7&qfj<(9cNsL(-1iezJo&2cV9C<31N4F5URe zwP$S4V0%ft8~t6ue#fpE=+5?5z}87NuPSrl_bDQ* zFMz}C_PZ5DQ6$@jiT;bYneB$RZEQq*!hwG-clp)D=RrE}c?P;4dI&&{Qb*)wE?V;k z0MFP1dt~DfIK5R(b##nL+DIN81up-(`P*w=BMH=#q*1^DvKh%X{hqO4^)!y>-Ucw9 zy?mlbHqOPQs@e;ai)!Qci&pEyl3H`@yY^nVvyKlaK;!S-E8q9-1QR{X%!R980LMLR ze=xHsT6=>>)mh`<>pC>yYvnkb=LS*y%jV_to})h<`_R`#y5jQy0dzjrk#XJ10h~~9)M&Ao@7cC;K@L0Fp>O@Y*o7X~tpGXd?94@LUJ)Ta;b7}r zk~-}h%~ok7TE)L@SuyWPQf}RC7j+vzl8c^}wM-FhR(}rQdYhe0VPqCTzSP>^1LUdM zrfWpYw_6Gi+>HEeqhmOv{g-Ut8QlVqWa!Pfc6Fqn;MM?`a!F;iZ=k#!-Kx?=t9e&# zRrR&`JAYHxUB-2n10=l-Z1PjYS^&cUm_*Sk@3bzwbRiPvCXN&27K`P$QQvS)-j8>j z?hZ-Rr2t6}kiKBe2%Z<$1Bkx_Pgl}zgUD(%Rp_*uEBCFx?QmB^)MWrkA~a*s>fs!? zEdZiLQ8WSKCCSs34A~`-)ncmAY8z+o-*D%lu2g4T0+2-gjI343f?3!JhzXbA=~8N3 zE-tAvV|k;lBK`3C2TpaBBnJ9e6(AmMpP6UV& zyVy!iZswxZ%K+{dm*5E`JPr_vR=LTfS-x}4tt|FtOTz1%RkfW4kX<}lXD(X(SAcuU z9_P6fUG51CfisI%v&>{@dVSXqcl=*g*0N5^x$YEzBrAXBf>n#a^WWH}C#=#+h#t{} zKl7UqIgaNn<`x*W^|$72yyx@I^2{z6AjvSBcKz4=<)UgofT*8o0$5LHlqINHOq%+- z=ChNJZTaKL&M>Mk5TNsRPsXCvxg59*dlFcWR$X#AkBMWVF*_p>I-MC`e|H+iC7N~t zFnmY^uDc=`g1}+@<}w^SS_hM`awx!X(e*|*0~-(Y}T5$fLs0(2C|@n(xzFVpL5U){Uz-aln#Zfae?(2-l}FhG*g zJY&J~Ndhn5)tl^|)Is5R{`X^%&{qw!MZ}Ih<#_6^6fB3|5Uu>*Tm%KlAQL#`pQyzP zukS)xg-wd}aEO>aWHL6RMOT%1VACU8fGi%!@lw6SGg=)4s8#Io84FkM;5cq_Z%|!Q zH;@Fn{TC^iJ}H4ops!b-#L};h+CJtu$Q4wi!+U%CuT#-CR>dUHhOKAuzb}uXu7Q@p z+gi_t$fnAS`i6bGf4GxnMs!q_bqJtV)wOWt?|4plv$v?O*1?tYNQ?!>jEsd|Z$aMv za#Ypm7(C|z@D9{Ckah!Pw|&Hng)86XIN|Qzq`F)OyA>ig@c1i<93k@5nLQUG z&TO?BWd>c%(mm_%y(24Y8Q0#T4($R+GMv-rEt|;8)jLV*^!9+E$w+JVyfI*X$uKF4rzpyt;AIAst4w0>kd>O@N zH|or(^EeJNd5AAo1Ms(m8y$qnm&G7DN(HM`L`j(z+wv-*(bPLY=e}zQBKqDb zm&GD6KA6?_sjk&y*S;#$*6U$1xER)M?5mK_aEuuqg~0>Dpi~NIY%<}{(OMLpX=eA+ z{mm|gbd~G(tiSKd_DCVW0FtE7)OkxMD&!Hn=>Y>_`_L4`^a*hoGEjx_WBMX8TnVkt zgd@jmv3_$g4j!onFY_D;=6MduiE2z76OQ!BiHM60hQ%V{)R{)C%PmIkj#8K{^WG44O`BlxTFcZ5Zv7i*=!+wJ(`+|F3;coe6GJzs67CQ=?hjY=6TsYfs#I> zhDRcOQXee5dN2qksnHzN-k;84$;XFKc&grGG&wFN2opw!;o;wmg;H_8*oRdVQB~c7 z7hc_3cYk zai2S~hTw{s@koqsYm8DLaOK(}eDuW;o6+lLUTgg5Xxw{yDpChhNoeP0GF$P(#$vqk z&K|FW_R>=`Fm*z_6Ts35yZ4>LJ0BdtnbNlLA?cX=?;MS5=L|qZxU$Xn6cp9ty-$x| z*S>S?vu=in#f1zlH4XLUKaDRq{N`!9DE2x->=Ph+)Y&>?{x^>bg7Wo1rfNL$n>1W~ zc@jvCxHgT}gxnn^c;z2V!@7kiV{%_S@$hH_2eqB=CEFwacrAYW#0HN5QD=Sh&Q%!D z-=?};TWPrle|~Kjju+N>yvB2nPeJDNBsK-&+G^_b`1gN*!n)08TR-YPh(vIlU@;pt zg0{Id`{0(x{{m$5Kz3^xWp@wd10Xi%Mdt}K7p~q3j+-EgR+@ARNU^8;?;MV+W+fs# zRMF;H8k>z+zxfQ_T)fxmGe=1@Z9*&_yDtsVQB;iHxsffj_h2O+&))2I@THFW_p7s+ z?c%6@q!Uh_YQQUR??J&SM`PUia({eiBIaZyBS_V@3(L=GvE+Y;v2lBe(@EV25odvD z74+J3hw|3nI|+c%R<+o3`m0xfq^R?Zt3I111ch(4RYPs9x$ITccg2TSW+q|Q^cYMU z7wx$2RHXC^bAAS^h;6&e@$s@_ zI8oFVz;1%5)tJ`S6kdI3Pxg;M7UylI-YYIjah62CM@-(m)bKDwTl5I1Uf}dK?BMhap6*U~Y4Lqn>$i zZ@s%8P0jZ6?I*f+P)u|%9{lwfj2a$|$Osj4+NS=4~VA0J{KorQUF?lGiiSai)` z%uerz*gnCK$$7N2n3&!4)v7{l+g%2O(S2q`cR<8(yv1T}AvL!6K<=XtWoB;T9Crio z_Hwy=W>a6INBVqj(-$8jTi!lbEO&|&PzSfo!$VsV^ijR|`Xp2L=1rO;^H!{Z2% z)uO?m{^7WK_5dU$gtB~~<0tE|@`pl}5a!rCy{RQeV@rT{=^yh}dXXUtOV@+I`J7GwDvF?%k{-N#t%8y&Z4X`9r--!a5w( z?&ouNg5!1xT@4Y(@nA8b`oabIyRuh%Q)9jW;?n1T{Q@tjo(xp%$5ZdSg~-nVrD(D@ zh(mr5cjS4h`%_MZo~JpNc#)-sR#t$FCHR_{xmzF@^ho|jDz zr1#|)M1I0^UY)szs5ihPJww+?BF-X;7NJE`x_9q}2Pyg9;7N_S?=Snj*VwuL7!;-+ zM1FBtAiXbdZ!wcZ?S#h@M7;@~E{2GCV|ra>b7keujN*gu9kPF48}GnvpGn@=^s7Jr zg-jLp1x>s6;^PHWBxa<2!itWqG%=8phqv)@eGmkBhrLwScn24YB^*wp1JX1Vc|GkT*+cV z9-D)dBlkZvL;;0@2Q9!Qw_Dd@hE`|pl-YE5Hjk&UzQ^mryMk$;VF*e zk5uRgJY55kZRLixsbt6gO%KfmvW-C7t0WR6TJ!Fqany0bs z6RAQ%-(aW|0%#JnstZM}9LFBZl^2>%m;xfy34Ka(MyvAFg7{g*-I^kt7&JvuR4iWU`>K$q2o{ay}Kr zvnce+VJE6HHo2k>Ky2+YAE* z^c>U{O~AhRFJ1H0nI^pY&%HQyvd*nK<9VADo0HKGQ^xm2s9J&YN-frJ zDZ%dj=g`#b9L#hPh5iUJbPhzK$Z-N^(AAh~tM<=1dEg)0fh^j0+9^!l1|Yiujmg)1 zvOuMb`pRC%*)JQ@ucvc!5asqnMJU+>BSn_$8;x!|pB4mWOpd}`x1>4c^N`Beva=NL zyng_7_T|NnaUP2N-jOu|S@TondMzdDYbl_#AR z8cN3|^bNs%cZ@{(ltiZ)dCDgEIOjN4u07?}79;S2R5JGcMw89v@|L}L;Se!HS~MCO zxyIUKcOTvTmydyLDu?eRT0H^8Prc@g-z$`%FLy`$XU3#Bj2RJ%!2=?&=RhUaZaR(1 zDs7vbo|_g7#N3Q{w^D?%0x22m%M~ZsSUCm@lj1}0!V}YwIw;aFfcE`Vg-4&wbvpLd z=Q1#9T%6lkc-M=bD6D6BMTMtb)}8^l^QIA4aMeJ>^l5AK9zIr!4?fGs{zFwRm*m(o z?5i(N!Pt?}ICiogtA04eY%g!^!XUDzcbK$7bN$Je4{d*%vhA%t0UAGkiG1I_`}i5x z<-8%tf*-qocc#Q z+FJbgxo%S^+zkN1c;h|aIeqli2lEgcO*zoM8Km6kr(fE^)S+v8_V<%9Yli!LAezPh z&qs%`e#`lMAjwsqJ2M#%{%RDWB2{d*|BK}(nUwR@E(9VeOHtEU^zp$hf4q16_$AhT z`|fjcRoiw)R+fOA97X#4Z@%CK<^1jd=x@(V#Lz)u%&;s!r@?yt-3dW zC^wq&l3)Huo>QL^L@9{^KKREKZj->=4FK6OcRoxt(a*QP|LE z+a7=jynp}qFxG9BQc}(j&lQ=;c;K#4ER&Ir%UM~7FP0bh;)i|SafrwhGs`rMr`I3I zeQZ9mvW&>_VFLkK0+6FjU$A^5$H^uGv|C`;CXmqzhe_iiFnmZ9w&#`OyLClw*Q#e- zHvn@o;xS}EgwsHhiBI6=tU8IWR<-Ta8IuR%(RGa zj{9bHAi}* znEqiNIDS}n07UoT&sz1Q#5kJ~eRCR1Yo(Y8WeJe`yLDF?-hO{S^U53>4R>Uu3U}R< zhK1J*@+yUB5G_^_FTSxG>$f_p5wIMjyKl7_@7|;kd2%1;9K*M3ics%RtwXveN(H(1 z_EE@~n!t=`dImCvH98YMUUr<>HuOB5(p+w|0}!#QX1eB*qP-h_I~f3_b~tVP>-;*| zVnBRK+FjAfL$1#Q_v&VA>YchxD)1Lf_6$jWg%uhW#37aaO@Mq}j`%C)uc zd+$yH*#HuTj(#Yq@4zebL~zmF2@sP+eymmZXSZ)xMI)CB7&j^g58pkGt>K3fqa+a0K zqp1+9%T&mPOi%cU%=yFo0F?s=UTC|lsO@)2!Nh9K*`n`fmKT0W%es66G;HbuIles+9_gliL)03L)|Z@JGpp>_msEw9bgX*` zl$n_=%gxOe(k4AStWVMeK}6ZG z@lT}2C8zHeMFa&>0!a_-D+&G*Jie5%?;dgwk)*<^^d&`WXO$IxdBCp1T0I2kE877Y zJnrE^3H`6w1#o0U_lWw3o*?qwHO`Vp9VEx>jAS;MNogT8iAi%;c?Zw2c{pEeju-mCUT3r@`#|Vzyr71=kh7qLt$WUavi; zIa|19R>i5W$%rQP9b;URqJvrRaQD6nwlI(7@HhuwTK`26;QxDI0>+JYAHyM#G+HC8jPb(j z=Lwtrq9;NlBca<-71M}05zAE9ozly%bS~jqDeZMO!W{4vI7JlBz?j1tsEyC-d$4} zK0A$;hJ-3`-|fRNZd4>l8c;SLNsq=R12$|a!3UomIS-LTCx?aFmJ{E3<8ZIZU<486 z+C2U84p6BU$3_WkkKQ}h=Y%SyxW4ykKE7Ljnk{*DRa^87cicD}bJCNbR?AsboTOJ( ztqz~$oM0fi1|dDY6rTF5Ba+7hL~JTU+gMz|*QS5w%}vJa8F3h$7VR{rMa31)lr-V9 zuTNm@#?x(<`NYSC;HlqDWD#V4+NN!#Y&PAoJ^u$=Sr&JxtghFjNHj&HsoI!pH(!6v zAlz`>U{H>dqadLdA@4vXKKk-FlSHnK*5S{XoPg28`=H=d12%3eLv4NAA`YDakM!NV zpk&oLG>xYZ?9ct(6~N$TpwOEH0*Aqa6(}qWo-yys4+VM1!tO}tc>eKmES-aLUC4g; zrm(eproWMRcUFC za@y5PUy`dLe%l=Yz4rVh3>_5Cz^JIw;=iBeW6cIz=QvhIr2*<`CI3Fpw&wku;oC0m>;ZI!n3asKyAykJooq{ zkCKe$;Qsy55&W3zP@;zE365nWK5*Aagoi2ETwTtpA}syJmVL<%>43rP9UhjE$d>jr zHxw;ByyMx2l9I9vrKLGEQP^4u)D>ASCFL$ziXqne);!B_;{Ip(-emTs20!LFU?{_IsIvyca-6o zS9UlZ`su%}LcgRCza-F4`89ZBG0n)g%?G;o_K~=DZi?G`DJW{ddrR}3?JqmAlvR1- zb%U7`aO^}qzF2Y6F5$WY9(r_JN~_7(EY#N=`TL2zuf7Om8h~6%dGHC4V%*GEuMLYz z`>Z>vu~MppN^W2!Zz;2|p~>iW;}Y7YDRXKxZd#D)Bu!{Z4pkR>`@I7!CDyf3^45dD z9?NR-_|x88d;s69DResYw|9*})^*OsJw073XH_9S|E2&nb!}}F3MJfk`zVYb8{-6{ z(PYK4m4z%#wKb2(aq}0Mz@(2lNXAMVllMsmf9Fdc>8b2V_4+!lx_svYr;fb86v#CC z1Sl;nOP-&fqZ~H&kx_92u2|n)(P)1*E>Q)AAv#iIOM2$aOlAd|8k-Hw^`?9vN@91N z38(I$(z@fv#Np}3CV91kC>e}O20!`Yb{7u{tf1BFe@;hytowW-soUuu{_);H964U+ zwpI`&kqsRjiEHN$z@%}p%#A-+rNz3G-MKv*@k~kn&e!G`3}s~i z$o}z`(#lR0fCME_9y)#Am!AqU^&CL#MR((*000(wNkl zf-20DokiJz^gF(<8ZsG&igQ}**mI6;97is)r(`fnXH8BDWdT-+5w zm6bmRO}Xl$r<6f4k9CJ9=GfK#Y+T}dXxzKBB*EgMgIGY2YAn)pM2o?K+B!Y6SzHI+ zT|Q5ApCE*XDp|Q;3T7IOR@65dm=y6E1oU;&Jq8||2WB?wWDPa>A0Eql>4~_wD_SZm ze)fkQ^#xlRP% zClIspZ6NZalP|&J&#U3%7>;9eVA`g$^(Du@UQk`JnF>si^l>tv*-Pf$>dX{?BSAn- z*tBcE{7fcSXLOe#?NJh4g2&gWcLF(*ZOK_gt66BOKfd?y_GhmLq8osbEkG{WKTgJ- zCmAio#H0mPSLcU}pR?q5>X5`g1qvYQ6|>3v8gN_B`J--p_wmnHZAtJ*0mLSuq4MC8 zwH4OcvX4%zThEaADtYZGH1E1LRsL-ym*J`5O*@PtM;6^;>?CSOHbzf2qfr$a><2vx{#-y=YTXhkWXuY!>7;7SuV(e#s*RfNs@@x zcTqyv#IbRRicq0hYsAqLbvSUi3KY%t)u>ELOdl08rX;aCJrp}CJl%jTyUN?<6ScXR zt-EN>ZpNep3`_}U(PUZ=MoY43&ALAu#svq-F?vKa(uPKX{wD8_!T_|qNQz~3pTX=J z60uciZLTXgerWqs^8r)?X*$;cVym<7p~I=Cgouc-Aq@=&)e|oN&*Q;i{T>T6K;$+L zAFRR+^HMRee;9M44Mre$CQ9Y-1`)aN32|z+M0wbdNS0qj15P^*QgNq`zBuZo zJe>_5iY487;|NR`8;d@XO3Y-SpV%qfYu<%U$Y z)Y@^0H6^0aOYr%(C%x`B)|vKR+hD9sed)C2#)`rmka%<<;D-3@&v3lAR^(%5)7 zc+8BKZV&G>@?~&*z-mTQKF~F@-6vyFiQUaRsXmbB9S5l}!hc@9+-;#LQe`B?9(aN_ zr1q@gKYDvEQj$a6rgc!cl^0&iYfZB_f0^^${M_#+VdgYjWe(RyHq?JUI>IJa-M6lT z$DY1nHMG?7b?5S4ED<^mWQJxt2G;nvE*Y~dE&k$CxzkVr>7w~vF*mZloGOKXBo2pzRP~H z`>uICI~`+3MY{!nc3ysSiHihsiC;bPn=#A=B3sI}6_?l~5UuWL+k6d`7op`OGCW>~ zE#J~KoUT4`aPf65O(!X%kE9QIUmokt__`~m#zI3=Lz|lm)Z;Jz=QHZix*%$puRPk&Q779bod%cZ$oV}p0!P9j1{L=-&}EK9j$93c%Te*2RQMzNp4 zDd8+NmvWkDqrAf6Mpm-U?6fY-pW*R?FR#-;HtAzA>4b*bBkPaue)+zTkT{J-Q%L}| zN#Ah&Hh=EWZcHbKG&Y`9_e;HPLjTkSIlPRvJ`RjaZ#MZ+8_?lNFHKK)g-qma(#KqW zYVDmBXVz>1!nHu7SL0c_qQ3xVdW5TrB>X6GWfBSFh(B$hW>AI^6aC&-le<8XA zk2iQk@GNm&Bh=R%T6=uYs}HNyF&eG5npOjlA?K8R=w z#}P!T;NX7YI$cTdxQy4HR7VW_HP6cfCWX8~bO|0`@Q{=QfwC7B|`DvH*C zZU-en|kfCjNbIkp}J!>dS>7ZQ-zgk_0wHsZQ6Z>H3hIvD9&7A%$B27~d zD}OkJ#%9+d=l)m-{v6{QXn$6zw88`4Y&L6UjdjQNc0K28kRErmK=pDG8o_jUd_xqM7F`A0OC6@&15^^&=kgwyb3(? zifeIk?{E5BFQl_7A+)Y5|9Bn#^5!14@7MW`^#=@pj_FKz*tOUgX&X9-{Mu zMGF(3cz6QFjf`fI=QZn#@$M%_{JUqnnxI*A+paqtw&zvg-B0t`;zpZT_XiArj`8D` z{8n3ZEnB`%i>6$tJ-6?zQ~B>N1|nN16zULl_MMgIa9bUD3P}plY+x`{sxavF!DBOC ze=8)s|6Ep6ri(Xc@uOSe43YC=lG+)b8pWm*XwOtC3)7yBOX&Lt^b2dPvax+n1zT3# zwQJSgJaxO_vCVfi*5z+Kn)k~6P^om#>nY|#s!N*l@+X_kLDKp&8tx1U$)HxNL!s5G zv(F2CG%*C)G>r;!Y5Qf1+!%2I~iI<;@gmG3K5kwQrL-z z@Yw7g+d8je>$x*OK2&z@E;&t4>VH1kVLe!+O%D& z%MpSL86=0;5Y$jALt!ukjhg<#vmxPwZj>v+dW1dHVM)~c;bE#vud5asYx7s0*#Fkk zP%2wsFp%0J_2qZO*%Kt4Asr-DrUZgR03DSNQ;nYS%0EKF`p=RpLoK2x2HZ1iH$)c+ zJO+Ke&|G(H`_VnGK4AB>DBeRq1W$)mS7%8eo7ZalA+L)4X|7CyC=6&+szL_E4I6j=;^5Gv)E;XST@3J0 zdWNA%&@`SbDm=9Ge!ccoIS_6D8l_+%Ngj_&bUI=gbT&YA57JZz)zl3J!oq+ig-jL| zK4S78-cg4ok5{N7$grm4y5jrW)ep=j>izIgVwly?QYUB{3Vu4Vf5}5;bA25UW(1lf zcqEUjT~iglIZiR^JAvWsX%henXeBEyDGc<9f;q5Wo)O5-_Mz+HW-#lAGzYwvYZ z*ZFP0i?rK2i>0+_DxhsXoqO`Y2hW+!^$k!&Sz)ZB03iV+!6Uiq7ZfP$DF8|8jN(L6 z#JUwCxm+$w9{Q_WBV*F;R|Lg`%9Y`wDAHc7l$_Q{1LdnHTt4>>Q77G#U+^%;*1~Zd zZ!$Jj2!eu)L@rQj%{@fj1rL)rR*vIDtJN&%wUy8|7w@b%v*9&u z{ox{xQ(BBh4S83R)S3@t2N3s zCi{p$>ekqi4Wdr!Dv$8k4P={SkCF2OjOXqXe3Wdk~(x_ zQUL^?%aGeWN`9QsNxkC7H@SIDCNKi+O>EE|s=H2SB{&N+|NR?a} zPFoO=Y9o)$o+i@uk72bqFWKqX6T9B0WZ#mF!z>EHY-ol-U#-_Pm8`ES-T0xl{%Em_ z)FD+xKaz{yZT614XYTr*_ubQyG?H9>l16rr)Iorjlgs5oc-++CF@2}}GAJ}LQ=yCq zCXjeuPFauS{&$OdyC8_1BoC7|BFE7(C^B*^ywT7IlfGW3*OhOsKDTRWV`bh^6Wh5( zEdp9nQ;y(Bb6NqBI*voy6996I7fI5HY$Jlm4wG7C2Z>ilj!KD5oUtf4H0g4MGAfZk z5@b}Thb^y$ZG~*t*-9OPh{408jR>1zOn(a&vmPcxBaHgmGHqk&rs~R_%XRffPMN4= zs|_4U(n#<~-~?3a^hAK9dvdgm$WtSb2qFfOLZMa|jW&s7GRcAm48QTJ;E4WLC{@uT z70U2nnLGr7j8$;8&{&BgfkZ!~Dm(98@ed+9FdR>kMznvwKJ90?Zs?FpPN4Ggxg7drE`Z0|Sw zK3)nwx`HH0B{>kHg2KqlnWO=4GMR+fq|9LikMC|Y2(m|(FO*pecXp{dGjYCNga zoI9v(D9EcS+jdMYm$NAb6G?0=2q=~Q`$Y8}H(afbA1M!t9HLZ&_Y-8nF@h{8j29GS zgoESd;CUG>`DJ-Qc8TTjUfFz|XeC<UI+@~IbO~2ayiG# z;@0v&}V!s^oIH zq~C1NFiArIF=#yfNYbWPfYWj1-%&ZzdFQnP;gJ1EAW8FV1d$}EWVGowAQu!0a7LpR za=F~`eD(sFOiUHg`2u7iDy1?~Aqa9A1cj~Uk;Q1WSWISvq22(qMyg<8u}c+6wb><% zNmMA*Fd9kSksEHLixV8ukE4{K|8tc#JzC=QW(nl!-W{cqB$=defCQHPw^9HM0-z8G zD#+zL(PrXwA}JENoY_*IUar=GHJLb(l%`w^<`{a+?Pjo804gqFASmcZ0z`sG`ahB~ z(vNiAUIk8XmO$=gnKbaOFi8eD0p<9&^l$n0!k4uNJcG7 zU~>48z>%bi^l!&w9Nq9<360|b^d=j~UnS@WldHOO1V;MX0if1JlG1sO-{}aACxBdm zay`e%)${j(dh&4>BS79%9ew5qhpRp02%o!gb5u8;;BZw*yxP#a&1KKfJuq>b|j8MuZLdzoA3}R-Cv2Bu=u}e0EA%$#~S_mOovYj2K z%-D|+}5_-}m^v|Gs~`$Fb%(=8uP&XYTucuKT*q>%7kE zPO`VPkdjoC+_Y(vl;s68hfSL{vqkUiTftx6Dwbn5Z925c((E_H4R?NimBZWd2L~FbmiwSHeK(h&U1djt{Ehhc?9?knW#~*&99&jT|-K20y)xzcLkX{OanhP2z_R zi6w^K7yJ@e`+DtA)c)<~Hi>m5K7Xt*Kc_+&|90KDDEbx0bd%T~{S)GQc)IJohBDvV zQWV1H>;0p3AMe^M`n+AvbJ3q*@AH|O%X))&)4}#}OOM7I*Is*idwYk?J~oUtao-L; z>e(#&@X@0o+E{u_SNQC5e&gT7Rkg=-L`1}Tr^-k7)}NzymBZr0`GfSw#xETU?TYq* z0WKVly*~avG;_#8nNa;r?~~0tPNGjij!(hH_iV9z^YUe0XIEEQ%=*emxbXM)@82)X z?_*3#oZT!Y`u_gdA3uInIIMhCUVjKypJy47FP?&4CujJ>D&5%^2x%}ezRt(f*OyW5v*il1Jl zC8YWO8k-hsSJJr?I8`{2DuDLhLgK<263^}2%UrVe$Z(%X~ z_0*|TO3asU-n>cZTapee+rB7KmR#UMTTmsQaFBuws%c9d`EcUP&MnJt)hiFNj0|@! zd4gL+ANi2t8aTpi8pY=Y@r%tHhgF77q_cRY0}FfV207*m{&r$REy~QYFaj+s#m3OQ zIN9{~SWN59<$2%5Yr^dzp`mo%_&#N2JO72ByO@Srz;X@+c}ncuxwG2)>eYtm7^8sQ zxpC7&bzg1c9kPPthQpG5YLdMcGth>Teq_q0P8G+NgUZT*HF(nl2M+ib%t0b%$J!Z) z-!D~ER+=m<(OnWwm3-f`IlOFtGG9Q;&h zkYevo?S0Y{AWa2}sU^92`=p&% z8 zt+!LhS;IVw^0h&t8A;$EOH%1+Y58r@INywG@mOYjW+v#ZIIn|-J|6IsQmFs( zbwlXMxCX)JulvBl&cXl6JNGgWNkr(rITn?_UTXv`)YQ-@v1yc_;6{}thF!T*@~s1P zk&>kAnv&`HQm5bFtg6eE!jU00XW>lgf*xCGl1Zm}&R}oFJ*Y#9v2{uM%5msf+2Y|! z7H;Z?X<^mqDb7vavC*%?3Fb}i_XP#%lD`IbQgzq0LNdg3d^!Tniie+{GqOA%MIJ@i!JfKTlzr`MqMXt~LQiJZKQ|rXA5N6bdy>k;S+)qC|DZh2IOU9z$(pi4xbtS!KMT#qP_rbvtp8-;=o(1bDod0_QlA;ANDJvvpX?5CN*aQ5^QEl~j~;axd=K#{e-F&p=}Fkd!u49XQFL?HB$UJzYtN^q??( zesAI4g!bA~MhO{sSSAiS&6zJkTOxupeKc;f&cLNz(jE1UC~uI`6lBoT@2rt&-0f6a zb7(`ilO2|>gN)(UgprC0X}f z;l)tF2*>|J)1doGEjx#s$;+`mY~%klMl<$+q7SZ|eAj zb#W15ZwSM&2qw2PqvV>nk5tJ;rFZCCIq-_*gEEwM9oOr_a9Tjl7K#s@lS_iA#iwyU zesnkwtd(Tu+kPRsn8aa}a;u#)k2j?u-W!LnxnAe$@*u)y z(S?dysk?ObhlBvfMZ z%Gy!d)g0h2?w|#B46Qyat-tq-c@=>`2;j5Wp1Thij6Ejr#3qH_xKX?BEsO0&pm9?| zNheoTZ}WAq!>D4?ZW4h6#%H&_Yv;~l4?evL(uqnT+6{G%?Kt*9P2Zl`}^X z`OnlYWsnXo79o<@_fdovE6RW$L!&?7_iePPkr>2J?>+k8#SN(BWgFGr^F?X1ZKT%( zTCS(?g6;#d*F)8_IvI;0w|mbVfH;`krkB$Zurn=OX0#0@+0!3~zVGYup3B7<;`>YE zU+VNdOyk{aRrKCmU>L4R;1BBbWl_nn6}?AmZmzEHeBekPF}Jzvs5rCC_dAiv5oNO58>fWo3}sIZ*p!3tH#}y zYUA$cPw~n(lU1uPGABbFGw{$1-wTwrn+^W>DyYl4kK;>BIC9KDTl-_R#+kKT{6mc> z0H~zetq!R4X=LO)MpJUdcB#WcQxFRB^4d^V09NOsuA)@@Fe(9{@Xi^>`~a>wf9pfZ8@7T zS801$E)!soQ-cmY8X`M$&Rdo`;%Ht1wQJz-K#r&T>)AfBe89VxbUNS1KexY?WRH4! zx+PaX^pgTn%YCaX@En`BuPSVg>FiaYPWmhoV!4e;^W7#bQ)L<~)nEFD?b!DD$K*n!)C1Mb{lq7?TxhGQEo|N9Gs*Ko#Kb8MkL~RWuuD%b45v1C7n28mOjOd*3PkUd17!C>#v*VpT>RE zUj5^kI?KEQ+T*9oDM!GR#3|RI=!OI5D^kzDyt2z0e4*#vyFVJ3JgQ3#=JMssR5)Yg zEDfz^Be#MlN6S|=SKu6w#ReuO(`>}c$&nKdI0r%vR%w**4NIlh z{z;g-cIE}aWob$h%S0=Qjni4&FH6#Lwho$o7XSLytD#(cna$|IXK@XZVPqZlJ*-sO zE&pbc7Sf-3v6aL>Ekic>#?f%-{1$BcmjSf9RF&Lm&A))W&ts|}OkS`E8G(0o*kQej zwi2A)pc=JHN*MV8?OxH7-H#BHFN|2%G^qQTMo#KA!63L6O#$0u&>|FaIZ968tfiZOlFOd{PkrhDyU}D4ET<~%Q3vEWLAL~+utn>I#9;-^1(_S zL1y661^6c+*i8M`XA=HX~+uY^D!^h#4F7wbC!>swqp#eAnx5 z^)n}#<>4ar>{cd`toAub9Zp5zQ&=7*f+H+d?mIOzk$d$Sk81JO&WR!--YyCRax35! z0)SAwt7dkW_p=B$&C1>B?d4DIM0&`UXCVo7B*%f?3gw(Iw8b#&#WX!;_UuLmrxYtC zo!h*Idm%U#r*X-0$tEITcIB9`W`N=Z0!&eNxsIZwE{~3(qTD<@Dk)Sdm50{M#&>!< zep@t<)XDB(WvF2lniA6R`jE*K7W)!istiT0d!sWnvaE`yx+J|Y`otT=Jp>_yM)ks3T_Iiuf*`1FN z9O=$=1tu)+LPWT>lKd_?U3@YSl9}TdLoR^qXUj}I6_#=kGesW>d8>YVcqlx1bZ<~? z1?Je^p+RDQFOL35nP~MyK4kE*BITrO!V-IG5@joifCeos&rz{7hNQx$h*0M z<=-tCC^8jEMka+!wA|UYn4O)iAg`dHke!v4<%B|^l+WI%S^%kzRg=3D@-UTZK+Hu8 zi^g)h#`P|sGSVgg6sln}c(OJUfi4t|73S@?;DBaQ!4`^!?#q`iQNQ$GS%I0-bx^Wo zEyVD`bPYzst)??yY5)F7!{D(uA5yfKKT{mbZ1WEuJZO9p%p|L8{BCgFBh8PwcJ7sn zKI>LfgI$kS1B43WAmspKpFv2dCYg~eeDEX#m<(&a@`n`^n?9LSpaV0^gQs#}cyx`w)eT=?%XWJ>SB0+7bcJNKQ7<=^d8y^!freI@W*Vk&#>Zp6Y9k{fmB&Io zqoP)4l4OtC?mrVe)&^pW2Y>~uPteB?zW07cu%mDLpuZ6uCSjY+pMDEoD%-aE;5!XX z%{Bk%=(SHnLqn6`)z#6_vAd7Wek(&(aWc6rxU%v+mwR730pe=ONy(K@qsOYSM@UalSv7#5ROiT?)ZTlg)`TydPg*-|c#I z=K7ajqT^NDNBY;MJ{11`wa#_QUN=wUiuOK$O#lA2Z6lU0NNi5B?`catf0>FR8{POh zGdc;zMpcgfIl2U$kQ<5E}Gf&)0}%4|CQ9z)R$DfH75I@ z)&2!ll-sWN=2a+JwDWVoGvrkL8t0{Wo-9usL{ynGI&5jf8 zXSGaYs#pSxmG?MHa*ltC4Ay?42i1$CzgD z@%(CmcgC01Yi%Sy&lD7L&x?^77%d{_`5BNBlZqB7+=rdsb21bm&agA>h{bvL7@@$a z>#>oc&gs)32^TWEw{8${sppGa$*iob?Ciji+G}6!`YJt|3F~VF{|@Jj3w)>eqkb^- zxDCaC+X&xbO$meSkMSS}1RgQGF^(NRuGBwL$#ru2xHqW8Vc>*7$#%0|9{ea$cCtO= zsD;RQx$kmLWdQfEJPq>KqZ76pK44SqSUovcmKh278hO)f6>*F8$D%^Uq6vJ=oQ)#ekmIKcR8@NX` ze3$z;-e0wE`NNSi0@FPyyl;6TJO~`8ha&=gdE*4&s*ox zPxo4t#x>{U=QpkOHLnTCyuQk=5(hQ8`#v44W-7@h%ZTE6+W9ilq4zTD;qj#Qr+550 zshV*Wlb`W@6=%{S23j}@WSMNR5Nsz13mA6olRc;zrmLo5;j%QjpxDc?1>-0vi$>1r zC81LQ#WVljaQe|r9<`CL- zV{Qt^?c{y;!uPz;mGes@7qk}Z^f?g6DjpVj@UI#Xma91tmm#|Z`>NR_@lt-Gfc9b! z6D>!4-`RO4r-DMM)j{TM)h&c!rTU!YN?G@ZnkB`qxr{2h; z8(&lP)~@;Ze3x4wYCjYqr*nr?Jy%@m>}5fp$9gju(Cpu{v$JoxToUY5-Iui_dk&UG zfN14-2}4op`!6}ZK+EGm7l9$&k~;v%^;j;bG1Xdfg2PeyAP-pE^VHcX*s3(1Vm zS8OLfOg9;2h;YJ9+tCHRAqMiNqB;es|&q}oa_L>n3JNnRwW@V+C#zb{ZtBU{4w(C_3N0>u{UYYNWa*G-v-_Q ztb522dm>_Lq&a5&Z}7X7F#?v;V4uNN2UbWGe8+h3nIuL&gu-Ezv8=suI9R{ORX*ZV z)mg==(i7NS{Xr6No?4ufe13+U#G>2 z1be5IGiX2#P*+C}v}EmT%ul3`^D3<<@un@AC#wZ4CX=~q0Nbu{eyU;G7NAM^yg+b(9sl-!Jz@Z)2EmKq->@`SupYGpa82zI8qSUk zIk}W%gF5j-Cg;IE3RXIu%-~$8;PH626^!=)0p}Sdvy8oa;_9iq%H{aOfTPYw2zeFD ztgKZH-9h6b0$H90vSJ20W`#5IcxiY#dT}?%y{_(vzn#oi_+JC44x~E}DL(mvxh|9S zpLQ|JJvF*=lPUBJS0T)1EffRkqtkW5Ezh{|p~v@jzZ5v@Dd5YJt)mH^=9HqMqKad2 z9w8ohN;Dl}PGWRIU0vYm50l5c3S#_mIIagM9CQIFbw&E>_y2Lh0pfdoNzpSeUc8`o z8Lv#5XnHVLQ?*bawtG@N<5W-(ZRgfpGZH`LFLgsS)(wpgk|w+H&xhWLEPvkX(h9b8 zRMb%B$zDVd`d92TA)rvIIG7?|Pir*pv|{oFjaZ_-k&%!*F)W;SIp2ttvduW3UrR|l}34T9R`CUvGio? zLbRb=!c51n7&lM25c4s;9oh37;{q>nFo&C9iL{Do>x+jD^H{PX=6?y<{oS4}nVm~*D8Oef7LYwBEjfV6FrLsnD zUl!bfSA~`20g%31{X}T}%*_y5f?PJ`L18OMvDJQWXR(p~;Dg>^xy;EjSYPK=_gflxS2{63c2IObHF#WHE$;y&MdvCmkKZVEhh+wVcGv-~L%% z&S7xh_2{M9D@Re4ltSdCU<=5}0UeC+V?wUvLS=9ffzqIfg0J9qlcNbVE7Gz+3s)gP zc1SW>As*$7_oPI@>eAf$Sp$OzZ^LspH8(u$em}7tJ9dmjgZyuO%7VhU%TmQ-Ss3!d zQ(P0$RG<|d;M{^bWGYRLQzF3h8%e2bG=zP`;+_|x^|zjuWOQbu*Oi?w6icEt8IYe`>51EMZs0(i6U)ISPWGfBVXy|1fnC#n` z<%#_CAwAnqnI~LX)JqHv390_pxAW5v#EdtVZrv7-1$j*KU6vLjuqGoto=^EqBodz` zhBgc*jRPuS&#hZYg4u5!HLDa)S+ZLZGMLU`yyEsr>C!O6pUX5+4W!P`pFJb|{o#>F zw`#5j>y=jHw8BWABB`Kp?5L(12Cl+>rW`fXvVI7AH6bIE&=E_)x-JmoX=^oBnH;c#>mlB*zOI|U3WHq{YX_N+7RiH?wMKb6->}<<$4Uc zmPqlfbVrv-!v(py5ppzb`;DmN*&uF1srPfOWpb}daF$8t6qtYQ)mB{FBJyZ|diE;O z)8tw^8!hBjCG@no&weyHDc3lx*)}I)TY+WC@Lq#Oj5&U@oum~?+Ba#pB@l{oaRJCP zS0%t$Fa}vC>B^8<5)2)%y{in*j2slLeSl0N1VvT=J56a68SuF2@{rj7XaRE2nR1jj zfI(JEQ>&ctRACQKx;H8SLyo;;;dvCy9XKoex8S;pVn~N18^e1nO@?pb`8d&O8hX*+ zAXFk|ln`U3KM?Q|G1H*$|}g7xTyfvXk8hq0Yr zuGG)qPP=Ibe~xb6w6S-N-a_|Gn3lb@P7GbiPjcF@&~uTgnThn5it5tpN5sKxHi*SMdlnO zQ3o6TL~Y|1;3D&)Xw5`AfJ3NOMVevv-i=#;i?_!_JjkZlMDac9*wp@fpMUspaB*et zKQk~B&EWi`?P*bEc+$bxzfb31WBYgS(6s+`1^+tg|6jx%PpxEnrd5gdT6p7) zAJ_Z6kGdYj*^WpdJ-!B77v5b8O4#2O1Iwl>{$wgQ8Jp;@esQrYPTzws7To9<6 zx8$dr7kFARKE%MSswkiaL&d@}Vcdu9UPF9<6{aV*0r+|!WWQP#WAJ}sa#fco-qv?D z=zHuIp^Pa}U=9tB+&?X1J3R|zMVAHP*O&)IA$S-9VmNPVLI0DK=)=YUaY*xwr@urQ ziQ;a9wFn3d^RG23i9SrQ6=fX*Q^&8=aTQ&x_Nz4%ZeiAzTQ{)ZE z23R_iBo z2mTKm03@I!r^2r;h-^`m2uLhok-3$$*ZUVv%fCY|2T9(Q^x zg#lSfs;g$%N+&2G-vg{8wWrKZ@9Nd7E?>WXrGjb}du+^$_oXd``uVzUPrHO+eS?CQ zyG_@-cg07K9_@Md?AZipLYU7t4A%w&nE=vQp!{$?0929;1ni1ZYQog` z1)$&y>bZZ~mhA}Z<%42P@5xLnxlotaqMG(`ET69QV?*Mz=Y$xPt?pDYq@BY(mNR8Y zv#O|b)tpX2s+d!DZWqCsJ&ERktIKuOzyjrrCT4g}8eeGt1_jG}qykEh#ou*CaP(Oq zzWB4<%e6PxjHsl7RAHmtQo=;5wBJT-xE0sa0(405&Ab}0L_oW#GJw&|qh@w|t1rEk z(uQrqP<2m38n2e#hM?eE%6cXqsUR(p-7u`t!vpz&QX;TcvwhNxl8k{knNz8#4k~R* zf`-dS;weCR)bt8~E3*0zV-dJIbV!WWN_wMH(AAKLl(25dZB#7;#f}oky0H?f=pUI@ zbwp2~3B2#<=vWCz#nG5Q<=&kWH85<7P{R3$idjSXa>&CceRK>wVfwH{<$?2Jc?bccQ zj@Jz;@*c~QuWYd<G%K;unbMEC#yQR{(cV>Trv^BaU3z_c`uA1_AU^bHHsJ(6_rOmJ%w@-}iy zDFEhkZMcg-6okC{R7la?;%8|CR`+UIS=stgY5cpX^DY~>*JN{&;A4sP`U+sGm0()F zR2J-nB`KYpse8I`84Kj%p_$rubVNFGFMFsq}16ta7<%tr#XlHm4Sf6vUhk zk`9W0RmxfsW}1l>`i_dsS*NvrecPsyJpj0$^ZSoE&p*2br$o2rJ~%@eKm-{VgySj6 zXduUv0u=|?rq}nCo%o(k>isHgF#PU7Fi8{^$j<^4(aoR;lhs&Ujtsq{fuSEmI<{uL zJ1r`3EX|Ft=OpTcWfyIv1S@&BT1AqvwUrX<>;O>Zd!e$bd%%z5uZoZ*2ROmxoT6d? z;hyf#?YoZ#yEpIp_3IVi*JR~Jr&ZZe#?!?lqNfK1b<^^SlpGDzG8w}U(NxEn<*MwjhZ7C=v{j*jSEBDzxr%VYy=N3@x zr(03#f2P8>Oy{ES-o2aeDM!odxS~L`0(>~E&Wf^z!9UzbSxH8Vp3fHAtI2@sjjoe* z*+0=*ZuRrqOt4awewXo}7$x^P+a68gMVAzK^4dfVT!B6F1bAEh|9oj%s)T*Q*jMY+DDqI_E-_3`q-R?f%ptVYoE{+>{M&I)vdd zG($eYDL_y*g&iN=(gi`8;E=7bI&LCLG~$dMz7 zI+*aH!yCC|?yV=U*k8UpNfIRZ)6&oyH`|}a@_izmsE-QS&Y41dyY(8kVBHCT=wLb@wSNxUvtVj zm}pd(NBA$y{lF7!-rlP6Im;ACx|wys-;z~O!0B8hmc~9Cph%k4zCk)5MRkF!+G3(7 zx!wya)v+%ZP1QF$O#@}zdOF+H_We6AAUPb)$^#0zFjSR_Q%pzdm8~4PfYk|4OBU>; zT7*%|+A1EH$+|Wu!|CSR;uX)xrkv%ABF(MmYex>9Ve>9C!&jWZPQidEY9~*755nd6_;}CNuE+2^ zw9bJ?fOr5}8orn`WBAouB@ns7T46b`Ywe8T?~-~9!K;O8tEy%pKd@_cD!h5+E{#Te z2E=Re#bcvuJc+0y|2%)wzq)-8Bo_DW>gsAID9o>ZH4#qOjVxp7bfk+@raj+)B2Odz z1fqx2G)!zFxQRC`Gq~qDlt)t~C0jX{!-BhkUZ4szK;Ayr_b$D6+D+R4z+ zlOdPhf}olMs@joh9e=z_1^t5uv zx8S=ASL{ApZ`4Z8?G*#6Gz?9sr7@uE@7l?v?6ueGtt7r2mW7 z5?d$wgbL~?2I6=oHp0Xu8QJ#JKOY&4e4q$D>FdwZj-yr=%8g~a8dB+N%YDt!Klnhb zve-|%EPLn9ouhM0tDbvjPybUCUP%WnbfBP&S^j^jRl3wK_cPN|<46FXfKszH6w!RX z3ZgN=)mRuXD+j8*;t(Du|er)MQiDBwO1m)UT$FEss5i5kW)* z&c}@vZRn<{nTuw9@Rob{K$@~0#R)hq=O@y!__e73kxH0K57Dt~mz|AG<0=p=<{RFe z9m^|mn7Hx3r(EayxB+ONvO)M0(v|cAq84B7Hd*!4i3Kuk6*^Tn`r>x=MlBi)M08U6 z!w9u2K*Iu!iJiZz9Nlm0&Q)cD-oP66Akp5ewtyv$cYHAzaJlCN<}y%ke&2BvXiN>x zoH?@u<`WH+yfYny0ok7p8%SkO{B!WQW1{Ce^^^fHeK!Oq4jkh0L@Y$Z`9*qj1y>>N zdvy%U!^6$lxtpz+Exq5JbzXU`=)Q4qn_8pR(%JT2s9>sIT4 zRrsoqQYC2vQydL!I!T1xMr!vwe|~P{!-o%_^8%S?e!Nl&T>T2J)M3ZdY|EZqTod~r z3%GqtoJiFL+S{7uwPoJ=;2!*D?cC(dN|Xu&QP@ zSK)h&hQ0wV;wKQ^nf%BbS^c}yWA%%|ctS$L`@NF!Y5Fmen1Ar=_@i5S(NqM?gls$m zw8#P=VyyIVYmO$^Mmh-vi1jedY;u`{TKLV{6G~`Pk=yd%BYwqZBwHKG;%g*rlF=X& z$#)d`15E;@j0>`L z@N!#8ehSiNRnlfH8pV<_4*CA4wb$&kJ30saOKa5E8k7H@ONikfk$(+Z~-VPL<)Ge zUnNO`Et45C(n`84s^b@&#S zi_sl>P&!aqvKhYJ2Ba|+9FpS8HXtzj*xK6q6THW0mtRMhShvebZdsro{Ls?cm#~qD zwC|nyuZFieFmyw~Yu)C2I~}yaL_B9ONHFUx30GLAYJVwX;HNaX6?CQMW=S;y@k#dF z;xkNG70_5YHSRljFwCj(Vk=I;q~<%T`49&Kjt7waOLQ(k@goz+WC!xa0cB<7=x>=$ zw#@mD)|HR-uYF04jg3`Ea^2@D+OoU$ZmuaE1kz?Jbi~h@!cs!>GEgrz*AZ40h5=B3 znDF}87lm;^8<1-+)X;_YmXtukAxi5w-O>0?bJv0A?eF~2M{YzqwzL-n_6R8;Q^4?X zdReVr5;pSmTp%x9P9sCKEuS)7L7Ry+aL`(fKnecZBYNpu-@SuI5m|2p=cJA?kBjg{ zO(~Gd#kd1+9RPIm3*jS#@VWQ-hR>|6t;xWAu9!H`Cp^|o|4v5eZ1L-JWyvcwm_72S zx5ok@H5;WT%Y&{sMdnE|t`0=Afx|ly3YyXuG6Vb!&@KTeC#PXW9ssHhj~+!MACAc6 z*ia6TwCg5Di=(St!ZSVjL;vqede{e$E?ZAtztX!w$;XKM6@caz&>w;$gV!@y^*V5_ zQR^TEeaZu^p%x_hl3dRWu2t@rP##f+_ypxak-^nbhR@trVU3Pns;MwIapLm=HQ~z6 z&`Wdojh8RnJWowg&@z@U+!_&=~ByWRJPh9zlLj;aMa&b z1Ag8B#s5`5e95Zc2s!`@2CBJ(zbY%6L;+o_ti`?kH$@HW&6Cs9Chv{=gnEDdJTH3A zeg&io*Jst$^EJ)u!s+yh|28DZ5pnfS4)C%b5}&7vb9|m-^D5u58gwh8*XzmA)dmIz zgRX9Fp_y5XG^wF`_62B4`~JCva->rOZNd|B(zzD|No${3?Kro>=oqX1F8BBK zK-BpW^>bzhM5}v1ILn;}vb7}O7K-9cFP+HlAeuV<)&@}n<@}NI(2@8+(mBp) zws7$u#r>&6hln77&n>+PI7ZSMez?KVQfJnpb3n{W!weGV-Dl z(@euast9lc(&SHFDkyS=7oMDq0ur8{=bYNyPDUF}>-&Uu@Y`Js)lz{#P+b};q@#dF zy)>0T!_4RI{WGYWtTm`gV#W8&y_IK&JpyiAApx-tnu%@z<@0>Jg1i35zCJw%SZ0E# z>t^uHx8OEc%|2ip5Lff(GRI9eBH+v)630?N1a%1N6+U)F8 z$#XtRowIM>zUAK8wwry>I0~H>BHYeWAexslN^#w!R?>u9%m}WQG1%8PULkuGPd0qF zH6SI7d@SG&+TWm-gCR3M9Si1HSF#G^8Ge`iUv~RvkQW$078ySB#K{tnO0{za(DZkp zp!NlFn)#h_76zQFQ-0+)@z7l{0uatC&VD%>fW+-!*s8o?r^t}Pl%ZGsr<(A zt*4Z?gNmAw*!`rBD>WaDvOsn4WLo(e&A$Ut(=$XU8_u5_#+hTv$(c08Oh72l$W7%Rv)!%~PW1y2{_}i0V8sHWLZaP`hL) z%^Mnelx$WVFkD|Uamj4}I^^E7HaPqtP%hv9hU-8J6m{UGmCbNzoOQ{^gfG%iq+voD zS(Rr|0h;MwhkQENGlHne&_RZ84igR%2)DeS5m#(W!w@>>hxJ-=(Jy`23R6>p%bz4f zInk%XpN~%n(FokQ>`kjjP}YK|FMMdbi?(xtoi|y^W;SLjEqdD=d4D&fFfKXSttK+g_vt4wI{LP=h*N=>np`c zV@v)-Xt3W7)I}mVMd3Jh*ziua9RS&raIvOjWY=5~DoIxwXMLN+H+wt9P(Ah=wB2SZ z?CCCUT&~v=4*xFU4YCq+LZ&#t%b{o&C*;$QgM+y)j>ux}vg z?~uvzgjb;K`b(2uzCn&RC9))Xihai+Jr<{S^WS+W&@jchW>r&9!`fHQ$`hBL0MV^1 zMZD3uk1;;oIn`Ar(s0d;iTmMdT&$B$aCpQBW*l*@o^MfcA2oE){AnRNV@0$5!fdq< z`#uKFgu118!;6y;MEbw|8NyR z;N_Rb2C2V?T1G|8KDOB*@)ir*V^3^WTSc$!tvWbYmOyBMI)pr7-8ZK~T@EOJqt^5F z_`Y9Mf2ln{1cw2z$5g)YefqLVF%9;|YOlBn19Z2XJ#{K0;v=1P@5Rtq;6M+C#|doC z&&|toOiK)ljW)3c?ijS6It3c_niJ*yK{^UrePiG{d&x#@U&(%Pj=yBT3QDENNc+VS zpc4BS&y%#>(G|d=@VYE zzr|yyl{xwC*@Y5-;Hbyq^437NFo6adVN8T%h^xu(KfBYXV$7dLmRijHCZZkAUKW$j z!Liw0;%q|XyH@TF-Ly-Q$^B-zW>4!s*JhBDSOqG&zFb$(&+&ym@yVXTwAXN;bFDCr z{0Cc(6QQ>Ft75$9-H@HiD|o+5xuJ{Cvkv&}ehhl(sfsV4eLsF&Q=lgV(}mPaW84&$ z7f}ZnNC^2op;DzELuJbom2;pVB}ZIWu??>-hRFKpwG4*O_Mww71wW4c%?GEH82$d- zBb=VdD%d&&2)+tx6952lDhf@YFB-nYIO3e&LohFgI(YomK7Y-yquD)wBgi5L(9u{%kA`!_jk7{NVM;Hjqv~lp$1EqSp&QI}cH(v3aB$ zKYgf(<`M_XH2jDfQNfg5^&_SRQ{G<3*)!Qx^KVq2|CF{x|#>)s$2X_vxJ7h4sR zbtDQxZ=MMk&59=D(v6qw~}N+Mdh)~qqL7A^y9AcqW!B^`Zy5OIxMS!s7gGXHGoX~1=U%PJ6( zn@CWW?Y`&Bu14OQEfmN){TEwZ%qSw}3WV_3 zf69sPT%MO4Ec@Lk2{c2K77VC$xvqd*!SE_{b&k_8e^;4T$bdEILsVo`P+PdiT9z%q zVGfPTO}WPftEPp2t;6X>PL@5<_2xwp%=Jcoi2dUoAPf3@^T?s!tp3P1uF>kVF9xTc z2}A9 zXOj*-Tgf*gcNNZo6O%N0?W>q*Lx~3yBjfynEyh~FWfy}}GHRAp=nIew9_97G&<1bw zRUI-&t-cPdZg5ahxvoGx$BHCFWII4yJj$cZOF$!C@v7qUWlB0%dHv_>2Oc~6nJ;bA zGfkOI6|{imdRr`OM?JL;T3BoCH~WqB28pjUAUR}!(~{6JQtT&A>pl*wGfj83+%ib{ zi_@H3a*S;aVY7+v>oLKGf8McKwp0tzkguvjzXG%5o=k}#+=Q+lYw42&%ah@{7nO>wbFm}K8w)g3U7wIq8MCJ?Gll+Xc zc;eFF*EQa0LIZFen2h_bk9#VO0d$?qt}+M9!2HN<^vg-FV{($ zL@gm5uwLV zqQ%K`N9`Vm@Mus@z!RO(!9mK%$>VQXb%lk87wz>fs(hd(?7a_on{BD*^hO7lzJ2?q zDV!p zVJwJ`92XKQCH@S%CNbP+K#7h5H5v+?oXBn^(VbUl+u6$E(Zw9!pr10vK6ma;i(J%S zva$AAYuAs@?)11S##*wKCbsvo;e<4tuy=~HOq}8^6AcCpNC9`V3D3G{Nf-EPocC*d zwqXRuZs>d;*SC`uXcsIv;uQH#JntO7hAe4oa1~EudWAMPnkh;4fm)tb9cOV;b8%+2r`HBRwGBEsS8CILvTt}g=6Q4@DOTcmyrbL zzL!P>ed`MywBhvh9l`nq`IZD}>f<88KtPkhA7P8|>G70}{kv6M)y6!3INGM1X(mhr z2Z|L8^9mN#k1mZ1)kY4gAR>LMFNC^)!}LbHL3?auT=4Mmbe20>_^z|l|AtnI5C2s2 z>|6B!*v)6to(`W{7RMkP3Fc?%s?ZMs_NpC#Mhm>r|MVumm~9if0vZv6%IeKahl@#b zD;Ft;d*E$seH>zP+MvLO`Ku#ia!XVl7(INIV}hHn%l_CZ+_HX+hrB0 zXOV(Ow(S=d1`oz58kr7f&8VzNgdIn%?2JCmQA_79IKvy|M-#es9Ql+ulC#nBu>XRX z{IvuRri=KXRC@DzhZA+cdu#z3oSaW^P_;jXY$r*+Wr8ftrbp_EJYe z%C=W?TmrA>+4R42yl+!*!B6_;^fBzG_lRp{U8L|OyV#)*Tw#$}=4eikqb;)nqY~gw8WI+6}rNyYD z4nysD#PY-0M-S1JQuR2yt8TGDwLnxr21ns-qD|47m2ZE#9J9xGm*`}}?UOeTzgo85f4X~r z^|TVX-~;&Urr4uEFU_sj16$=icyc%Bs%~=>?Jr zMK2wViGP_8XmV)42xQ@*2vsC`yWi-dxfwq`#yI{BmuyC!=0qcsS0RNHfCEUh68o{2 zSCm?2XS_G#sjSneHg9;wyH{CP&&8BHvWn%WH!{{dFD@T!4!t+YbGN^?fe)_{BqnxE ziG6Ojv2qN+NP$~zy8Z^>jKyl-$L(M6%#r>#9?&81%!1XMR_un>PoFwO&$QAR8bdZs z!bEyLJpC>nUo+Isq`3sthbNS^{WAjBjUc}GJghROk1HXDU8Tnbd>|#{KaBFqfN&Nk zLPUP4xWGBoE`OmW(<4*Dh>H(ZNg{sL787~o5rai@Mpq<2J7y4gbfrf#r$mQ;w{e9V z^0y3O3yHX_&4U`1r$B>7QzSuqLX-e) z?TVXywl_yXw<80+GKkEHh(w8~h>Dng5!e@TN((Im9$j_%bmMwUiM001tb7;Y$t7xXw6>I8+s}o0=AR${+s)fjo^Lnl z%8N*cnT22-$zpeDOF#PiP`|NtGUG$Z!M$O`l17DgkmgyVhe4sR5nxwtvG&aCaky6< z;{AiFQM4gspCAI7HAP-^bG1Hv zG0O7MbS$}FeW@XPI$B_7VCY5T(mf$&?0pYh?5cD*M3Yd8B!~kHAzbMfd*UflCrK8^ z`pJ0KYzWnl#{nD`gIxAoiaFtnD~4?{zah4Z*W8;(%tBnb)-Pl$i$yCJDCG<87x4_a4G z?9-QPPViFfvn%>EH<=VB$aiVr(s$2(HWVW_CGL zQe>3j5`Tgr!|#SNarpz))mrSp5yS zagc59{y|mEM3EAWk19@r|A94O=p0`EtGh;Dw-q}q>huSB9&E^X=6i@!^+7Fr#0F(v z@gG-`$gw+%1EJ?wZ4BUHsgfcZ`g_}kNIcDfQ0S(5hK0y8Jlx!$6=*O^v-HuM86YZT zvIJ14%ai^ItC$SSP$jHxw6b&|O?TEh!HYxyCcR+B%Ac!1QF5 zwlmcsA`R2!Sr@q<#4+rq*}uceKLFH_o^m6~+Fh5g*? z8yj)V>sPdezkm02EDmaMlmnGBAM#TCKvTr^*w0b1U)sC2g4w!I^q`HC*gHQzuLmaL z8Wa@ty2WTP<0u8v)s8swU$)Yf5lLrwa}4Red}_M9hsuD03CvZ^pRRyIMt&PW-{UN{ zCZ5EDfQl#H()$S^@O*(Z`0xw&@oD!8PSMlTQ(IbkH2mu7s`?9s{xR0!&Yww22vqD- zR{W^NVWV$*2}pq-KS=arI};KFs}~#R7Z*3taByH{{a#7aGaq1{?FVmPKEf>8J^vHzw0TI$P7o}gw;&)OunmuiG3D=WCh5+>@C)43XZ}HxJnE{sf`F3F zci}%S)Qadwq%mbt&!(!X8Zj7&7kD(4lc28vua9-ODJv5C@QJ4_5QgXBnT&IQDnYVp z+DuMeU7ZP^$HnSG{}KZUAHwZt`m&W+qfz354lk0=19-2wi9jx(sHn&=I5-&5WGqEd zAcYM&P#EO)oCH%zqwy3FYJ(qrpMluaeCR4wsATBr*{ZIrJlhx-7k9MYchUr#pK#}g z0os<64war+UVi#is`5?aszMFKGhmV_M_pN7uALnldsSRTF;lyQ zR|8F82XZK0G-IubA2yP(>19SfyhmE%xtk07gF`ZJ#;T&Md^4z+FV@b2D|hXOE{J-a zN|ikNfR0Aj!YxacP=lCS+)=ara&d^&)qz?wJvTR}q^eqPw$m5(3nmQ;QVeu4G`Fzu z92^pocS!M#=T~p$8&X;>J5f(Q5fPEDv$ON@uTR8TwNA%MiRvgC7*!CYAX}bLAF0gD zOk2sq8Q5Rl0&_Xsc9W3kbqx(3^K)}v%no})o^HZ>f(6n@m=Jqzq4)Rq#t6Xy&Iq^- zFR&=g-|b8eKC!a0DyXW?mxWoSUVuNk5y^Jnm#07nKNXE zRjT@}0N1lG?e?CER4_`6yiQQlz+n4~zN#tDZ8V8tW`8uJwG#4$r*4Ra!AD1j;)_sDR0 zQ8vm#d{KR%SkzVisA-UbND0TV5jp}qJQ_#tFP*42h)T6n;1b^Tmnh~>UE#h!@>Xmx z$EmSq1~`g^0F9un!TjK5Cb}{AGv|TBSW(P{g^d+YqA+o~@9VqM`EN8#;{2cJ zJgjwtnw}_nJN|WaD-EqFa>)%!o}SdAA@t@aeS%u7OaWf=Itb3834TPvaLOeW6=xT; z%0*stn~J$UT0GI*cdK78Dh|%s@$mervrQL-_^NlnQ@p1c$EDwQ$*5+ z=2m|%u;d$p=I%R<>{0Am2(6HjC{-z{KSLH%E}P_{{4Hv zs8v_eCLo*pP5}~DotvJ%{+pb_eCBuQV7CxeN1AgfFTGjoTSH#C_C(ZqyGNO*Q3J$L#Ns5(6} zLsni=;%55#c>Rf#Zcfh}{Y@Cuv0XTOTvVzdMJjc)X@b-gL$h|OYrgp^q@*Uq|+GQ$*!Z*#+oTgu_T;ifXn(YLpj8q03 zQka&8ucN3q?VPORvfPoFh`GGh?D+CSWY!d{k%8U@SI5}BZ9!wp%aq5zKvtQTmv(zj z^$mZV;X?W_bI=pE?%%Af!%b!t$*u>Okz}M`2x-gpMevq03L`tbCzeW!E zWgM{Gv2U_csge8p;b>8EN^pZX*mI_>Q-UPJH#E-A-2ddng4_G~How+n++&t3(i02q z1Ph|+R!tr?3!K zd`RcCP_M*q2nhd*(5`)q%q;&5^NHV-&qJu_R_2FG5sfnRIF_qAgompr{;1Qsb!-)W zhiC~A4Wgr?E6K^(x@dMhB-6$W7jhDjV1-!E2T_Rmcqjhi;s`e$=mTZqo^zyS)kj*95Z?1?7XkBFi`Oa$6~@pAL~ zG1MgVZSrq{%K7I7JuF(!l=abcWvfF|20umcQ@2LZcgT9%B}p&kR0j9r6}%03h{ml7 zc2i}ow4c{>-@y>uYqYlUk4yEHVwo((R%3Ra6sud z_ z@Po>LODrG#?I?-T9upgk?iRE=#;mTTWid1{q1$FQo!8zT26q<%8hVPuMG9HmcX;Z} z!h9N@uq}8iExg_J=cYpD;c2xc8-ZA2wrw$2M3N=k6@T~9m1FCUCYCxkGp?W>SaxwUgB%=KZ7ltiNMxH6RKrI0WOP0 zu?bd}@0A4Kn_EuOL}G&yH7*^luC5XSywX%W^fart6!VL#e$I;}ID>C$YKnv&*!ruy z2*#Gh88KlMRtZdqFL>DpV`F0}@EBBQ0M>^GGS9(e50SW+m=}8Un+0CF@+sxk?t5-h z@9iG@cc+^j-0(1wPF)9y0Gv&UV&!IJ6}8gFi1QQ)EZI)xl#8aX3#9MO@HfNig>?dz z($A{|yJAnXucN)@6NMA?D#p$P?GKw|bYB+Y8|GbVM2;EqB@H3Xp6=`uGeT7u9X!#y z4mfa;{<4@(BocEwnO&^AZt64{k79?Vc#&=~9Q06up zFBo%?vyGIsJ*m6D)UfHdii^`6zw=<28wul}62@&EcM|7DDm%|D*yvq7z6_i1nE86V zz8kg1P}OaI++_<(@u^Lo`FN7^sz|C&hUF9@=4UdhOEyPm>1Fp4I$2f@3Y_gz=9a)= zt-E@n%MzYWzH?mAl5{mMICwxpxjJwF^Q1IaAn=3d)r)D=BFrp`$yY zzJ0vLJWTG~;}b}pJ*d7Z{aduosBZuk(qii5Put0BrE3oAO@o^3^a=RuKv43xXq*ux zzvnlrwF7FUR`kE4i(a+8gI)&Hqb*zHxv4oD*NLy>Z)WfNXsnmt2B}azP3Ns|@5O^v zRPqYd+O6|?pzsA&vTbzG#q$$Rf} zO=5AuT~EI)>Q@BH=TC6>zHSQKsF1%o<)rw?RT}0>pZasJ*67=|7#Lv6X5x0`kvD|I zLh0Esf0kY{R9h7$EdRdUcijhevzwyg zPp=3%En0zvND7CJi#^SFI@UrZ^MK-5M`?3lu%NGGd43BF0PT*I!zZb$0DmzjT*_Et7?1WN=L65te}BXSi5 zg;azO%oLjeRNJN4RwxkUYnVMok%HD(NfLEFbxK@?eMh*|iyB}QQ zdp+LlmfR(xh6U{3sXcAZlpnRT(rwGQJczw~d_Srr;?j|vlEp9>Buz{XTA&fJc}?wu zGO32RpqV**zx*QdEmfew_Eb9C+&~oGPr9=c{kHmy6u)StYIC>vS`|>y_^`S9v>pbv zggI-*`gd(@jhLz9@n^vy3I5(3l0z_P?DgrqaTC2rF0)0R?)LyPGG<;@Z7A{(^Doxn-|dB&nx4~ zZ(1SYQBi=TH6e@F{a+^FHTheNN0TOi7Z-2PDjtN!4uS9_OrSyQ55~?BjNa@CIKR$T zDX==ITXJip{^!tqvL!6~tJj62B$%`PTWaJT`uOlLmm4q%Jy{WJ%f%`-9=c>FG0@US zd?4&6s<8|%7Gs*_j|PeDNT{D6Wc1sjkVUM&JNRE8zTs{iKI|PXI^rzPo1UCHUqN#7 z@NC1WU#!$yZYRj|!wYnsnW-<4LI8_xJDA9%r=_DyOHN5?!f@%NrtG{k5dwB=hbLA) zWaOJl8Xh;dq;PzdTZ@Qj#|aAd&;E-_+;qZiP4DzDClB(}Sd%E`jN~9y>s+oRsV7gf z`QL|_-*LY#u8=KqQ9$(M#_#O>RJO1?C52qoKqa23U##?OXU@Z?Km{}TSfltj zfor_N4>}0pU$U}OV)*_^&URIeP!+Dj-C}(->u58He?QVU0OL!^XK-G>=7~mRNlQw8 z9na*!S>0f-B|b+7pO zLCv&I#Wt6$f*uQu^#lGZzteV~pxOu=JmXpy`a}%Wd_#lWif2wpbhcGqSsHs%XN(F= z8%=?UlcX=6EIy6|jx0(+m?7kZT5xmvcfKWxEgwNc!+doyu>l;%gE7r!tL4AZKyX-c z4kAJqB#Rq57)#Axt2LdJYyRQ$q(BP#w-aN!Fgu(9;{uKlq07C}$CAax5K(4=qarp| z4^OBauiT|hr`=azNSM1vkY)aK0ujG6?=)P83bWGXSG91kuxBxiPkZhL`4+DwT|8O$ zH&fpe65bL+47LWLDplFqHKZYn*aR!wFc!vN$Ic8(j~Gw1HqY&P9Q5PsZ;ESYG_^-Z1trr zKEX%c&s_LRh9+S-2kNR2T;3UiB1S+&GzQg+f|p(;Xdf+1DT(+u1f$09=^Huy;v7IM zX8q&WtW?9vh2P*{>E=Ms@|}#iEXI`uwFwPhUS)DR1LpD8I?2M!@eTgzy4p!;c)-y0 zL>sd!x%h`zoUAN4{(^F!ZBm5zqC>F%`#%1(BJ2p^@yQfe#u^$>*Qi=*bH7=`(ewHP zmpcWxot`4rKhmHG$S>nVLn-V)tmZ=x>swrB@48ajrpdEWgE&;6bawlUBWFK6UY_@1 z#aP5*-0~Tknwdc?N?|t5Gk#c}fjYI~^a|b*oh12SD-Py)JJ~|G{&&isvlfjsK9)oU zDq6x6Shm(y-zqYvDm!OEj5T*duIQ|{}w@nt;=5qvXrjaQJPv2o#ExqtS3Y&O)`GEw-#5aC9S!RXX&RR#vZ``ubbD7fBx< zr_=ZzmWB(<0dXK-uF=-c!v?4YL4@8GFEqAp0{&qGBGR)3D0-s`wh`h>DehIG?lh=E zEbF=pJ+6wJ0o}M}zEb2;_f=&3$daCGX)V6Dmwe&YzB&%#JgF(Im`#BJMmvLxTq<13 zr2B}SX>_sSu^h==59}VuDZ3Fp4c~Bt@cJ`CR^s0{lrdMvRJcREzgRx>NhG_z=SqZe z0tfT5_``9W9EeQkKU!TFq(C~0Ai$-?ov$`dYM0O3D3s4PHm5^+J&G{2-zZ|Ao`n#4 z_4N%>zD$>C?@X@rEKn@9l&5TLW=MOq58K#t(iQw9Q@QOLL0fMThLg1W(jNJKSzatL zyJB8zG#xh#j?KNm_VKej<57{e_0}+Z=r|i6zTlYo^;ruV`N|Uqar@46#2KlHIat9| z-?F9(b(^lmS5#fGjln$H+2`q;aD;EYCr@`ODPR0~wsLV0!y@r(hJW@Xj{-#vs$V8; zQdU-nApn0HCsJ98y*E3&*&o1GX@bD=ehWY6D=Abj`sS<9#X;_=z4gh~JHQQ0BgBWxN}39^~B^>1S% zBf^&38R_YEC@!HXFkc=bJG?%;|44j7!f#DYO;0R@{(dS9FJFgr7>&@x4BFBYaIWzo z)=Ygltm&jW5<2E@3)=HWrDqdY==lW#4++~Kv~7uv`Y-;=v;1Y7vp7LajU8yDQx4o| z5ZW3U7;RhOa9Vbv6sI_Jgj~T|D=p;#(V12?^o7I zp}3-77?JS`LH?H-`0_Y%a6gHzt)v~{E&qg~(y_mxev68}GHBhHBKZlspiHE7 z+4dRA%+fLtW++9#_x(41RFU!WU*pUM;oNArt-G_@$&lB5Cf{ZHYQqR;S_&>oR`2)SQgL<@I=qf zWOK8f%0`+0HlwC;tf{Bc=9Qt3hq2$wK933k4ny5=a+d8+;cFP9d+mIuf?$f~a{p)4 zE%1IF6P)e)?hY(vG_nd^@ZUx2rN_GO$J@-u>!E;sxmx84eZnyMS{z7&*Ay>f!A}ql zl|k`at@e?M4`Qw{T#ug_0<Ln|dVl8Zg^k=MMp0tEAe!s+27X!J4tj_Yeu+Gz;ttLz z)+DgBb$B|JO#y-ch{7*G0qC{;VWagvieqD_`Lg3h=Cb|a zv#|bp28lMlABJE9fPEGJbKai-Y|x_vPm%=nM!USFLWTuKsmLGD2>lZyeP8^d9<5KZ zYb{=J2~D5|$K+F6p20TcT-O`95PF0d&Ij#d*1)#h&s)w$nrUA59{akmIjsjwV5*v( zgQL;r=3soWTD$S0$(W@=oMMOyqQPpJOdME^IDVG|A7ftq?LDagSHr5Sv*AtB@i!whWtv$$Ze|!gpdpon zO@w|Xiym?BysvvgfMnH(JA)ENR^vrq1T22?ue$SdOQ${RM{BWwzbmy@gQq07IOagTFG#jMcZ3j$OS*N6~li z^YgFg8&#zk1z2(yD$&ACb$GwrpA!4NUPH$4{*yQ)ux*^~30@v0iN`l;^$f+V>P_)F~W4 z1CfEU@uOmp|B_MfyRc1e$UMv*c0h5iSOCAU56}&AQOmfct5PS8h_I)XuX8wOsHB& z%MsAEDc_I~_|Os;xTrP=CM$_QIl&LxL-=V5rQgWLSacf8Yo(RTszmlDGY+G)YEmyeteas`@pwAM7F)IK>p(@m$}Jc+=lgsr1Zs5p@lA z6^_UGMCJUyl>PQ@QBS~roNW=;^?YSN4ZaV)#%8@`sW{umBl!m-@%Awkss%Ws7ZE^s$Z7f)MN+Rq7zE@jehEG(nCz;&n0_IWn1q5*%=ZWu#6SFq`PyPt|8;JCQGzyB&#{;021 zOfBxfD#wnJQ$mQ|Mk)t!0QQ!X`FlRw-wX6?Tl&Hit(UU-ILm=_dJa7e7S&b@>gSV!zJ@%=euu{A(XVncd?Sn z=2)3u32VOZ^+}X9VR(x=c%nCqh^9oiOff6QMAx+K?SxI+p zvfI{A^>JM~j{_Y~d9>@g+#XFwjxu!;Qj4==pxuK&KFRQY^S1z@^>KH1mw9OeRbpwD zKc@V9493=so%z_ie+)G|;@V)?q-4APGwe*+(P?IJ>XTvhIUL1SMTD?MbbI^GRoRNm z%A+QlbZ`j97ZZw@E5k$2ZWo+*#Hbo}Z|{(BDd(VjhANaqN^o6y67{!34bI2c`FiWy z;pF~`&`sR{qJvZ}wnUpBn9}fn8e9#wH}){=rkKp@Rg^YH{>4^hVTi*2u_#uo^8ZI$ zA=yRWQ>RsV1~@z(R@;p>$|1E>7Sm`00C_T^`LU6v^Sb|a6%z|7tE#%tBPAtmY}FRU z#n<+JR%Nub1v7tt-ew&zjxd}s5!XuCY9$^$3LI~)I2qABguY$tTh{e$;tMl})P_8m z9KGDrr0dB@7wF;AFI#J%h(6H4p0+*-?3|x%&Bk`2oLRn)v)(`?)UN|r4dQ{CJ|1lo z$cqPJTVrL_%8jb(0C)7AIj2i&a!swKN(kA16NAuBbe*YbX~=tr^rpq5Oq#fZ_`b^o zkkCHw-oog1U{*G^VV}3V#q$Vk1}#1S<#>yU!LSO({FPV*#7-6Dgkw1XU;Ysm7Utfw z9=-$C(zczWrHZ}>S;d14)V2GP(;FV`<(*?gOe_;#r19}n{hGS57W;p)?Y z^x`vn*Z%Cb#0Qfti?teo44CMoa}kkqzd2&`snu5SA(4IfJC&AI4Z9@fWsk&Y@*vu!MTG?s={Ku9&-v%l$e~F!WwtU&%8%V4X45J5=(qryorUGRg$_ z$N5zkW65{jc}&8!dG4#$_QKog!{)iUfHSF86PU6xl5w?7_5iV^X%J}c=G2ietIZ|` z#EheW#eTYTA$om9{r;vXq)t^D3K0eEyVJoFzhtZJ7g+l-(^;$8!v37Pf?v@^wUK<$ z;S5!dQp;v%OKd}%cUvJwH|@lk8Kq$$!e{9< zJM5P)>iK#PHdwE2RT$W39)N}DCDbc4a$oln2v5aMDEA5EpAtm^b6 z+ctof#Ng@S(c1PJS&Y)yNOfjVj|`#U(!es`hJ%0Q*XL&HRR2v~4K&4^OaayD+|3is ziH;Nqzg$nzpH{Bvc#3I60xEwUy%aHbPy8h7&ssRez)mJLY*Y65ibe7rbVbVU<9t~J zqJBrMr3uj$p|I}K3M-lJJBiYa$v{cXjj%1MW!&0eKWu~H{B1xYA z$*5o8<7rZ_NH*Ps)8m#V2Hac#K>;Myie0c8?HDPdL=4kxit#5_&hT)MREvvr5KQ&Z7T0%Ujea!Gh z94rW?2ph}Q+-3d>0K90>@;gm+-3IKDxZTQ+qW6q!oW5*s=d!cr!z}GK$HR%dzP`SD zpkAnpxRnTMk~|KA$7lo0eoM1NTT6@m>FH^lEmfw5;K$^NLrA#KV{0r_6@!twJI)Twc@f#Bpz?32&ii6b74|B-Jfr8QBn*`;^U#_4}krmXD*`t zx|z_;#7q5!f#Lkh89;-z#-Bh3@-ec^6*285j3wXhg!OU&c&#cb+JB>{sQA!y`UE2J zx7@l!f&ZHQ$C<&!HpYZ?W*Y<9Dj(iJm@}LNHVKAnzX>ok@ts z5bI1|uLY4u;d>^SS7J!MGJaV~FOowkI#v!a+ez`OT_>r)>Bfh%W0yZ*{lhQxBzmL= zWxCqu6@Mf_ya0t8W>VF62EU|{U` z_xF#X*_fHR2>?57;p!BmL)k6J;A30xJH-<(YqNP82JGhUj+dU6)&>xCD2$qa_gu&< zgbaU>?Kp#~8pRt^g#Jk;P(2x$n9u>#_-7(Ei@Dj0Gg!FfVJ(bMh>R4=U){%q8G*TY ze|iyLIx8w<{`!8rBfD;TKh!2r$y$t#jrE~0U&0-JgRqK}dWCdj?GT0-!GV zyFVOF1-h_-Y)k8Z+195k?F~F0f-f8#i%mc(BmQyU*y-)O9gNeE&1nyYs=)(0V~;~X z7y(itrO&)>3e6sOCr6DN9;ft$N?bGR?0tmoAp-+qiyQG0FW$JXRSf00{$vMQr+0@8 z(*R$h_&g)cwEhgp6!v5ASc(`pIFfm~*b^!UvoJq_`vwL^00UM5ShJInk*a&lXT z#yK<7>K-igTjT3Y?@kR2{gfY76-Sp4uos}k`T1cbW#xwrubc6Q$Cnq&x3{-DV`F1x z-@a^2+iQp%=siGBrB2N6wZsG5`TOJ9;?AH|$KpOt^(1Kt@E%HT2*_RJs5$KZXo$2Y z1l>hLC)Ddc^gc(iO3f0WD2t6}5eN+60zKkpR$V^HQ(vPe{q$egCOk3?NT5#m>qYGo zRIZVy->6y45?@uBfZEdUNEQS8#4BM^`>^(zgir`K)p3kVjzG5pU*1VCiBo*W)F zcisc>u=r~jLN2||7Rf3T@p-7+J#>C}-(mo{ZJ|;r(hUVmC}d#-lujw?pd9=3^_W!j;-Nx4f= z&a6GUkM9f`>S+`n%UHr24h7RU7CPK|MxJdtF0x9;q*SIyt1)NxHjxPy0H4EVt;u3{AnI2_eEe;(eD(kgt^h`tNoriJqjd@~DjHgDNmZ3tbVW;9 z*~xlnXee|RDoQ;JVS%2cCK1mD+@UdPIR-w6i6~u)=8F*V$Et0pVdapHIZw3AXuyuz z^G@rxva;z~R?7x+%D9@K#wIi37Ap^$@n+Vw!h6a`!h=W3`lS0etaSygM|3% z7@TyB!U&0xWuWW56_ z9>1%@+(PN(Dv?JPGBROx9i1pB&UBtG)B0kJ(mwV+eVC}vd|H{w$;I4uTV3G*Q08a) zEybV~yY5A%4!x11qpnbq`~8=+<~3I|g>XxNT^CZ1y%1-={p-;Mb^lWBZX9F~BLv-0FHc`rj3Lp3WCP z1>8W>li}jKs|onJv(~P}SU~XZc2=JHD`GN4IztjpqZo86$1)Spbz5$s!c(FH%oQ@W9%%3hSC0VM-^~#;-&N z_Gss1aN6g+XS!}^K5c%yKZtmFwRIE}h~U20X&ax9LG?VafP+FpJOJy>Wk_x*DA=n{ zNlBr6rNLMKyh2p9+|nAv?iD{i6R8QwK@ivo*WKJoj?vP{_{W)Vtdz+$afK3-KX5G* zaR7QIo0!n>hNrS{yZrKCCYRh9Wi_9q*J=9qbOrhtp!K;dgRio6a#Cmr%6xp>(#h9! zg!uYBk`>3XlI7~=NM2SJIZuFgG?}S0IkZj$YLyt8*=6^`^w4Ens2Q&y1;~+XfgI^y z>t%;FukZUS$G!uX7DS7+L&jZgvkE3t^55Hiw(^8!+M@~GrR2@u(>SZrL<|4ONNskG zKpqEifB2GC7hbE|GQa0H9V^Q>yJ z_|!g&PvasH1lhg<^7)4P@Ct{^9qAE2N#)^Ww9&SLClO)L4F{keeMyu$P+vMR`gMqM zt3JhclXnErg{d%3?Ei~?Rer>aSNGJSqM|e3f1!ALP4Ycd5OLW2&~|ZQFX)s$_;g?| z3VC&kimXIIOcB(hX_q3Og{qpj%3ndxD9H?Nes-V$(ViPgyG={U~?J%YH z>tW?}SBJbcn#Fnh)=?$6uvTk>Z06)kx*Ao-FhwDWFEpY*qpn|wj?N3>1js*$Jd_Sl zC#H>?v$}k9fG8<}g+maDnHEv&JS*|b41~|sy(M_NTr|~SQf}`^h)lY0T>7D$-}6OH z_F;`Ze#dam#WF$%+LQzSbfhW|Yc-=X#u!-^Xfv3(y>%J~ilufOKRayd07zMS?SnYU$60lM|LE?ZS#!AvNTu%xJscZ%jmM$dwFWav56a zErS|pj&#BemC%fVx>;PenF(^|R*IgpJLW0)mrqHR%@6-0QOZiED~?g~>v<0`8i|+E zgn(2R@M9*{a+AYHJ85{zq~NnO(D-3&OesbDu;KG^{^|Mgu?~P{r}zW}!TT|Co@dQv z5O%&+%19PwEG!|EA|4&Yu)<*u z{DPwUu~Lr(_AkaIu?j<`X3gHuOos59yBaZ?pzMr&HRB1Gm^VwP5}zx>NLN#0$2kbv zYuqStgpr%Wu2nY0UtP{{vpMs~mk{`(F>H}Sglu~ADP-?(257{TX8HClaub+r8Xyj^ zS9f!3>L@CLnaOSxbSmvl!3AfmVWZ27pWc=v<=X~fZW|D5^N22_`%mr9i1m9X< zHSPj~wjECgJYNX(mhME4W{nRYDkitVk`-()jv@9QUJed_^@N1{9|ocbaMtX4k!_)2 zV5E2%WLui?OsP4EfBKOO_NT}~nyc3#?O~PX=5zP&ad;6N% zSXfv!Z@%s44XYRa>z9Xz#eg(S`1msZW)%n6db|+q(5NWYp4qyd=Kujh zO8Wf#?2&u3n*UN;TaR@LdG!P|(E{6;2$tp)7g>&(+QT!bY?}UvT z$%joPeBXw^Jrrv1;AafGU+p0A7x=2N7%ulTww^2m_sRFn`-Q&WPn81n2P{9U&JiC| zmq~xSVB_HI&Lv-}S8Cm*04mGT{eNmvVvw`qZqE_Y6SjJ+ApX(sd1E*=W)S<3pLk$;CnKzmy!&?iXIh{>;$s4@jcpJ3BK>KtK z{YWLIU0rHh@oh@N8jh5?GA3|78ojKb%%i{Y1V09I2>@Qa-1FtU@$%*Qw35GK=Z{O7h*R?o+vHlZ6XK zIT8;sg+NcLp90{Y<-FW4{{SrrY-D6T3OYLDM0z4Vgh_nd9trJi{!Q5Wnt4k&KyRID zzOG=UTDh{avHr$nlyL~E2z3?=cwisE18)FIp&d%s4fjJHG&Ho0 zZ>eLugg@UCt782+nG4jn62%Eq{4p>M?js3~~bb58NKdfI-5S;TI8$rmDSZkYPk%vO(2Qht!}?xi2=qv2gVgX zo|Gk4Z1`9{biETg`!Pr^JcdI;rYb1tC-3OUl6Jz+W;~Lp3gC#$BP|9K(q}jMw`Y5C z3RHfK`0;PC_}(>X|HA8Jg!NoiS#zDxil-h9p3=3sm!2S7mFP-DEsdaGIFoVG`nhe3 zIc_5U+n<-PA0>Be`+IvsC`8zW#`8`&*|wYfhwJ9x^8vj#1k6U z12G)fj-l(DXfAY5Z||Fhg~c8a_1A8BF57O_Q&MmXlarIh#e%I;zk9nk%f*q;sGvJC zy-}oQ@&}}N{)P4tLA~>6M}l1?J=jigm;r%McmMlefRBT8+Y3ZQM3#kx1v2jLQ*Zay z1l?5rH)AmTp~1N_Cwxy&j~CE+w6EuVHy;RS_q{mD$iR2$ydHZ_XzSPDl>bJn;+?&E z{c>VBF*cU?nbS^x*D!|fUP?nlL)_ZBvSw-Bp!K`@f;$PEU4z@_A_YK`-16rSnvefO zcOdL0KA*?!zL1cR3}UGJ@XyaC%vJMdTfSVx?e1b{Y$T_@gww)iZwtMN- ztJ*%HZ;sreQMKJkKJW7M6BOTXwoj3o6e$2VqNTZ6)Be1EaiHU>2ay0MY3y!&0=ki6 zR!K1U8(7ehMD4iq+fqy$oEcyR@Yg_?eMv-FC#82V_9@0PWGtbOVyuzKGD>#Cj9sF!CSf93vPYI8 zlL(b1$}417l$R-DjEV2@e&09O^}FW3-|}3~bIyJ4bKgf5HTcG3o0HD!nB^wUOs||b z_|<6K0)Ws#rN=nv2pV~Ndt<@NAQwN^m08E^LdHtxHKF4&wu(9CIl!N)+HqyF*?-6> z@D+Ot7K?2xO8?`Rcv{5%&t9litUE20Q$KPivsO5>x*B2T=s2M*fZiN#oSvRe+}aB1 z-VypaS2@`J4%eBd2Q`E6UmxEYm+{ym+Ei}(`1-!?T#DRU4fmgFy|GbJQsTyKhE{bo zr9Xe>=QX3<0xO-1`1-nSS-JX(zW7!PQsb@gSA$qG zSumJD=vW=Y;Vl`Xl)X(autA&x1M4ryWrP{yM6ovpHfx?d$(#-vLVK(OZaC)ni4$19tHS@k z%i;2S!MAj7%p3py24pbwYZOB65g{S>=Edy|xVG|+km70!xf~t%yhM?4lg~P4b{C2f zp6xrn0)!_z(Z9ccs#5??yrjfL{?kFG{}wr<+4bs*3aW$4C$PVkDBAuL*#Rv2@1>-E zvw&o{_ebJ)1II4|24pPXqyjc8fDAf`LXDRf7aKkYEZL2!OLfuV-N`~X=H})KM{31a z+`hQFas_NRB9s2DKcqOK7q{~O4!e5){(VtgvtPJyrarjA$Khe>BXoQ7rOVT(hqKbW z(o`u}*vL`Shj)^b&jVMr1?axN>BdThFD`*ldEvu{4@R+UH8opzt-d#-j7lTpX!j9Y zdIo;L;@50pt!l_L-D8*Stlo*;#2nRxWv?FKSqJIN9lD|8e&rz1>xP zlQaoUC9s=TmzEL|XvrI#tCg(R;NrJ4XIP^}BpjBOmdr**N7VuQS94-?WaJ5mp_OH2 zCf-}L%Q1Dnk&#thLkTIeh>G#$2p1h|?17{EYTZl5cYnZzhoJyu>3!<{^~0d*iC5>L`sbt; ze^WpARHlJ~oB{mZp?}xlwl9E)aDpw*zG}(cO3mG_6pr-2!x2Zah+=*%9*kD>J=Bu?a&zP}q7I18;ZI>?3_0IMip zs`}(@IOH4F_F4YU21UJJC7Vi+Js(5J)p?_Pru)pf%fFJ^ZzwweVL6+^haYvF(d*fY zwrjUjQ*E&(Ci$LfM@D?mHj=FvR#oERApaQR%*dXNjf;!&z`J*&kITzr7=W4TjMGXu z97(Yt@JGj==0ty7;VNBw$P(|_Wc2`5#Rt~Eqs_G*91$Kd6&I#4sDI)Cr-ABQHsBO) z9o=Y!A3d63aBu)8#b`XGdS|r5K!XlE!$r$x3Y@`P#%}9DI+O>xx*hIRH63Tiz^c?K zK4e!D4E_dI=s{(^UTzj6Xc@6#eFZ zEO-ZdCp*2`LOtFxJp43x()Y%vPhUo_HuR1yJUe-a`>6ATJ5n4)PZ+F4Hu#^{YI6!N zUjr8ZJRCMT?2KlKF?XIZji=r)1Sr<5a6nrS2fER=9v&WwNTgt!@iKDug0W!c|Gx+4 z=#>B9!Go)yO^{8Y#LNS-I4l$dZ=dlM(eYjK=23ccfpZH>r;ah{Xo9K#4*MMljqeb5 zLRW7uc6wss)XMTQEdn&eFP$qu2~Efd8w21>dUCd-uy<81?%$w4F-?@F81@`KliSqN z@($RVE5PsjVtnL?P`F@+_~H^`J$Eh^p{ zO6NEy`MwCP!&Idx-A--OXTLz80?` zalZ`!{rh7~CR18}ceQal2E3$=DFGDWtKTsb&`k_0ggLc%`dfyS^^MpteHRGisry3F|XQJ`uC) zNbx+A%b<_31Q1yJab@MT`Q&7-I&hT_ajR&r$as0;YB|AIu z)YR0wQhHJJje{1;HHd5R`TF;RV`KKR^qtPr^n?piE$ZRbGo|H%RQrnT(85_Sp-~PH z3`lb9Ck(OJq{WmIMXk&OPpP7o*48|Y7I^%ed>g|9v!cdc`Gm8|IIQUpE^kz7JCoTcyEQBjEfw*UzwqB!Z zb~$8m9qfY(fsI`Js^=bAsB~;Hz$!X`#3MV*MIw<9QMXeXas)7&9Nx8v5Pa<%e0cy3 z(|>I!u<>SoTumwYbr%pS{Iqp-a*8^ssTsTry2ftbk+WbnNQzatZwthgE4sLC;ew4T zT}n3tg8Akwt}L2=_C5S5GYr)BA@W_o&i`-4;VUd6QkR^bZp9CSWq<(~n7`Zt0_0TH z>Q#Q6Z7|1E1J>33{l_hYwGqW`TeAESskvFQ6Lyy_B}sdPhljfZXSs?_$m)3T@^G;_ z>#Tel3GebVng1Rg6NFt}eBRN&u%bY&*%b>Yf(^)7LC7qNG@GhV^q46u8FbYYr6ZP$ z9Y7Z>Us6;w*gY%^#k~R32MR?9e`MQXbr}EVY5DlS;DUKt)jgkKI+a!G0lkQAcS6%|)9L4)LmjFEu>L_MRvU;bXBdRyKj@6WC% zi{w`$!a&+m9|Xg*=-{;#f2^*;iBbyuL{}UR=Wy|2jZw2W_5$mr3?bYQZn@CXfhFP z%R?#Y>PDRdkXPgR#Ln(+7KI``%J1S*oggI7rmc;TD3Mf+s6dFlSCnn7(Ywp1sQkr2 zpO6~<1~M}}J^0*yp}exP@>y|lamn-NXId&MmM??zb};QkjVB{v3vH7V9-B{wjA^|T zq_-;F&0!e5;tVWJYIS}62kI*qI6!S;i9W>5u3q?1l$QfqXXv#7_9PuBX}zZalX3!h zF7EKbU?~DzT*6|?NrhjMX<(zhZTZuP8vb&3Kmo4gKlRuk@Oe-*TR>x@et zD-t@6sps*JWcv3(V@~E9Y%O20WRucc0p&IH8Hd~{8mH&0{hJYdq1|-3Olz$0amdGH4n^->FtIbK7WW+Np$;-j-#UJ5I z+t~lw?Us*mo9Bhu_8vho6nxPOqZql%*z{I=!PrhoA%r6|p4?>@s|6WmlfWz|6^J5_ z9TTjD+g93fm-_GS?1b+!7_nS7V7$b}2pJ!zaV5*XO4C~-e+v{99WHg(I5Av)A#yJql#q`Eh5|Ep)`uO{d%7 zIFWJCB8%|p$RJbW;BIBwjyc3vge=l^rr;Etu6jzVf*|v&=PdlY*1ZH78cdvMDE#go zuG~jm#*qseDZRo;A0R0*mDuW(Qt*~+vWC^)MDne#{9O3?H)Wko@TCDxAyZSfbzf#v zz8Xe-T{%`NeEk^iYv%A+Gke6|e*B!NZ~tB2Fvr;7b{EvQaJ~qf%9n-vQ$qqWa42V$ zl9FsT12a1*Ptv6AY+sI}KtJYlIsM`}cClEi{%k=2|4se6tX^yFYLcE(?eR~+Z59SOeI6A@4YwK2Gd+BOC2bIrqG$pL013u0aZ1#}weM z<98o?^+5_?5CDTra9vYi5CGTp_7A@NAOHq=;JT*3AOQMo`$Z1x{+C;OW;~;DZEZ?O zv`$H>73q8HC!7_r?nx2g*uMu??@}P7P3hfR4}`0AGC47L>*yFRx3SPIG3`2cufE~B zbv%KoFd>(Zx!5WaKnB6la|#avKs61!N^~_$KI1EgwZ`(QXpNpX!O0ukoXaS3ZX?I@ z1`eVix_K?#p5xsP5u8hOyRDqaTX<2hK;yPLZEmwAGrjG|3o{)7AJYSlL5-n$Gdn&w z2!KE|^Dq`k_x${&PG28gvEn0BdyFGZ1LV5h$mD=wpg$tg!SM-z7!M#8fC+#BfZ+K< zw3q2m<_-OEdHz@dm;tl^ToXihBREt6C=r1Yo=3S8D2!^=R&U*U6Me4R%FElK>C_Uv ztc^nFvxxo1AOO6#X5BhIFMkQom}mVx#E=~;@4+1gce8mofN?y>O@;7-wQJuN7>M(Bx_jL; zi&)lH_h5qnAUb&@eK)g)z;J5DXt=nUBDi_rxM_em7C?d@@`|)P(!BFW=ZDqO+XqtE zSDDtJ<>&s50Cyguc#MO%4}y3&f6|eQU6|hAyQ<@t0rx4j8#3TtoL-0|BeRpkhM>vz!*9LFjB69U5ljuYQ?a@h3g zhLwd%t)M2t)msmFt*+&^}`d&>@4D_$?=(ZB_OCz>ONFUhu#5x6@=j{6dTr3wZhK~MHP znKlEB>HXnE1_SvGN*>t3iQ+4*E^(vmD^NIfAV-e|9ss;dojJE`i8bhPA2{)=9@}1K z3X=BZ#}d;IJUXaT5kvq21E~e2RyYApd_gPd-`u|b#%4KSFc3|n0krY5BPS)SC_!b5 za(y10_$`3N>S?iLlPHRU$B|XXCfCQOsNRS)p;9ZHg~x=Q`Ucm8)VC*sGX02GW*(HuE+8382kH;+I-Ag7sE_z7D@4o~gcc-t;| zi-DjG`Yiw?;!Ebvg4OS3Xn4(!!Qo*5IuDCEMN!m9R?pz-83i~e$8j3ZHS7@alGE*c zYR{%M6`ervT`SeI`}X~}`yl|jO8vas-@jkvxSs>aQ850XjoTAh~EIX$FtYu+)~o&dI@FrK8vfnBJ;HrQKPp74&VP| z<83AMb>$wZyWF+?RKEd$(&Slu=a$cKqWCm`A%o`5wPK(yW>KZcao^pw@z#I$H%9 z@6IiAMNxd-Q=LgKGw9?-3}1E81}B_O*Vp!JUcJ9Rm_!i^0Hw*Z}?9TIF1(>2wcwpG}P5SbY|bf4Uq_fhys92pk=pj8R6nYiYQPi1BE>~QFIT6 zH+!2+`}TTnj^nA)RuJ8;qjpQ%y$814cPY|95Fr5QOl~c@bMtf_{5udq&F6#me%~@_ zUteA1IGzNU#_e_%S#7PKIrQQEha#zjA_4%=8RlGk$ChOr#D4)u0pJitQ9Eez^fixO zjq7s`j^ng$m$TOHwB2`L%RSp7B}{sa0U!;VqNxQ-)@)e?LHs8~Ha};O`L70FUe$Ye zK;U+moi@t@`#${ayEKjCT919ah5+c0{O-Klx2zF4@t>Z-QG@aQtIC*H^JY?n$nA7k zT~5mbdq4Q>hP7+o<~vK-ujaEz_qt{P@Hj)RC2KaX1kb-c$oyA-^RLYvB@norR;$xt zzHk4BpMN(mZ-?M-@?Kv*<23<52lKCfFAsvSNltJLmM{19c1OzfWe`}}9MhLEIQ*`L6Yl5o^ z0IxXzM*v0)I=okn<09}zoC9!cT~2FZtGVvhlRLg~;cDjzt{MR3!nVBI-;EbJ-Btjz z2AMwsdGe}1k^};$!+f-%wrIuqgFmXjnmq+q2LLSG#YS{WUP--q|#$wsww@=TvT_f-G@b!kZhT$kLj`PTsdgfxqWl{Z|4`}ZmR z1~1+_6rhZ;=yFxHSDns+%Zuv?qHacKLO|8_N;;ywj{%=~$)-^VK=upEOoaY-tq0deGP&>1Ay$vELid4dLn|0I&liSfY8!?e9Maj{EvRcY2c&^ca~Fi)oXR;Bbn#Qr3nO zXX{a0Z$$_vBX#5E%pp;jI5rW(GNa*ixpCr511=S{przG5&^TZ5KAh9-vT7XG=2s7F zd+4Fgg2>)KDz;AmKnG47d10n=@$H+|a-6^>1(4%AknR43v(u2CB4GKVY&aZloH}2J zoqJ1h{!#;6E;qD#vi?F}YgY|NN}_-XW0GKZxUpkTDGnX0!j11eaz-x$pd)O>FS-5w*T8Z24|LN< z-hg%An~rg#Vv(90#r{)GT|4$2uEeu19fj5EIboIKpw-cdsp{8Tf5}5slm>Az(!|Hh z#m)H72L*U{OF_p)2C62Y{D8}8(b%nx>kn@G^1V{{ymv#Ry$XPiI-fQFxrgJm)Yt;) zm?7CGP`~m0?UP^o!Z?h`j$)>Y%PpelN;7utE5pYBUWCm?$B}iCIusE6e%%~In*?O0 zo0w)fda?#vca&h~{<1D48lWIx`6Dugtk%Xa9{uE-ul06RsMi1>n?CdJ*qEY)o~8$n zxgJa(nG2^(NJM(FfLoX6FkAijnHuEpDP^`gF|PMg3xXRKWnkzK9i~i3f!*Q4M>~pf z{B$j zn1}VeS}hMwG$YEWVYa&6?t;bYgu_WmZ{JG|2-x-9X6SVSX;ZXYob1|8mjo*B4IH2# zaJiiAg3a3Sx5L}N_D!r?M`t_xCu|5i*ed{#O`nBp{xe$;v>$ug8V7XL#}|zqHg=j& z=L&q6mLf(^5KoE@i<(m&M5HN?B1dP>O{e@$@9)Dx) z+PAr$9@C_jmcBPsDp?hC^496I<7a-%aoqgtS^6u96dDMmZBP@*p@>K*YhZzZw17=x zvost&bZUJbs<*ad-8wc^Bovx-u~NhRB7M(e`@0ve-uR#(=wBX`{#~i54g_6gP_Ki4 zDish z0)xOe`Fjln3O{7vfPizkT{gjLtvh}B^7e&|h3m=QBtnLz1;PeEhxA|bpDzf!meu)R zFG;UZWvOov1SWltLEys)A0Qy;rUmlycJSejRS6FO9_c@FckYxpOuO6qZ8P($~0&o8l11k z{v%b42H>UQy9iw@B4oEVz-q4e;_=--d_CNVP#6H{i2DmmZr}VaIDTb+kp9aTW?;(r z7_3;D!?LR0tF_IJ?YpjE!}}LeR?!NlGk6JeT8a_r$sE4?z$AjZbo)>7U6 zD{q~~zC-1xuCu7(r;Icc7R<@SS00!Qy^aUZcikq^QkM!F@z>W*qPVmLt*ticx&b7= zAn+KG6NlSx8Hp8n*#T%!iuIc>p|aY{XrR&3sMg3^qy?Ogc8#sQ=HtVkeDfA*k~qUf zNU#kV0J7~r@3w!=)#+lX(@Q6cr1T^Ec+x-pd@kZ*H5fM3e>LXC%Z;pnZNq;rqSe!I z5~zfE!OS$QSelM0k2A9iQ_Df?Jji#RF?cASuBJo!0;P9fc*$tcdN+4d;UbfHvgr)uZvi-Q$p$VDS5S zi$@E*_U|(|c&s|;b*ZN4``?^}IWy7&(xA59!pxwT-Z+hhrcN3}A_(a00f)U+u$rs> zel-6(4^vJm)SN&_0FZ6}Su38)j4}<|4RFImQFH-f#5cKbeB}n1qBH>+wYkNH^97Cg z)t?TauD-L{lDNwk2v*;ejW6Ff21bJhg5aN&RWIJxJ4o?g55ZG=)Dp&kHI=#%ImELyW^6VD4b_Xp=! z-ni#~y8tmJ4Thxocj~B#W#6Gnyt&~lNE>u4Kg}$8^M+v6icE~kjStAIhfh>9AK?9M zg+3Y8dlPP6HXLi$jK=8Pc)yHIVb%jjD)FBWF5}d>x*!1Hn3j6zz6n@7H!}zgT3Fxl z#{XXKN(03mA_)YtGi)_i!Q7kvF-0Gh_zBJU=?~7Yyl1{KjKi?3Snyt- zrA8RL-Hq4ZK8xK4%2}6~_wuy?xjFGzwlE71tQ`jmUwS_RMVCrSTbP}G?otB_sl|pXWv#3=^8M|FXlb!~@(aFLwet=HBR|c3Tr~Zmsy$$=y%+K_4&~Y#2K-0XOF5AS)vV27`umSdnD@cvlG< zVbW&y%-c~>&rcwrGKch36J}3K$K072$jXR@+YRPGp1n}doZq^7i)!YV$)(pz=Gu)* zhOs_lO5_ng67%mrTFFc`0)u}h^}V(6ae9m)8Y~&co|VF*1Xju?e7vg^=L?7ij-b0n zfMWKrMj8TeEti}bZf`5!e{{#sZv?1clu59lIRRAwkjYm{ z(oS@>u_+50fd|KPENe?zfS7=?!mNK+1@p_-BoMe=ZH$q~xuomTqO32ORRl1Xi%w1N z+zT~CCk7KVJZrI}5Gy6J=n`~Yo7Dx2%>_3h&FAue2Z8568En!r8V#9O9D6nz=0(pc z(I9YLnauq1ts?*gEGJ-XuW4;=zPRSXf#2*>YX+&=3%TqW3s=7Lh@dt8UaEUzL{jzr zYbhPP@7=9!(fb1-FuxK6{@ND1T|OLQg!D{(yCvStA0Z&1>C&)U8@aZYlAoX2^W&f8 z}t%QpcIqMpIJ9NJsxEI z`Z!PJCo>ZL=l)g8lxzFJa2nVyZTMW&TSAyVrV}6NJViN7#|dnfsJXRl&$0aP+ysDXIf(iF zhP47x+hhN8GnV~km??JLj)7wT``S2lAn;8t3a?U_l0uAfT#Q1NdP5A%ZOz@npnjQB z!TiL0@^$Gy%fBMylV*>ypRB>AZ&pv4ztbGLnwo%fL39i4ZRM5q)kkhFI{gy)0b-!6 za6ka$<*n1?=da^t-~7rlqcLp@+5P>c_$?f^2&aLan1158WR|QNJ}eILv3i#DqH^kr zDl;o7xKz}L=4M50Q4pJ-n2)YAX>1b4k4<8UHfrLb_Dz}zT2k7I%O%aYRM^xfAm}aT zzXl+na42VOuXeXIT>RX*L;trC$PhJbHnG{qCFgz<7 z(Nqg0aEu|Tva+PC4UNrqmI>~v34D`i=#Xg4oRWrn?;Oi&b$qp1%9~G}W(SW|;gj8^ zC@O7%)1fFbQ!qc7QB(oCd~r4_hNJ8HTjq8r&Rwj>jy>fJ2o+Urs+1nxgFs46JXFg> z?Un={YOrZ+vZ<;8>UtyfK1<*G1d<=%u(xW=ttIPE?E1myfwd06zatz30GyDLGQluz z{x7$1yk=2<2S9S70VxS?+;T%Ma1o8{KQ$0r6*=C{gmVQ?Eahp%SemDmp(fhsmVG}(>WEJk^N2%B~?C_luQsC z44a*r!F^|TSy}Of6s);<1S@_E)Lf!u7OJtStTE%of1JXJv$agxDpzu%kyVs_?#?mD z%8UuvwWa(XHONzO+&?#7U;w82Bi}9t$9fh>v)q)IjUnkKR=-3VfV3XfLQ$dJ$Ggk0 zZD$F)PT*=#^^)KFdHPlpNRF_%t+b-5X#3Lg!gq^2Q6QhS-G1M~;{fxsm;ZT&F*au_ zz(tGVwNHT2X^dk=#9`W`WLC^oR?&|AN2^g;ZSi>!g-rY}-a8sOSw_s8ImBo87BSM^ zLlxM(?J`cDsq<)p?jRsj=bqK0nVB+jxH{=CKLgqCTk}g;!}-O+#x8s@A}1bqtsI5L zb29=q*!yB`IyULU9VK{wYoXstPOVnJoT+KJ^~T|tJ2Txs4Gvf0y$>$q?8OGZ{Qy*V zL)EFIMMIjQ9IhO$Vil9Z+~DF=>Lb@?i3m2W;Y z6*)ttK7&veMVyYEuEn!29Y?*QnO}Jg>Ii%I{)wz3EIrkK2{V;N=kF=UJMR}TC%*gQ z7y_;@u+E7bWSblpAzfhQ7FgSLi(ubw&d)N2^|ZJ^*; z+R$!}a4-OHb8mg~>w10sA0lP!;dj0~5i=$yAT8CzHi9NO5Hr2-`Uy08rWp7F!N!-D z!(`G1G%ctxhB~Z%{p>*&y^)s^1Y|@1=BJA=esmHmD-LB*Su{;rc;YeS8jPP7T}?Pc%4svKG(2e8NYknZz#i zjQ{iPnM@1I<6zF5Z@`B43$T56X|Tub^84Ng0rLYyo3(*!Zo2gIbNhbwON{)s7%~7R zOjxTub7sA;aOK;-5VWSpBBlQS@vlw7tf@&zN;I-44mGbIJypX_W9%4Z;-i86-B)j5 zP4R)4mZCw_4*APJ9_Ru9r6!=UDu4XNQWmWVl~E}?T3gqSKfio}O^Z`53a9@3hx3_V z5>hf4U}g`^^ZCUe4*CTEJvRYt=9JW+G&t^aDnzHOBmn&6@i~|>KB;5G3gsl$Zz^D> zSg5OaK_G=fsU)JM`O?d$_dNOS2@}@3&YW3KT|VkH0FWmD`TB*cH@+wc`p-s+1N_-L zMqup7XiONL2(oKwGQzHXrP%b*Wwg;CCqE7B-p7sl+9c8@C(hL2*_V!WnTey+1bVHF zX@GH~=>DN;fIueDe9{2lo5!5$P=VEH0{N2K($iDK>#?s-$J`m|9Y?PErhzmU=;gQ0 zbZAuXXc&c2KX=y{&@*SGn^+ii@8N3Z-_Xd$kQX)o2%(vi{_nv6z)GXrnhW1QvHJ)2 z0(mwd-)Ansj|s$Pu9G3EU$pw&cX>faH9!$D|A!plv?LA-=Vr1<&c%WT<^xb-$k%~% zas&IX|KBVm#A%u1>Px~>B!tYLPd+WhmhGKW(UgQHVx^=e;~QTX#pdhKe9=%A#qK{n zP|nWyJ#(SH%U7pOO2s1&PsLDb)zpXP1C*4tB7aXA-rjV{kKHa!hP!*!C@fo)g^@XN z0cg;Ok9L%>F_BVhWOo*!T*9c~ahN}Q2(1G5<+o0=ktSA~vOI-j*CFlnjRz;Qnj*DYpt8E1&GDg8CR8Hft0Y1$Zy+r& zc2t7Yz&|4$smaC;8qjqp0(R(l4GU>Hy=V{$AXR-f;2__gnnO}^OnY-lLBZL7-P~NW zmmDr4xGDf}GiH26bL7Yi{D|q_%^I4$Y&$r9SR?_U3kX8+7^6)(WDYT5`lNJLW~U3J>DBiz{#7Rg}jAXY%p$Al$JT<{uW*H;^l^p0lAcU?Of9L z$oZx6jJsBjWF;24!{XQ|M}Lc?GbQl$9;#&19QOK|4(DClL(w2A;~GDE*H#2$@l& zVTh?dJy3!Fd?-2U?v4o&UGG4q86}n$&dJ2`MOh34lzFB|+-kP7%s4qr3;@5iVYCVg+y%t)Vb5jWhAK zz56@!6WD3-LTLVwhmKVHBUswXTI$O8ttvYA+96=AD|7%X{MqD$%$1i=|jCbs%dD$V#%z7@)6)q${!&k}-(5gz12f2L3}d$Q#B zzDtN8aB&MHlGE;{|nr@$>P;Dc`E5I#*HI{3Oce;q%0!7pbdq)yo`iXsiX zj93jI6Dyq47`re}7<(Ja=7!>bg!d@nfGeEugz$7B0MZ}xhoK1=04(N8dtK%JI|@&| zl#iST-6;M$6*mQSg87`hbvg+EKbsMsI(<7t^a}uV*97V}SN$gkCBJI+??vVh5d@M3 zFjv?cD)-%f`P3^rJpdpL(4}77*S_;3M}AvdQ1Gl~!rY%tO&&6Rn<&EAA2dK$O`x8o z)qir3`L8AOhX4Xe1GH6GYby5KQGDj_yMbGrzy}n64i12voCkHq#eWwj&v|lELdGlt zKy-fsfTRh!W?KDiTu+&woM0-6pjJy7xlXwS3RO~mfl43fEMF=s_SdN5@42Y&fUcPk zZ|FFJiLOgI1+&?KmNvWJ11y3wX;^O^{IVU6l=|xjGkbjBlmjpLKRriEc##uaX|5~V zb4Ss+zwZU|TtL1$4Il$x%>HU-l8oi_&_se`lBP# zvTpc@xA68Go7}EH?0(-ax&zYgbE&Fsk37QUgIFC99~EfX0|utxg<0Rf_|M zE3xNrB}-!YtCu0>r|d74M&Ga`3prVFh%yQc5On$sp z_MQ(oUKrkA0ie_bG|Gf}Z>gCjK3*yVpreqe_>JmcNNW2WTS6D{a_DAEPQ$`E8Mt9_ zHfyx;J|tVYQ53VM!#5}!ymMa}%L({e^gL9pNnKmhCZzn*rYNHnner$L|_^nt_M^>+Tj)!iJDN+Hb6C1oWS z-d$5y@yUgd0DuV-G&plcJ7mbRT1+1xft%Re?P(Q=j{{Fv!tb%@RiR` zWCO7Roe`|OA05HEeOD>|`R)Z)zU*7Oc$i2{x()qH+z&ET24E zhw`cr=L}s#=J#z5Q8AoTXlp7gC^-7+s@B$1)TTz#pCnIkCm6`%sTqd)C>E`LcQY^O z=Ja;}~Q9Xc1vqI@6*YVbUGpB0BBQH z1AvUHsD-OGyd`K1H%1BoGKWNA&a_l4o|g`thDYI*R&3sSh5aP^*x&l`ccvmWNr#DJ zlYG{~lY@HVbS<{-EWyq_WTrTL4yq+P|G|65W6|79Ru&z~BGc!frejAX z;{LnGV)~?%fJd(Sx*tjJUHdB-<92Oi?_?hGBW_tX3^y*x3QU7Db=b1KgjJdP>n-4U z9yDfV>cmuJ4~=2|$G*c=C@yVfMS8wgZ`u68=*4tOM6d!`olE<+JQVf zkgo~=L^T0vX?j#w8yBqn*Pk@nn9oH@N7$+r*~rZ@V9LZ4X3x?j2kNiQ-&4wLYieNk zwO)T_2~1H!K+{4VH%P~i(gAe77S-td=+QZtIw>V!YoV|25WW=u)N zcfUHF9gIi5N+^rWt5fG2@cX|URdi%^m7Fvc;#&_*#)4Tx0@I+%j6DZvGRAp!dZw?X z(`m43#c<4twROCaWwj!UJf5QmvV>}ydy{qLS!j4`7U0y@6FzDwoNbox4tFCk}G zx#rKzz`F0xWfi8O_5>5~sVV(`e}90TNa?HOLYfLO8w9jqG$51e&##>HT&w$=L`CWF zqeo^iArKp_Wgj?qsS)pNF2J^3U8h1^UFMenKuz&Zhna7#Kl{qrgTMTKO3DOVZS5Hv z^Pw65eDavpQFRwKX=mN|{1>C5hyE^7#-cp&jmc~(1SN>538kUQ#+q6F^dd>WuA@wp zTc>6!L`$ok%^7;?k2Ds=KLDQjr%pvqD)Wy@ldyE7V=F908f5z4rWXy&FNpmw6r-`W6U34IPMz&9LE~$pL~24 zCXY|wy=m!CW+ZN^fkz;x0d_C*A zrFwqlnmc0%e*B$T9YcFnl7oGW!mN}Nc<~M8B!{k7AQR}DUz&{hvxWquL3yQ_g;n3& zaG^U5JjkSQ?TRJYSh^q+xjC^c!MAlsDLZ7F!pRK8VX;ZCuofGPWieNY^_7PoDLVV| zo4{l{aFV2>dH`f(%+Oa<9MO%N_W0z~oTZxpE-n&ABa#ywYjR10sWd#xjGn$w&l*GI zMs_6`We_~})rrVRH?a6RC6&AveV2yUez3g=dkwzpkrsV)8FfzpCa zyMPQkP$5TwRA~SXIXOBM7wa>I-<&>T%GbB>oF+F?B0+)be0<3e0>QXZ@t8g_7PlaY6L8qmx+}ta#2qja_*f~O|^$;I4&{2+zSvC07O3?n4kg9 zkiB49uR^FJ)!gpjAP=k75 zNi&oDC(hO}Kf?cL59ws}m}o8TyK5|NyCFyQAX@?$Wo=)4<219=y<_ZTR-~px;fZg~ zz?cyUsXoEVhT{6uu;Ik?nrl4Z|1>NTX4>lU?WI5}Y_!#~k$z8uTmX z?>r~0rSamy)BD!l?a2X<`O_^4CYfr!7kNnc`aO56^A0o?enVycDmkwiL#XtvSP;`ly z|Gf_{v*A(QlU0EK}HOc!keZnSp2=ux3W{>=qqR4RqtnD>iW9`Xb7o2$R4~dB*tqlzY6w)Kx zuv@0oAMdbam?sxtm@xOJ^OA21Z)&7UBoO|m7AjJyQ`pf|YlH?2kX=#)7)zv5ULvwG< z96s@@|KWwmafH1$Ry7Dh*xX>uFFynM5@Z5VDKwc?#K3GWkW*@mvD(}|%asF-E|Jgj zBBrP7vLjg8DTQDq9~4q0Z4lBZLN#azfj*JN{L)Zdw^RgIR(j#Rdm3u?UI5Z;fbT4D zFaYpCjut3pj_~}I|9)AkjlL<89N~~b5W?oFWqvh0*HaB0Pc(Z&qfNB8HRaqn`K7MLc zQ`2$%ggH+xO&&7qA0i8biV^1r1O!0{n>#4^gWx2rkV9We{*KxamH@M~l{p*B4n10U z@%0TrjtwX#0Qigm1&iho0EFb^F^0Oj3x?F;H)V{T^tBCwpc@e>39&$1)u9OnnSX#w zehFOiNc8sRqSAs3@7&v3bLbL~Yz69M2iRw=d?08_WziU_1zLba>V5REVGHs@XjSaFuANKJkBr zr~dXVkZA+T&4C=?U?vc81uLpdNXRudHWnJQMtyE{&bYPj@PaO-KbS!>NtGa=jH`UI z3DHm#e`A_k|hC6#B(H9Qoaqzo%%nnMp&%4(fsqtU6}h@zk*a^$h=!O9*2 zy$78Z!>&u>O(Fs)0Z!L+$*rIrzGXPVA)N1oK>2QFtyKSGZZ2x9EZzEGb|}khFf%_q0z=pZlu;isy9+UyGPm*Vo)%*rqBbGY@a+=#}4xj=O7ECL5rao(X1?*Dmo210T!DRSIXO1yCzk1(l{4MItF78 zUz85#J3V23sruCm6=7*#qGtSvyDQP=IDnjm7*F1w`iOI0EwpPgIk6-&=4fD!=fX0&# zFb)}Y=g8c#_rI;t=p*vf7=OfHzAyt*Cd6SyUbfG|H7bFo@gf`lTfn5O8WSVNq{Enz z3G4*+(Ieu!wMdfrL&asU{_`vwyW(8}-St^JWf9fbFPJ?9U%r2$&lX9VJa?(634eR- zG@Cw0&mL@PGy-Ul*P5G#lSZJJ zn~UnpOWyx{ZON|VK%50=R)#m%poXdFFuO0`HxZM^Cj~5v-gA)7@wyV=6!os#uzX<_ z?zkQRAHLGw*nu0T+GHV23#D+%)k5Y8jYp%ha!8Z|5-+t3Y%G9FHMF}Lj&o) zYS^d;+w7P5rSb>6tx0HWytw1cfnPpM=Y|6y+n;&>{Ko&)nn3c~5tHkpqen!ywOuw$ znD^6FiK#RG%<~#VLYJ5t(*EoDrR=15I*rlaqMCg&S)O_6xX**Ky}w6ok?WqA>nT+8 z-)Bp;_S6aX*2eQbZrz=E?p`$#_un-p;PeKXT}17mudhFkgGa0Ulfc6~RQmkHH>P3E z^t7NfIB>KEFTF|amA^@lG zo39ki6CI_+Pad0vnNw1O(7=vkr)%--OQ%%OKn?qZ%<>AWD$w;M=}+^2+L|sEUpo5A zy%tL`jijKBqd$J@f0R$8_6?OzVFuBc#(MhyPqhx1v7SfJUU_gTdy z{geLQ+ehPpwPV?J{Vj5SDQfldn`c=MbGPLsIjNcdhmX!+ldJ>LfTaH6lePHktEak5 z+3<0LVC3o9?}KLWrST^ga~0oGf9~~*$Nsb~Dr%Uuy}g8_zbf-bHgD8Cs2mN_MMtNb z+S;lNStCC)E_>YCe`_>GIzcj`YlG+opa1Ow#F#X!iQC^Qy3)d&RhqCy+924XgRQ^) z@KiP;B@nYxHyAnC)C@1Jz;cJW%+{_RiBY-nejkCH>-|To@!ki8-KNa>nyX^eYw*y0 zDljtGC!lCTNItVxw*Ktx@7woD@#5)2t-?f zHj4hJGJk^aMCWUCM1z0?17M2++D)^T|MfS9=!`o!@J?`|CfLUIj4D0*_Gi}QV(f@$ zES{I?v*DcL|KtF_yQKgZ3K~^)SS7|A*`O(s*2A)5x=mW3Mipu{e|`NqHW`{CHfm^; zn-j;J)d$v&VZ8<3{6NtqIwSa{H_qT(K_i=p(Xsq64~1-}PE5w?n}%cY+>8J;sK7h# zUj|K@pvl>hC;91#L=ex}t&N(N#&g@x9s2FpfhaSeZwJ_LDB1Z9n%Puq0?}PPNipb6 zrc{&JTw@$L3qLlX1T^frprG^_04rRR-{)?vpfM&?3Ly{g zqBhIs7JJCk8>q)vqCqAy)1#r&@r>Dt2D|oEu>R$CpEL-CRf18_mts+SeGxpTaoVj- zn%2hiht3@Q)dK*C@#&A;{1PzvrM$b^yUOMgeV&+H9~G4q)81Zc7(46n8Uk@*3RJ+y!fn{ik@mbkm7>m^xv6>yJ z#)zJc%9ZF4Zqi)gj4t6hskVr&OV^|grN<+4jc7nWBUkd%p7CzL&9}E+K||%iCyLI$ zwb4`dOozhB&MzBdsD|XB06+!-%LxE6Mxd3vsi;{uzVxyoDtQ6NX(C<=I2|M?!drt? zo#D|f;I~wpJ(Bk%jXi17v@~5jc6R?$_jwXul=US?NVW4TKT|jWkVB#dqcJnaVky^; znem+!N$K;R(`Zeen#I0O4fbp!!U4e`^Y@JAKEE9j^D|bZ`ZLblQX9{isx7yh{c zNVEYBB>h8je!~TT(i!fm1(yHiIfH4)GLF|e0e3`4gya2_#>yBP0sM7yyR} zuo|Z=dHUz3*sQyG!N5-GQxo$J_JDo;`#_ptkoo(7`k|XW>>;S<*V1fS0IeBlCDTWF`im;(wehTW!N5`r=|=!yh!(?h7t;c_H=9^wQy2+l|rJl zDEt{LT-!f7x%}^p*Yk_SYVED1TtnTd7m7~3@CP8y4m8V-FGYR=wmk;ofp7sJYXR0Y zPk8}EMVZjvZUl6u8Oxu3)fkmNo#%BCUm~F-4uK#X=BEv!*_~r@mpl(=AJ6#ZhkoLvvD2>#F# z3Fk~tXWeF0Z$r|*ptu>k_m^Y)t}-}0J+{HG)%_E9-Zql;1=B2l0umjCM8#@HPS$k$ z@IYgJfOm^-2jA9GWUHyz^H@c}dmjVwHlRr<{bkc9B-_8IK7jK39eDu&Mi>lHuv+z# z=KtdRG4Z(%YIHH4uCbnAEgaSf|2yhI(D_buvdd@h9F6o8snU{W?bF%0e|_x~tbUGL z3i^Z`haWvU6LV*zBR-ZaO|Wu}_dYDfrmcltzCN&+pS>FO`nua&ONEw(b8lZf{@gm~ z^>)~7B>71LgcbMq)Vf()000qUNkl6H%z2SL|&@$TZH?y^J2Yw)KRj{7}tEZ~EBT&E`=pWUU4iw>iv z66g(EE&&}8;_i2Rec&-aIljEhZfz1;nl4>Bd-U1+;b@^l)rjf6YkoqC`}YL^hGV#wKFf!Ynq)!R~b9)Y*D` zysH!kkJtDdjjo3I=`+jb55=-YG#w&=`2f^cKvk>f3$FQTjQ(FCgt$j{@Oq*?E}PKS zeA!l4zUMpTh41GBu}+|c>dEDPUwPa~Sf)>JnLx_x5C9~H7%=MfvC%eLi+23%AAdbI zam=@LhIs1Vl%q$zBBig!MY@B)w-%$);;hVQj2o56d;mJZrJ$&p^%e&!u>n1j0B?3-k^iBRAF~4N`0G!y~TFf`roq473)Qi8@>th`@TZ^*U zJ>a;*Q23&^Y!aEVJ%w@#QwY#cTm0MSjM15kG`eVy7U-?phVrW6f3_0@ef-=#XPzK0 z8R^e2nLbu?jnLY3;o!N$zyFHD-j_`uWx-pIq(2d>Hz^{ULaba`GKCD3A=bsE%^Es# z{1;v^n9{NYjot-t{USl8*()K`GHQyxR*7-AoCL&NQG`KMQE%&^-S^E*Iv}?V;nYH zt1{%-tENwHJHg(dl5+zTye3n~2#C~7ubVLUC;t;2m-{)rA&GQeUudBoSt4q_+-sWP zx@Ug2{cOf;d+QahrSamsmySR8B%rqgHVS#lGk)Z9hmfm1gY9Q;YXI-4kis7zbBOr{ z+Q|!k@pM#7)-s(TflMK4PVB4a2=@MA|Gvi{2;r3nrp+%!e57PoxzN^pY0vp1Pk+l} z>X5l3cX`Qne^|wC!8W+B7*81$>IjVjdJ|yNYPCr*6XrhgoH2Un46Q!4UpmD-@(Bi+ zpYbKfaW0Fwn(Y45myW&kHK((&5zsq;j%=@N_xGsWArJ`q3IIxffV2RaLY~M_jES6L zQ_|%0Q4>D@7i090(OOn6(f=YtVS!+f`8$~3YN->3=osZ)Iqdl}$@NL9_{I6OuEQ=4Ovt`DeXpNS0O`?F7d~^jH;t1XXPg4Kjbn zP%E3YLDSw+SW#ZG?U9Dc0~Y|w5wWRma-C0~+5LSP1@grsa#Tpx1QG~ziP5k(@afq% zjvbP7^PddSLxv1!5DYTEB>BNPZPrGOxw)XawtV+v)n&U*L6;!H-bfXmzL>w)LZ1GZ zQ;nwR$!BDLK+X?zY64xNi9nE+vtoQk_KH6kOz9Z|(kB>X{tmOpW@!-2&6lfdDtCRa z=F0999_A;rM~?cC>I`n$+_uw`lz%l zogvNzHoB@;Gu1r-vFh)3GlvG5-xKZO+}8Fw!Q4_?wOzXm(G%d+uB|w zw6~O8t}Na5gNDk(m%Jpu%>2qCw?1e7s|^5UWT;E!r~(9>DQ1!(aF+F?>%8|E~tVo0kAhJ%^o?{ zA9inVxZ8fUOdwyHfSls4ngG$v9D+7BYQpqKpNfjfT&9moMZc{bQUQX2%KTK==5{*; zOKTb0S_*exIQi-i;cRUMOrmFsGf4=g6;fAO{}{8PM0+4jFff^4N^rTHR)GfCwzU+#bLsfseko0Eh!#DePLlZEW>2q| zIjGSJ*FpmX0)fXl))@i2pw()H?C}qMHa>Cew{*soC{Mzy-}wc;Krrx_pG+Q3Arwwo*%D!-eN73;y+*gG~j{xd6Ky<|F_pv%J@Y`LCr0@CO1pL@EP8qt%L<^kJ(P zB&E;%zAh>yTW?GuzkqDZe$`W;1i?ULerkE8v*N7gYR=MjrL3{`#P4fLx8^$>oD;B< zc_T}F`YDGxd!?;WjikTUVbDO&=v_CY0D)c)Xbf7dozq2)NE<%(?jP$-Ll!GcqJE_f z2m}L*`8%b)%V`rVZRIq;YVVbz51(?h6_h(1w3TMLtU)$=lyUxRCi#^TxF-PWt?zn+ zK$417IlHpdmzkf!oL4>68BF^278CdMI!X}8WfKZ* zpwr8KK}zP0QI{I`&<<7$jdtbKmWs^s)?dh}1&Tw|8k0~7TBPq)!lwnejCLnE~(`vOM z?{GM@qo+Oc&FI+dd$fjRqt1{3p4X5a+An;A;2`MZtqGa=8RN6QT~QPTyR{xxbEU=H zR=Tm^#PiQ+wOYHw!MOoDNqCw0mCmm6)~@h$QBx?cv=V2hr_v2-fym*xIYA+M0_t6rKCW z>m>C7o#=3wN$SgtFaPvq??)8#M=}7s!=!SLF*(PwHlUxR4fL`$FvLyD%*;%|Ws~QcM|%2;6C6w%$RJSq1|ASlNd*G}6Im%4%cmuzPrFZVOj)Sa zCunv0c<_QYqBVls#h$(IR#3A?7S6nzXN>O_?6yYOEOid6rD|_u&8asVDt8`Hm^*SJ zOUe8)<42^u?~Ay7EOL5nKV@@BSyD~fKrW*oAZP)d9$JytN=^WumUG*pxWw_F(HoOz zX?5`$tsx$QKp9CobC;ZD$+3%+)n_0G$ow9O&qA6aWX5+`8=RK*>LaZU7yn&T`r%H- z`1AqE(N!|P{CAo8l~JCEGkLuCI&yYj9TzJ70&;R?Z6Ip`9k~XQX(V!5Eht*V4IOp+ zqL_rycNq-HvoyMR14WDkjgh78JI$lW07I{Xz$f!}N_#SMNLaX>HqK#dgx%I)wOVQp zw>4beSYEh!CxzT3sn0%V_e6PQsV_UZat(h(g*er)RDT12?6-L547`Cr+CU3vb+TDR zqMl5n*rf5R4aVdJ8be%?R-ZsoBNjfT3sWkefOD<2La%|K3-ilNPxU(N&=RHv=~NuM ztqD$RQ@zbnv$v`K+-8rd<6(Rq2RLjV#+RL4CF6THutdDnR|2Cy0zm1!GgHS?B`SkJ zc9dlkNduU=0Kt?nIXfwB<}JqP)FpaD(nvuYBWQK8q!nmFk!&J)z;JD11w94^`BAt2EKqGgMq-IVOpWnN8lU|(J*wxss%9#xl48WgsED6{18DK4XrK)yr8GD zUbeX&Gl?Qe9)WRnxc>)U+K&$ncf%U(>?kf<153A>e(%FKdDTfDS;rDR1gqk4Iu#m8bPad$PB_6 zqDN#Trq7sbj2<#iuZthYz@UkeOeBqg%p`hy$x)Q@3kpE=oh@un4scSrvdrM}PhX}E2?bf| z_glsvXaMkK7I_0fVG^44p1^j7A@q!E2&S z8jTSI3W2l(&l1fH5K>f$2|^DLWla%o;H@iPDL}v&-6P#S{L8eF#PDt>n_%s9w!`IY zH#==D6?S{`1#3&?(Z;&7M_QZClxel}>JS|cVq&uI&1A#N1!_tFD7AoGw%o7Hop5&} za^=47CzI_H*+1|Gg2xclCUMBDanZ3^6ZKIEW3}4YY+e(U zE@+}+2nd4K2%gtbo`KEv@*K0OGz+?LbFkB5d>qrt-pB1?r626?qMMlA0WxbSiRN-z z;c{DBUG}yrhqLX9-CTdc+*Wp~q4MZCjx*D|9R<_VHQ2G0vhzwmWe~`Jmwyge#vh0p zz#9(!fIv*H457+^pq~PuBQOX+ltvPkon{g-phMJ~QqramH=2gz>I{h^b^4g0g4UR> z(L^Qjyf%sx40QehI9@|pXet@@{NdS8^0GUbT))Xw$`~E?bSA0Ynjv1Twt-371matD1x)i>ub@m8 zuTQ(Wdyy&*AO(3+C9T0;si7~^@3K9=V+Q5?tXIbNgVc&!E;G#mt; zlg7S~`Q)Y)6hyaE6kQI{?Xrt*hutkY+ucq_v)gTLa@fsvE{D0!W~-|-H&vFmwv{v~ zm|e-BWZrO8qvJ7eWGU`T>MON?3=9_jR51L2Wc=$v0|e3tN~c-Y2ujW1{dd`n@|=Lf zOeJd2p+Y<|nUo+?-j{yQY;-`Q)9X`>g3hGpb$Xq^^Sr=o1aco-E~ne&cDvnno84tM z+ibQP3*cl2LdZ6|*UK=bbU4Udlb%6hSZ3PDlG_*KD?#8b?Paq~X7~Zk_}3!Q^a0ipc27Z6B8kR!?La{v{6cK@0@}X5K6{Zm_{9E zqA5Y7ybhTn1Q2=#Pgyqon^`PgW!fy~K-C7a5X{hclj zaxjLt-hMv_fZ#jsOKSTwon&VB)+EY*dxJpv1WM`b{dZsg_UE|z0#xufy$(My2!QZ5 z-JdDrOLKTjdo=)1N^M^f+#iEq7m=Irwk)u!@6BsokJs`iNCF9%Kt6ys4gE3pAj9{N a+x|Zz0f6lPpLYNN0000 + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml new file mode 100644 index 0000000..c4b0286 --- /dev/null +++ b/app/src/main/res/drawable/ic_add.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_app_drawer_icon.xml b/app/src/main/res/drawable/ic_app_drawer_icon.xml new file mode 100644 index 0000000..c40b424 --- /dev/null +++ b/app/src/main/res/drawable/ic_app_drawer_icon.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_apps_drawer.xml b/app/src/main/res/drawable/ic_apps_drawer.xml new file mode 100644 index 0000000..fb22642 --- /dev/null +++ b/app/src/main/res/drawable/ic_apps_drawer.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_right.xml b/app/src/main/res/drawable/ic_arrow_right.xml new file mode 100644 index 0000000..bf3cb5d --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_right.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_back.xml b/app/src/main/res/drawable/ic_back.xml new file mode 100644 index 0000000..38fbc26 --- /dev/null +++ b/app/src/main/res/drawable/ic_back.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_back_pressed.xml b/app/src/main/res/drawable/ic_back_pressed.xml new file mode 100644 index 0000000..ec2d764 --- /dev/null +++ b/app/src/main/res/drawable/ic_back_pressed.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_back_selector.xml b/app/src/main/res/drawable/ic_back_selector.xml new file mode 100644 index 0000000..2fa27d7 --- /dev/null +++ b/app/src/main/res/drawable/ic_back_selector.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_backup.xml b/app/src/main/res/drawable/ic_backup.xml new file mode 100644 index 0000000..9b51834 --- /dev/null +++ b/app/src/main/res/drawable/ic_backup.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_clear.xml b/app/src/main/res/drawable/ic_clear.xml new file mode 100644 index 0000000..d11cc5c --- /dev/null +++ b/app/src/main/res/drawable/ic_clear.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_done.xml b/app/src/main/res/drawable/ic_done.xml new file mode 100644 index 0000000..99caef9 --- /dev/null +++ b/app/src/main/res/drawable/ic_done.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_fa.xml b/app/src/main/res/drawable/ic_fa.xml new file mode 100644 index 0000000..b93bab6 --- /dev/null +++ b/app/src/main/res/drawable/ic_fa.xml @@ -0,0 +1,66 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_fa_notification.xml b/app/src/main/res/drawable/ic_fa_notification.xml new file mode 100644 index 0000000..6ce4451 --- /dev/null +++ b/app/src/main/res/drawable/ic_fa_notification.xml @@ -0,0 +1,66 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_folder.xml b/app/src/main/res/drawable/ic_folder.xml new file mode 100644 index 0000000..4e958a6 --- /dev/null +++ b/app/src/main/res/drawable/ic_folder.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu.xml b/app/src/main/res/drawable/ic_menu.xml new file mode 100644 index 0000000..1d81586 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_nav_right.xml b/app/src/main/res/drawable/ic_nav_right.xml new file mode 100644 index 0000000..a3d1622 --- /dev/null +++ b/app/src/main/res/drawable/ic_nav_right.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_notification.png b/app/src/main/res/drawable/ic_notification.png new file mode 100644 index 0000000000000000000000000000000000000000..caaf908e5d17a3e81ed48a87f682da410659fbcb GIT binary patch literal 2819 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 V12sWK0ucZJ002ovPDHLkV1hv&G>ZTL literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/ic_play.xml b/app/src/main/res/drawable/ic_play.xml new file mode 100644 index 0000000..bf9b895 --- /dev/null +++ b/app/src/main/res/drawable/ic_play.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_restore.xml b/app/src/main/res/drawable/ic_restore.xml new file mode 100644 index 0000000..5a3137b --- /dev/null +++ b/app/src/main/res/drawable/ic_restore.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_sad_face.xml b/app/src/main/res/drawable/ic_sad_face.xml new file mode 100644 index 0000000..e0be02e --- /dev/null +++ b/app/src/main/res/drawable/ic_sad_face.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..b1ab121 --- /dev/null +++ b/app/src/main/res/drawable/ic_search.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_select_all.xml b/app/src/main/res/drawable/ic_select_all.xml new file mode 100644 index 0000000..4cdbe19 --- /dev/null +++ b/app/src/main/res/drawable/ic_select_all.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_selected_apps.xml b/app/src/main/res/drawable/ic_selected_apps.xml new file mode 100644 index 0000000..fac8f73 --- /dev/null +++ b/app/src/main/res/drawable/ic_selected_apps.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml new file mode 100644 index 0000000..ace746c --- /dev/null +++ b/app/src/main/res/drawable/ic_settings.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml new file mode 100644 index 0000000..7cebafd --- /dev/null +++ b/app/src/main/res/drawable/ic_share.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_stop.xml b/app/src/main/res/drawable/ic_stop.xml new file mode 100644 index 0000000..c428d72 --- /dev/null +++ b/app/src/main/res/drawable/ic_stop.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_trash.xml b/app/src/main/res/drawable/ic_trash.xml new file mode 100644 index 0000000..689db8c --- /dev/null +++ b/app/src/main/res/drawable/ic_trash.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/left_border.xml b/app/src/main/res/drawable/left_border.xml new file mode 100644 index 0000000..8bb9ccf --- /dev/null +++ b/app/src/main/res/drawable/left_border.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/list_divider.xml b/app/src/main/res/drawable/list_divider.xml new file mode 100644 index 0000000..b9fa9a8 --- /dev/null +++ b/app/src/main/res/drawable/list_divider.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/right_border.xml b/app/src/main/res/drawable/right_border.xml new file mode 100644 index 0000000..86d8d62 --- /dev/null +++ b/app/src/main/res/drawable/right_border.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/splash_screen_drawable.xml b/app/src/main/res/drawable/splash_screen_drawable.xml new file mode 100644 index 0000000..ff5f009 --- /dev/null +++ b/app/src/main/res/drawable/splash_screen_drawable.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/toolbar_shadow.xml b/app/src/main/res/drawable/toolbar_shadow.xml new file mode 100644 index 0000000..8a84c33 --- /dev/null +++ b/app/src/main/res/drawable/toolbar_shadow.xml @@ -0,0 +1,8 @@ + + + + diff --git a/app/src/main/res/drawable/top_border.xml b/app/src/main/res/drawable/top_border.xml new file mode 100644 index 0000000..b84bd22 --- /dev/null +++ b/app/src/main/res/drawable/top_border.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/top_shadow.xml b/app/src/main/res/drawable/top_shadow.xml new file mode 100644 index 0000000..9670ce3 --- /dev/null +++ b/app/src/main/res/drawable/top_shadow.xml @@ -0,0 +1,8 @@ + + + + diff --git a/app/src/main/res/layouts/floating_layouts/layout/floating_folder_layout.xml b/app/src/main/res/layouts/floating_layouts/layout/floating_folder_layout.xml new file mode 100644 index 0000000..fa7e4dc --- /dev/null +++ b/app/src/main/res/layouts/floating_layouts/layout/floating_folder_layout.xml @@ -0,0 +1,38 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/floating_layouts/layout/horizontal_layout.xml b/app/src/main/res/layouts/floating_layouts/layout/horizontal_layout.xml new file mode 100644 index 0000000..9e41380 --- /dev/null +++ b/app/src/main/res/layouts/floating_layouts/layout/horizontal_layout.xml @@ -0,0 +1,36 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/floating_layouts/layout/transparency_layout.xml b/app/src/main/res/layouts/floating_layouts/layout/transparency_layout.xml new file mode 100644 index 0000000..5918af1 --- /dev/null +++ b/app/src/main/res/layouts/floating_layouts/layout/transparency_layout.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/floating_layouts/layout/vertical_layout.xml b/app/src/main/res/layouts/floating_layouts/layout/vertical_layout.xml new file mode 100644 index 0000000..881628b --- /dev/null +++ b/app/src/main/res/layouts/floating_layouts/layout/vertical_layout.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/activity_main.xml b/app/src/main/res/layouts/main_layouts/layout/activity_main.xml new file mode 100644 index 0000000..0df5f33 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/activity_main.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layouts/main_layouts/layout/app_details_layout.xml b/app/src/main/res/layouts/main_layouts/layout/app_details_layout.xml new file mode 100644 index 0000000..1fbedb8 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/app_details_layout.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/create_edit_folder.xml b/app/src/main/res/layouts/main_layouts/layout/create_edit_folder.xml new file mode 100644 index 0000000..a78199f --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/create_edit_folder.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/select_folder_apps_layout.xml b/app/src/main/res/layouts/main_layouts/layout/select_folder_apps_layout.xml new file mode 100644 index 0000000..82589ea --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/select_folder_apps_layout.xml @@ -0,0 +1,18 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/settings_layout.xml b/app/src/main/res/layouts/main_layouts/layout/settings_layout.xml new file mode 100644 index 0000000..3dbde9d --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/settings_layout.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/sign_in_layout.xml b/app/src/main/res/layouts/main_layouts/layout/sign_in_layout.xml new file mode 100644 index 0000000..c3e5532 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/sign_in_layout.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_elevation.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_elevation.xml new file mode 100644 index 0000000..61e091c --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_elevation.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_elevation_dark.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_elevation_dark.xml new file mode 100644 index 0000000..ccf22f8 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_elevation_dark.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_search_elevation.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_search_elevation.xml new file mode 100644 index 0000000..ad27114 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_search_elevation.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_tabbed_elevation.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_tabbed_elevation.xml new file mode 100644 index 0000000..c13b315 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_tabbed_elevation.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/crop_image_layout.xml b/app/src/main/res/layouts/other_layouts/layout/crop_image_layout.xml new file mode 100644 index 0000000..d7e6779 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/crop_image_layout.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml b/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml new file mode 100644 index 0000000..149c696 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/empty_layout.xml b/app/src/main/res/layouts/other_layouts/layout/empty_layout.xml new file mode 100644 index 0000000..635d458 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/empty_layout.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/grid_list.xml b/app/src/main/res/layouts/other_layouts/layout/grid_list.xml new file mode 100644 index 0000000..c07b4b6 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/grid_list.xml @@ -0,0 +1,20 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/icon_chooser_layout.xml b/app/src/main/res/layouts/other_layouts/layout/icon_chooser_layout.xml new file mode 100644 index 0000000..732d396 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/icon_chooser_layout.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/message_dialog.xml b/app/src/main/res/layouts/other_layouts/layout/message_dialog.xml new file mode 100644 index 0000000..7f616cf --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/message_dialog.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/progress_layout.xml b/app/src/main/res/layouts/other_layouts/layout/progress_layout.xml new file mode 100644 index 0000000..b4b9728 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/progress_layout.xml @@ -0,0 +1,18 @@ + + diff --git a/app/src/main/res/layouts/other_layouts/layout/small_grid_list.xml b/app/src/main/res/layouts/other_layouts/layout/small_grid_list.xml new file mode 100644 index 0000000..3be1fec --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/small_grid_list.xml @@ -0,0 +1,19 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/app_details_header.xml b/app/src/main/res/layouts/row_layouts/layout/app_details_header.xml new file mode 100644 index 0000000..ab03996 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/app_details_header.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layouts/row_layouts/layout/app_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/app_row_item.xml new file mode 100644 index 0000000..7274d1e --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/app_row_item.xml @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/floating_apps_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/floating_apps_row_item.xml new file mode 100644 index 0000000..1d692f0 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/floating_apps_row_item.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/folder_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/folder_row_item.xml new file mode 100644 index 0000000..765adee --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/folder_row_item.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/icon_pack_layout.xml b/app/src/main/res/layouts/row_layouts/layout/icon_pack_layout.xml new file mode 100644 index 0000000..bbffafa --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/icon_pack_layout.xml @@ -0,0 +1,41 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/permission_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/permission_row_item.xml new file mode 100644 index 0000000..1981387 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/permission_row_item.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/select_apps_folder_row.xml b/app/src/main/res/layouts/row_layouts/layout/select_apps_folder_row.xml new file mode 100644 index 0000000..66c9515 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/select_apps_folder_row.xml @@ -0,0 +1,47 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/add_menu.xml b/app/src/main/res/menu/add_menu.xml new file mode 100644 index 0000000..a819672 --- /dev/null +++ b/app/src/main/res/menu/add_menu.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml new file mode 100644 index 0000000..a5a6cbb --- /dev/null +++ b/app/src/main/res/menu/bottom_nav_menu.xml @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/drawer_menu.xml b/app/src/main/res/menu/drawer_menu.xml new file mode 100644 index 0000000..52323e2 --- /dev/null +++ b/app/src/main/res/menu/drawer_menu.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/remove_menu.xml b/app/src/main/res/menu/remove_menu.xml new file mode 100644 index 0000000..42b488a --- /dev/null +++ b/app/src/main/res/menu/remove_menu.xml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..0e9115e276e60a6bba04614a5f502c1312370a36 GIT binary patch literal 5125 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ca5dc0b04b1f66ad5430d7d1a45c7643c59803db GIT binary patch literal 3191 zcmV--42biIP)1V&SAD> zgo$E(IB_}KuxHd5Dr?&4YRy=4hQVt7Q9??JbT?R9PCy6vi0OO#@IV{^hKN*p zfPi!Y&<;Sb0;(QBB?Z0C6Ye|(azr32^V@`r9?<5yB+?=Rrn#q#w#|cFY*8jlM z0wD|#`?TcJzDtqKgIkobD|soOB3K;&Gn% zX?r$MU_QW9?4GoRQdJFaAKeC%#&kw>R50=j?8wNv-q>_rVM(HMQ)c>8^WDPpVe`DG zA>fVxqlHn^(iZ|`jUstA{;t6X2l4oL*<b_fX%Yg;2A3^yo-N($ic}fM*>2!?9+5b#-!#v?5;BWWS(@#)}p^C%GPBrV9KKPTR zSHJ{j%t^=fvKlOzKMd0+cWd&!ykE+(@GUENL#TF~J7^dr!ErKkk7bw~0sXLg33yFs z>h5_U+^34^u;=oa?p?yrAzGVh)i&t+Wy>#vAW&@EI2oNghBZt4^>;II{8R}HMhyuT zt|_G=Cpao!J#pa0_5P;hUQuCWN=$DX$|DazAGhPG<9v@U1ksTpJ}`3V*1A)1X*I51 ztHj75ow4Gr5zT^U1CC`EBl-Q~@>neihK1t=q3+VfOSz_s3oENUm}LYWMkA+u`vT#N zUn&vtPY}%TSWv>m#`1q~?5vX^HnD*y%RM*I*mJSIbQ7Ujw z$F12p2WJ1vgPFOxH*Aia`rQFS_zC{D@4tFW2yEGQ2D`RSMP!7Uu%li?R?c;d9o0oc zEP45H9Lp&NQ8ddN{2X8L1y_CL;S>9xpP*C&gm@Cfuqmm%j9kcR0O3ke)+!Ag`td5Z zu76wuGUs$D(!Vdld&$E!&$jP8k4;<8sLYZ#cuiI!gyTffQDwJZ9(wlJYXuBD@r0$g z#MGB~zU>xwjiX;Cv_u2HUcQ5rBo;K(*XA$JApKwwc5O`rr}7~n=X4pCzH>}@!RKE- z63m$e;;1QGko&{DjSRb2196FIpYeQ~IRNCiuV=Uo30%Eag*R7ZY8?4?r2|tZ_QISO z`e~+FyzD4)^UAPo!{g}InJL?Mm6X-u>ACxK<)@HfQV6BuY--77Sr*U6R=@E|#N z=@#ZLKBQW7$ETCgxl{8cL_;=9-_1gftyB-ZLV)8X(P6()a$-bb-aiXu0uPNy=^7P1 z;ABfpNJGF+VyRma(D7cK;;b2+yz$-%WSuJUGfP#uB5ObpYRig$I~w=fna#ht3$^|; zBV)TH=JI?H^QwSNNJU`D4}Q=H(zYZZ=3f00x+xCH%d?T0>)z-PRXUQP$^@Lw%3sg@ z^2N}q>(&Ynz2LZnuMhLawsEZ|;GVLz1a!bF1i(8Tx3W(j`pXyqbwnwOFnsd1&kR8k zGh0I7%C#!I@m?mJE>Q`6K6R&ko`9GRY7Ja1uEP4y^JRjA2iylsqBe{&4P@o|OsGLo zASbfA>f-ITjD<7J<_vgB31QIK4GY?acUiA&+}#>%a5c=tERoGxcu*Oo9Gw0<+PiC z5fC+eR~#Q43`lbJd$3O=632JNPiM6brk8YHp4kr( z;Xx`Jmwg~9L(Z@X`SG=wkcg*ny+htql$D zI)&qna5<~Ig-m5Ai3tG`)x zdhLbNt2O{AZ3?_53hA1G9A49Tz}BHl@2BEpx=mOT+_r;>N(?{o5MjM7cUck`c)3@_ z!VKXIJf)OKk`wi{<+ifl4z0d+X_pl+l>;^=^(H%?&1k?wi4v1(v%zMY$M%RZ_YY2b zHZr>J(;OGnhxvxPNhzm2R_?m0^0>_6SPdG26g{?`3K4U3)jhH+lkD*SE+r~&_JC^4I@ywy6|sQjHEqJ8Y} z-cjxQ4-5(G^pGK_T{nZFO?$!xg%ZNCF|3vBqEx7ng!*!)>(14>%IjzC6{k;E6dx}H zz|K%A&E^c3)jFD)OpDt6cR@fQ;Xy%Raw>K@tDV&~B~@_U zVJB7&wiWbz%;pUG|NXOvMyD+C&EQ}f$C&`wZ1dO%7Pr9=6~v);F;y#@{Rxi002ovPDHLkV1lc)8{Gf^ literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ea4da7f0559bd0b9bc0bd321d02e7f30511ec583 GIT binary patch literal 7179 zcmV+m9Q5OfP)aG`}g0jCW3KBut^+HzEUBMGn zgowx?3M>$iOCa08*@)*;Tw%U=JY7eHJ#;kLV5I{*vN*b3F(}n9&l4JJ3hxS_2S>?`Afy`wZ4aO&fM@^_Akc$CmJ$%yL16(<0l*C45&^jYN>AAd zJqF?qPbWwn3q$mRp1%@GOL!A(ULPQQIW^Da&^ip<*#3%RZG8QH>Ne#pk@Y}i2 z5|En8v6U(_vUl9OD&EEk|D*&H9KhSHikfk_j@RyG2W0i6BZOmcFXQdflufJ06f#>T zue3wBpbHrRa_5v4>yYt3k0N&aCji<}Dlb0StamJ$em|GeXW2enpd9z~wiP4SsYW{3 z)w%odLqdS7zE2wa(+o;5$7R+lhVJ)+yh~3N2Z7VcpV{fmZL5=+I;E~-Zpg?QOn}-E zCIOeEh|d8$;sU;-m&S}5Zp9Hn%9e!-dhPyP0MnTkQ6jj82>CO~CBY3#~qO7uSi7(l6=>CLO@ zRtAfM)_RKDN(4~b?vg7PM;+PzOi4o|At(Zz;HPYfq*C<;fDWY8riiK5vHYIPF_pyW z>~?8)LE-tkm?Q*CLcj#5-j1U4*8;fv{}%Y_#BtaKo2_QUjx`^S2GS*0Pf+Xh3XFi% zR8IAQhmQN{D~G|ocGb>xotxplQJv8Jx@bh3^q_W%VzUK@GmG)<%G0=9ENaEcQ#qD# zvjKL&CRKm4W9@{Aa?HsEBQ1>wM1achka25YB_MAo2Dd5VH(JKxEYrVl9A0?3C*oU# zd97DmT7z#_oWR=u6rjcuRKkt5EvG#xwQ<&(iqze|JoI{?QlOat)!HYGTXi>u@Us$D zV4lG>+;hmn|$tB-o{@3q>V`1G08Jm#5VzYaoCsWeA3jUHc6P`J)!2yXwo~Fc@5NA%S7y zwe*qWmofF#&CnT4b;^t#*%4D7PYC)hJND$^mAN~?@!>(XL9C#5oz+^Nwrkx(6KZov zzJqsu2~e3FGUmq#gwuVe#CDiJ?6dCLC3hksJoMq8LzzXG{PHFlB%QvQ{JUifBfj}~ z7zEz$aD0Nh;M0RxzWO8tU1TsMP(nCjlSEj>l1F~q`1lenQsA@4szK>La$Pf{!Ja{Z zZjR)M|G-*P5TKH<;LU;P**zv0(CXBwtdj89^Xrj+sS1KFBAE7MRU}!;bIza3x+OO= zwb-9g)ZW{W5%lvozLUSZ#Kc=*Vj7s6#ZozGIrJbga}gtnflFLo(}PG`o$dTAa7iE%wM#-xbguF9O_BW;mjhW@4Vn_Ye@fgm^))o@NIjknVD6L zr~k)c=+!Gg5?Dr!m#pQ*#YJZZp4jusNg!1KQtRzI@<@Q9e(Xc;UG*yAg*nQKH{b== zr}GA*YsaXN0kmRmHs1dvLurp-=8FSx*RYNuYhP`Mtu-c2-hlJDWkHib2xqt1YB;g7 zaPGcMlV*6c1@#F~Vi~>ed?zA0yvH5@H){2K+>vNJ0toavPBy;LCPT;xU=1$#>=2f( zI_YeiC^m=}G_Mn6Z_!#)nsxm6iUFl(e=PMBC#pw)s{02ge?Nv3!d7ba`#qu1I0QI6 zl->z(_~;*OGo7|;_4*v#KBzq+Bebn{x9`cv^f$K4jjQ0RchW`zrG)TAvR0w8?7~9_ zx4pR3lPz!~z`5!rgU7D=ihzF@EZRwwUC7$T>MYfm1UxjpJ0?BaTXT;lzq}a}#@v7* z1KVnfG8=mjFfm^uJ?Kys=rU z3`$AcV2rOi!p0=vjhAmj(rxWDfypAD;~!gt2HX<%RzsJEy)Er+^4v z@auiaE~!N<$uBs&Yv7sVADvTzmrhpe5THcyq+64h-KP^Gzi){8VV!JD0+uhj2W?tu zTdi*1egU)I-i=NjnqkR@cWEZz?;q^L&zsJAC|?VkZxU+NP(}H(@y9L_o$< z@}@Oe7F=6bydOF!dF29**FDpa+25E1#Ksu$<5%};j<(KUcmONbo|1L>vPC1&x}`Sa zmaWRhN1q>ZBcQ(D;+q6wqg3LnEAl_zw`tN7DJje4jcfG@aAtCngdt;I*agD(yA}zU z|H*#z?%5I_{(YF{nf&CmO*o!iESFFH>j2y_L|e#ucSZqTn(Z*e9_DME`}-h4jvk0r zmk;jQ@Yp~AEDgt8dRYxQ=~TU+e#1V#KEl*t7X@X}t$;!g?ucknK`bkE{N$DTV0s8W zT+FXPc1{UK4ex^KQ*O~j01GW7Ph1U)lJ$CE+zpugST9X=bMq?j;G|#tg0D8_g#_6S zSZmCsMR^B?WgmR!5Rl5Ni?VtI3>^9G7`@S?x}OcocxfTv)i<|e>+W2?V(u#Vk3W2q z=J?Oi<5w{0Z=0R%|DkUyy!ZNGO$1maJ4Qda8e)z1l%)p}?1XR}b4SZcPCa~N$MkPq z-BIVbRQ-S3JD>U)hjW~Cq?uyuFWkSI7M%N-NPe9qKxU%f*8wb)~oaJf&{Yld)y;ql#^n*8`3b*KVcI4<55}4I#Qao1Oq|;Ir<2@xfi_ z)|ovl>HnHLe=mOCT-TNSYQbIT($SGk^LNdew-+0?p7&SGW5~Uh1R}BRE7g^S>3cUm zF$zGnin%KRG(P^$@EZm^vmJ!*6N)Y6+9lv(y#e~l7yR($y_!SNFVES59ebS*M9TO1 z=bK5m`KCDkpt6|Ir-zZYrZzO~v69DphhqdBFUP9nxR6*?bac;#*@J8w1Y(4efkHUf6kGs3>W*Xelt{M|Sh^xC>MWyV(QKU`OZy#3lB z4D8oh69Hd-cO0KDWse$rxqN`H*5G)(jS!x%slIY9>u}nTlDst+)aYm(0&W_V+BvpG z;!X-M1=}DOl-)cS0(@r52!W}Y0c*b=qX|4#==51LDk_}|Pq`jj5t}sHfbZ9w220Qc zI`iGi+jt?2g(NOrJilq!`OGhldm@1L95UyI*x0^15P~&8Fa-DmpS9UKJ`&3pF*VvW z*SbyT@Q)8_y(s5hHOzdM9?B9RN!6u!x#@SDJG}6q>Iu0@0PWd-R?pbh{n*lvWl@?$ z0{*k@JkGf!KGttJhx`I|;(*KLGT6=?OjsO1Jg1>FZQh=X)OUXK+8^}`;&Yb{aRlXR z%;kj_c8)lEY~fx{1fXaCSqV)|fIC1_W~5{PA@(4UrNey`NRNM3BZlF%8;HVCM{GPs%q1P49^A)L)_m-q_vnPrE5{oCV6NvTHKa{0(K_k4i9|A^0~86x6m z*Jkj2Z$tMbAq|rN&&#r_ML=-i%i4u)Pk~JmiMcrIt<2r2vy+mxSk#kb+zAl+CcQH@ zD!Ru~$wpDc#C+~sIDH--ZtfIa*5!%y-VOm(gsx<=#XUfP0j z%mzI7$~GVK%;)-@)l(8Ol_<*J^~9-zAARk}hB>w=x)Z>4y=l@-?YfR!PeGbDbTzC+ z0$!cF6Wi)!#C#7Z5CRyH$q%oo2j2M6-7w`zZF`D*6W|woS^qn>rW6;S&;DU-{+XYC z1K9DIZUiWXnC<B z%uIFa*t!IyEZ1kI-LLO?>)dg%Eqg6i?110r!MrI*?JB5#LdIL0SDygw;L8S>6NuGP zj^g~C&z?N^udk4hYJoQblm(fgdFvsadfYN~J;&+T2AZIwqFM-;F?T1n?$%DgEqz*H z9!n}|xI%9O0s&v1{<8kBuE@*FKJ;0#`EmwJPP0dEJa0{u$CQwuM`mX9fV;kWUmq6x zASi9r&AEXPz;?Fv>m9F|fUoZauGSG;Mf;xttrE$-0jcg z99_6HAtANORsYvB!g6KD4hbV*iob32!qvPkyl1d+p->Uvx<9|c1Q3Gpqq+v@h6X@D zZ4}qx{gj>0%1EC%1}JCGRG6mS}i04MnJ?5C2ok}D}X@WF|_@4nftT}pXwZd$dw5P2j(QA1(PTMh2s-U|iCM65tL#>wM4zxa1cag@C&G3)%RJmHC&l4}G3eTD12dkXQ|5)ZHE6nV3W6oT8~8E-ec~}s z?1`)ubn)i+Fs+oWz$BXgo zbT7fUdf-!VM6gNL3cjc?<6qes^XA6IC6pEwWmbBc{hqxb*U6HYs6$3Z6!fvJ2i!jY zd%ZEHdm!tAVYjx1)#CeDu%joh;PMrRZSn`cLjr;)Kn*E}gaFS8dU=9Yn9pY)*qJ&3 z)>8IN7<)HCJ>9QG0%T0$;*uhYiqcKjCr%mDvd!R+*#7rG9^96!jC}u>7VsNFfNMOz z!320d`@&8L&((;%YXzk;C=S{mjDND0!*eTn9Z?$ljgq_*{sueju&i{ zYB$LKNYDy?umrd#QyN5omxD)G(9I@^eCd_UwVAu;Ooho*46~WdexI*J(XzfK?b;1A z=H~7)>B8H$PaHCPsovPUD=3jbyq_Di=-okR9bfxYIeWCo&lykt#e^lTBXsE2x$bFM z-YPO9oILTTdS3@kfVWd$WGtvqVLp5I$e#Bel&UYD0os%Sc}%zZJnmi#0c-#q&?O4U zF?C9KY*?F)BR&=M%>-XwQDYt0q=_Y^P)G^zz9~!b`3t4I^Xn()o?P(@(8Ubou>F;O zpKa1g02`7nGO}BAMa3yo!XI9JB08?uOM*Vqt3CLyBEW+i>QHM`*83K*6jus=`)BsS zk3Woz>}Ia0IK`gs_G)-tCs7~-5TKI*C^7++F}(-RofT=i?g2p;Zl{#(FRD95K7DTx zDk{C_b_1Eo!K$u`Dl1-jbC=t#2!;-9gYoyU*Od9ca?X`w{-V0i3M=5t;RdUvoHJiO zy5iX0f6M?PN`OlC@C6GwYkJd0AOt9?2u!gvB^=Xt=)3bGnspw*3kDmdcFvsyPsTS8 zgXy@hopR-HWYQC)a_?Dx)XHNydb`~)3*@{>5D-#1HfOUumVj_VO z2MNRGe;g6n{#Gp{{C9yb^5y32-;V5Vhfrx^I`tx%VNw&lP@Hv8RQI_Fo?f{_4q z{U88sOh6tZA-eaFx8913>NG+z%u2|jwt1W6@%@^CyQWt~?Z`uRJn?QRM_Fms=FDAl zUII`Iv?&Mj82HTJ*QECwDgmyNpaWW&fC5HBWY1e)eLN>V;r@S} zKK#jNj<>c(l>y~yoF^#oLqULxIzl9jMiWFaqFuN92F7<7Hr*KBs*9ituO|&Qsa|5p z_atcYnNL9|C(n9z#zR#_UQXe~^tba*uh|Zxu@a)lW<4{wL8+ZksUY`u1RyrdXf(u# zVt%*~7T3IcpUKlAOa^~)L`&KB>}EBfq6ehpm{WKg{>FDI`x=%du)8-)5h@l8w7n6 z^M=@(fvHT6?HKks^_vWQc9xs0ZkXEPt(G!WR~2NH6z*Mg?!@wq4#1mN0aw@xS52%3 zt#%qi0$kf`MHUaG1rYZ7-L)Ux(G%D)2()!R9(kLI2&qo z@Z~!>_UIFi^_keLRj8@HQeZAQvGUZxg^K}enbBwxMbTCcR4{$dmiC$#Sz3&1fR<28 zlX4l>F5Bp91Y%7nh7mu``xy zjK)?qqFBIYJj*6A7gN@mnx|g?1sjt9SKGh_&A<;gnmR;@=JSjcc3_XO-F5d5Y}UMc zQdoG)n|Z<5kr#~MIK3BC8h3L%pI$4xt?cG@oa{vsEJts0F;T4FG$uQ!3Clw3cURF+iAo2sav| z!bLHkk)YS^cWCuYP8Ow13&(4iyYML2Irlni}u5)kY z9hNdt3~+YltlcizZMLc_QccDAn(E8PDoW2D$j{w;fY{6>R;!h%6^qf>+9HbORX_y; zp6Pi8d`NY@H;|e_0^IMd62YXv0ECCZXg5F<85ugAPRCoVR(({9p7BwpZk@x!TX)hM zO>H?{cuQUgi{Uw46ybD6j&M4sm{7aTPN|hrt7x}b%k4I?SduD>EMnP3u_FJh*?js; z`Q<}}I-Sm9wOSdtRv3*Ih+GX&#av1@+nK6qGT>d+gVq@w>T-(Fm5sGR23tqy^rBeE zNMfI}A5N#!aaOC9Ne>Sp%3v_GFzWRY23{{X^tnZ{SuB+`H8q#3A;}Mz*>pOc&FXmF z68m8@T{0Tu?V@P40L8ALv+o*B$NK~AYDj=5M?fWm0jdBWX#fm5qfsx2DB&QA4*lc! zQTy%Mf7Nn3KsOrgM#R`f(INpgR-l5-a+wI1neMdq{(x$%@2>>{d=a9mD;0P~5C=qh zdSfdEDpVDs{$^yj{`;x}-jr@=s3wj3Z1*(#*}YU($lLEw^(Un5{4X})_7yy!zIOls N002ovPDHLkV1khD1Oos7 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ca1e73f696ae2ee9d3543cf3892be248bbd1bccd GIT binary patch literal 11010 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..6e82da14bf4c449311b551744414e82f6013ee07 GIT binary patch literal 15595 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 ud3h=r4@om?4Zww%1azC@$`EK3 + 46dp + 5 + 140dp + + diff --git a/app/src/main/res/values-sw600dp-land/dimens.xml b/app/src/main/res/values-sw600dp-land/dimens.xml new file mode 100644 index 0000000..5e6d98e --- /dev/null +++ b/app/src/main/res/values-sw600dp-land/dimens.xml @@ -0,0 +1,7 @@ + + + 52dp + 6 + 24dp + 2 + \ No newline at end of file diff --git a/app/src/main/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml new file mode 100644 index 0000000..e1a3b2b --- /dev/null +++ b/app/src/main/res/values-sw600dp/dimens.xml @@ -0,0 +1,7 @@ + + + 32dp + 5 + 24dp + 1 + \ No newline at end of file diff --git a/app/src/main/res/values-sw720dp-land/dimens.xml b/app/src/main/res/values-sw720dp-land/dimens.xml new file mode 100644 index 0000000..251c3b2 --- /dev/null +++ b/app/src/main/res/values-sw720dp-land/dimens.xml @@ -0,0 +1,7 @@ + + + 82dp + 6 + 24dp + 2 + \ No newline at end of file diff --git a/app/src/main/res/values-sw720dp/dimens.xml b/app/src/main/res/values-sw720dp/dimens.xml new file mode 100644 index 0000000..3c35b7c --- /dev/null +++ b/app/src/main/res/values-sw720dp/dimens.xml @@ -0,0 +1,11 @@ + + + 58dp + 5 + 24dp + 1 + 320dp + 56dp + 72dp + 96dp + \ No newline at end of file diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml new file mode 100644 index 0000000..862bf83 --- /dev/null +++ b/app/src/main/res/values-v21/styles.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-w820dp-land/dimens.xml b/app/src/main/res/values-w820dp-land/dimens.xml new file mode 100755 index 0000000..29515b7 --- /dev/null +++ b/app/src/main/res/values-w820dp-land/dimens.xml @@ -0,0 +1,6 @@ + + 84dp + 7 + 24dp + 3 + diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml new file mode 100755 index 0000000..9c8d2bf --- /dev/null +++ b/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ + + 64dp + 6 + 24dp + 2 + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml new file mode 100644 index 0000000..dc5345b --- /dev/null +++ b/app/src/main/res/values/arrays.xml @@ -0,0 +1,43 @@ + + + + + Apps + Folders + + + + Small + Medium + Large + + + + #FF2A456B + #213755 + #ff3f51b5 + #ff9e9e9e + #ff424242 + #ff1c1c1c + #ff000000 + #ff607d8b + #ff37474f + #ff795548 + #ffd32f2f + #ffe91e63 + #ff9c27b0 + #ff5e35b1 + #ff1976d2 + #ff03a9f4 + #ff00bcd4 + #ff009688 + #ff43a047 + #ff7cb342 + #ffc0ca33 + #fffbc02d + #ffffb300 + #fffb8c00 + #fff4511e + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..b76d2cb --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..2ee1c62 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,19 @@ + + + #FF2A456B + #213755 + #C5CAE9 + #448AFF + #212121 + #727272 + @color/white + #B6B6B6 + #00000000 + #ff000000 + #ffffff + #80000000 + #ffF5F5F5 + #ECEFF1 + #CFD8DC + #111C2C + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..bd51310 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,21 @@ + + 16dp + 4dp + 8dp + 16dp + 24dp + 32dp + 48dp + 64dp + 56dp + 72dp + 16dp + 60dp + 4 + 1 + 64dp + 280dp + 48dp + 56dp + 72dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..1b2f723 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,136 @@ + + Fast Access + com.fastaccess.ui.widgets.recyclerview.layout_manager.LinearManager + com.fastaccess.ui.widgets.recyclerview.layout_manager.GridManager + com.fastaccess.ui.widgets.recyclerview.layout_manager.StaggeredManager + @string/appbar_scrolling_view_behavior + Skip + In Progress, Please Wait… + Close + Action + Settings + Are you sure? + Cancel + Reload + No Data. + Search + No Applications + Permission is needed so Fast Access can function at its best. Please allow the permission manually from the settings screen. + Open Settings Screen. + Terminate App + This permission is needed to save your backups into the SDCARD + We need this permission to be able to store your backups into your sdcard. + Write To SDCARD Permission + This permission is needed to be able to restore your backups. + We need this permission to be able to restore your backups from your sdcard. + Read From SDCARD Permission + Clear + Select All + Clear All + Uninstall + Share + Menu + General Settings + Application Version + Open Source Libraries + Check FA source code + Backup apps with their data. + Cancelling, please wait… + Your fav apps are always a click away. + Get Theme Packs + No Theme Packs Found. + Choose Theme Pack + Default + Icon Pack is not supported + My Apps + Device Apps + Selected + Edit + Add Apps + No folders yet, click on + button to start adding folders + Save + Folder Name + Required + Add + Apps + Delete + Click here to change color + Select Apps + Add All + Done + Remove All + Click to open FA + Click here to start FA service + Choose Background + About + Background color of FA apps list. + FA Apps Background + FA Floating Mode + Select FA floating mode. + Auto Save Last Position + Auto save last position of FA floating icon. + Sticky FA Floating Icon + Keep FA floating icon attached to screen edges. + Keep FA floating apps always showing. + FA Floating App Visibility + Make the status bar icon transparent + Status Bar Icon + Make FA floating icon semi-transparent when is not touched. + Semi-Transparent FA Floating Icon + Change the transparency value of FA Floating icon. + FA Floating Icon Transparency + Adjust FA apps background transparency + FA App Background Transparency + Choose icons theme pack. + Icons Theme Pack + Choose custom icon to use as FA floating icon + Custom FA Icon + FA Apps Customization + FA Icon Customization + Predefined FA Floating Icon Size + Choose from predefined icon sizes. + Choose Icon Size + Custom FA Floating Icon Size + Manually choose the size that fits you. + Choose Icon Gap + Choose from predefined icon gaps. + FA Floating Icons Gap + Auto Start FA + Auto start FA when device is rebooted. + FA Orientation Mode + Choose FA orientation mode to display horizontally. + Requires FA service to be restarted.\nLongPress FA icon to restart from notification bar. + Change Transparency + Value + Change Icon Size + Folders + Start Service + Stop Service + Please enable FA as floating window to be able to use FA. + Back + App Permissions Details + From Icon Pack + From Gallery + Icon Pack does not support sending icons to other apps, please use different icon pack. + Choose Icon + Crop Image. + No Apps Selected, Select ones from Device Apps Tab. + FA Folder Mode Not Available\ + FA Folder Mode + FA App Mode + Across Devices Backup & Restore + Backup + Restore + + Sign-In with Google+ + Failed Sign-In + + You must Sign-In first + Backup in progress, Please wai… + Successfully Restored, App restart is required + Restore in progress, Please wait… + No data to restore, please backup first. + Ok + This will overwrite any existing backup you have made so far.\nAre you sure? + Restoring will overwrite all your settings and data within the app.\nAre you sure? + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..44842cd --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/fa_settings.xml b/app/src/main/res/xml/fa_settings.xml new file mode 100644 index 0000000..95b5b0c --- /dev/null +++ b/app/src/main/res/xml/fa_settings.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/fa_shortcuts.xml b/app/src/main/res/xml/fa_shortcuts.xml new file mode 100644 index 0000000..fac95ca --- /dev/null +++ b/app/src/main/res/xml/fa_shortcuts.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..15ea4dd --- /dev/null +++ b/build.gradle @@ -0,0 +1,24 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.2.2' + classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' + classpath 'com.google.gms:google-services:3.0.0' + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/color-picker/.gitignore b/color-picker/.gitignore new file mode 100755 index 0000000..796b96d --- /dev/null +++ b/color-picker/.gitignore @@ -0,0 +1 @@ +/build diff --git a/color-picker/build.gradle b/color-picker/build.gradle new file mode 100755 index 0000000..0c87afb --- /dev/null +++ b/color-picker/build.gradle @@ -0,0 +1,28 @@ +apply plugin: 'com.android.library' + + +android { + compileSdkVersion 25 + buildToolsVersion "24.0.2" + + defaultConfig { + minSdkVersion 18 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + ext { supportVerion = "25.0.0" } + compile "com.android.support:appcompat-v7:${supportVerion}" + compile "com.android.support:design:${supportVerion}" + compile "com.android.support:preference-v14:${supportVerion}" +} \ No newline at end of file diff --git a/color-picker/proguard-rules.pro b/color-picker/proguard-rules.pro new file mode 100755 index 0000000..7928f2a --- /dev/null +++ b/color-picker/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /home/ty/Android/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 *; +#} diff --git a/color-picker/src/main/AndroidManifest.xml b/color-picker/src/main/AndroidManifest.xml new file mode 100755 index 0000000..ddfefa3 --- /dev/null +++ b/color-picker/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/color-picker/src/main/java/org/xdty/preference/AppCompatColorPreference.java b/color-picker/src/main/java/org/xdty/preference/AppCompatColorPreference.java new file mode 100755 index 0000000..4dce613 --- /dev/null +++ b/color-picker/src/main/java/org/xdty/preference/AppCompatColorPreference.java @@ -0,0 +1,283 @@ +package org.xdty.preference; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.OvalShape; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.preference.PreferenceManager; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceViewHolder; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.xdty.preference.colorpicker.ColorPickerDialog; +import org.xdty.preference.colorpicker.R; + +/** + * A preference showing a {@link ColorPickerDialog} to allow the user to select a color to save as {@link Preference}. + */ +@SuppressWarnings("JavaDoc") public class AppCompatColorPreference extends Preference implements SharedPreferences.OnSharedPreferenceChangeListener { + + private static final int DEFAULT_VALUE = Color.BLACK; + + private int mTitle = R.string.color_picker_default_title; + private int mCurrentValue; + private int[] mColors; + private int mColumns; + private boolean mMaterial; + private View mColorView; + + public AppCompatColorPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable + .ColorPreference, 0, 0); + try { + int id = a.getResourceId(R.styleable.ColorPreference_colorDialogColors, R.array.default_rainbow); + if (id != 0) { + mColors = getContext().getResources().getIntArray(id); + } + id = a.getResourceId(R.styleable.ColorPreference_colorDialogTitle, 0); + if (id != 0) { + mTitle = a.getResourceId(R.styleable.ColorPreference_colorDialogTitle, R.string.color_picker_default_title); + } + mColumns = a.getInt(R.styleable.ColorPreference_colorDialogColumns, 5); + mMaterial = a.getBoolean(R.styleable.ColorPreference_colorDialogMaterial, true); + } finally { + a.recycle(); + } + } + + @Override protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getInteger(index, DEFAULT_VALUE); + } + + @Override public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + View view = holder.itemView; + mColorView = new View(getContext()); + mColorView.setId("ID".hashCode()); + int size = (int) dpToPx(32); + mColorView.setLayoutParams(new ViewGroup.LayoutParams(size, size)); + ViewGroup frame = (ViewGroup) view.findViewById(android.R.id.widget_frame); + frame.setVisibility(View.VISIBLE); + addView(frame, mColorView); + if (mMaterial) { + TextView textTitle = (TextView) view.findViewById(android.R.id.title); + TextView textSummary = (TextView) view.findViewById(android.R.id.summary); + textTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); + textSummary.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); + textTitle.setTextColor(getColor(android.R.attr.textColor)); + textSummary.setTextColor(getColor(android.R.attr.textColorSecondary)); + View parent = (View) textSummary.getParent().getParent(); + parent.setPadding((int) dpToPx(16), 0, (int) dpToPx(16), 0); + } + } + + @Override protected void onClick() { + int[] colors = mColors.length != 0 ? mColors : new int[]{ + Color.BLACK, Color.WHITE, Color + .RED, Color.GREEN, Color.BLUE + }; + ColorPickerDialog colorPickerDialog = ColorPickerDialog.newInstance(mTitle, + colors, mCurrentValue, mColumns, + ColorPickerDialog.SIZE_SMALL, getKey()); + AppCompatActivity appCompatActivity = getActivity(getContext()); + if (appCompatActivity != null) colorPickerDialog.show(appCompatActivity.getSupportFragmentManager(), "ColorPickerDialog"); + } + + @Override public void onDetached() { + super.onDetached(); + PreferenceManager.getDefaultSharedPreferences(getContext()).unregisterOnSharedPreferenceChangeListener(this); + } + + @Override public void onAttached() { + super.onAttached(); + PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this); + } + + @Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { + if (restorePersistedValue) { + // Restore existing state + mCurrentValue = this.getPersistedInt(DEFAULT_VALUE); + } else { + // Set default state from the XML attribute + mCurrentValue = (Integer) defaultValue; + persistInt(mCurrentValue); + } + } + + @Override protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + // Check whether this Preference is persistent (continually saved) + if (isPersistent()) { + // No need to save instance state since it's persistent, + // use superclass state + return superState; + } + + // Create instance of custom BaseSavedState + final SavedState myState = new SavedState(superState); + // Set the state's value with the class member that holds current + // setting value + myState.current = mCurrentValue; + myState.colors = mColors; + myState.columns = mColumns; + return myState; + } + + @Override protected void onRestoreInstanceState(Parcelable state) { + // Check whether we saved the state in onSaveInstanceState + if (state == null || !state.getClass().equals(SavedState.class)) { + // Didn't save the state, so call superclass + super.onRestoreInstanceState(state); + return; + } + + // Cast state to custom BaseSavedState and pass to superclass + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + + // Update own values + mCurrentValue = myState.current; + mColors = myState.colors; + mColumns = myState.columns; + + // Update shown color + updateShownColor(); + + // Set this Preference's widget to reflect the restored state + //mNumberPicker.setValue(myState.value); + } + + /** + * hacky way to receive the changed color when activity is rotated. + * + * @param sharedPreferences + * @param key + */ + @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Log.e(key, key); + if (getKey().equalsIgnoreCase(key)) { + mCurrentValue = sharedPreferences.getInt(key, mCurrentValue); + persistInt(mCurrentValue); + updateShownColor(); + } + } + + private void updateShownColor() { + if (mColorView == null) { + try { + notifyChanged(); + } catch (Exception ignored) {}//hack, avoid calling notify when recyclerview is manipulating views. + return; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mColorView.setBackground(new ShapeDrawable(new OvalShape())); + ((ShapeDrawable) mColorView.getBackground()).getPaint().setColor(mCurrentValue); + } else { + mColorView.setBackground(new ColorCircleDrawable(mCurrentValue)); + } + mColorView.invalidate(); + } + + /** + * Convert a dp size to pixel. Useful for specifying view sizes in code. + * + * @param dp + * The size in density-independent pixels. + * @return {@code px} - The size in generic pixels (density-dependent). + */ + private float dpToPx(float dp) { + return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, + getContext().getResources().getDisplayMetrics()); + } + + private int getColor(int attrId) { + TypedValue typedValue = new TypedValue(); + Resources.Theme theme = getContext().getTheme(); + theme.resolveAttribute(attrId, typedValue, true); + TypedArray arr = getContext().obtainStyledAttributes(typedValue.data, new int[]{attrId}); + int color = arr.getColor(0, -1); + arr.recycle(); + return color; + } + + @Nullable public static AppCompatActivity getActivity(@Nullable Context cont) { + if (cont == null) return null; + else if (cont instanceof AppCompatActivity) return (AppCompatActivity) cont; + else if (cont instanceof ContextWrapper) return getActivity(((ContextWrapper) cont).getBaseContext()); + return null; + } + + private static class SavedState extends BaseSavedState { + // Standard creator object using an instance of this class + public static final Creator CREATOR = + new Creator() { + + public AppCompatColorPreference.SavedState createFromParcel(Parcel in) { + return new AppCompatColorPreference.SavedState(in); + } + + public AppCompatColorPreference.SavedState[] newArray(int size) { + return new AppCompatColorPreference.SavedState[size]; + } + }; + // Member that holds the preference's values + int current; + int[] colors; + int columns; + + public SavedState(Parcelable superState) { + super(superState); + } + + public SavedState(Parcel source) { + super(source); + // Get the current preference's values + current = source.readInt(); + source.readIntArray(colors); + columns = source.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + // Write the preference's values + dest.writeInt(current); + dest.writeIntArray(colors); + dest.writeInt(columns); + } + } + + /** + * recycling the added view to avoid adding it multiple times. + * + * @param view + * @param toAdd + */ + private void addView(ViewGroup view, View toAdd) { + if (view != null && toAdd != null) { + if (toAdd.getParent() != null) { + ((ViewGroup) toAdd.getParent()).removeView(toAdd); + } + view.removeAllViews(); + view.addView(toAdd); + } + updateShownColor(); + } + +} \ No newline at end of file diff --git a/color-picker/src/main/java/org/xdty/preference/ColorCircleDrawable.java b/color-picker/src/main/java/org/xdty/preference/ColorCircleDrawable.java new file mode 100755 index 0000000..f374a35 --- /dev/null +++ b/color-picker/src/main/java/org/xdty/preference/ColorCircleDrawable.java @@ -0,0 +1,46 @@ +package org.xdty.preference; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; + +public class ColorCircleDrawable extends Drawable { + private final Paint mPaint; + private int mRadius = 0; + + public ColorCircleDrawable(final int color) { + this.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + this.mPaint.setColor(color); + } + + @Override + public void draw(@NonNull final Canvas canvas) { + final Rect bounds = getBounds(); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), mRadius, mPaint); + } + + @Override + protected void onBoundsChange(final Rect bounds) { + super.onBoundsChange(bounds); + mRadius = Math.min(bounds.width(), bounds.height()) / 2; + } + + @Override + public void setAlpha(final int alpha) { + mPaint.setAlpha(alpha); + } + + @Override + public void setColorFilter(final ColorFilter cf) { + mPaint.setColorFilter(cf); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } +} \ No newline at end of file diff --git a/color-picker/src/main/java/org/xdty/preference/ColorPreference.java b/color-picker/src/main/java/org/xdty/preference/ColorPreference.java new file mode 100755 index 0000000..0477063 --- /dev/null +++ b/color-picker/src/main/java/org/xdty/preference/ColorPreference.java @@ -0,0 +1,236 @@ +package org.xdty.preference; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.OvalShape; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.preference.Preference; +import android.support.v7.app.AppCompatActivity; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.xdty.preference.colorpicker.ColorPickerDialog; +import org.xdty.preference.colorpicker.ColorPickerSwatch; +import org.xdty.preference.colorpicker.R; + +/** + * A preference showing a {@link ColorPickerDialog} to allow the user to select a color to save as {@link Preference}. + */ +public class ColorPreference extends Preference implements ColorPickerSwatch + .OnColorSelectedListener { + + private static final int DEFAULT_VALUE = Color.BLACK; + + private int mTitle = R.string.color_picker_default_title; + private int mCurrentValue; + private int[] mColors; + private int mColumns; + private boolean mMaterial; + + private View mColorView; + + public ColorPreference(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ColorPreference, 0, 0); + try { + int id = a.getResourceId(R.styleable.ColorPreference_colorDialogColors, R.array.default_rainbow); + if (id != 0) { + mColors = getContext().getResources().getIntArray(id); + } + id = a.getResourceId(R.styleable.ColorPreference_colorDialogTitle, 0); + if (id != 0) { + mTitle = a.getResourceId(R.styleable.ColorPreference_colorDialogTitle, R.string.color_picker_default_title); + } + mColumns = a.getInt(R.styleable.ColorPreference_colorDialogColumns, 5); + mMaterial = a.getBoolean(R.styleable.ColorPreference_colorDialogMaterial, true); + } finally { + a.recycle(); + } + } + + @Override protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getInteger(index, DEFAULT_VALUE); + } + + @Override protected View onCreateView(ViewGroup parent) { + View s = super.onCreateView(parent); + mColorView = new View(getContext()); + int size = (int) dpToPx(32); + mColorView.setLayoutParams(new ViewGroup.LayoutParams(size, size)); + updateShownColor(); + ViewGroup w = (ViewGroup) s.findViewById(android.R.id.widget_frame); + w.setVisibility(View.VISIBLE); + w.addView(mColorView); + return s; + } + + @Override protected void onBindView(View view) { + super.onBindView(view); + if (mMaterial) { + TextView textTitle = (TextView) view.findViewById(android.R.id.title); + TextView textSummary = (TextView) view.findViewById(android.R.id.summary); + + textTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); + textSummary.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); + textTitle.setTextColor(getColor(android.R.attr.textColorPrimary)); + textSummary.setTextColor(getColor(android.R.attr.textColorSecondary)); + + View parent = (View) textSummary.getParent().getParent(); + parent.setPadding((int) dpToPx(16), 0, (int) dpToPx(16), 0); + } + } + + @Override protected void onClick() { + int[] colors = mColors.length != 0 ? mColors : new int[]{ + Color.BLACK, Color.WHITE, Color + .RED, Color.GREEN, Color.BLUE + }; + ColorPickerDialog d = ColorPickerDialog.newInstance(mTitle, + colors, mCurrentValue, mColumns, + ColorPickerDialog.SIZE_SMALL); + d.setOnColorSelectedListener(this); + d.show(((AppCompatActivity) getContext()).getSupportFragmentManager(), "ColorPickerDialog"); + } + + @Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { + if (restorePersistedValue) { + // Restore existing state + mCurrentValue = this.getPersistedInt(DEFAULT_VALUE); + } else { + // Set default state from the XML attribute + mCurrentValue = (Integer) defaultValue; + persistInt(mCurrentValue); + } + } + + @Override protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + // Check whether this Preference is persistent (continually saved) + if (isPersistent()) { + // No need to save instance state since it's persistent, + // use superclass state + return superState; + } + + // Create instance of custom BaseSavedState + final SavedState myState = new SavedState(superState); + // Set the state's value with the class member that holds current + // setting value + myState.current = mCurrentValue; + myState.colors = mColors; + myState.columns = mColumns; + return myState; + } + + @Override protected void onRestoreInstanceState(Parcelable state) { + // Check whether we saved the state in onSaveInstanceState + if (state == null || !state.getClass().equals(SavedState.class)) { + // Didn't save the state, so call superclass + super.onRestoreInstanceState(state); + return; + } + + // Cast state to custom BaseSavedState and pass to superclass + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + + // Update own values + mCurrentValue = myState.current; + mColors = myState.colors; + mColumns = myState.columns; + + // Update shown color + updateShownColor(); + + // Set this Preference's widget to reflect the restored state + //mNumberPicker.setValue(myState.value); + } + + @Override public void onColorSelected(int color) { + persistInt(color); + mCurrentValue = color; + updateShownColor(); + } + + private void updateShownColor() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mColorView.setBackground(new ShapeDrawable(new OvalShape())); + ((ShapeDrawable) mColorView.getBackground()).getPaint().setColor(mCurrentValue); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mColorView.setBackground(new ColorCircleDrawable(mCurrentValue)); + } else { + mColorView.setBackground(new ColorCircleDrawable(mCurrentValue)); + } + mColorView.invalidate(); + } + + /** + * Convert a dp size to pixel. Useful for specifying view sizes in code. + * + * @param dp + * The size in density-independent pixels. + * @return {@code px} - The size in generic pixels (density-dependent). + */ + private float dpToPx(float dp) { + return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, + getContext().getResources().getDisplayMetrics()); + } + + private int getColor(int attrId) { + TypedValue typedValue = new TypedValue(); + Resources.Theme theme = getContext().getTheme(); + theme.resolveAttribute(attrId, typedValue, true); + TypedArray arr = getContext().obtainStyledAttributes(typedValue.data, new int[]{attrId}); + int color = arr.getColor(0, -1); + arr.recycle(); + return color; + } + + private static class SavedState extends BaseSavedState { + // Standard creator object using an instance of this class + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + // Member that holds the preference's values + int current; + int[] colors; + int columns; + + public SavedState(Parcelable superState) { + super(superState); + } + + public SavedState(Parcel source) { + super(source); + // Get the current preference's values + current = source.readInt(); + source.readIntArray(colors); + columns = source.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + // Write the preference's values + dest.writeInt(current); + dest.writeIntArray(colors); + dest.writeInt(columns); + } + } +} \ No newline at end of file diff --git a/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerDialog.java b/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerDialog.java new file mode 100755 index 0000000..7b55cc6 --- /dev/null +++ b/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerDialog.java @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2013 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 org.xdty.preference.colorpicker; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.support.v7.preference.PreferenceManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ProgressBar; + +import org.xdty.preference.colorpicker.ColorPickerSwatch.OnColorSelectedListener; + + +/** + * A dialog which takes in as input an array of colors and creates a palette allowing the user to select a specific color swatch, which invokes a + * listener. + */ +public class ColorPickerDialog extends DialogFragment implements OnColorSelectedListener { + + public static final int SIZE_LARGE = 1; + public static final int SIZE_SMALL = 2; + + protected AlertDialog mAlertDialog; + + protected static final String KEY_TITLE_ID = "title_id"; + protected static final String KEY_COLORS = "colors"; + protected static final String KEY_COLOR_CONTENT_DESCRIPTIONS = "color_content_descriptions"; + protected static final String KEY_SELECTED_COLOR = "selected_color"; + protected static final String KEY_COLUMNS = "columns"; + protected static final String KEY_SIZE = "size"; + + protected int mTitleResId = R.string.color_picker_default_title; + protected int[] mColors = null; + protected String[] mColorContentDescriptions = null; + protected int mSelectedColor; + protected int mColumns; + protected int mSize; + protected String key; + private ColorPickerPalette mPalette; + private ProgressBar mProgress; + + protected OnColorSelectedListener mListener; + + public static ColorPickerDialog newInstance(int titleResId, int[] colors, int selectedColor, + int columns, int size) { + ColorPickerDialog ret = new ColorPickerDialog(); + ret.initialize(titleResId, colors, selectedColor, columns, size); + return ret; + } + + @Override public void onAttach(Context context) { + super.onAttach(context); + Log.e("ColorPickerPalette", context + " " + getParentFragment()); + if (getParentFragment() != null && (getParentFragment() instanceof OnColorSelectedListener)) { + mListener = (OnColorSelectedListener) getParentFragment(); + } else if (context instanceof OnColorSelectedListener) { + mListener = (OnColorSelectedListener) context; + } + } + + @Override public void onDetach() { + super.onDetach(); + mListener = null; + } + + @Override public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putIntArray(KEY_COLORS, mColors); + outState.putInt(KEY_SELECTED_COLOR, mSelectedColor); + outState.putStringArray(KEY_COLOR_CONTENT_DESCRIPTIONS, mColorContentDescriptions); + outState.putString("key", key); + } + + @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mTitleResId = getArguments().getInt(KEY_TITLE_ID); + mColumns = getArguments().getInt(KEY_COLUMNS); + mSize = getArguments().getInt(KEY_SIZE); + key = getArguments().getString("key"); + } + if (savedInstanceState != null) { + mColors = savedInstanceState.getIntArray(KEY_COLORS); + mSelectedColor = savedInstanceState.getInt(KEY_SELECTED_COLOR); + mColorContentDescriptions = savedInstanceState.getStringArray( + KEY_COLOR_CONTENT_DESCRIPTIONS); + key = savedInstanceState.getString("key"); + } + } + + @SuppressLint("InflateParams") @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + View view = LayoutInflater.from(getActivity()).inflate(R.layout.color_picker_dialog, null, false); + final Activity activity = getActivity(); + mProgress = (ProgressBar) view.findViewById(android.R.id.progress); + mPalette = (ColorPickerPalette) view.findViewById(R.id.color_picker); + mPalette.init(mSize, mColumns, this); + + if (mColors != null) { + showPaletteView(); + } + + mAlertDialog = new AlertDialog.Builder(activity) + .setTitle(mTitleResId) + .setView(view) + .create(); + mAlertDialog.setCanceledOnTouchOutside(true); + return mAlertDialog; + } + + @Override public void onColorSelected(int color) { + if (mListener != null) { + mListener.onColorSelected(color); + } + PreferenceManager.getDefaultSharedPreferences(getContext()) + .edit().putInt(key, color).apply(); + if (getTargetFragment() instanceof OnColorSelectedListener) { + final OnColorSelectedListener listener = (OnColorSelectedListener) getTargetFragment(); + listener.onColorSelected(color); + } + if (color != mSelectedColor) { + mSelectedColor = color; + mPalette.drawPalette(mColors, mSelectedColor); + } + dismiss(); + } + + public void initialize(int titleResId, int[] colors, int selectedColor, int columns, int size) { + setArguments(titleResId, columns, size); + setColors(colors, selectedColor); + } + + public void setArguments(int titleResId, int columns, int size) { + Bundle bundle = new Bundle(); + bundle.putInt(KEY_TITLE_ID, titleResId); + bundle.putInt(KEY_COLUMNS, columns); + bundle.putInt(KEY_SIZE, size); + setArguments(bundle); + } + + public void setOnColorSelectedListener(OnColorSelectedListener listener) { + mListener = listener; + } + + public void showPaletteView() { + if (mProgress != null && mPalette != null) { + mProgress.setVisibility(View.GONE); + refreshPalette(); + mPalette.setVisibility(View.VISIBLE); + } + } + + public void showProgressBarView() { + if (mProgress != null && mPalette != null) { + mProgress.setVisibility(View.VISIBLE); + mPalette.setVisibility(View.GONE); + } + } + + public void setColors(int[] colors, int selectedColor) { + if (mColors != colors || mSelectedColor != selectedColor) { + mColors = colors; + mSelectedColor = selectedColor; + refreshPalette(); + } + } + + public void setColors(int[] colors) { + if (mColors != colors) { + mColors = colors; + refreshPalette(); + } + } + + public void setSelectedColor(int color) { + if (mSelectedColor != color) { + mSelectedColor = color; + refreshPalette(); + } + } + + public void setColorContentDescriptions(String[] colorContentDescriptions) { + if (mColorContentDescriptions != colorContentDescriptions) { + mColorContentDescriptions = colorContentDescriptions; + refreshPalette(); + } + } + + private void refreshPalette() { + if (mPalette != null && mColors != null) { + mPalette.drawPalette(mColors, mSelectedColor, mColorContentDescriptions); + } + } + + public int[] getColors() { + return mColors; + } + + public int getSelectedColor() { + return mSelectedColor; + } + + public static ColorPickerDialog newInstance(int titleResId, int[] colors, int selectedColor, + int columns, int size, String key) { + ColorPickerDialog ret = new ColorPickerDialog(); + ret.initialize(titleResId, colors, selectedColor, columns, size, key); + return ret; + } + + private void initialize(int titleResId, int[] colors, int selectedColor, int columns, int size, String key) { + setArguments(titleResId, columns, size, key); + setColors(colors, selectedColor); + } + + private void setArguments(int titleResId, int columns, int size, String key) { + Bundle bundle = new Bundle(); + bundle.putInt(KEY_TITLE_ID, titleResId); + bundle.putInt(KEY_COLUMNS, columns); + bundle.putInt(KEY_SIZE, size); + bundle.putString("key", key); + setArguments(bundle); + } +} diff --git a/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerPalette.java b/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerPalette.java new file mode 100755 index 0000000..bf7f39b --- /dev/null +++ b/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerPalette.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2013 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 org.xdty.preference.colorpicker; + +import android.content.Context; +import android.content.res.Resources; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TableLayout; +import android.widget.TableRow; + +import org.xdty.preference.colorpicker.ColorPickerSwatch.OnColorSelectedListener; + + +/** + * A color picker custom view which creates an grid of color squares. The number of squares per + * row (and the padding between the squares) is determined by the user. + */ +public class ColorPickerPalette extends TableLayout { + + public OnColorSelectedListener mOnColorSelectedListener; + + private String mDescription; + private String mDescriptionSelected; + + private int mSwatchLength; + private int mMarginSize; + private int mNumColumns; + + public ColorPickerPalette(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ColorPickerPalette(Context context) { + super(context); + } + + /** + * Initialize the size, columns, and listener. Size should be a pre-defined size (SIZE_LARGE + * or SIZE_SMALL) from ColorPickerDialogFragment. + */ + public void init(int size, int columns, OnColorSelectedListener listener) { + mNumColumns = columns; + Resources res = getResources(); + if (size == ColorPickerDialog.SIZE_LARGE) { + mSwatchLength = res.getDimensionPixelSize(R.dimen.color_swatch_large); + mMarginSize = res.getDimensionPixelSize(R.dimen.color_swatch_margins_large); + } else { + mSwatchLength = res.getDimensionPixelSize(R.dimen.color_swatch_small); + mMarginSize = res.getDimensionPixelSize(R.dimen.color_swatch_margins_small); + } + mOnColorSelectedListener = listener; + + mDescription = res.getString(R.string.color_swatch_description); + mDescriptionSelected = res.getString(R.string.color_swatch_description_selected); + } + + private TableRow createTableRow() { + TableRow row = new TableRow(getContext()); + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + row.setLayoutParams(params); + return row; + } + + /** + * Adds swatches to table in a serpentine format. + */ + public void drawPalette(int[] colors, int selectedColor) { + drawPalette(colors, selectedColor, null); + } + + /** + * Adds swatches to table in a serpentine format. + */ + public void drawPalette(int[] colors, int selectedColor, String[] colorContentDescriptions) { + if (colors == null) { + return; + } + + this.removeAllViews(); + int tableElements = 0; + int rowElements = 0; + int rowNumber = 0; + + // Fills the table with swatches based on the array of colors. + TableRow row = createTableRow(); + for (int color : colors) { + View colorSwatch = createColorSwatch(color, selectedColor); + setSwatchDescription(rowNumber, tableElements, rowElements, color == selectedColor, + colorSwatch, colorContentDescriptions); + addSwatchToRow(row, colorSwatch, rowNumber); + + tableElements++; + rowElements++; + if (rowElements == mNumColumns) { + addView(row); + row = createTableRow(); + rowElements = 0; + rowNumber++; + } + } + + // Create blank views to fill the row if the last row has not been filled. + if (rowElements > 0) { + while (rowElements != mNumColumns) { + addSwatchToRow(row, createBlankSpace(), rowNumber); + rowElements++; + } + addView(row); + } + } + + /** + * Appends a swatch to the end of the row for even-numbered rows (starting with row 0), + * to the beginning of a row for odd-numbered rows. + */ + private static void addSwatchToRow(TableRow row, View swatch, int rowNumber) { + if (rowNumber % 2 == 0) { + row.addView(swatch); + } else { + row.addView(swatch, 0); + } + } + + /** + * Add a content description to the specified swatch view. Because the colors get added in a + * snaking form, every other row will need to compensate for the fact that the colors are added + * in an opposite direction from their left->right/top->bottom order, which is how the system + * will arrange them for accessibility purposes. + */ + private void setSwatchDescription(int rowNumber, int index, int rowElements, boolean selected, + View swatch, String[] contentDescriptions) { + String description; + if (contentDescriptions != null && contentDescriptions.length > index) { + description = contentDescriptions[index]; + } else { + int accessibilityIndex; + if (rowNumber % 2 == 0) { + // We're in a regular-ordered row + accessibilityIndex = index + 1; + } else { + // We're in a backwards-ordered row. + int rowMax = ((rowNumber + 1) * mNumColumns); + accessibilityIndex = rowMax - rowElements; + } + + if (selected) { + description = String.format(mDescriptionSelected, accessibilityIndex); + } else { + description = String.format(mDescription, accessibilityIndex); + } + } + swatch.setContentDescription(description); + } + + /** + * Creates a blank space to fill the row. + */ + private ImageView createBlankSpace() { + ImageView view = new ImageView(getContext()); + TableRow.LayoutParams params = new TableRow.LayoutParams(mSwatchLength, mSwatchLength); + params.setMargins(mMarginSize, mMarginSize, mMarginSize, mMarginSize); + view.setLayoutParams(params); + return view; + } + + /** + * Creates a color swatch. + */ + private ColorPickerSwatch createColorSwatch(int color, int selectedColor) { + ColorPickerSwatch view = new ColorPickerSwatch(getContext(), color, + color == selectedColor, mOnColorSelectedListener); + TableRow.LayoutParams params = new TableRow.LayoutParams(mSwatchLength, mSwatchLength); + params.setMargins(mMarginSize, mMarginSize, mMarginSize, mMarginSize); + view.setLayoutParams(params); + return view; + } +} diff --git a/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerSwatch.java b/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerSwatch.java new file mode 100755 index 0000000..cc1ad4b --- /dev/null +++ b/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorPickerSwatch.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013 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 org.xdty.preference.colorpicker; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.support.v4.content.ContextCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; + +/** + * Creates a circular swatch of a specified color. Adds a checkmark if marked as checked. + */ +public class ColorPickerSwatch extends FrameLayout implements View.OnClickListener { + private int mColor; + private ImageView mSwatchImage; + private ImageView mCheckmarkImage; + private OnColorSelectedListener mOnColorSelectedListener; + + /** + * Interface for a callback when a color square is selected. + */ + public interface OnColorSelectedListener { + + /** + * Called when a specific color square has been selected. + */ + void onColorSelected(int color); + } + + public ColorPickerSwatch(Context context, int color, boolean checked, OnColorSelectedListener listener) { + super(context); + mColor = color; + mOnColorSelectedListener = listener; + LayoutInflater.from(context).inflate(R.layout.color_picker_swatch, this); + mSwatchImage = (ImageView) findViewById(R.id.color_picker_swatch); + mCheckmarkImage = (ImageView) findViewById(R.id.color_picker_checkmark); + setColor(color); + setChecked(checked); + setOnClickListener(this); + } + + protected void setColor(int color) { + Drawable[] colorDrawable = new Drawable[]{ContextCompat.getDrawable(getContext(), R.drawable.color_picker_swatch)}; + mSwatchImage.setImageDrawable(new ColorStateDrawable(colorDrawable, color)); + } + + private void setChecked(boolean checked) { + if (checked) { + mCheckmarkImage.setVisibility(View.VISIBLE); + } else { + mCheckmarkImage.setVisibility(View.GONE); + } + } + + @Override public void onClick(View v) { + if (mOnColorSelectedListener != null) { + mOnColorSelectedListener.onColorSelected(mColor); + } + } +} diff --git a/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorStateDrawable.java b/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorStateDrawable.java new file mode 100755 index 0000000..009a6e6 --- /dev/null +++ b/color-picker/src/main/java/org/xdty/preference/colorpicker/ColorStateDrawable.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013 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 org.xdty.preference.colorpicker; + +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; + +/** + * A drawable which sets its color filter to a color specified by the user, and changes to a + * slightly darker color when pressed or focused. + */ +public class ColorStateDrawable extends LayerDrawable { + + private static final float PRESSED_STATE_MULTIPLIER = 0.70f; + + private int mColor; + + public ColorStateDrawable(Drawable[] layers, int color) { + super(layers); + mColor = color; + } + + @Override + protected boolean onStateChange(int[] states) { + boolean pressedOrFocused = false; + for (int state : states) { + if (state == android.R.attr.state_pressed || state == android.R.attr.state_focused) { + pressedOrFocused = true; + break; + } + } + + if (pressedOrFocused) { + super.setColorFilter(getPressedColor(mColor), PorterDuff.Mode.SRC_ATOP); + } else { + super.setColorFilter(mColor, PorterDuff.Mode.SRC_ATOP); + } + + return super.onStateChange(states); + } + + /** + * Given a particular color, adjusts its value by a multiplier. + */ + private static int getPressedColor(int color) { + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + hsv[2] = hsv[2] * PRESSED_STATE_MULTIPLIER; + return Color.HSVToColor(hsv); + } + + @Override + public boolean isStateful() { + return true; + } +} diff --git a/color-picker/src/main/java/org/xdty/preference/colorpicker/HsvColorComparator.java b/color-picker/src/main/java/org/xdty/preference/colorpicker/HsvColorComparator.java new file mode 100755 index 0000000..9887244 --- /dev/null +++ b/color-picker/src/main/java/org/xdty/preference/colorpicker/HsvColorComparator.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013 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 org.xdty.preference.colorpicker; + +import android.graphics.Color; + +import java.util.Comparator; + +/** + * A color comparator which compares based on hue, saturation, and value. + */ +public class HsvColorComparator implements Comparator { + + @Override + public int compare(Integer lhs, Integer rhs) { + float[] hsv = new float[3]; + Color.colorToHSV(lhs, hsv); + float hue1 = hsv[0]; + float sat1 = hsv[1]; + float val1 = hsv[2]; + + float[] hsv2 = new float[3]; + Color.colorToHSV(rhs, hsv2); + float hue2 = hsv2[0]; + float sat2 = hsv2[1]; + float val2 = hsv2[2]; + + if (hue1 < hue2) { + return 1; + } else if (hue1 > hue2) { + return -1; + } else { + if (sat1 < sat2) { + return 1; + } else if (sat1 > sat2) { + return -1; + } else { + if (val1 < val2) { + return 1; + } else if (val1 > val2) { + return -1; + } + } + } + return 0; + } +} diff --git a/color-picker/src/main/res/drawable-hdpi/ic_colorpicker_swatch_selected.png b/color-picker/src/main/res/drawable-hdpi/ic_colorpicker_swatch_selected.png new file mode 100755 index 0000000000000000000000000000000000000000..3cbfe1a840d085dc922421217f0fc590d4681b5c GIT binary patch literal 2414 zcmZ`*Yg7{07Cs;#VG>S=MoN0~5sn&aK2pb^RG`K}e57T*0=0ahkq@vUA2n*BX@i>M zql_`l@sXM~YHCG}i&1NQXOU)VKFGRCrRI2Pe%!V0kGs#>=R0Sg{jG1Wb$;xf&Nxg} zN8wQb0ChUenW;qDH%B6ryO+G4ssval#f<_$U6$I{Ah_}lIm4vx2i3hgv&xI!NgC4) z0G<&5f>Z!jl_9}90M3#Cmwrdk z8DaZMZTuE@^j-u}FXs-{-K7+0!LDJ`QK_G{VtM@;YU4R}t%jpLxQacyAcZ3d3w5D~ zclT~Cwtg#_+{QmOv-@h5UGbUXrNWuLGkbTd*u}p6n14}><{-e zOq0wO3#$;Gs)4#bRKKelU3Lrn4%er)-b0awdIa)zp9?3cG&5t(KQkS7#mV-Wki$Fu z+Hf2}@E?OIQ{KeyQH>~ul}}085K?Han{#x{!Q<3LKQUa8=85$BGj^{qrEAi6f%2{_ z1Swg*6(T@p97t>&$25&yO>!z(T1h%IS~KRom28jESRi^y_zA_vm6es@Lsgx!Hoooc z{@E*f$jnB{V8l}1h@U2T75O~Xq$gdOm8=KIyuiS5TWS_zeeCLX+qm1zinnuvcjraT z){NjYi3;z)`Yq&Iynt)h&9bz%vH7GJ`t5l8ySceHLp1>#QjVQt;`*vW)v2V0BAQ|z z-{lh}QaP@9$D|bF(;GDZhh)i7!{wSmZg*N;UER*-VarmbNTp++N7I;GRvYxVx2Mo{ zUrXZB^zGsK-#oCA1P6HLcPPEcU(eU;KTVM|o#_9mi36kPr8@@)ak_Z-Y=@T{bC{<`C-%?Om1cPM)8o+d{J zMj1DtAJZlfWc&}~ogAA&x0Ut3<5ywDGwH7vjnkdqD5j)&7q(|g&TkO9e^cM`TVs$&>*~W#y{=eULYYRSEP7J`F z9T7ndGJ>@PXUmV2$aZ9Xs|$W0r2_KTz~Ad@Cqc5Zl5!&>qbqtBK)LcOwZMx5HyIB& zT=I?r2+JlH*WsG>S%|#O+?DZ&n2{r^5AB;~>>5CeV&+qzs^pI=Nj=wSZ)cQVW_J93 zk}mr4sS_t&jX9};lAe&zOP4OKA`pm&ThjJF%-bDM-Oy)|p;CCd)n-yXWB_I3euArb zCXYLF&oq?B<2?xaY`22mJ*488Op1q9X zxww{!pav#{^T6+Yz)Ww^{9TN&u1GC#EtI`CZ4@)v@hE~mwUlUrOrD?ZFE2=NJb$;T zDLxZX!GKm^d+R4ACLW&b5}q4=`O=T5qf3L5Wt)Ain4LJOs4YOm{zmK0HI9Ds@rzv7 zAx;6swZZqVS~eb>9yE!GimGPXtvZ^j=hB14EqLiA-%SRe%cxm@ z<>ux#-H#l*?}e2#+8Z3Kh*k0)*ZC|IibNtKwQ(R(wavnt=646`Dl%s5>~E*1r!Nl- z49JU%i;pNPJVZ2m*?wVzwg?ik4rJh)qct=7& zenG(sKR!O5#pA688+^ACuCx!5Of8gHWM-wIei&`!f&ZSlh|V7w{gB}3caxDl_Tt5t zqc#4-j9bl?1)Cc&Xw~~MU#fEUSB?1gq+AVSS1@)l@}!bOIWW*F;ehGE4aofDX*6x0 z|50x>O_z(6mD%iVxW^Nny=q>qtwDpbB!nbalP!-O8Mk&E=}gn|#)eJJ3OD-%ymgI4 zTfE~~g5pVP!q>E9UH^Xz5CFyt8gG9_H|x5XWw$5L#-6vYccL39Xdb;W1BwSYCeXvQ|*3TAy2?VyB<9=Kkr_|83cbb*=K6RO6NB z(T2*g!jS9Y!(|0=+4d)6*-8MGBnvAulBJo2rKcsyo@8ZjX>CTbvnP?9@RvsZhY%Uf zIu(-m{|QH^PAny1+cyP|=n!svP%IlzSkb|3J$htND4WR+VkO3Ov%k$ffbMeGxq5$K G@_zuE;6>m7 literal 0 HcmV?d00001 diff --git a/color-picker/src/main/res/drawable-mdpi/ic_colorpicker_swatch_selected.png b/color-picker/src/main/res/drawable-mdpi/ic_colorpicker_swatch_selected.png new file mode 100755 index 0000000000000000000000000000000000000000..acbdecac269ea57935434357d986e8b974c10351 GIT binary patch literal 1662 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 literal 0 HcmV?d00001 diff --git a/color-picker/src/main/res/drawable/color_picker_swatch.xml b/color-picker/src/main/res/drawable/color_picker_swatch.xml new file mode 100755 index 0000000..db71091 --- /dev/null +++ b/color-picker/src/main/res/drawable/color_picker_swatch.xml @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/color-picker/src/main/res/layout/color_picker_dialog.xml b/color-picker/src/main/res/layout/color_picker_dialog.xml new file mode 100755 index 0000000..a4f1780 --- /dev/null +++ b/color-picker/src/main/res/layout/color_picker_dialog.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/color-picker/src/main/res/layout/color_picker_swatch.xml b/color-picker/src/main/res/layout/color_picker_swatch.xml new file mode 100755 index 0000000..5afa4a5 --- /dev/null +++ b/color-picker/src/main/res/layout/color_picker_swatch.xml @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/color-picker/src/main/res/values-af/strings.xml b/color-picker/src/main/res/values-af/strings.xml new file mode 100755 index 0000000..2622bcd --- /dev/null +++ b/color-picker/src/main/res/values-af/strings.xml @@ -0,0 +1,22 @@ + + + + + "Kies \'n kleur" + "Kleur %1$d" + "Kleur %1$d gekies" + diff --git a/color-picker/src/main/res/values-am/strings.xml b/color-picker/src/main/res/values-am/strings.xml new file mode 100755 index 0000000..47bd2b8 --- /dev/null +++ b/color-picker/src/main/res/values-am/strings.xml @@ -0,0 +1,22 @@ + + + + + "ቀለም ምረጥ" + "ቀለም %1$d" + "ቀለም %1$d ተመርጧል" + diff --git a/color-picker/src/main/res/values-ar/strings.xml b/color-picker/src/main/res/values-ar/strings.xml new file mode 100755 index 0000000..e619ee4 --- /dev/null +++ b/color-picker/src/main/res/values-ar/strings.xml @@ -0,0 +1,22 @@ + + + + + "تحديد لون:" + "اللون %1$d" + "تم تحديد اللون %1$d" + diff --git a/color-picker/src/main/res/values-bg/strings.xml b/color-picker/src/main/res/values-bg/strings.xml new file mode 100755 index 0000000..979f2d6 --- /dev/null +++ b/color-picker/src/main/res/values-bg/strings.xml @@ -0,0 +1,22 @@ + + + + + "Избиране на цвят" + "Цвят %1$d" + "Избрахте цвят %1$d" + diff --git a/color-picker/src/main/res/values-bn-rBD/strings.xml b/color-picker/src/main/res/values-bn-rBD/strings.xml new file mode 100755 index 0000000..cd4a26d --- /dev/null +++ b/color-picker/src/main/res/values-bn-rBD/strings.xml @@ -0,0 +1,22 @@ + + + + + "একটি রঙ নির্বাচন করুন" + "রঙ %1$d" + "%1$d রঙ নির্বাচন করা হয়েছে" + diff --git a/color-picker/src/main/res/values-ca/strings.xml b/color-picker/src/main/res/values-ca/strings.xml new file mode 100755 index 0000000..613b935 --- /dev/null +++ b/color-picker/src/main/res/values-ca/strings.xml @@ -0,0 +1,22 @@ + + + + + "Selecciona un color" + "Color %1$d" + "S\'ha seleccionat el color %1$d" + diff --git a/color-picker/src/main/res/values-cs/strings.xml b/color-picker/src/main/res/values-cs/strings.xml new file mode 100755 index 0000000..08aaab8 --- /dev/null +++ b/color-picker/src/main/res/values-cs/strings.xml @@ -0,0 +1,22 @@ + + + + + "Vyberte barvu" + "Barva %1$d" + "Barva %1$d je vybrána" + diff --git a/color-picker/src/main/res/values-da/strings.xml b/color-picker/src/main/res/values-da/strings.xml new file mode 100755 index 0000000..ff3bfb5 --- /dev/null +++ b/color-picker/src/main/res/values-da/strings.xml @@ -0,0 +1,22 @@ + + + + + "Vælg en farve" + "Farve %1$d" + "Farve %1$d valgt" + diff --git a/color-picker/src/main/res/values-de/strings.xml b/color-picker/src/main/res/values-de/strings.xml new file mode 100755 index 0000000..f8ef0ba --- /dev/null +++ b/color-picker/src/main/res/values-de/strings.xml @@ -0,0 +1,22 @@ + + + + + "Farbe auswählen:" + "Farbe %1$d" + "Farbe %1$d ausgewählt" + diff --git a/color-picker/src/main/res/values-el/strings.xml b/color-picker/src/main/res/values-el/strings.xml new file mode 100755 index 0000000..d72feb0 --- /dev/null +++ b/color-picker/src/main/res/values-el/strings.xml @@ -0,0 +1,22 @@ + + + + + "Επιλέξτε χρώμα" + "Χρώμα %1$d" + "Επιλέχτηκε το χρώμα %1$d" + diff --git a/color-picker/src/main/res/values-en-rAU/strings.xml b/color-picker/src/main/res/values-en-rAU/strings.xml new file mode 100755 index 0000000..0d2fdc3 --- /dev/null +++ b/color-picker/src/main/res/values-en-rAU/strings.xml @@ -0,0 +1,22 @@ + + + + + "Select a Colour" + "Colour %1$d" + "Colour %1$d selected" + diff --git a/color-picker/src/main/res/values-en-rGB/strings.xml b/color-picker/src/main/res/values-en-rGB/strings.xml new file mode 100755 index 0000000..0d2fdc3 --- /dev/null +++ b/color-picker/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,22 @@ + + + + + "Select a Colour" + "Colour %1$d" + "Colour %1$d selected" + diff --git a/color-picker/src/main/res/values-en-rIN/strings.xml b/color-picker/src/main/res/values-en-rIN/strings.xml new file mode 100755 index 0000000..0d2fdc3 --- /dev/null +++ b/color-picker/src/main/res/values-en-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + "Select a Colour" + "Colour %1$d" + "Colour %1$d selected" + diff --git a/color-picker/src/main/res/values-es-rUS/strings.xml b/color-picker/src/main/res/values-es-rUS/strings.xml new file mode 100755 index 0000000..c7ff625 --- /dev/null +++ b/color-picker/src/main/res/values-es-rUS/strings.xml @@ -0,0 +1,22 @@ + + + + + "Seleccionar un color" + "Color %1$d" + "Color %1$d seleccionado" + diff --git a/color-picker/src/main/res/values-es/strings.xml b/color-picker/src/main/res/values-es/strings.xml new file mode 100755 index 0000000..5a8db84 --- /dev/null +++ b/color-picker/src/main/res/values-es/strings.xml @@ -0,0 +1,22 @@ + + + + + "Selecciona un color" + "Color %1$d" + "Color %1$d seleccionado" + diff --git a/color-picker/src/main/res/values-et-rEE/strings.xml b/color-picker/src/main/res/values-et-rEE/strings.xml new file mode 100755 index 0000000..544e32c --- /dev/null +++ b/color-picker/src/main/res/values-et-rEE/strings.xml @@ -0,0 +1,22 @@ + + + + + "Valige värv" + "Värv %1$d" + "Valitud on värv %1$d" + diff --git a/color-picker/src/main/res/values-eu-rES/strings.xml b/color-picker/src/main/res/values-eu-rES/strings.xml new file mode 100755 index 0000000..ddb1966 --- /dev/null +++ b/color-picker/src/main/res/values-eu-rES/strings.xml @@ -0,0 +1,22 @@ + + + + + "Hautatu kolorea" + "%1$d" + "%1$d hautatu da" + diff --git a/color-picker/src/main/res/values-fa/strings.xml b/color-picker/src/main/res/values-fa/strings.xml new file mode 100755 index 0000000..ebc96f1 --- /dev/null +++ b/color-picker/src/main/res/values-fa/strings.xml @@ -0,0 +1,22 @@ + + + + + "انتخاب رنگ" + "رنگ %1$d" + "رنگ %1$d انتخاب شد" + diff --git a/color-picker/src/main/res/values-fi/strings.xml b/color-picker/src/main/res/values-fi/strings.xml new file mode 100755 index 0000000..5529866 --- /dev/null +++ b/color-picker/src/main/res/values-fi/strings.xml @@ -0,0 +1,22 @@ + + + + + "Valitse väri" + "Väri %1$d" + "Väri %1$d on valittu" + diff --git a/color-picker/src/main/res/values-fr-rCA/strings.xml b/color-picker/src/main/res/values-fr-rCA/strings.xml new file mode 100755 index 0000000..4a68b78 --- /dev/null +++ b/color-picker/src/main/res/values-fr-rCA/strings.xml @@ -0,0 +1,22 @@ + + + + + "Sélectionnez une couleur" + "Couleur %1$d" + "Couleur %1$d sélectionnée" + diff --git a/color-picker/src/main/res/values-fr/strings.xml b/color-picker/src/main/res/values-fr/strings.xml new file mode 100755 index 0000000..61ae1c3 --- /dev/null +++ b/color-picker/src/main/res/values-fr/strings.xml @@ -0,0 +1,22 @@ + + + + + "Sélectionner une couleur" + "Couleur %1$d" + "Couleur %1$d sélectionnée" + diff --git a/color-picker/src/main/res/values-gl-rES/strings.xml b/color-picker/src/main/res/values-gl-rES/strings.xml new file mode 100755 index 0000000..264956a --- /dev/null +++ b/color-picker/src/main/res/values-gl-rES/strings.xml @@ -0,0 +1,22 @@ + + + + + "Selecciona unha cor" + "Cor %1$d" + "Seleccionouse a cor %1$d" + diff --git a/color-picker/src/main/res/values-gu-rIN/strings.xml b/color-picker/src/main/res/values-gu-rIN/strings.xml new file mode 100755 index 0000000..5b7215a --- /dev/null +++ b/color-picker/src/main/res/values-gu-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + "એક રંગ પસંદ કરો" + "રંગ %1$d" + "રંગ %1$d પસંદ કર્યો" + diff --git a/color-picker/src/main/res/values-hi/strings.xml b/color-picker/src/main/res/values-hi/strings.xml new file mode 100755 index 0000000..7b27b66 --- /dev/null +++ b/color-picker/src/main/res/values-hi/strings.xml @@ -0,0 +1,22 @@ + + + + + "कोई रंग चुनें:" + "रंग %1$d" + "रंग %1$d चयनित" + diff --git a/color-picker/src/main/res/values-hr/strings.xml b/color-picker/src/main/res/values-hr/strings.xml new file mode 100755 index 0000000..2ad3fcf --- /dev/null +++ b/color-picker/src/main/res/values-hr/strings.xml @@ -0,0 +1,22 @@ + + + + + "Odabir boje" + "Boja %1$d" + "Odabrana je boja %1$d" + diff --git a/color-picker/src/main/res/values-hu/strings.xml b/color-picker/src/main/res/values-hu/strings.xml new file mode 100755 index 0000000..4e22944 --- /dev/null +++ b/color-picker/src/main/res/values-hu/strings.xml @@ -0,0 +1,22 @@ + + + + + "Válasszon színt" + "%1$d. szín" + "%1$d. szín kiválasztva" + diff --git a/color-picker/src/main/res/values-hy-rAM/strings.xml b/color-picker/src/main/res/values-hy-rAM/strings.xml new file mode 100755 index 0000000..5a63133 --- /dev/null +++ b/color-picker/src/main/res/values-hy-rAM/strings.xml @@ -0,0 +1,22 @@ + + + + + "Ընտրեք գույնը" + "Գույնը %1$d" + "Ընտրվել է %1$d գույնը" + diff --git a/color-picker/src/main/res/values-in/strings.xml b/color-picker/src/main/res/values-in/strings.xml new file mode 100755 index 0000000..ef7d665 --- /dev/null +++ b/color-picker/src/main/res/values-in/strings.xml @@ -0,0 +1,22 @@ + + + + + "Pilih warna:" + "Warna %1$d" + "Warna %1$d dipilih" + diff --git a/color-picker/src/main/res/values-is-rIS/strings.xml b/color-picker/src/main/res/values-is-rIS/strings.xml new file mode 100755 index 0000000..1998b88 --- /dev/null +++ b/color-picker/src/main/res/values-is-rIS/strings.xml @@ -0,0 +1,22 @@ + + + + + "Veldu lit" + "Litur %1$d" + "Liturinn %1$d valinn" + diff --git a/color-picker/src/main/res/values-it/strings.xml b/color-picker/src/main/res/values-it/strings.xml new file mode 100755 index 0000000..8b899e4 --- /dev/null +++ b/color-picker/src/main/res/values-it/strings.xml @@ -0,0 +1,22 @@ + + + + + "Seleziona un colore" + "Colore %1$d" + "Colore selezionato: %1$d" + diff --git a/color-picker/src/main/res/values-iw/strings.xml b/color-picker/src/main/res/values-iw/strings.xml new file mode 100755 index 0000000..a4511f9 --- /dev/null +++ b/color-picker/src/main/res/values-iw/strings.xml @@ -0,0 +1,22 @@ + + + + + "בחר צבע" + "צבע %1$d" + "צבע %1$d נבחר" + diff --git a/color-picker/src/main/res/values-ja/strings.xml b/color-picker/src/main/res/values-ja/strings.xml new file mode 100755 index 0000000..7454447 --- /dev/null +++ b/color-picker/src/main/res/values-ja/strings.xml @@ -0,0 +1,22 @@ + + + + + "色の選択" + "色%1$d" + "色%1$dを選択しました" + diff --git a/color-picker/src/main/res/values-ka-rGE/strings.xml b/color-picker/src/main/res/values-ka-rGE/strings.xml new file mode 100755 index 0000000..594ba6d --- /dev/null +++ b/color-picker/src/main/res/values-ka-rGE/strings.xml @@ -0,0 +1,22 @@ + + + + + "ფერის არჩევა" + "ფერი %1$d" + "არჩეულია ფერი %1$d" + diff --git a/color-picker/src/main/res/values-kk-rKZ/strings.xml b/color-picker/src/main/res/values-kk-rKZ/strings.xml new file mode 100755 index 0000000..1eb2f26 --- /dev/null +++ b/color-picker/src/main/res/values-kk-rKZ/strings.xml @@ -0,0 +1,22 @@ + + + + + "Түсті таңдаңыз" + "%1$d түсі" + "%1$d түсі таңдалды" + diff --git a/color-picker/src/main/res/values-km-rKH/strings.xml b/color-picker/src/main/res/values-km-rKH/strings.xml new file mode 100755 index 0000000..7ca023b --- /dev/null +++ b/color-picker/src/main/res/values-km-rKH/strings.xml @@ -0,0 +1,22 @@ + + + + + "ជ្រើស​ពណ៌" + "ពណ៌ %1$d" + "បាន​ជ្រើស​ពណ៌ %1$d" + diff --git a/color-picker/src/main/res/values-kn-rIN/strings.xml b/color-picker/src/main/res/values-kn-rIN/strings.xml new file mode 100755 index 0000000..35becd1 --- /dev/null +++ b/color-picker/src/main/res/values-kn-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + "ಬಣ್ಣ ಆಯ್ಕೆಮಾಡಿ" + "ಬಣ್ಣ %1$d" + "%1$d ಬಣ್ಣವನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ" + diff --git a/color-picker/src/main/res/values-ko/strings.xml b/color-picker/src/main/res/values-ko/strings.xml new file mode 100755 index 0000000..5e06f99 --- /dev/null +++ b/color-picker/src/main/res/values-ko/strings.xml @@ -0,0 +1,22 @@ + + + + + "색상 선택" + "색상 %1$d" + "색상 %1$d이(가) 선택됨" + diff --git a/color-picker/src/main/res/values-ky-rKG/strings.xml b/color-picker/src/main/res/values-ky-rKG/strings.xml new file mode 100755 index 0000000..cb0f889 --- /dev/null +++ b/color-picker/src/main/res/values-ky-rKG/strings.xml @@ -0,0 +1,22 @@ + + + + + "Түс тандаңыз" + "Түс %1$d" + "%1$d түс тандалды" + diff --git a/color-picker/src/main/res/values-lo-rLA/strings.xml b/color-picker/src/main/res/values-lo-rLA/strings.xml new file mode 100755 index 0000000..8f005fe --- /dev/null +++ b/color-picker/src/main/res/values-lo-rLA/strings.xml @@ -0,0 +1,22 @@ + + + + + "ເລືອກ​ສີ​" + "ສີ %1$d" + "​ເລືອກສີ %1$d" + diff --git a/color-picker/src/main/res/values-lt/strings.xml b/color-picker/src/main/res/values-lt/strings.xml new file mode 100755 index 0000000..1610952 --- /dev/null +++ b/color-picker/src/main/res/values-lt/strings.xml @@ -0,0 +1,22 @@ + + + + + "Pasirinkite spalvą" + "%1$d spalva" + "%1$d spalva pasirinkta" + diff --git a/color-picker/src/main/res/values-lv/strings.xml b/color-picker/src/main/res/values-lv/strings.xml new file mode 100755 index 0000000..e844bce --- /dev/null +++ b/color-picker/src/main/res/values-lv/strings.xml @@ -0,0 +1,22 @@ + + + + + "Krāsas atlase" + "Krāsa Nr. %1$d" + "Atlasīta krāsa Nr. %1$d" + diff --git a/color-picker/src/main/res/values-mk-rMK/strings.xml b/color-picker/src/main/res/values-mk-rMK/strings.xml new file mode 100755 index 0000000..46bf1c0 --- /dev/null +++ b/color-picker/src/main/res/values-mk-rMK/strings.xml @@ -0,0 +1,22 @@ + + + + + "Изберете боја" + "Боја %1$d" + "Избрана е %1$d боја" + diff --git a/color-picker/src/main/res/values-ml-rIN/strings.xml b/color-picker/src/main/res/values-ml-rIN/strings.xml new file mode 100755 index 0000000..d5c1230 --- /dev/null +++ b/color-picker/src/main/res/values-ml-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + "ഒരു വർണ്ണം തിരഞ്ഞെടുക്കുക" + "വർണ്ണം %1$d" + "വർണ്ണം %1$d തിരഞ്ഞെടുത്തു" + diff --git a/color-picker/src/main/res/values-mn-rMN/strings.xml b/color-picker/src/main/res/values-mn-rMN/strings.xml new file mode 100755 index 0000000..25041c5 --- /dev/null +++ b/color-picker/src/main/res/values-mn-rMN/strings.xml @@ -0,0 +1,22 @@ + + + + + "Өнгө сонгоно уу" + "Өнгө %1$d" + "Өнгө %1$d сонгогдсон" + diff --git a/color-picker/src/main/res/values-mr-rIN/strings.xml b/color-picker/src/main/res/values-mr-rIN/strings.xml new file mode 100755 index 0000000..8b9c617 --- /dev/null +++ b/color-picker/src/main/res/values-mr-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + "एक रंग निवडा" + "रंग %1$d" + "%1$d रंग निवडला" + diff --git a/color-picker/src/main/res/values-ms-rMY/strings.xml b/color-picker/src/main/res/values-ms-rMY/strings.xml new file mode 100755 index 0000000..fbac381 --- /dev/null +++ b/color-picker/src/main/res/values-ms-rMY/strings.xml @@ -0,0 +1,22 @@ + + + + + "Pilih Warna" + "Warna %1$d" + "Warna %1$d dipilih" + diff --git a/color-picker/src/main/res/values-my-rMM/strings.xml b/color-picker/src/main/res/values-my-rMM/strings.xml new file mode 100755 index 0000000..eb3f1cb --- /dev/null +++ b/color-picker/src/main/res/values-my-rMM/strings.xml @@ -0,0 +1,22 @@ + + + + + "အရောင်ကို ရွေးပါ" + "အရောင် %1$d" + "အရောင်ကို %1$d ရွေးပြီး" + diff --git a/color-picker/src/main/res/values-nb/strings.xml b/color-picker/src/main/res/values-nb/strings.xml new file mode 100755 index 0000000..ce5a81e --- /dev/null +++ b/color-picker/src/main/res/values-nb/strings.xml @@ -0,0 +1,22 @@ + + + + + "Velg en farge" + "Farge %1$d" + "Farge %1$d er valgt" + diff --git a/color-picker/src/main/res/values-ne-rNP/strings.xml b/color-picker/src/main/res/values-ne-rNP/strings.xml new file mode 100755 index 0000000..d3a7275 --- /dev/null +++ b/color-picker/src/main/res/values-ne-rNP/strings.xml @@ -0,0 +1,22 @@ + + + + + "एउटा रङ्ग चयन गर्नहोस्" + "रङ्ग %1$d" + "%1$d रङ्ग चयन गरियो" + diff --git a/color-picker/src/main/res/values-nl/strings.xml b/color-picker/src/main/res/values-nl/strings.xml new file mode 100755 index 0000000..2dec3ea --- /dev/null +++ b/color-picker/src/main/res/values-nl/strings.xml @@ -0,0 +1,22 @@ + + + + + "Een kleur selecteren" + "Kleur %1$d" + "Kleur %1$d geselecteerd" + diff --git a/color-picker/src/main/res/values-pa-rIN/strings.xml b/color-picker/src/main/res/values-pa-rIN/strings.xml new file mode 100755 index 0000000..9fecb18 --- /dev/null +++ b/color-picker/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + "ਇੱਕ ਰੰਗ ਚੁਣੋ" + "ਰੰਗ %1$d" + "ਰੰਗ %1$d ਚੁਣਿਆ ਗਿਆ" + diff --git a/color-picker/src/main/res/values-pl/strings.xml b/color-picker/src/main/res/values-pl/strings.xml new file mode 100755 index 0000000..04b43ec --- /dev/null +++ b/color-picker/src/main/res/values-pl/strings.xml @@ -0,0 +1,22 @@ + + + + + "Wybierz kolor" + "Kolor %1$d" + "Wybrałeś kolor %1$d" + diff --git a/color-picker/src/main/res/values-pt-rPT/strings.xml b/color-picker/src/main/res/values-pt-rPT/strings.xml new file mode 100755 index 0000000..30fd75b --- /dev/null +++ b/color-picker/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,22 @@ + + + + + "Selecionar uma Cor" + "Cor %1$d" + "Cor %1$d selecionada" + diff --git a/color-picker/src/main/res/values-pt/strings.xml b/color-picker/src/main/res/values-pt/strings.xml new file mode 100755 index 0000000..5eca2e0 --- /dev/null +++ b/color-picker/src/main/res/values-pt/strings.xml @@ -0,0 +1,22 @@ + + + + + "Selecione uma cor" + "Cor %1$d" + "Cor %1$d selecionada" + diff --git a/color-picker/src/main/res/values-ro/strings.xml b/color-picker/src/main/res/values-ro/strings.xml new file mode 100755 index 0000000..bcc245d --- /dev/null +++ b/color-picker/src/main/res/values-ro/strings.xml @@ -0,0 +1,22 @@ + + + + + "Selectați o culoare" + "Culoarea %1$d" + "Culoarea %1$d este selectată" + diff --git a/color-picker/src/main/res/values-ru/strings.xml b/color-picker/src/main/res/values-ru/strings.xml new file mode 100755 index 0000000..0fc7a22 --- /dev/null +++ b/color-picker/src/main/res/values-ru/strings.xml @@ -0,0 +1,22 @@ + + + + + "Выберите цвет" + "Цвет: %1$d" + "Выбран цвет %1$d" + diff --git a/color-picker/src/main/res/values-si-rLK/strings.xml b/color-picker/src/main/res/values-si-rLK/strings.xml new file mode 100755 index 0000000..3aa4bf0 --- /dev/null +++ b/color-picker/src/main/res/values-si-rLK/strings.xml @@ -0,0 +1,22 @@ + + + + + "වර්ණයක් තෝරන්න" + "වර්ණය %1$d" + "%1$d වර්ණය තෝරාගන්නා ලදී" + diff --git a/color-picker/src/main/res/values-sk/strings.xml b/color-picker/src/main/res/values-sk/strings.xml new file mode 100755 index 0000000..900d3b2 --- /dev/null +++ b/color-picker/src/main/res/values-sk/strings.xml @@ -0,0 +1,22 @@ + + + + + "Vyberte farbu" + "Farba %1$d" + "Bola vybratá farba %1$d" + diff --git a/color-picker/src/main/res/values-sl/strings.xml b/color-picker/src/main/res/values-sl/strings.xml new file mode 100755 index 0000000..e62c9d3 --- /dev/null +++ b/color-picker/src/main/res/values-sl/strings.xml @@ -0,0 +1,22 @@ + + + + + "Izberite barvo:" + "Barva %1$d" + "Izbrana je barva %1$d" + diff --git a/color-picker/src/main/res/values-sq-rAL/strings.xml b/color-picker/src/main/res/values-sq-rAL/strings.xml new file mode 100755 index 0000000..2e21621 --- /dev/null +++ b/color-picker/src/main/res/values-sq-rAL/strings.xml @@ -0,0 +1,22 @@ + + + + + "Zgjidh një ngjyrë" + "Ngjyra %1$d" + "U zgjodh ngjyra %1$d" + diff --git a/color-picker/src/main/res/values-sr/strings.xml b/color-picker/src/main/res/values-sr/strings.xml new file mode 100755 index 0000000..6ca8340 --- /dev/null +++ b/color-picker/src/main/res/values-sr/strings.xml @@ -0,0 +1,22 @@ + + + + + "Изаберите боју" + "Боја %1$d" + "Боја %1$d је изабрана" + diff --git a/color-picker/src/main/res/values-sv/strings.xml b/color-picker/src/main/res/values-sv/strings.xml new file mode 100755 index 0000000..ac2514b --- /dev/null +++ b/color-picker/src/main/res/values-sv/strings.xml @@ -0,0 +1,22 @@ + + + + + "Välj en färg" + "Färg %1$d" + "Färg %1$d vald" + diff --git a/color-picker/src/main/res/values-sw/strings.xml b/color-picker/src/main/res/values-sw/strings.xml new file mode 100755 index 0000000..fb1d587 --- /dev/null +++ b/color-picker/src/main/res/values-sw/strings.xml @@ -0,0 +1,22 @@ + + + + + "Chagua Rangi" + "Rangi %1$d" + "Rangi %1$d iliyochaguliwa" + diff --git a/color-picker/src/main/res/values-ta-rIN/strings.xml b/color-picker/src/main/res/values-ta-rIN/strings.xml new file mode 100755 index 0000000..bb5a952 --- /dev/null +++ b/color-picker/src/main/res/values-ta-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + "வண்ணத்தைத் தேர்ந்தெடுக்கவும்" + "வண்ணம் %1$d" + "வண்ணம் %1$d தேர்ந்தெடுக்கப்பட்டது" + diff --git a/color-picker/src/main/res/values-te-rIN/strings.xml b/color-picker/src/main/res/values-te-rIN/strings.xml new file mode 100755 index 0000000..97332f9 --- /dev/null +++ b/color-picker/src/main/res/values-te-rIN/strings.xml @@ -0,0 +1,22 @@ + + + + + "రంగును ఎంచుకోండి" + "రంగు %1$d" + "రంగు %1$d ఎంచుకోబడింది" + diff --git a/color-picker/src/main/res/values-th/strings.xml b/color-picker/src/main/res/values-th/strings.xml new file mode 100755 index 0000000..e2d2934 --- /dev/null +++ b/color-picker/src/main/res/values-th/strings.xml @@ -0,0 +1,22 @@ + + + + + "เลือกสี" + "สี %1$d" + "เลือกสี %1$d" + diff --git a/color-picker/src/main/res/values-tl/strings.xml b/color-picker/src/main/res/values-tl/strings.xml new file mode 100755 index 0000000..e7fb303 --- /dev/null +++ b/color-picker/src/main/res/values-tl/strings.xml @@ -0,0 +1,22 @@ + + + + + "Pumili ng Kulay" + "Kulay na %1$d" + "Napili ang kulay na %1$d" + diff --git a/color-picker/src/main/res/values-tr/strings.xml b/color-picker/src/main/res/values-tr/strings.xml new file mode 100755 index 0000000..4157d96 --- /dev/null +++ b/color-picker/src/main/res/values-tr/strings.xml @@ -0,0 +1,22 @@ + + + + + "Bir Renk Seçin" + "Renk %1$d" + "Renk %1$d seçildi" + diff --git a/color-picker/src/main/res/values-uk/strings.xml b/color-picker/src/main/res/values-uk/strings.xml new file mode 100755 index 0000000..a8bf87b --- /dev/null +++ b/color-picker/src/main/res/values-uk/strings.xml @@ -0,0 +1,22 @@ + + + + + "Вибрати колір" + "Колір %1$d" + "Вибрано колір: %1$d" + diff --git a/color-picker/src/main/res/values-ur-rPK/strings.xml b/color-picker/src/main/res/values-ur-rPK/strings.xml new file mode 100755 index 0000000..f748471 --- /dev/null +++ b/color-picker/src/main/res/values-ur-rPK/strings.xml @@ -0,0 +1,22 @@ + + + + + "ایک رنگ منتخب کریں" + "رنگ %1$d" + "رنگ %1$d منتخب کیا گیا" + diff --git a/color-picker/src/main/res/values-uz-rUZ/strings.xml b/color-picker/src/main/res/values-uz-rUZ/strings.xml new file mode 100755 index 0000000..81ac010 --- /dev/null +++ b/color-picker/src/main/res/values-uz-rUZ/strings.xml @@ -0,0 +1,22 @@ + + + + + "Rang tanlash" + "%1$d rangi" + "%1$d rangi tanlandi" + diff --git a/color-picker/src/main/res/values-vi/strings.xml b/color-picker/src/main/res/values-vi/strings.xml new file mode 100755 index 0000000..e027169 --- /dev/null +++ b/color-picker/src/main/res/values-vi/strings.xml @@ -0,0 +1,22 @@ + + + + + "Chọn màu" + "Màu %1$d" + "Đã chọn màu %1$d" + diff --git a/color-picker/src/main/res/values-zh-rCN/strings.xml b/color-picker/src/main/res/values-zh-rCN/strings.xml new file mode 100755 index 0000000..3e12d6f --- /dev/null +++ b/color-picker/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,35 @@ + + + + + "选择颜色" + "颜色 %1$d" + "已选择颜色 %1$d" + + 番茄红 + 橘红 + 香蕉黄 + 罗勒绿 + 鼠尾草绿 + 孔雀蓝 + 蓝莓色 + 薰衣草色 + 葡萄紫 + 红鹤色 + 石墨黑 + 默认颜色 + diff --git a/color-picker/src/main/res/values-zh-rHK/strings.xml b/color-picker/src/main/res/values-zh-rHK/strings.xml new file mode 100755 index 0000000..5fffb7f --- /dev/null +++ b/color-picker/src/main/res/values-zh-rHK/strings.xml @@ -0,0 +1,22 @@ + + + + + "選取顏色" + "顏色 %1$d" + "已選取顏色 %1$d" + diff --git a/color-picker/src/main/res/values-zh-rTW/strings.xml b/color-picker/src/main/res/values-zh-rTW/strings.xml new file mode 100755 index 0000000..86e4782 --- /dev/null +++ b/color-picker/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,22 @@ + + + + + "選取顏色" + "色彩 %1$d" + "已選取色彩 %1$d" + diff --git a/color-picker/src/main/res/values-zu/strings.xml b/color-picker/src/main/res/values-zu/strings.xml new file mode 100755 index 0000000..98e213f --- /dev/null +++ b/color-picker/src/main/res/values-zu/strings.xml @@ -0,0 +1,22 @@ + + + + + "Khetha umbala" + "Umbala we-%1$d" + "Umbala we-%1$d ukhethiwe" + diff --git a/color-picker/src/main/res/values/arrays.xml b/color-picker/src/main/res/values/arrays.xml new file mode 100755 index 0000000..c975211 --- /dev/null +++ b/color-picker/src/main/res/values/arrays.xml @@ -0,0 +1,29 @@ + + + + @color/tomato + @color/tangerine + @color/banana + @color/basil + @color/sage + @color/peacock + @color/blueberry + @color/lavender + @color/grape + @color/flamingo + @color/graphite + + + @string/tomato + @string/tangerine + @string/banana + @string/basil + @string/sage + @string/peacock + @string/blueberry + @string/lavender + @string/grape + @string/flamingo + @string/graphite + + \ No newline at end of file diff --git a/color-picker/src/main/res/values/attrs.xml b/color-picker/src/main/res/values/attrs.xml new file mode 100755 index 0000000..5176273 --- /dev/null +++ b/color-picker/src/main/res/values/attrs.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/color-picker/src/main/res/values/colors.xml b/color-picker/src/main/res/values/colors.xml new file mode 100755 index 0000000..a80da26 --- /dev/null +++ b/color-picker/src/main/res/values/colors.xml @@ -0,0 +1,30 @@ + + + + #33b5e5 + #ff8800 + #ff4444 + + #FF007F + #FF0000 + #FF7F00 + #FFFF00 + #00FF00 + #00FFFF + #007FFF + #0000FF + #7F00FF + #FF00FF + + #d50000 + #f4511e + #f6bf26 + #0b8043 + #33b679 + #039be5 + #3f51b5 + #7986cb + #8e24aa + #e67c73 + #616161 + \ No newline at end of file diff --git a/color-picker/src/main/res/values/dimens.xml b/color-picker/src/main/res/values/dimens.xml new file mode 100755 index 0000000..fc78f2f --- /dev/null +++ b/color-picker/src/main/res/values/dimens.xml @@ -0,0 +1,21 @@ + + + + 64dip + 48dip + 8dip + 4dip + \ No newline at end of file diff --git a/color-picker/src/main/res/values/strings.xml b/color-picker/src/main/res/values/strings.xml new file mode 100755 index 0000000..00af993 --- /dev/null +++ b/color-picker/src/main/res/values/strings.xml @@ -0,0 +1,36 @@ + + + + + Select a Color + + Color %1$d + + Color %1$d selected + + Tomato + Tangerine + Banana + Basil + Sage + Peacock + Blueberry + Lavender + Grape + Flamingo + Graphite + Default color + \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..aac7c9b --- /dev/null +++ b/gradle.properties @@ -0,0 +1,17 @@ +# 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. +org.gradle.jvmargs=-Xmx1536m + +# 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 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..13372aef5e24af05341d49695ee84e5f9b594659 GIT binary patch literal 53636 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ⅅ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 H-+%o-(+5aQ literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..04e285f --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Dec 28 10:00:20 PST 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..9d82f78 --- /dev/null +++ b/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..12fb689 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app', ':color-picker'