From 22db727dbf1d04fe001659a361778ad540ffd4af Mon Sep 17 00:00:00 2001
From: Floens
Date: Mon, 18 May 2015 00:59:30 +0200
Subject: [PATCH] Remove old classes and xml files
Removing all old activities/fragments/views that are not used in the new UI system.
Make all icons material.
Make lint happy(ier)
Add license headers where missing.
---
Clover/app/src/main/AndroidManifest.xml | 59 +-
.../android/dslv/DragSortController.java | 469 ---
.../android/dslv/DragSortCursorAdapter.java | 239 --
.../mobeta/android/dslv/DragSortItemView.java | 92 -
.../dslv/DragSortItemViewCheckable.java | 46 -
.../mobeta/android/dslv/DragSortListView.java | 2974 -----------------
.../dslv/ResourceDragSortCursorAdapter.java | 155 -
.../dslv/SimpleDragSortCursorAdapter.java | 448 ---
.../android/dslv/SimpleFloatViewManager.java | 87 -
.../src/main/java/org/floens/chan/Chan.java | 220 ++
.../java/org/floens/chan/ChanApplication.java | 204 +-
.../org/floens/chan/chan/ImageSearch.java | 6 +-
.../chan/controller/ControllerLogic.java | 17 +
.../chan/controller/FadeInTransition.java | 17 +
.../chan/controller/FadeOutTransition.java | 17 +
.../chan/{utils => core/cache}/FileCache.java | 9 +-
.../floens/chan/core/loader/ChanLoader.java | 62 +-
.../floens/chan/core/loader/ChanParser.java | 12 +-
.../chan/core/loader/EndOfLineException.java | 37 -
.../chan/core/manager/BoardManager.java | 10 +-
.../chan/core/manager/ThreadManager.java | 604 ----
.../chan/core/manager/WatchManager.java | 26 +-
.../org/floens/chan/core/model/Loadable.java | 40 +-
.../java/org/floens/chan/core/model/Post.java | 6 +-
.../org/floens/chan/core/model/PostImage.java | 17 +
.../chan/core/net/ByteArrayRequest.java | 47 -
.../chan/core/net/ChanReaderRequest.java | 50 +-
.../org/floens/chan/core/net/FileRequest.java | 58 -
.../chan/core/net/JsonReaderRequest.java | 11 +-
.../core/presenter/ImageViewerPresenter.java | 17 +
.../chan/core/presenter/ReplyPresenter.java | 31 +-
.../chan/core/presenter/ThreadPresenter.java | 8 +-
.../org/floens/chan/core/reply/HttpCall.java | 17 +
.../floens/chan/core/reply/ReplyHttpCall.java | 17 +
.../floens/chan/core/reply/ReplyManager.java | 189 +-
.../chan/core/settings/BooleanSetting.java | 17 +
.../chan/core/settings/ChanSettings.java | 201 +-
.../floens/chan/core/settings/Setting.java | 17 +
.../chan/core/settings/StringSetting.java | 17 +
.../floens/chan/core/watch/PinWatcher.java | 6 +-
.../org/floens/chan/test/TestActivity.java | 6 +-
.../org/floens/chan/ui/ThemeActivity.java | 48 -
.../chan/ui/activity/AboutActivity.java | 41 -
.../ui/activity/AdvancedSettingsActivity.java | 134 -
.../floens/chan/ui/activity/BaseActivity.java | 384 ---
.../floens/chan/ui/activity/BoardEditor.java | 451 ---
.../floens/chan/ui/activity/ChanActivity.java | 759 -----
.../chan/ui/activity/DeveloperActivity.java | 109 -
.../chan/ui/activity/ImagePickActivity.java | 4 +-
.../chan/ui/activity/ImageViewActivity.java | 271 --
.../chan/ui/activity/LicenseActivity.java | 38 -
.../ui/activity/PassSettingsActivity.java | 188 --
.../chan/ui/activity/ReplyActivity.java | 81 -
.../chan/ui/activity/SettingsActivity.java | 90 -
.../chan/ui/activity/StartActivity.java | 25 +-
.../ui/activity/WatchSettingsActivity.java | 198 --
.../chan/ui/adapter/ImageViewAdapter.java | 67 -
.../chan/ui/adapter/ImageViewerAdapter.java | 17 +
.../floens/chan/ui/adapter/PinAdapter.java | 36 +-
.../floens/chan/ui/adapter/PinnedAdapter.java | 231 --
.../chan/ui/animation/ScrollerRunnable.java | 140 -
.../SwipeDismissListViewTouchListener.java | 409 ---
.../ui/animation/ViewFlipperAnimations.java | 55 -
.../org/floens/chan/ui/cell/PostCell.java | 36 +-
.../floens/chan/ui/cell/ThreadStatusCell.java | 19 +-
.../AdvancedSettingsController.java | 24 +-
.../ui/controller/BoardEditController.java | 23 +-
.../chan/ui/controller/BrowseController.java | 12 +-
.../DeveloperSettingsController.java | 27 +-
.../ui/controller/ImageViewerController.java | 25 +-
.../ImageViewerNavigationController.java | 17 +
.../ui/controller/LicensesController.java | 17 +
.../ui/controller/PassSettingsController.java | 21 +-
.../ui/controller/PostRepliesController.java | 35 +-
.../controller/RootNavigationController.java | 6 +-
.../chan/ui/controller/ThreadController.java | 21 +-
.../ui/controller/ViewThreadController.java | 10 +-
.../controller/WatchSettingsController.java | 17 +
.../ui/drawable/DropdownArrowDrawable.java | 17 +
.../chan/ui/drawable/ThumbDrawable.java | 18 +-
.../chan/ui/fragment/FolderPickFragment.java | 6 +-
.../chan/ui/fragment/ImageViewFragment.java | 354 --
.../chan/ui/fragment/PostRepliesFragment.java | 175 -
.../chan/ui/fragment/ReplyFragment.java | 609 ----
.../chan/ui/fragment/SettingsFragment.java | 201 --
.../chan/ui/fragment/ThreadFragment.java | 648 ----
.../org/floens/chan/ui/helper/PostHelper.java | 17 +
.../chan/ui/helper/SwipeItemAnimator.java | 17 +
.../floens/chan/ui/helper/SwipeListener.java | 19 +-
.../floens/chan/ui/layout/ReplyLayout.java | 19 +-
.../floens/chan/ui/layout/ThreadLayout.java | 6 +-
.../floens/chan/ui/service/WatchNotifier.java | 17 +-
.../chan/ui/settings/BooleanSettingView.java | 17 +
.../chan/ui/settings/LinkSettingView.java | 17 +
.../chan/ui/settings/ListSettingView.java | 17 +
.../floens/chan/ui/settings/SettingView.java | 17 +
.../chan/ui/settings/SettingsController.java | 17 +
.../chan/ui/settings/SettingsGroup.java | 17 +
.../chan/ui/settings/StringSettingView.java | 17 +
.../chan/ui/toolbar/NavigationItem.java | 2 -
.../org/floens/chan/ui/toolbar/Toolbar.java | 11 +-
.../floens/chan/ui/toolbar/ToolbarMenu.java | 2 +-
.../chan/ui/toolbar/ToolbarMenuItem.java | 10 +-
.../chan/ui/transition/ImageTransition.java | 10 -
.../floens/chan/ui/view/CrossfadeView.java | 17 +
.../chan/ui/view/CustomNetworkImageView.java | 296 --
.../chan/ui/view/CustomScaleImageView.java | 18 +
.../org/floens/chan/ui/view/DragGripView.java | 119 -
.../org/floens/chan/ui/view/FloatingMenu.java | 1 -
.../floens/chan/ui/view/HackyViewPager.java | 58 -
.../org/floens/chan/ui/view/LoadingBar.java | 17 +
.../floens/chan/ui/view/MultiImageView.java | 15 +-
.../chan/ui/view/OptionalSwipeViewPager.java | 17 +
.../org/floens/chan/ui/view/PostView.java | 633 ----
.../ui/view/SelectionListeningEditText.java | 17 +
.../floens/chan/ui/view/ThumbnailView.java | 21 +-
.../ui/view/TouchBlockingFrameLayout.java | 20 +-
.../chan/ui/view/TransitionImageView.java | 17 +
.../floens/chan/ui/view/ViewPagerAdapter.java | 21 +-
.../org/floens/chan/utils/AndroidUtils.java | 35 +-
.../java/org/floens/chan/utils/IconCache.java | 40 -
.../org/floens/chan/utils/ImageSaver.java | 11 +-
.../org/floens/chan/utils/ThemeHelper.java | 10 +-
.../drawable-hdpi/ic_action_attachment.png | Bin 509 -> 0 bytes
.../ic_action_attachment_dark.png | Bin 472 -> 0 bytes
.../main/res/drawable-hdpi/ic_action_back.png | Bin 351 -> 0 bytes
.../res/drawable-hdpi/ic_action_back_dark.png | Bin 296 -> 0 bytes
.../res/drawable-hdpi/ic_action_cancel.png | Bin 438 -> 0 bytes
.../drawable-hdpi/ic_action_cancel_dark.png | Bin 353 -> 0 bytes
.../main/res/drawable-hdpi/ic_action_done.png | Bin 1320 -> 0 bytes
.../res/drawable-hdpi/ic_action_done_dark.png | Bin 392 -> 0 bytes
.../main/res/drawable-hdpi/ic_action_new.png | Bin 262 -> 0 bytes
.../main/res/drawable-hdpi/ic_action_play.png | Bin 437 -> 0 bytes
.../res/drawable-hdpi/ic_action_refresh.png | Bin 531 -> 0 bytes
.../res/drawable-hdpi/ic_action_write.png | Bin 351 -> 0 bytes
.../ic_arrow_back_black_24dp.png | Bin 0 -> 147 bytes
.../ic_arrow_back_white_24dp.png | Bin 0 -> 152 bytes
.../main/res/drawable-hdpi/ic_bookmark.png | Bin 330 -> 0 bytes
.../res/drawable-hdpi/ic_bookmark_filled.png | Bin 273 -> 0 bytes
.../ic_bookmark_outline_white_24dp.png | Bin 0 -> 239 bytes
.../drawable-hdpi/ic_bookmark_white_24dp.png | Bin 0 -> 185 bytes
.../drawable-hdpi/ic_create_white_24dp.png | Bin 0 -> 214 bytes
.../res/drawable-hdpi/ic_done_black_24dp.png | Bin 0 -> 177 bytes
.../res/drawable-hdpi/ic_done_white_24dp.png | Bin 0 -> 188 bytes
.../src/main/res/drawable-hdpi/ic_drawer.png | Bin 2826 -> 0 bytes
.../src/main/res/drawable-hdpi/ic_more.png | Bin 219 -> 0 bytes
.../drawable-hdpi/ic_more_vert_white_24dp.png | Bin 0 -> 134 bytes
.../drawable-hdpi/ic_refresh_white_24dp.png | Bin 0 -> 387 bytes
.../main/res/drawable-hdpi/panel_shadow.9.png | Bin 111 -> 0 bytes
.../progress_primary_holo_light.9.png | Bin 873 -> 0 bytes
.../res/drawable-hdpi/skip_arrow_down.png | Bin 595 -> 0 bytes
.../main/res/drawable-hdpi/skip_arrow_up.png | Bin 572 -> 0 bytes
.../drawable-mdpi/ic_action_attachment.png | Bin 379 -> 0 bytes
.../ic_action_attachment_dark.png | Bin 379 -> 0 bytes
.../main/res/drawable-mdpi/ic_action_back.png | Bin 336 -> 0 bytes
.../res/drawable-mdpi/ic_action_back_dark.png | Bin 272 -> 0 bytes
.../res/drawable-mdpi/ic_action_cancel.png | Bin 328 -> 0 bytes
.../drawable-mdpi/ic_action_cancel_dark.png | Bin 272 -> 0 bytes
.../main/res/drawable-mdpi/ic_action_done.png | Bin 1197 -> 0 bytes
.../res/drawable-mdpi/ic_action_done_dark.png | Bin 246 -> 0 bytes
.../main/res/drawable-mdpi/ic_action_new.png | Bin 185 -> 0 bytes
.../main/res/drawable-mdpi/ic_action_play.png | Bin 339 -> 0 bytes
.../res/drawable-mdpi/ic_action_refresh.png | Bin 346 -> 0 bytes
.../res/drawable-mdpi/ic_action_write.png | Bin 272 -> 0 bytes
.../ic_arrow_back_black_24dp.png | Bin 0 -> 114 bytes
.../ic_arrow_back_white_24dp.png | Bin 0 -> 118 bytes
.../main/res/drawable-mdpi/ic_bookmark.png | Bin 262 -> 0 bytes
.../res/drawable-mdpi/ic_bookmark_filled.png | Bin 223 -> 0 bytes
.../ic_bookmark_outline_white_24dp.png | Bin 0 -> 176 bytes
.../drawable-mdpi/ic_bookmark_white_24dp.png | Bin 0 -> 139 bytes
.../drawable-mdpi/ic_create_white_24dp.png | Bin 0 -> 165 bytes
.../res/drawable-mdpi/ic_done_black_24dp.png | Bin 0 -> 130 bytes
.../res/drawable-mdpi/ic_done_white_24dp.png | Bin 0 -> 139 bytes
.../src/main/res/drawable-mdpi/ic_drawer.png | Bin 2816 -> 0 bytes
.../src/main/res/drawable-mdpi/ic_more.png | Bin 202 -> 0 bytes
.../drawable-mdpi/ic_more_vert_white_24dp.png | Bin 0 -> 112 bytes
.../drawable-mdpi/ic_refresh_white_24dp.png | Bin 0 -> 254 bytes
.../main/res/drawable-mdpi/panel_shadow.9.png | Bin 100 -> 0 bytes
.../progress_primary_holo_light.9.png | Bin 561 -> 0 bytes
.../res/drawable-mdpi/skip_arrow_down.png | Bin 452 -> 0 bytes
.../main/res/drawable-mdpi/skip_arrow_up.png | Bin 424 -> 0 bytes
.../drawable-xhdpi/ic_action_attachment.png | Bin 653 -> 0 bytes
.../ic_action_attachment_dark.png | Bin 590 -> 0 bytes
.../res/drawable-xhdpi/ic_action_back.png | Bin 468 -> 0 bytes
.../drawable-xhdpi/ic_action_back_dark.png | Bin 401 -> 0 bytes
.../res/drawable-xhdpi/ic_action_cancel.png | Bin 513 -> 0 bytes
.../drawable-xhdpi/ic_action_cancel_dark.png | Bin 415 -> 0 bytes
.../res/drawable-xhdpi/ic_action_done.png | Bin 1546 -> 0 bytes
.../drawable-xhdpi/ic_action_done_dark.png | Bin 475 -> 0 bytes
.../main/res/drawable-xhdpi/ic_action_new.png | Bin 234 -> 0 bytes
.../res/drawable-xhdpi/ic_action_play.png | Bin 522 -> 0 bytes
.../res/drawable-xhdpi/ic_action_refresh.png | Bin 637 -> 0 bytes
.../res/drawable-xhdpi/ic_action_write.png | Bin 378 -> 0 bytes
.../ic_arrow_back_black_24dp.png | Bin 0 -> 146 bytes
.../ic_arrow_back_white_24dp.png | Bin 0 -> 151 bytes
.../main/res/drawable-xhdpi/ic_bookmark.png | Bin 401 -> 0 bytes
.../res/drawable-xhdpi/ic_bookmark_filled.png | Bin 341 -> 0 bytes
.../ic_bookmark_outline_white_24dp.png | Bin 0 -> 273 bytes
.../drawable-xhdpi/ic_bookmark_white_24dp.png | Bin 0 -> 213 bytes
.../drawable-xhdpi/ic_create_white_24dp.png | Bin 0 -> 239 bytes
.../res/drawable-xhdpi/ic_done_black_24dp.png | Bin 0 -> 188 bytes
.../res/drawable-xhdpi/ic_done_white_24dp.png | Bin 0 -> 199 bytes
.../src/main/res/drawable-xhdpi/ic_drawer.png | Bin 1038 -> 0 bytes
.../src/main/res/drawable-xhdpi/ic_more.png | Bin 269 -> 0 bytes
.../ic_more_vert_white_24dp.png | Bin 0 -> 158 bytes
.../drawable-xhdpi/ic_refresh_white_24dp.png | Bin 0 -> 509 bytes
.../res/drawable-xhdpi/panel_shadow.9.png | Bin 119 -> 0 bytes
.../progress_primary_holo_light.9.png | Bin 1285 -> 0 bytes
.../res/drawable-xhdpi/skip_arrow_down.png | Bin 705 -> 0 bytes
.../main/res/drawable-xhdpi/skip_arrow_up.png | Bin 690 -> 0 bytes
.../drawable-xxhdpi/ic_action_attachment.png | Bin 926 -> 0 bytes
.../ic_action_attachment_dark.png | Bin 822 -> 0 bytes
.../res/drawable-xxhdpi/ic_action_back.png | Bin 527 -> 0 bytes
.../drawable-xxhdpi/ic_action_back_dark.png | Bin 463 -> 0 bytes
.../res/drawable-xxhdpi/ic_action_cancel.png | Bin 567 -> 0 bytes
.../drawable-xxhdpi/ic_action_cancel_dark.png | Bin 574 -> 0 bytes
.../res/drawable-xxhdpi/ic_action_done.png | Bin 649 -> 0 bytes
.../drawable-xxhdpi/ic_action_done_dark.png | Bin 619 -> 0 bytes
.../res/drawable-xxhdpi/ic_action_new.png | Bin 288 -> 0 bytes
.../res/drawable-xxhdpi/ic_action_play.png | Bin 702 -> 0 bytes
.../res/drawable-xxhdpi/ic_action_refresh.png | Bin 875 -> 0 bytes
.../res/drawable-xxhdpi/ic_action_write.png | Bin 490 -> 0 bytes
.../ic_arrow_back_black_24dp.png | Bin 0 -> 179 bytes
.../ic_arrow_back_white_24dp.png | Bin 0 -> 188 bytes
.../main/res/drawable-xxhdpi/ic_bookmark.png | Bin 525 -> 0 bytes
.../drawable-xxhdpi/ic_bookmark_filled.png | Bin 419 -> 0 bytes
.../ic_bookmark_outline_white_24dp.png | Bin 0 -> 370 bytes
.../ic_bookmark_white_24dp.png | Bin 0 -> 273 bytes
.../drawable-xxhdpi/ic_create_white_24dp.png | Bin 0 -> 302 bytes
.../drawable-xxhdpi/ic_done_black_24dp.png | Bin 0 -> 227 bytes
.../drawable-xxhdpi/ic_done_white_24dp.png | Bin 0 -> 255 bytes
.../main/res/drawable-xxhdpi/ic_drawer.png | Bin 202 -> 0 bytes
.../src/main/res/drawable-xxhdpi/ic_more.png | Bin 313 -> 0 bytes
.../ic_more_vert_white_24dp.png | Bin 0 -> 216 bytes
.../drawable-xxhdpi/ic_refresh_white_24dp.png | Bin 0 -> 734 bytes
.../res/drawable-xxhdpi/panel_shadow.9.png | Bin 144 -> 0 bytes
.../progress_primary_holo_light.9.png | Bin 3029 -> 0 bytes
.../res/drawable-xxhdpi/skip_arrow_down.png | Bin 969 -> 0 bytes
.../res/drawable-xxhdpi/skip_arrow_up.png | Bin 899 -> 0 bytes
.../drawable-xxxhdpi/ic_action_refresh.png | Bin 1148 -> 0 bytes
.../res/drawable-xxxhdpi/ic_action_write.png | Bin 632 -> 0 bytes
.../ic_arrow_back_black_24dp.png | Bin 0 -> 216 bytes
.../ic_arrow_back_white_24dp.png | Bin 0 -> 231 bytes
.../main/res/drawable-xxxhdpi/ic_bookmark.png | Bin 659 -> 0 bytes
.../drawable-xxxhdpi/ic_bookmark_filled.png | Bin 517 -> 0 bytes
.../ic_bookmark_outline_white_24dp.png | Bin 0 -> 466 bytes
.../ic_bookmark_white_24dp.png | Bin 0 -> 351 bytes
.../drawable-xxxhdpi/ic_create_white_24dp.png | Bin 0 -> 355 bytes
.../drawable-xxxhdpi/ic_done_black_24dp.png | Bin 0 -> 277 bytes
.../drawable-xxxhdpi/ic_done_white_24dp.png | Bin 0 -> 308 bytes
.../src/main/res/drawable-xxxhdpi/ic_more.png | Bin 393 -> 0 bytes
.../ic_more_vert_white_24dp.png | Bin 0 -> 305 bytes
.../ic_refresh_white_24dp.png | Bin 0 -> 967 bytes
.../res/drawable-xxxhdpi/skip_arrow_down.png | Bin 1108 -> 0 bytes
.../res/drawable-xxxhdpi/skip_arrow_up.png | Bin 1089 -> 0 bytes
.../src/main/res/drawable/pin_icon_blue.xml | 27 -
.../src/main/res/drawable/pin_icon_gray.xml | 27 -
.../src/main/res/drawable/pin_icon_red.xml | 27 -
.../preference_description_bottom.xml | 5 -
.../drawable/preference_description_top.xml | 5 -
.../main/res/drawable/progressbar_no_bg.xml | 24 -
.../setting_description_bottom.xml} | 10 +-
.../setting_description_top.xml} | 10 +-
.../app/src/main/res/layout/activity_base.xml | 61 -
.../src/main/res/layout/board_edit_item.xml | 42 -
.../src/main/res/layout/board_select_add.xml | 30 -
.../main/res/layout/board_select_spinner.xml | 29 -
.../layout/board_select_spinner_dropdown.xml | 29 -
.../src/main/res/layout/cell_board_edit.xml | 26 +-
.../res/layout/cell_board_edit_header.xml | 22 +-
.../app/src/main/res/layout/cell_header.xml | 26 +-
Clover/app/src/main/res/layout/cell_link.xml | 26 +-
Clover/app/src/main/res/layout/cell_pin.xml | 28 +-
Clover/app/src/main/res/layout/cell_post.xml | 22 +-
.../main/res/layout/cell_thread_status.xml | 24 +-
.../main/res/layout/controller_board_edit.xml | 30 +-
.../res/layout/controller_image_viewer.xml | 26 +-
.../layout/controller_navigation_drawer.xml | 12 +-
.../controller_navigation_image_viewer.xml | 4 +-
.../main/res/layout/dialog_video_error.xml | 40 +-
.../{watch_description.xml => dialog_web.xml} | 10 +-
...lder_pick.xml => fragment_folder_pick.xml} | 8 +-
.../main/res/layout/header_switch_layout.xml | 63 -
Clover/app/src/main/res/layout/image_view.xml | 48 -
.../app/src/main/res/layout/layout_reply.xml | 6 -
.../main/res/layout/layout_reply_input.xml | 18 +-
.../main/res/layout/layout_thread_error.xml | 26 +-
.../main/res/layout/layout_thread_list.xml | 18 +-
Clover/app/src/main/res/layout/pin_item.xml | 84 -
.../src/main/res/layout/pin_item_header.xml | 32 -
.../app/src/main/res/layout/post_replies.xml | 8 +-
.../res/layout/post_replies_bottombuttons.xml | 8 +-
.../src/main/res/layout/preference_pass.xml | 44 -
.../app/src/main/res/layout/reply_input.xml | 146 -
Clover/app/src/main/res/layout/reply_view.xml | 84 -
.../src/main/res/layout/setting_boolean.xml | 22 +-
.../main/res/layout/setting_description.xml | 23 +-
.../src/main/res/layout/setting_divider.xml | 18 +-
.../app/src/main/res/layout/setting_group.xml | 38 +-
.../app/src/main/res/layout/setting_link.xml | 22 +-
.../app/src/main/res/layout/settings_pass.xml | 66 +-
.../src/main/res/layout/settings_watch.xml | 20 +-
Clover/app/src/main/res/layout/toolbar.xml | 26 -
.../src/main/res/layout/toolbar_activity.xml | 30 -
.../app/src/main/res/layout/toolbar_menu.xml | 46 +-
.../src/main/res/layout/toolbar_menu_item.xml | 26 +-
Clover/app/src/main/res/layout/web_dialog.xml | 11 -
.../src/main/res/menu/action_bar_switch.xml | 27 -
Clover/app/src/main/res/menu/base.xml | 144 -
Clover/app/src/main/res/menu/board_edit.xml | 33 -
Clover/app/src/main/res/menu/image_view.xml | 55 -
Clover/app/src/main/res/menu/settings.xml | 25 -
Clover/app/src/main/res/values/attrs.xml | 2 +
Clover/app/src/main/res/values/colors.xml | 25 -
Clover/app/src/main/res/values/dimens.xml | 25 -
Clover/app/src/main/res/values/ids.xml | 30 -
.../app/src/main/res/values/string_arrays.xml | 68 -
Clover/app/src/main/res/values/strings.xml | 233 +-
Clover/app/src/main/res/values/styles.xml | 156 +-
.../app/src/main/res/values/watch_strings.xml | 41 -
Clover/app/src/main/res/xml/preference.xml | 125 -
.../src/main/res/xml/preference_advanced.xml | 65 -
.../app/src/main/res/xml/preference_pass.xml | 33 -
.../app/src/main/res/xml/preference_watch.xml | 68 -
324 files changed, 1820 insertions(+), 15226 deletions(-)
delete mode 100644 Clover/app/src/main/java/com/mobeta/android/dslv/DragSortController.java
delete mode 100644 Clover/app/src/main/java/com/mobeta/android/dslv/DragSortCursorAdapter.java
delete mode 100644 Clover/app/src/main/java/com/mobeta/android/dslv/DragSortItemView.java
delete mode 100644 Clover/app/src/main/java/com/mobeta/android/dslv/DragSortItemViewCheckable.java
delete mode 100644 Clover/app/src/main/java/com/mobeta/android/dslv/DragSortListView.java
delete mode 100644 Clover/app/src/main/java/com/mobeta/android/dslv/ResourceDragSortCursorAdapter.java
delete mode 100644 Clover/app/src/main/java/com/mobeta/android/dslv/SimpleDragSortCursorAdapter.java
delete mode 100644 Clover/app/src/main/java/com/mobeta/android/dslv/SimpleFloatViewManager.java
create mode 100644 Clover/app/src/main/java/org/floens/chan/Chan.java
rename Clover/app/src/main/java/org/floens/chan/{utils => core/cache}/FileCache.java (98%)
delete mode 100644 Clover/app/src/main/java/org/floens/chan/core/loader/EndOfLineException.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/core/net/ByteArrayRequest.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/core/net/FileRequest.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/ThemeActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/AboutActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/AdvancedSettingsActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/BoardEditor.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/DeveloperActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/ImageViewActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/LicenseActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/PassSettingsActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/ReplyActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/SettingsActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/activity/WatchSettingsActivity.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewAdapter.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/animation/ScrollerRunnable.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/animation/SwipeDismissListViewTouchListener.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/animation/ViewFlipperAnimations.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/fragment/ImageViewFragment.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/fragment/PostRepliesFragment.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/fragment/ReplyFragment.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/fragment/SettingsFragment.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/transition/ImageTransition.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/view/CustomNetworkImageView.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/view/DragGripView.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/view/HackyViewPager.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java
delete mode 100644 Clover/app/src/main/java/org/floens/chan/utils/IconCache.java
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_attachment.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_attachment_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_back.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_back_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_cancel.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_cancel_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_done.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_done_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_new.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_play.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_refresh.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_action_write.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_arrow_back_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_arrow_back_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_bookmark.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_bookmark_filled.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_bookmark_outline_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_bookmark_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_create_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_done_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_done_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_drawer.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_more.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_more_vert_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/panel_shadow.9.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/progress_primary_holo_light.9.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/skip_arrow_down.png
delete mode 100644 Clover/app/src/main/res/drawable-hdpi/skip_arrow_up.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_attachment.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_attachment_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_back.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_back_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_cancel.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_cancel_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_done.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_done_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_new.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_play.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_refresh.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_action_write.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_arrow_back_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_arrow_back_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_bookmark.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_bookmark_filled.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_bookmark_outline_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_bookmark_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_create_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_done_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_done_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_drawer.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_more.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_more_vert_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/panel_shadow.9.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/progress_primary_holo_light.9.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/skip_arrow_down.png
delete mode 100644 Clover/app/src/main/res/drawable-mdpi/skip_arrow_up.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_attachment.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_attachment_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_back.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_back_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_cancel.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_cancel_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_done.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_done_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_new.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_play.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_refresh.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_action_write.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_arrow_back_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_arrow_back_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_bookmark.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_bookmark_filled.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_bookmark_outline_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_bookmark_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_create_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_done_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_done_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_drawer.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_more.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_more_vert_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/panel_shadow.9.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/progress_primary_holo_light.9.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/skip_arrow_down.png
delete mode 100644 Clover/app/src/main/res/drawable-xhdpi/skip_arrow_up.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_attachment.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_attachment_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_back.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_back_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_cancel_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_done.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_done_dark.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_new.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_play.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_refresh.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_action_write.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_arrow_back_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_bookmark.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_bookmark_filled.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_bookmark_outline_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_bookmark_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_create_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_done_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_done_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_drawer.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_more.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_more_vert_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxhdpi/ic_refresh_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/panel_shadow.9.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/progress_primary_holo_light.9.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/skip_arrow_down.png
delete mode 100644 Clover/app/src/main/res/drawable-xxhdpi/skip_arrow_up.png
delete mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_action_refresh.png
delete mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_action_write.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_arrow_back_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_bookmark.png
delete mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_bookmark_filled.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_bookmark_outline_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_bookmark_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_create_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_done_black_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_done_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_more.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_more_vert_white_24dp.png
create mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/ic_refresh_white_24dp.png
delete mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/skip_arrow_down.png
delete mode 100644 Clover/app/src/main/res/drawable-xxxhdpi/skip_arrow_up.png
delete mode 100644 Clover/app/src/main/res/drawable/pin_icon_blue.xml
delete mode 100644 Clover/app/src/main/res/drawable/pin_icon_gray.xml
delete mode 100644 Clover/app/src/main/res/drawable/pin_icon_red.xml
delete mode 100644 Clover/app/src/main/res/drawable/preference_description_bottom.xml
delete mode 100644 Clover/app/src/main/res/drawable/preference_description_top.xml
delete mode 100644 Clover/app/src/main/res/drawable/progressbar_no_bg.xml
rename Clover/app/src/main/res/{anim/fade_out.xml => drawable/setting_description_bottom.xml} (79%)
rename Clover/app/src/main/res/{anim/fade_in.xml => drawable/setting_description_top.xml} (79%)
delete mode 100644 Clover/app/src/main/res/layout/activity_base.xml
delete mode 100644 Clover/app/src/main/res/layout/board_edit_item.xml
delete mode 100644 Clover/app/src/main/res/layout/board_select_add.xml
delete mode 100644 Clover/app/src/main/res/layout/board_select_spinner.xml
delete mode 100644 Clover/app/src/main/res/layout/board_select_spinner_dropdown.xml
rename Clover/app/src/main/res/layout/{watch_description.xml => dialog_web.xml} (84%)
rename Clover/app/src/main/res/layout/{folder_pick.xml => fragment_folder_pick.xml} (93%)
delete mode 100644 Clover/app/src/main/res/layout/header_switch_layout.xml
delete mode 100644 Clover/app/src/main/res/layout/image_view.xml
delete mode 100644 Clover/app/src/main/res/layout/layout_reply.xml
delete mode 100644 Clover/app/src/main/res/layout/pin_item.xml
delete mode 100644 Clover/app/src/main/res/layout/pin_item_header.xml
delete mode 100644 Clover/app/src/main/res/layout/preference_pass.xml
delete mode 100644 Clover/app/src/main/res/layout/reply_input.xml
delete mode 100644 Clover/app/src/main/res/layout/reply_view.xml
delete mode 100644 Clover/app/src/main/res/layout/toolbar.xml
delete mode 100644 Clover/app/src/main/res/layout/toolbar_activity.xml
delete mode 100644 Clover/app/src/main/res/layout/web_dialog.xml
delete mode 100644 Clover/app/src/main/res/menu/action_bar_switch.xml
delete mode 100644 Clover/app/src/main/res/menu/base.xml
delete mode 100644 Clover/app/src/main/res/menu/board_edit.xml
delete mode 100644 Clover/app/src/main/res/menu/image_view.xml
delete mode 100644 Clover/app/src/main/res/menu/settings.xml
delete mode 100644 Clover/app/src/main/res/values/colors.xml
delete mode 100644 Clover/app/src/main/res/values/dimens.xml
delete mode 100644 Clover/app/src/main/res/values/ids.xml
delete mode 100644 Clover/app/src/main/res/values/string_arrays.xml
delete mode 100644 Clover/app/src/main/res/values/watch_strings.xml
delete mode 100644 Clover/app/src/main/res/xml/preference.xml
delete mode 100644 Clover/app/src/main/res/xml/preference_advanced.xml
delete mode 100644 Clover/app/src/main/res/xml/preference_pass.xml
delete mode 100644 Clover/app/src/main/res/xml/preference_watch.xml
diff --git a/Clover/app/src/main/AndroidManifest.xml b/Clover/app/src/main/AndroidManifest.xml
index 5ebdb2af..75d89b03 100644
--- a/Clover/app/src/main/AndroidManifest.xml
+++ b/Clover/app/src/main/AndroidManifest.xml
@@ -24,26 +24,22 @@ along with this program. If not, see .
+ android:theme="@style/Chan.Theme">
+
+ android:configChanges="keyboardHidden|orientation|screenSize"
+ android:label="@string/app_name">
-
-
-
-
+
@@ -76,48 +72,15 @@ along with this program. If not, see .
android:scheme="https" />
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortController.java b/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortController.java
deleted file mode 100644
index 008dcd32..00000000
--- a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortController.java
+++ /dev/null
@@ -1,469 +0,0 @@
-package com.mobeta.android.dslv;
-
-import android.graphics.Point;
-import android.view.GestureDetector;
-import android.view.HapticFeedbackConstants;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.widget.AdapterView;
-
-/**
- * Class that starts and stops item drags on a {@link DragSortListView} based on
- * touch gestures. This class also inherits from {@link SimpleFloatViewManager},
- * which provides basic float View creation.
- *
- * An instance of this class is meant to be passed to the methods
- * {@link DragSortListView#setTouchListener()} and
- * {@link DragSortListView#setFloatViewManager()} of your
- * {@link DragSortListView} instance.
- */
-public class DragSortController extends SimpleFloatViewManager implements View.OnTouchListener,
- GestureDetector.OnGestureListener {
-
- /**
- * Drag init mode enum.
- */
- public static final int ON_DOWN = 0;
- public static final int ON_DRAG = 1;
- public static final int ON_LONG_PRESS = 2;
-
- private int mDragInitMode = ON_DOWN;
-
- private boolean mSortEnabled = true;
-
- /**
- * Remove mode enum.
- */
- public static final int CLICK_REMOVE = 0;
- public static final int FLING_REMOVE = 1;
-
- /**
- * The current remove mode.
- */
- private int mRemoveMode;
-
- private boolean mRemoveEnabled = false;
- private boolean mIsRemoving = false;
-
- private GestureDetector mDetector;
-
- private GestureDetector mFlingRemoveDetector;
-
- private int mTouchSlop;
-
- public static final int MISS = -1;
-
- private int mHitPos = MISS;
- private int mFlingHitPos = MISS;
-
- private int mClickRemoveHitPos = MISS;
-
- private int[] mTempLoc = new int[2];
-
- private int mItemX;
- private int mItemY;
-
- private int mCurrX;
- private int mCurrY;
-
- private boolean mDragging = false;
-
- private float mFlingSpeed = 500f;
-
- private int mDragHandleId;
-
- private int mClickRemoveId;
-
- private int mFlingHandleId;
- private boolean mCanDrag;
-
- private DragSortListView mDslv;
- private int mPositionX;
-
- /**
- * Calls {@link #DragSortController(DragSortListView, int)} with a 0 drag
- * handle id, FLING_RIGHT_REMOVE remove mode, and ON_DOWN drag init. By
- * default, sorting is enabled, and removal is disabled.
- *
- * @param dslv
- * The DSLV instance
- */
- public DragSortController(DragSortListView dslv) {
- this(dslv, 0, ON_DOWN, FLING_REMOVE);
- }
-
- public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitMode, int removeMode) {
- this(dslv, dragHandleId, dragInitMode, removeMode, 0);
- }
-
- public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitMode, int removeMode,
- int clickRemoveId) {
- this(dslv, dragHandleId, dragInitMode, removeMode, clickRemoveId, 0);
- }
-
- /**
- * By default, sorting is enabled, and removal is disabled.
- *
- * @param dslv
- * The DSLV instance
- * @param dragHandleId
- * The resource id of the View that represents the drag handle in
- * a list item.
- */
- public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitMode, int removeMode,
- int clickRemoveId, int flingHandleId) {
- super(dslv);
- mDslv = dslv;
- mDetector = new GestureDetector(dslv.getContext(), this);
- mFlingRemoveDetector = new GestureDetector(dslv.getContext(), mFlingRemoveListener);
- mFlingRemoveDetector.setIsLongpressEnabled(false);
- mTouchSlop = ViewConfiguration.get(dslv.getContext()).getScaledTouchSlop();
- mDragHandleId = dragHandleId;
- mClickRemoveId = clickRemoveId;
- mFlingHandleId = flingHandleId;
- setRemoveMode(removeMode);
- setDragInitMode(dragInitMode);
- }
-
- public int getDragInitMode() {
- return mDragInitMode;
- }
-
- /**
- * Set how a drag is initiated. Needs to be one of {@link ON_DOWN},
- * {@link ON_DRAG}, or {@link ON_LONG_PRESS}.
- *
- * @param mode
- * The drag init mode.
- */
- public void setDragInitMode(int mode) {
- mDragInitMode = mode;
- }
-
- /**
- * Enable/Disable list item sorting. Disabling is useful if only item
- * removal is desired. Prevents drags in the vertical direction.
- *
- * @param enabled
- * Set true
to enable list item sorting.
- */
- public void setSortEnabled(boolean enabled) {
- mSortEnabled = enabled;
- }
-
- public boolean isSortEnabled() {
- return mSortEnabled;
- }
-
- /**
- * One of {@link CLICK_REMOVE}, {@link FLING_RIGHT_REMOVE},
- * {@link FLING_LEFT_REMOVE}, {@link SLIDE_RIGHT_REMOVE}, or
- * {@link SLIDE_LEFT_REMOVE}.
- */
- public void setRemoveMode(int mode) {
- mRemoveMode = mode;
- }
-
- public int getRemoveMode() {
- return mRemoveMode;
- }
-
- /**
- * Enable/Disable item removal without affecting remove mode.
- */
- public void setRemoveEnabled(boolean enabled) {
- mRemoveEnabled = enabled;
- }
-
- public boolean isRemoveEnabled() {
- return mRemoveEnabled;
- }
-
- /**
- * Set the resource id for the View that represents the drag handle in a
- * list item.
- *
- * @param id
- * An android resource id.
- */
- public void setDragHandleId(int id) {
- mDragHandleId = id;
- }
-
- /**
- * Set the resource id for the View that represents the fling handle in a
- * list item.
- *
- * @param id
- * An android resource id.
- */
- public void setFlingHandleId(int id) {
- mFlingHandleId = id;
- }
-
- /**
- * Set the resource id for the View that represents click removal button.
- *
- * @param id
- * An android resource id.
- */
- public void setClickRemoveId(int id) {
- mClickRemoveId = id;
- }
-
- /**
- * Sets flags to restrict certain motions of the floating View based on
- * DragSortController settings (such as remove mode). Starts the drag on the
- * DragSortListView.
- *
- * @param position
- * The list item position (includes headers).
- * @param deltaX
- * Touch x-coord minus left edge of floating View.
- * @param deltaY
- * Touch y-coord minus top edge of floating View.
- *
- * @return True if drag started, false otherwise.
- */
- public boolean startDrag(int position, int deltaX, int deltaY) {
-
- int dragFlags = 0;
- if (mSortEnabled && !mIsRemoving) {
- dragFlags |= DragSortListView.DRAG_POS_Y | DragSortListView.DRAG_NEG_Y;
- }
- if (mRemoveEnabled && mIsRemoving) {
- dragFlags |= DragSortListView.DRAG_POS_X;
- dragFlags |= DragSortListView.DRAG_NEG_X;
- }
-
- mDragging = mDslv.startDrag(position - mDslv.getHeaderViewsCount(), dragFlags, deltaX, deltaY);
- return mDragging;
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent ev) {
- if (!mDslv.isDragEnabled() || mDslv.listViewIntercepted()) {
- return false;
- }
-
- mDetector.onTouchEvent(ev);
- if (mRemoveEnabled && mDragging && mRemoveMode == FLING_REMOVE) {
- mFlingRemoveDetector.onTouchEvent(ev);
- }
-
- int action = ev.getAction() & MotionEvent.ACTION_MASK;
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mCurrX = (int) ev.getX();
- mCurrY = (int) ev.getY();
- break;
- case MotionEvent.ACTION_UP:
- if (mRemoveEnabled && mIsRemoving) {
- int x = mPositionX >= 0 ? mPositionX : -mPositionX;
- int removePoint = mDslv.getWidth() / 2;
- if (x > removePoint) {
- mDslv.stopDragWithVelocity(true, 0);
- }
- }
- case MotionEvent.ACTION_CANCEL:
- mIsRemoving = false;
- mDragging = false;
- break;
- }
-
- return false;
- }
-
- /**
- * Overrides to provide fading when slide removal is enabled.
- */
- @Override
- public void onDragFloatView(View floatView, Point position, Point touch) {
-
- if (mRemoveEnabled && mIsRemoving) {
- mPositionX = position.x;
- }
- }
-
- /**
- * Get the position to start dragging based on the ACTION_DOWN MotionEvent.
- * This function simply calls {@link #dragHandleHitPosition(MotionEvent)}.
- * Override to change drag handle behavior; this function is called
- * internally when an ACTION_DOWN event is detected.
- *
- * @param ev
- * The ACTION_DOWN MotionEvent.
- *
- * @return The list position to drag if a drag-init gesture is detected;
- * MISS if unsuccessful.
- */
- public int startDragPosition(MotionEvent ev) {
- return dragHandleHitPosition(ev);
- }
-
- public int startFlingPosition(MotionEvent ev) {
- return mRemoveMode == FLING_REMOVE ? flingHandleHitPosition(ev) : MISS;
- }
-
- /**
- * Checks for the touch of an item's drag handle (specified by
- * {@link #setDragHandleId(int)}), and returns that item's position if a
- * drag handle touch was detected.
- *
- * @param ev
- * The ACTION_DOWN MotionEvent.
- *
- * @return The list position of the item whose drag handle was touched; MISS
- * if unsuccessful.
- */
- public int dragHandleHitPosition(MotionEvent ev) {
- return viewIdHitPosition(ev, mDragHandleId);
- }
-
- public int flingHandleHitPosition(MotionEvent ev) {
- return viewIdHitPosition(ev, mFlingHandleId);
- }
-
- public int viewIdHitPosition(MotionEvent ev, int id) {
- final int x = (int) ev.getX();
- final int y = (int) ev.getY();
-
- int touchPos = mDslv.pointToPosition(x, y); // includes headers/footers
-
- final int numHeaders = mDslv.getHeaderViewsCount();
- final int numFooters = mDslv.getFooterViewsCount();
- final int count = mDslv.getCount();
-
- // Log.d("mobeta", "touch down on position " + itemnum);
- // We're only interested if the touch was on an
- // item that's not a header or footer.
- if (touchPos != AdapterView.INVALID_POSITION && touchPos >= numHeaders && touchPos < (count - numFooters)) {
- final View item = mDslv.getChildAt(touchPos - mDslv.getFirstVisiblePosition());
- final int rawX = (int) ev.getRawX();
- final int rawY = (int) ev.getRawY();
-
- View dragBox = id == 0 ? item : (View) item.findViewById(id);
- if (dragBox != null) {
- dragBox.getLocationOnScreen(mTempLoc);
-
- if (rawX > mTempLoc[0] && rawY > mTempLoc[1] && rawX < mTempLoc[0] + dragBox.getWidth()
- && rawY < mTempLoc[1] + dragBox.getHeight()) {
-
- mItemX = item.getLeft();
- mItemY = item.getTop();
-
- return touchPos;
- }
- }
- }
-
- return MISS;
- }
-
- @Override
- public boolean onDown(MotionEvent ev) {
- if (mRemoveEnabled && mRemoveMode == CLICK_REMOVE) {
- mClickRemoveHitPos = viewIdHitPosition(ev, mClickRemoveId);
- }
-
- mHitPos = startDragPosition(ev);
- if (mHitPos != MISS && mDragInitMode == ON_DOWN) {
- startDrag(mHitPos, (int) ev.getX() - mItemX, (int) ev.getY() - mItemY);
- }
-
- mIsRemoving = false;
- mCanDrag = true;
- mPositionX = 0;
- mFlingHitPos = startFlingPosition(ev);
-
- return true;
- }
-
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-
- final int x1 = (int) e1.getX();
- final int y1 = (int) e1.getY();
- final int x2 = (int) e2.getX();
- final int y2 = (int) e2.getY();
- final int deltaX = x2 - mItemX;
- final int deltaY = y2 - mItemY;
-
- if (mCanDrag && !mDragging && (mHitPos != MISS || mFlingHitPos != MISS)) {
- if (mHitPos != MISS) {
- if (mDragInitMode == ON_DRAG && Math.abs(y2 - y1) > mTouchSlop && mSortEnabled) {
- startDrag(mHitPos, deltaX, deltaY);
- } else if (mDragInitMode != ON_DOWN && Math.abs(x2 - x1) > mTouchSlop && mRemoveEnabled) {
- mIsRemoving = true;
- startDrag(mFlingHitPos, deltaX, deltaY);
- }
- } else if (mFlingHitPos != MISS) {
- if (Math.abs(x2 - x1) > mTouchSlop && mRemoveEnabled) {
- mIsRemoving = true;
- startDrag(mFlingHitPos, deltaX, deltaY);
- } else if (Math.abs(y2 - y1) > mTouchSlop) {
- mCanDrag = false; // if started to scroll the list then
- // don't allow sorting nor fling-removing
- }
- }
- }
- // return whatever
- return false;
- }
-
- @Override
- public void onLongPress(MotionEvent e) {
- // Log.d("mobeta", "lift listener long pressed");
- if (mHitPos != MISS && mDragInitMode == ON_LONG_PRESS) {
- mDslv.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- startDrag(mHitPos, mCurrX - mItemX, mCurrY - mItemY);
- }
- }
-
- // complete the OnGestureListener interface
- @Override
- public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- return false;
- }
-
- // complete the OnGestureListener interface
- @Override
- public boolean onSingleTapUp(MotionEvent ev) {
- if (mRemoveEnabled && mRemoveMode == CLICK_REMOVE) {
- if (mClickRemoveHitPos != MISS) {
- mDslv.removeItem(mClickRemoveHitPos - mDslv.getHeaderViewsCount());
- }
- }
- return true;
- }
-
- // complete the OnGestureListener interface
- @Override
- public void onShowPress(MotionEvent ev) {
- // do nothing
- }
-
- private GestureDetector.OnGestureListener mFlingRemoveListener = new GestureDetector.SimpleOnGestureListener() {
- @Override
- public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- // Log.d("mobeta", "on fling remove called");
- if (mRemoveEnabled && mIsRemoving) {
- int w = mDslv.getWidth();
- int minPos = w / 5;
- if (velocityX > mFlingSpeed) {
- if (mPositionX > -minPos) {
- mDslv.stopDragWithVelocity(true, velocityX);
- }
- } else if (velocityX < -mFlingSpeed) {
- if (mPositionX < minPos) {
- mDslv.stopDragWithVelocity(true, velocityX);
- }
- }
- mIsRemoving = false;
- }
- return false;
- }
- };
-
-}
diff --git a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortCursorAdapter.java b/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortCursorAdapter.java
deleted file mode 100644
index 0ba1e299..00000000
--- a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortCursorAdapter.java
+++ /dev/null
@@ -1,239 +0,0 @@
-package com.mobeta.android.dslv;
-
-import java.util.ArrayList;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.support.v4.widget.CursorAdapter;
-import android.util.SparseIntArray;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListAdapter;
-
-/**
- * A subclass of {@link android.widget.CursorAdapter} that provides reordering
- * of the elements in the Cursor based on completed drag-sort operations. The
- * reordering is a simple mapping of list positions into Cursor positions (the
- * Cursor is unchanged). To persist changes made by drag-sorts, one can retrieve
- * the mapping with the {@link #getCursorPositions()} method, which returns the
- * reordered list of Cursor positions.
- *
- * An instance of this class is passed to
- * {@link DragSortListView#setAdapter(ListAdapter)} and, since this class
- * implements the {@link DragSortListView.DragSortListener} interface, it is
- * automatically set as the DragSortListener for the DragSortListView instance.
- */
-public abstract class DragSortCursorAdapter extends CursorAdapter implements DragSortListView.DragSortListener {
-
- public static final int REMOVED = -1;
-
- /**
- * Key is ListView position, value is Cursor position
- */
- private final SparseIntArray mListMapping = new SparseIntArray();
-
- private final ArrayList mRemovedCursorPositions = new ArrayList();
-
- @SuppressWarnings("deprecation")
- public DragSortCursorAdapter(Context context, Cursor c) {
- super(context, c);
- }
-
- public DragSortCursorAdapter(Context context, Cursor c, boolean autoRequery) {
- super(context, c, autoRequery);
- }
-
- public DragSortCursorAdapter(Context context, Cursor c, int flags) {
- super(context, c, flags);
- }
-
- /**
- * Swaps Cursor and clears list-Cursor mapping.
- *
- * @see android.widget.CursorAdapter#swapCursor(android.database.Cursor)
- */
- @Override
- public Cursor swapCursor(Cursor newCursor) {
- Cursor old = super.swapCursor(newCursor);
- resetMappings();
- return old;
- }
-
- /**
- * Changes Cursor and clears list-Cursor mapping.
- *
- * @see android.widget.CursorAdapter#changeCursor(android.database.Cursor)
- */
- @Override
- public void changeCursor(Cursor cursor) {
- super.changeCursor(cursor);
- resetMappings();
- }
-
- /**
- * Resets list-cursor mapping.
- */
- public void reset() {
- resetMappings();
- notifyDataSetChanged();
- }
-
- private void resetMappings() {
- mListMapping.clear();
- mRemovedCursorPositions.clear();
- }
-
- @Override
- public Object getItem(int position) {
- return super.getItem(mListMapping.get(position, position));
- }
-
- @Override
- public long getItemId(int position) {
- return super.getItemId(mListMapping.get(position, position));
- }
-
- @Override
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return super.getDropDownView(mListMapping.get(position, position), convertView, parent);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- return super.getView(mListMapping.get(position, position), convertView, parent);
- }
-
- /**
- * On drop, this updates the mapping between Cursor positions and ListView
- * positions. The Cursor is unchanged. Retrieve the current mapping with
- * {@link getCursorPositions()}.
- *
- * @see DragSortListView.DropListener#drop(int, int)
- */
- @Override
- public void drop(int from, int to) {
- if (from != to) {
- int cursorFrom = mListMapping.get(from, from);
-
- if (from > to) {
- for (int i = from; i > to; --i) {
- mListMapping.put(i, mListMapping.get(i - 1, i - 1));
- }
- } else {
- for (int i = from; i < to; ++i) {
- mListMapping.put(i, mListMapping.get(i + 1, i + 1));
- }
- }
- mListMapping.put(to, cursorFrom);
-
- cleanMapping();
- notifyDataSetChanged();
- }
- }
-
- /**
- * On remove, this updates the mapping between Cursor positions and ListView
- * positions. The Cursor is unchanged. Retrieve the current mapping with
- * {@link getCursorPositions()}.
- *
- * @see DragSortListView.RemoveListener#remove(int)
- */
- @Override
- public void remove(int which) {
- int cursorPos = mListMapping.get(which, which);
- if (!mRemovedCursorPositions.contains(cursorPos)) {
- mRemovedCursorPositions.add(cursorPos);
- }
-
- int newCount = getCount();
- for (int i = which; i < newCount; ++i) {
- mListMapping.put(i, mListMapping.get(i + 1, i + 1));
- }
-
- mListMapping.delete(newCount);
-
- cleanMapping();
- notifyDataSetChanged();
- }
-
- /**
- * Does nothing. Just completes DragSortListener interface.
- */
- @Override
- public void drag(int from, int to) {
- // do nothing
- }
-
- /**
- * Remove unnecessary mappings from sparse array.
- */
- private void cleanMapping() {
- ArrayList toRemove = new ArrayList();
-
- int size = mListMapping.size();
- for (int i = 0; i < size; ++i) {
- if (mListMapping.keyAt(i) == mListMapping.valueAt(i)) {
- toRemove.add(mListMapping.keyAt(i));
- }
- }
-
- size = toRemove.size();
- for (int i = 0; i < size; ++i) {
- mListMapping.delete(toRemove.get(i));
- }
- }
-
- @Override
- public int getCount() {
- return super.getCount() - mRemovedCursorPositions.size();
- }
-
- /**
- * Get the Cursor position mapped to by the provided list position (given
- * all previously handled drag-sort operations).
- *
- * @param position
- * List position
- *
- * @return The mapped-to Cursor position
- */
- public int getCursorPosition(int position) {
- return mListMapping.get(position, position);
- }
-
- /**
- * Get the current order of Cursor positions presented by the list.
- */
- public ArrayList getCursorPositions() {
- ArrayList result = new ArrayList();
-
- for (int i = 0; i < getCount(); ++i) {
- result.add(mListMapping.get(i, i));
- }
-
- return result;
- }
-
- /**
- * Get the list position mapped to by the provided Cursor position. If the
- * provided Cursor position has been removed by a drag-sort, this returns
- * {@link #REMOVED}.
- *
- * @param cursorPosition
- * A Cursor position
- * @return The mapped-to list position or REMOVED
- */
- public int getListPosition(int cursorPosition) {
- if (mRemovedCursorPositions.contains(cursorPosition)) {
- return REMOVED;
- }
-
- int index = mListMapping.indexOfValue(cursorPosition);
- if (index < 0) {
- return cursorPosition;
- } else {
- return mListMapping.keyAt(index);
- }
- }
-
-}
diff --git a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortItemView.java b/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortItemView.java
deleted file mode 100644
index c6d5eeb4..00000000
--- a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortItemView.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.mobeta.android.dslv;
-
-import android.content.Context;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-
-/**
- * Lightweight ViewGroup that wraps list items obtained from user's ListAdapter.
- * ItemView expects a single child that has a definite height (i.e. the child's
- * layout height is not MATCH_PARENT). The width of ItemView will always match
- * the width of its child (that is, the width MeasureSpec given to ItemView is
- * passed directly to the child, and the ItemView measured width is set to the
- * child's measured width). The height of ItemView can be anything; the
- *
- *
- * The purpose of this class is to optimize slide shuffle animations.
- */
-public class DragSortItemView extends ViewGroup {
-
- private int mGravity = Gravity.TOP;
-
- public DragSortItemView(Context context) {
- super(context);
-
- // always init with standard ListView layout params
- setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
-
- //setClipChildren(true);
- }
-
- public void setGravity(int gravity) {
- mGravity = gravity;
- }
-
- public int getGravity() {
- return mGravity;
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- final View child = getChildAt(0);
-
- if (child == null) {
- return;
- }
-
- if (mGravity == Gravity.TOP) {
- child.layout(0, 0, getMeasuredWidth(), child.getMeasuredHeight());
- } else {
- child.layout(0, getMeasuredHeight() - child.getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight());
- }
- }
-
- /**
- *
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-
- int height = MeasureSpec.getSize(heightMeasureSpec);
- int width = MeasureSpec.getSize(widthMeasureSpec);
-
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-
- final View child = getChildAt(0);
- if (child == null) {
- setMeasuredDimension(0, width);
- return;
- }
-
- if (child.isLayoutRequested()) {
- // Always let child be as tall as it wants.
- measureChild(child, widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- }
-
- if (heightMode == MeasureSpec.UNSPECIFIED) {
- ViewGroup.LayoutParams lp = getLayoutParams();
-
- if (lp.height > 0) {
- height = lp.height;
- } else {
- height = child.getMeasuredHeight();
- }
- }
-
- setMeasuredDimension(width, height);
- }
-
-}
diff --git a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortItemViewCheckable.java b/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortItemViewCheckable.java
deleted file mode 100644
index a5a81235..00000000
--- a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortItemViewCheckable.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.mobeta.android.dslv;
-
-import android.content.Context;
-import android.view.View;
-import android.widget.Checkable;
-
-/**
- * Lightweight ViewGroup that wraps list items obtained from user's ListAdapter.
- * ItemView expects a single child that has a definite height (i.e. the child's
- * layout height is not MATCH_PARENT). The width of ItemView will always match
- * the width of its child (that is, the width MeasureSpec given to ItemView is
- * passed directly to the child, and the ItemView measured width is set to the
- * child's measured width). The height of ItemView can be anything; the
- *
- *
- * The purpose of this class is to optimize slide shuffle animations.
- */
-public class DragSortItemViewCheckable extends DragSortItemView implements Checkable {
-
- public DragSortItemViewCheckable(Context context) {
- super(context);
- }
-
- @Override
- public boolean isChecked() {
- View child = getChildAt(0);
- if (child instanceof Checkable)
- return ((Checkable) child).isChecked();
- else
- return false;
- }
-
- @Override
- public void setChecked(boolean checked) {
- View child = getChildAt(0);
- if (child instanceof Checkable)
- ((Checkable) child).setChecked(checked);
- }
-
- @Override
- public void toggle() {
- View child = getChildAt(0);
- if (child instanceof Checkable)
- ((Checkable) child).toggle();
- }
-}
diff --git a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortListView.java b/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortListView.java
deleted file mode 100644
index ca2e618e..00000000
--- a/Clover/app/src/main/java/com/mobeta/android/dslv/DragSortListView.java
+++ /dev/null
@@ -1,2974 +0,0 @@
-/*
- * DragSortListView.
- *
- * A subclass of the Android ListView component that enables drag
- * and drop re-ordering of list items.
- *
- * Copyright 2012 Carl Bauer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.mobeta.android.dslv;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-
-import android.content.Context;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.graphics.Point;
-import android.graphics.drawable.Drawable;
-import android.os.Environment;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseBooleanArray;
-import android.util.SparseIntArray;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.BaseAdapter;
-import android.widget.Checkable;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-
-/**
- * ListView subclass that mediates drag and drop resorting of items.
- *
- *
- * @author heycosmo
- *
- */
-@SuppressWarnings("unused")
-public class DragSortListView extends ListView {
-
- /**
- * The View that floats above the ListView and represents the dragged item.
- */
- private View mFloatView;
-
- /**
- * The float View location. First based on touch location and given deltaX
- * and deltaY. Then restricted by callback to
- * FloatViewManager.onDragFloatView(). Finally restricted by bounds of DSLV.
- */
- private final Point mFloatLoc = new Point();
-
- private final Point mTouchLoc = new Point();
-
- /**
- * The middle (in the y-direction) of the floating View.
- */
- private int mFloatViewMid;
-
- /**
- * Flag to make sure float View isn't measured twice
- */
- private boolean mFloatViewOnMeasured = false;
-
- /**
- * Watch the Adapter for data changes. Cancel a drag if coincident with a
- * change.
- */
- private final DataSetObserver mObserver;
-
- /**
- * Transparency for the floating View (XML attribute).
- */
- private final float mFloatAlpha = 1.0f;
- private float mCurrFloatAlpha = 1.0f;
-
- /**
- * While drag-sorting, the current position of the floating View. If
- * dropped, the dragged item will land in this position.
- */
- private int mFloatPos;
-
- /**
- * The first expanded ListView position that helps represent the drop slot
- * tracking the floating View.
- */
- private int mFirstExpPos;
-
- /**
- * The second expanded ListView position that helps represent the drop slot
- * tracking the floating View. This can equal mFirstExpPos if there is no
- * slide shuffle occurring; otherwise it is equal to mFirstExpPos + 1.
- */
- private int mSecondExpPos;
-
- /**
- * Flag set if slide shuffling is enabled.
- */
- private final boolean mAnimate = false;
-
- /**
- * The user dragged from this position.
- */
- private int mSrcPos;
-
- /**
- * Offset (in x) within the dragged item at which the user picked it up (or
- * first touched down with the digitalis).
- */
- private int mDragDeltaX;
-
- /**
- * Offset (in y) within the dragged item at which the user picked it up (or
- * first touched down with the digitalis).
- */
- private int mDragDeltaY;
-
- /**
- * The difference (in x) between screen coordinates and coordinates in this
- * view.
- */
- private int mOffsetX;
-
- /**
- * The difference (in y) between screen coordinates and coordinates in this
- * view.
- */
- private int mOffsetY;
-
- /**
- * A listener that receives callbacks whenever the floating View hovers over
- * a new position.
- */
- private DragListener mDragListener;
-
- /**
- * A listener that receives a callback when the floating View is dropped.
- */
- private DropListener mDropListener;
-
- /**
- * A listener that receives a callback when the floating View (or more
- * precisely the originally dragged item) is removed by one of the provided
- * gestures.
- */
- private RemoveListener mRemoveListener;
-
- /**
- * Enable/Disable item dragging
- *
- * @attr name dslv:drag_enabled
- */
- private boolean mDragEnabled = true;
-
- /**
- * Drag state enum.
- */
- private final static int IDLE = 0;
- private final static int REMOVING = 1;
- private final static int DROPPING = 2;
- private final static int STOPPED = 3;
- private final static int DRAGGING = 4;
-
- private int mDragState = IDLE;
-
- /**
- * Height in pixels to which the originally dragged item is collapsed during
- * a drag-sort. Currently, this value must be greater than zero.
- */
- private final int mItemHeightCollapsed = 1;
-
- /**
- * Height of the floating View. Stored for the purpose of providing the
- * tracking drop slot.
- */
- private int mFloatViewHeight;
-
- /**
- * Convenience member. See above.
- */
- private int mFloatViewHeightHalf;
-
- /**
- * Save the given width spec for use in measuring children
- */
- private int mWidthMeasureSpec = 0;
-
- /**
- * Sample Views ultimately used for calculating the height of ListView items
- * that are off-screen.
- */
- private View[] mSampleViewTypes = new View[1];
-
- /**
- * Drag-scroll encapsulator!
- */
- private final DragScroller mDragScroller;
-
- /**
- * Determines the start of the upward drag-scroll region at the top of the
- * ListView. Specified by a fraction of the ListView height, thus screen
- * resolution agnostic.
- */
- private float mDragUpScrollStartFrac = 1.0f / 3.0f;
-
- /**
- * Determines the start of the downward drag-scroll region at the bottom of
- * the ListView. Specified by a fraction of the ListView height, thus screen
- * resolution agnostic.
- */
- private float mDragDownScrollStartFrac = 1.0f / 3.0f;
-
- /**
- * The following are calculated from the above fracs.
- */
- private int mUpScrollStartY;
- private int mDownScrollStartY;
- private float mDownScrollStartYF;
- private float mUpScrollStartYF;
-
- /**
- * Calculated from above above and current ListView height.
- */
- private float mDragUpScrollHeight;
-
- /**
- * Calculated from above above and current ListView height.
- */
- private float mDragDownScrollHeight;
-
- /**
- * Maximum drag-scroll speed in pixels per ms. Only used with default linear
- * drag-scroll profile.
- */
- private float mMaxScrollSpeed = 0.5f;
-
- /**
- * Defines the scroll speed during a drag-scroll. User can provide their
- * own; this default is a simple linear profile where scroll speed increases
- * linearly as the floating View nears the top/bottom of the ListView.
- */
- private DragScrollProfile mScrollProfile = new DragScrollProfile() {
- @Override
- public float getSpeed(float w, long t) {
- return mMaxScrollSpeed * w;
- }
- };
-
- /**
- * Current touch x.
- */
- private int mX;
-
- /**
- * Current touch y.
- */
- private int mY;
-
- /**
- * Last touch x.
- */
- private int mLastX;
-
- /**
- * Last touch y.
- */
- private int mLastY;
-
- /**
- * The touch y-coord at which drag started
- */
- private int mDragStartY;
-
- /**
- * Drag flag bit. Floating View can move in the positive x direction.
- */
- public final static int DRAG_POS_X = 0x1;
-
- /**
- * Drag flag bit. Floating View can move in the negative x direction.
- */
- public final static int DRAG_NEG_X = 0x2;
-
- /**
- * Drag flag bit. Floating View can move in the positive y direction. This
- * is subtle. What this actually means is that, if enabled, the floating
- * View can be dragged below its starting position. Remove in favor of
- * upper-bounding item position?
- */
- public final static int DRAG_POS_Y = 0x4;
-
- /**
- * Drag flag bit. Floating View can move in the negative y direction. This
- * is subtle. What this actually means is that the floating View can be
- * dragged above its starting position. Remove in favor of lower-bounding
- * item position?
- */
- public final static int DRAG_NEG_Y = 0x8;
-
- /**
- * Flags that determine limits on the motion of the floating View. See flags
- * above.
- */
- private int mDragFlags = 0;
-
- /**
- * Last call to an on*TouchEvent was a call to onInterceptTouchEvent.
- */
- private boolean mLastCallWasIntercept = false;
-
- /**
- * A touch event is in progress.
- */
- private boolean mInTouchEvent = false;
-
- /**
- * Let the user customize the floating View.
- */
- private FloatViewManager mFloatViewManager = null;
-
- /**
- * Given to ListView to cancel its action when a drag-sort begins.
- */
- private final MotionEvent mCancelEvent;
-
- /**
- * Enum telling where to cancel the ListView action when a drag-sort begins
- */
- private static final int NO_CANCEL = 0;
- private static final int ON_TOUCH_EVENT = 1;
- private static final int ON_INTERCEPT_TOUCH_EVENT = 2;
-
- /**
- * Where to cancel the ListView action when a drag-sort begins
- */
- private int mCancelMethod = NO_CANCEL;
-
- /**
- * Determines when a slide shuffle animation starts. That is, defines how
- * close to the edge of the drop slot the floating View must be to initiate
- * the slide.
- */
- private final float mSlideRegionFrac = 0.25f;
-
- /**
- * Number between 0 and 1 indicating the relative location of a sliding item
- * (only used if drag-sort animations are turned on). Nearly 1 means the
- * item is at the top of the slide region (nearly full blank item is
- * directly below).
- */
- private float mSlideFrac = 0.0f;
-
- /**
- * Wraps the user-provided ListAdapter. This is used to wrap each item View
- * given by the user inside another View (currenly a RelativeLayout) which
- * expands and collapses to simulate the item shuffling.
- */
- private AdapterWrapper mAdapterWrapper;
-
- /**
- * Turn on custom debugger.
- */
- private final boolean mTrackDragSort = false;
-
- /**
- * Debugging class.
- */
- private DragSortTracker mDragSortTracker;
-
- /**
- * Needed for adjusting item heights from within layoutChildren
- */
- private boolean mBlockLayoutRequests = false;
-
- /**
- * Set to true when a down event happens during drag sort; for example, when
- * drag finish animations are playing.
- */
- private boolean mIgnoreTouchEvent = false;
-
- /**
- * Caches DragSortItemView child heights. Sometimes DSLV has to know the
- * height of an offscreen item. Since ListView virtualizes these, DSLV must
- * get the item from the ListAdapter to obtain its height. That process can
- * be expensive, but often the same offscreen item will be requested many
- * times in a row. Once an offscreen item height is calculated, we cache it
- * in this guy. Actually, we cache the height of the child of the
- * DragSortItemView since the item height changes often during a drag-sort.
- */
- private static final int sCacheSize = 3;
- private final HeightCache mChildHeightCache = new HeightCache(sCacheSize);
-
- private RemoveAnimator mRemoveAnimator;
-
- private LiftAnimator mLiftAnimator;
-
- private DropAnimator mDropAnimator;
-
- private boolean mUseRemoveVelocity;
- private float mRemoveVelocityX = 0;
-
- public DragSortListView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- int defaultDuration = 150;
- int removeAnimDuration = defaultDuration; // ms
- int dropAnimDuration = defaultDuration; // ms
-
- mDragScroller = new DragScroller();
-
- float smoothness = 0.5f;
- if (removeAnimDuration > 0) {
- mRemoveAnimator = new RemoveAnimator(smoothness, removeAnimDuration);
- }
- // mLiftAnimator = new LiftAnimator(smoothness, 100);
- if (dropAnimDuration > 0) {
- mDropAnimator = new DropAnimator(smoothness, dropAnimDuration);
- }
-
- mCancelEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0f, 0f, 0f, 0f, 0, 0f, 0f, 0, 0);
-
- // construct the dataset observer
- mObserver = new DataSetObserver() {
- private void cancel() {
- if (mDragState == DRAGGING) {
- cancelDrag();
- }
- }
-
- @Override
- public void onChanged() {
- cancel();
- }
-
- @Override
- public void onInvalidated() {
- cancel();
- }
- };
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mCancelEvent.recycle();
- }
-
- public boolean isDragging() {
- return mDragState == DRAGGING;
- }
-
- /**
- * Usually called from a FloatViewManager. The float alpha will be reset to
- * the xml-defined value every time a drag is stopped.
- */
- public void setFloatAlpha(float alpha) {
- mCurrFloatAlpha = alpha;
- }
-
- public float getFloatAlpha() {
- return mCurrFloatAlpha;
- }
-
- /**
- * Set maximum drag scroll speed in positions/second. Only applies if using
- * default ScrollSpeedProfile.
- *
- * @param max
- * Maximum scroll speed.
- */
- public void setMaxScrollSpeed(float max) {
- mMaxScrollSpeed = max;
- }
-
- /**
- * For each DragSortListView Listener interface implemented by
- * adapter
, this method calls the appropriate set*Listener
- * method with adapter
as the argument.
- *
- * @param adapter
- * The ListAdapter providing data to back DragSortListView.
- *
- * @see android.widget.ListView#setAdapter(android.widget.ListAdapter)
- */
- @Override
- public void setAdapter(ListAdapter adapter) {
- if (adapter != null) {
- mAdapterWrapper = new AdapterWrapper(adapter);
- adapter.registerDataSetObserver(mObserver);
-
- if (adapter instanceof DropListener) {
- setDropListener((DropListener) adapter);
- }
- if (adapter instanceof DragListener) {
- setDragListener((DragListener) adapter);
- }
- if (adapter instanceof RemoveListener) {
- setRemoveListener((RemoveListener) adapter);
- }
- } else {
- mAdapterWrapper = null;
- }
-
- super.setAdapter(mAdapterWrapper);
- }
-
- /**
- * As opposed to {@link ListView#getAdapter()}, which returns a heavily
- * wrapped ListAdapter (DragSortListView wraps the input ListAdapter {\emph
- * and} ListView wraps the wrapped one).
- *
- * @return The ListAdapter set as the argument of {@link setAdapter()}
- */
- public ListAdapter getInputAdapter() {
- if (mAdapterWrapper == null) {
- return null;
- } else {
- return mAdapterWrapper.getAdapter();
- }
- }
-
- private class AdapterWrapper extends BaseAdapter {
- private final ListAdapter mAdapter;
-
- public AdapterWrapper(ListAdapter adapter) {
- super();
- mAdapter = adapter;
-
- mAdapter.registerDataSetObserver(new DataSetObserver() {
- @Override
- public void onChanged() {
- notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated() {
- notifyDataSetInvalidated();
- }
- });
- }
-
- public ListAdapter getAdapter() {
- return mAdapter;
- }
-
- @Override
- public long getItemId(int position) {
- return mAdapter.getItemId(position);
- }
-
- @Override
- public Object getItem(int position) {
- return mAdapter.getItem(position);
- }
-
- @Override
- public int getCount() {
- return mAdapter.getCount();
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return mAdapter.areAllItemsEnabled();
- }
-
- @Override
- public boolean isEnabled(int position) {
- return mAdapter.isEnabled(position);
- }
-
- @Override
- public int getItemViewType(int position) {
- return mAdapter.getItemViewType(position);
- }
-
- @Override
- public int getViewTypeCount() {
- return mAdapter.getViewTypeCount();
- }
-
- @Override
- public boolean hasStableIds() {
- return mAdapter.hasStableIds();
- }
-
- @Override
- public boolean isEmpty() {
- return mAdapter.isEmpty();
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
-
- DragSortItemView v;
- View child;
- // Log.d("mobeta",
- // "getView: position="+position+" convertView="+convertView);
- if (convertView != null) {
- v = (DragSortItemView) convertView;
- View oldChild = v.getChildAt(0);
-
- child = mAdapter.getView(position, oldChild, DragSortListView.this);
- if (child != oldChild) {
- // shouldn't get here if user is reusing convertViews
- // properly
- if (oldChild != null) {
- v.removeViewAt(0);
- }
- v.addView(child);
- }
- } else {
- child = mAdapter.getView(position, null, DragSortListView.this);
- if (child instanceof Checkable) {
- v = new DragSortItemViewCheckable(getContext());
- } else {
- v = new DragSortItemView(getContext());
- }
- v.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- v.addView(child);
- }
-
- // Set the correct item height given drag state; passed
- // View needs to be measured if measurement is required.
- adjustItem(position + getHeaderViewsCount(), v, true);
-
- return v;
- }
- }
-
- private void drawDivider(int expPosition, Canvas canvas) {
-
- final Drawable divider = getDivider();
- final int dividerHeight = getDividerHeight();
- // Log.d("mobeta", "div="+divider+" divH="+dividerHeight);
-
- if (divider != null && dividerHeight != 0) {
- final ViewGroup expItem = (ViewGroup) getChildAt(expPosition - getFirstVisiblePosition());
- if (expItem != null) {
- final int l = getPaddingLeft();
- final int r = getWidth() - getPaddingRight();
- final int t;
- final int b;
-
- final int childHeight = expItem.getChildAt(0).getHeight();
-
- if (expPosition > mSrcPos) {
- t = expItem.getTop() + childHeight;
- b = t + dividerHeight;
- } else {
- b = expItem.getBottom() - childHeight;
- t = b - dividerHeight;
- }
- // Log.d("mobeta", "l="+l+" t="+t+" r="+r+" b="+b);
-
- // Have to clip to support ColorDrawable on <= Gingerbread
- canvas.save();
- canvas.clipRect(l, t, r, b);
- divider.setBounds(l, t, r, b);
- divider.draw(canvas);
- canvas.restore();
- }
- }
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
-
- if (mDragState != IDLE) {
- // draw the divider over the expanded item
- if (mFirstExpPos != mSrcPos) {
- drawDivider(mFirstExpPos, canvas);
- }
- if (mSecondExpPos != mFirstExpPos && mSecondExpPos != mSrcPos) {
- drawDivider(mSecondExpPos, canvas);
- }
- }
-
- if (mFloatView != null) {
- // draw the float view over everything
- final int w = mFloatView.getWidth();
- final int h = mFloatView.getHeight();
-
- int x = mFloatLoc.x;
-
- int width = getWidth();
- if (x < 0)
- x = -x;
- float alphaMod;
- if (x < width) {
- alphaMod = ((float) (width - x)) / ((float) width);
- alphaMod *= alphaMod;
- } else {
- alphaMod = 0;
- }
-
- final int alpha = (int) (255f * mCurrFloatAlpha * alphaMod);
-
- canvas.save();
- // Log.d("mobeta", "clip rect bounds: " + canvas.getClipBounds());
- canvas.translate(mFloatLoc.x, mFloatLoc.y);
- canvas.clipRect(0, 0, w, h);
-
- // Log.d("mobeta", "clip rect bounds: " + canvas.getClipBounds());
- canvas.saveLayerAlpha(0, 0, w, h, alpha, Canvas.ALL_SAVE_FLAG);
- mFloatView.draw(canvas);
- canvas.restore();
- canvas.restore();
- }
- }
-
- private int getItemHeight(int position) {
- View v = getChildAt(position - getFirstVisiblePosition());
-
- if (v != null) {
- // item is onscreen, just get the height of the View
- return v.getHeight();
- } else {
- // item is offscreen. get child height and calculate
- // item height based on current shuffle state
- return calcItemHeight(position, getChildHeight(position));
- }
- }
-
- private void printPosData() {
- Log.d("mobeta", "mSrcPos=" + mSrcPos + " mFirstExpPos=" + mFirstExpPos + " mSecondExpPos=" + mSecondExpPos);
- }
-
- private class HeightCache {
-
- private final SparseIntArray mMap;
- private final ArrayList mOrder;
- private final int mMaxSize;
-
- public HeightCache(int size) {
- mMap = new SparseIntArray(size);
- mOrder = new ArrayList(size);
- mMaxSize = size;
- }
-
- /**
- * Add item height at position if doesn't already exist.
- */
- public void add(int position, int height) {
- int currHeight = mMap.get(position, -1);
- if (currHeight != height) {
- if (currHeight == -1) {
- if (mMap.size() == mMaxSize) {
- // remove oldest entry
- mMap.delete(mOrder.remove(0));
- }
- } else {
- // move position to newest slot
- mOrder.remove((Integer) position);
- }
- mMap.put(position, height);
- mOrder.add(position);
- }
- }
-
- public int get(int position) {
- return mMap.get(position, -1);
- }
-
- public void clear() {
- mMap.clear();
- mOrder.clear();
- }
-
- }
-
- /**
- * Get the shuffle edge for item at position when top of item is at y-coord
- * top. Assumes that current item heights are consistent with current float
- * view location and thus expanded positions and slide fraction. i.e. Should
- * not be called between update of expanded positions/slide fraction and
- * layoutChildren.
- *
- * @param position
- * @param top
- * @param height
- * Height of item at position. If -1, this function calculates
- * this height.
- *
- * @return Shuffle line between position-1 and position (for the given view
- * of the list; that is, for when top of item at position has
- * y-coord of given `top`). If floating View (treated as horizontal
- * line) is dropped immediately above this line, it lands in
- * position-1. If dropped immediately below this line, it lands in
- * position.
- */
- private int getShuffleEdge(int position, int top) {
-
- final int numHeaders = getHeaderViewsCount();
- final int numFooters = getFooterViewsCount();
-
- // shuffle edges are defined between items that can be
- // dragged; there are N-1 of them if there are N draggable
- // items.
-
- if (position <= numHeaders || (position >= getCount() - numFooters)) {
- return top;
- }
-
- int divHeight = getDividerHeight();
-
- int edge;
-
- int maxBlankHeight = mFloatViewHeight - mItemHeightCollapsed;
- int childHeight = getChildHeight(position);
- int itemHeight = getItemHeight(position);
-
- // first calculate top of item given that floating View is
- // centered over src position
- int otop = top;
- if (mSecondExpPos <= mSrcPos) {
- // items are expanded on and/or above the source position
-
- if (position == mSecondExpPos && mFirstExpPos != mSecondExpPos) {
- if (position == mSrcPos) {
- otop = top + itemHeight - mFloatViewHeight;
- } else {
- int blankHeight = itemHeight - childHeight;
- otop = top + blankHeight - maxBlankHeight;
- }
- } else if (position > mSecondExpPos && position <= mSrcPos) {
- otop = top - maxBlankHeight;
- }
-
- } else {
- // items are expanded on and/or below the source position
-
- if (position > mSrcPos && position <= mFirstExpPos) {
- otop = top + maxBlankHeight;
- } else if (position == mSecondExpPos && mFirstExpPos != mSecondExpPos) {
- int blankHeight = itemHeight - childHeight;
- otop = top + blankHeight;
- }
- }
-
- // otop is set
- if (position <= mSrcPos) {
- edge = otop + (mFloatViewHeight - divHeight - getChildHeight(position - 1)) / 2;
- } else {
- edge = otop + (childHeight - divHeight - mFloatViewHeight) / 2;
- }
-
- return edge;
- }
-
- private boolean updatePositions() {
-
- final int first = getFirstVisiblePosition();
- int startPos = mFirstExpPos;
- View startView = getChildAt(startPos - first);
-
- if (startView == null) {
- startPos = first + getChildCount() / 2;
- startView = getChildAt(startPos - first);
- }
- int startTop = startView.getTop();
-
- int itemHeight = startView.getHeight();
-
- int edge = getShuffleEdge(startPos, startTop);
- int lastEdge = edge;
-
- int divHeight = getDividerHeight();
-
- // Log.d("mobeta", "float mid="+mFloatViewMid);
-
- int itemPos = startPos;
- int itemTop = startTop;
- if (mFloatViewMid < edge) {
- // scanning up for float position
- // Log.d("mobeta", " edge="+edge);
- while (itemPos >= 0) {
- itemPos--;
- itemHeight = getItemHeight(itemPos);
-
- if (itemPos == 0) {
- edge = itemTop - divHeight - itemHeight;
- break;
- }
-
- itemTop -= itemHeight + divHeight;
- edge = getShuffleEdge(itemPos, itemTop);
- // Log.d("mobeta", " edge="+edge);
-
- if (mFloatViewMid >= edge) {
- break;
- }
-
- lastEdge = edge;
- }
- } else {
- // scanning down for float position
- // Log.d("mobeta", " edge="+edge);
- final int count = getCount();
- while (itemPos < count) {
- if (itemPos == count - 1) {
- edge = itemTop + divHeight + itemHeight;
- break;
- }
-
- itemTop += divHeight + itemHeight;
- itemHeight = getItemHeight(itemPos + 1);
- edge = getShuffleEdge(itemPos + 1, itemTop);
- // Log.d("mobeta", " edge="+edge);
-
- // test for hit
- if (mFloatViewMid < edge) {
- break;
- }
-
- lastEdge = edge;
- itemPos++;
- }
- }
-
- final int numHeaders = getHeaderViewsCount();
- final int numFooters = getFooterViewsCount();
-
- boolean updated = false;
-
- int oldFirstExpPos = mFirstExpPos;
- int oldSecondExpPos = mSecondExpPos;
- float oldSlideFrac = mSlideFrac;
-
- if (mAnimate) {
- int edgeToEdge = Math.abs(edge - lastEdge);
-
- int edgeTop, edgeBottom;
- if (mFloatViewMid < edge) {
- edgeBottom = edge;
- edgeTop = lastEdge;
- } else {
- edgeTop = edge;
- edgeBottom = lastEdge;
- }
- // Log.d("mobeta", "edgeTop="+edgeTop+" edgeBot="+edgeBottom);
-
- int slideRgnHeight = (int) (0.5f * mSlideRegionFrac * edgeToEdge);
- float slideRgnHeightF = slideRgnHeight;
- int slideEdgeTop = edgeTop + slideRgnHeight;
- int slideEdgeBottom = edgeBottom - slideRgnHeight;
-
- // Three regions
- if (mFloatViewMid < slideEdgeTop) {
- mFirstExpPos = itemPos - 1;
- mSecondExpPos = itemPos;
- mSlideFrac = 0.5f * (slideEdgeTop - mFloatViewMid) / slideRgnHeightF;
- // Log.d("mobeta",
- // "firstExp="+mFirstExpPos+" secExp="+mSecondExpPos+" slideFrac="+mSlideFrac);
- } else if (mFloatViewMid < slideEdgeBottom) {
- mFirstExpPos = itemPos;
- mSecondExpPos = itemPos;
- } else {
- mFirstExpPos = itemPos;
- mSecondExpPos = itemPos + 1;
- mSlideFrac = 0.5f * (1.0f + (edgeBottom - mFloatViewMid) / slideRgnHeightF);
- // Log.d("mobeta",
- // "firstExp="+mFirstExpPos+" secExp="+mSecondExpPos+" slideFrac="+mSlideFrac);
- }
-
- } else {
- mFirstExpPos = itemPos;
- mSecondExpPos = itemPos;
- }
-
- // correct for headers and footers
- if (mFirstExpPos < numHeaders) {
- itemPos = numHeaders;
- mFirstExpPos = itemPos;
- mSecondExpPos = itemPos;
- } else if (mSecondExpPos >= getCount() - numFooters) {
- itemPos = getCount() - numFooters - 1;
- mFirstExpPos = itemPos;
- mSecondExpPos = itemPos;
- }
-
- if (mFirstExpPos != oldFirstExpPos || mSecondExpPos != oldSecondExpPos || mSlideFrac != oldSlideFrac) {
- updated = true;
- }
-
- if (itemPos != mFloatPos) {
- if (mDragListener != null) {
- mDragListener.drag(mFloatPos - numHeaders, itemPos - numHeaders);
- }
-
- mFloatPos = itemPos;
- updated = true;
- }
-
- return updated;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (mTrackDragSort) {
- mDragSortTracker.appendState();
- }
- }
-
- private class SmoothAnimator implements Runnable {
- protected long mStartTime;
-
- private final float mDurationF;
-
- private final float mAlpha;
- private final float mA, mB, mC;
-
- private float mD;
-
- private boolean mCanceled;
-
- public SmoothAnimator(float smoothness, int duration) {
- mAlpha = smoothness;
- mDurationF = duration;
- mA = mD = 1f / (2f * mAlpha * (1f - mAlpha));
- mB = mAlpha / (2f * (mAlpha - 1f));
- mC = 1f / (1f - mAlpha);
- }
-
- public float transform(float frac) {
- if (frac < mAlpha) {
- return mA * frac * frac;
- } else if (frac < 1f - mAlpha) {
- return mB + mC * frac;
- } else {
- return 1f - mD * (frac - 1f) * (frac - 1f);
- }
- }
-
- public void start() {
- mStartTime = SystemClock.uptimeMillis();
- mCanceled = false;
- onStart();
- post(this);
- }
-
- public void cancel() {
- mCanceled = true;
- }
-
- public void onStart() {
- // stub
- }
-
- public void onUpdate(float frac, float smoothFrac) {
- // stub
- }
-
- public void onStop() {
- // stub
- }
-
- @Override
- public void run() {
- if (mCanceled) {
- return;
- }
-
- float fraction = (SystemClock.uptimeMillis() - mStartTime) / mDurationF;
-
- if (fraction >= 1f) {
- onUpdate(1f, 1f);
- onStop();
- } else {
- onUpdate(fraction, transform(fraction));
- post(this);
- }
- }
- }
-
- /**
- * Centers floating View under touch point.
- */
- private class LiftAnimator extends SmoothAnimator {
-
- private float mInitDragDeltaY;
- private float mFinalDragDeltaY;
-
- public LiftAnimator(float smoothness, int duration) {
- super(smoothness, duration);
- }
-
- @Override
- public void onStart() {
- mInitDragDeltaY = mDragDeltaY;
- mFinalDragDeltaY = mFloatViewHeightHalf;
- }
-
- @Override
- public void onUpdate(float frac, float smoothFrac) {
- if (mDragState != DRAGGING) {
- cancel();
- } else {
- mDragDeltaY = (int) (smoothFrac * mFinalDragDeltaY + (1f - smoothFrac) * mInitDragDeltaY);
- mFloatLoc.y = mY - mDragDeltaY;
- doDragFloatView(true);
- }
- }
- }
-
- /**
- * Centers floating View over drop slot before destroying.
- */
- private class DropAnimator extends SmoothAnimator {
-
- private int mDropPos;
- private int srcPos;
- private float mInitDeltaY;
- private float mInitDeltaX;
-
- public DropAnimator(float smoothness, int duration) {
- super(smoothness, duration);
- }
-
- @Override
- public void onStart() {
- mDropPos = mFloatPos;
- srcPos = mSrcPos;
- mDragState = DROPPING;
- mInitDeltaY = mFloatLoc.y - getTargetY();
- mInitDeltaX = mFloatLoc.x - getPaddingLeft();
- }
-
- private int getTargetY() {
- final int first = getFirstVisiblePosition();
- final int otherAdjust = (mItemHeightCollapsed + getDividerHeight()) / 2;
- View v = getChildAt(mDropPos - first);
- int targetY = -1;
- if (v != null) {
- if (mDropPos == srcPos) {
- targetY = v.getTop();
- } else if (mDropPos < srcPos) {
- // expanded down
- targetY = v.getTop() - otherAdjust;
- } else {
- // expanded up
- targetY = v.getBottom() + otherAdjust - mFloatViewHeight;
- }
- } else {
- // drop position is not on screen?? no animation
- cancel();
- }
-
- return targetY;
- }
-
- @Override
- public void onUpdate(float frac, float smoothFrac) {
- final int targetY = getTargetY();
- final int targetX = getPaddingLeft();
- final float deltaY = mFloatLoc.y - targetY;
- final float deltaX = mFloatLoc.x - targetX;
- final float f = 1f - smoothFrac;
- if (f < Math.abs(deltaY / mInitDeltaY) || f < Math.abs(deltaX / mInitDeltaX)) {
- mFloatLoc.y = targetY + (int) (mInitDeltaY * f);
- mFloatLoc.x = getPaddingLeft() + (int) (mInitDeltaX * f);
- doDragFloatView(true);
- }
- }
-
- @Override
- public void onStop() {
- dropFloatView();
- }
-
- }
-
- /**
- * Collapses expanded items.
- */
- private class RemoveAnimator extends SmoothAnimator {
-
- private float mFloatLocX;
- private float mFirstStartBlank;
- private float mSecondStartBlank;
-
- private int mFirstChildHeight = -1;
- private int mSecondChildHeight = -1;
-
- private int mFirstPos;
- private int mSecondPos;
- private int srcPos;
-
- public RemoveAnimator(float smoothness, int duration) {
- super(smoothness, duration);
- }
-
- @Override
- public void onStart() {
- mFirstChildHeight = -1;
- mSecondChildHeight = -1;
- mFirstPos = mFirstExpPos;
- mSecondPos = mSecondExpPos;
- srcPos = mSrcPos;
- mDragState = REMOVING;
-
- mFloatLocX = mFloatLoc.x;
- if (mUseRemoveVelocity) {
- float minVelocity = 2f * getWidth();
- if (mRemoveVelocityX == 0) {
- mRemoveVelocityX = (mFloatLocX < 0 ? -1 : 1) * minVelocity;
- } else {
- minVelocity *= 2;
- if (mRemoveVelocityX < 0 && mRemoveVelocityX > -minVelocity)
- mRemoveVelocityX = -minVelocity;
- else if (mRemoveVelocityX > 0 && mRemoveVelocityX < minVelocity)
- mRemoveVelocityX = minVelocity;
- }
- } else {
- destroyFloatView();
- }
- }
-
- @Override
- public void onUpdate(float frac, float smoothFrac) {
- float f = 1f - smoothFrac;
-
- final int firstVis = getFirstVisiblePosition();
- View item = getChildAt(mFirstPos - firstVis);
- ViewGroup.LayoutParams lp;
- int blank;
-
- if (mUseRemoveVelocity) {
- float dt = (float) (SystemClock.uptimeMillis() - mStartTime) / 1000;
- if (dt == 0)
- return;
- float dx = mRemoveVelocityX * dt;
- int w = getWidth();
- mRemoveVelocityX += (mRemoveVelocityX > 0 ? 1 : -1) * dt * w;
- mFloatLocX += dx;
- mFloatLoc.x = (int) mFloatLocX;
- if (mFloatLocX < w && mFloatLocX > -w) {
- mStartTime = SystemClock.uptimeMillis();
- doDragFloatView(true);
- return;
- }
- }
-
- if (item != null) {
- if (mFirstChildHeight == -1) {
- mFirstChildHeight = getChildHeight(mFirstPos, item, false);
- mFirstStartBlank = item.getHeight() - mFirstChildHeight;
- }
- blank = Math.max((int) (f * mFirstStartBlank), 1);
- lp = item.getLayoutParams();
- lp.height = mFirstChildHeight + blank;
- item.setLayoutParams(lp);
- }
- if (mSecondPos != mFirstPos) {
- item = getChildAt(mSecondPos - firstVis);
- if (item != null) {
- if (mSecondChildHeight == -1) {
- mSecondChildHeight = getChildHeight(mSecondPos, item, false);
- mSecondStartBlank = item.getHeight() - mSecondChildHeight;
- }
- blank = Math.max((int) (f * mSecondStartBlank), 1);
- lp = item.getLayoutParams();
- lp.height = mSecondChildHeight + blank;
- item.setLayoutParams(lp);
- }
- }
- }
-
- @Override
- public void onStop() {
- doRemoveItem();
- }
- }
-
- public void removeItem(int which) {
-
- mUseRemoveVelocity = false;
- removeItem(which, 0);
- }
-
- /**
- * Removes an item from the list and animates the removal.
- *
- * @param which
- * Position to remove (NOTE: headers/footers ignored! this is a
- * position in your input ListAdapter).
- * @param velocityX
- */
- public void removeItem(int which, float velocityX) {
- if (mDragState == IDLE || mDragState == DRAGGING) {
-
- if (mDragState == IDLE) {
- // called from outside drag-sort
- mSrcPos = getHeaderViewsCount() + which;
- mFirstExpPos = mSrcPos;
- mSecondExpPos = mSrcPos;
- mFloatPos = mSrcPos;
- View v = getChildAt(mSrcPos - getFirstVisiblePosition());
- if (v != null) {
- v.setVisibility(View.INVISIBLE);
- }
- }
-
- mDragState = REMOVING;
- mRemoveVelocityX = velocityX;
-
- if (mInTouchEvent) {
- switch (mCancelMethod) {
- case ON_TOUCH_EVENT:
- super.onTouchEvent(mCancelEvent);
- break;
- case ON_INTERCEPT_TOUCH_EVENT:
- super.onInterceptTouchEvent(mCancelEvent);
- break;
- }
- }
-
- if (mRemoveAnimator != null) {
- mRemoveAnimator.start();
- } else {
- doRemoveItem(which);
- }
- }
- }
-
- /**
- * Move an item, bypassing the drag-sort process. Simply calls through to
- * {@link DropListener#drop(int, int)}.
- *
- * @param from
- * Position to move (NOTE: headers/footers ignored! this is a
- * position in your input ListAdapter).
- * @param to
- * Target position (NOTE: headers/footers ignored! this is a
- * position in your input ListAdapter).
- */
- public void moveItem(int from, int to) {
- if (mDropListener != null) {
- final int count = getInputAdapter().getCount();
- if (from >= 0 && from < count && to >= 0 && to < count) {
- mDropListener.drop(from, to);
- }
- }
- }
-
- /**
- * Cancel a drag. Calls {@link #stopDrag(boolean, boolean)} with
- * true
as the first argument.
- */
- public void cancelDrag() {
- if (mDragState == DRAGGING) {
- mDragScroller.stopScrolling(true);
- destroyFloatView();
- clearPositions();
- adjustAllItems();
-
- if (mInTouchEvent) {
- mDragState = STOPPED;
- } else {
- mDragState = IDLE;
- }
- }
- }
-
- private void clearPositions() {
- mSrcPos = -1;
- mFirstExpPos = -1;
- mSecondExpPos = -1;
- mFloatPos = -1;
- }
-
- private void dropFloatView() {
- // must set to avoid cancelDrag being called from the
- // DataSetObserver
- mDragState = DROPPING;
-
- if (mDropListener != null && mFloatPos >= 0 && mFloatPos < getCount()) {
- final int numHeaders = getHeaderViewsCount();
- mDropListener.drop(mSrcPos - numHeaders, mFloatPos - numHeaders);
- }
-
- destroyFloatView();
-
- adjustOnReorder();
- clearPositions();
- adjustAllItems();
-
- // now the drag is done
- if (mInTouchEvent) {
- mDragState = STOPPED;
- } else {
- mDragState = IDLE;
- }
- }
-
- private void doRemoveItem() {
- doRemoveItem(mSrcPos - getHeaderViewsCount());
- }
-
- /**
- * Removes dragged item from the list. Calls RemoveListener.
- */
- private void doRemoveItem(int which) {
- // must set to avoid cancelDrag being called from the
- // DataSetObserver
- mDragState = REMOVING;
-
- // end it
- if (mRemoveListener != null) {
- mRemoveListener.remove(which);
- }
-
- destroyFloatView();
-
- adjustOnReorder();
- clearPositions();
-
- // now the drag is done
- if (mInTouchEvent) {
- mDragState = STOPPED;
- } else {
- mDragState = IDLE;
- }
- }
-
- private void adjustOnReorder() {
- final int firstPos = getFirstVisiblePosition();
- // Log.d("mobeta", "first="+firstPos+" src="+mSrcPos);
- if (mSrcPos < firstPos) {
- // collapsed src item is off screen;
- // adjust the scroll after item heights have been fixed
- View v = getChildAt(0);
- int top = 0;
- if (v != null) {
- top = v.getTop();
- }
- // Log.d("mobeta", "top="+top+" fvh="+mFloatViewHeight);
- setSelectionFromTop(firstPos - 1, top - getPaddingTop());
- }
- }
-
- /**
- * Stop a drag in progress. Pass true
if you would like to
- * remove the dragged item from the list.
- *
- * @param remove
- * Remove the dragged item from the list. Calls a registered
- * RemoveListener, if one exists. Otherwise, calls the
- * DropListener, if one exists.
- *
- * @return True if the stop was successful. False if there is no floating
- * View.
- */
- public boolean stopDrag(boolean remove) {
- mUseRemoveVelocity = false;
- return stopDrag(remove, 0);
- }
-
- public boolean stopDragWithVelocity(boolean remove, float velocityX) {
-
- mUseRemoveVelocity = true;
- return stopDrag(remove, velocityX);
- }
-
- public boolean stopDrag(boolean remove, float velocityX) {
- if (mFloatView != null) {
- mDragScroller.stopScrolling(true);
-
- if (remove) {
- removeItem(mSrcPos - getHeaderViewsCount(), velocityX);
- } else {
- if (mDropAnimator != null) {
- mDropAnimator.start();
- } else {
- dropFloatView();
- }
- }
-
- if (mTrackDragSort) {
- mDragSortTracker.stopTracking();
- }
-
- return true;
- } else {
- // stop failed
- return false;
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mIgnoreTouchEvent) {
- mIgnoreTouchEvent = false;
- return false;
- }
-
- if (!mDragEnabled) {
- return super.onTouchEvent(ev);
- }
-
- boolean more = false;
-
- boolean lastCallWasIntercept = mLastCallWasIntercept;
- mLastCallWasIntercept = false;
-
- if (!lastCallWasIntercept) {
- saveTouchCoords(ev);
- }
-
- // if (mFloatView != null) {
- if (mDragState == DRAGGING) {
- onDragTouchEvent(ev);
- more = true; // give us more!
- } else {
- // what if float view is null b/c we dropped in middle
- // of drag touch event?
-
- // if (mDragState != STOPPED) {
- if (mDragState == IDLE) {
- if (super.onTouchEvent(ev)) {
- more = true;
- }
- }
-
- int action = ev.getAction() & MotionEvent.ACTION_MASK;
-
- switch (action) {
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- doActionUpOrCancel();
- break;
- default:
- if (more) {
- mCancelMethod = ON_TOUCH_EVENT;
- }
- }
- }
-
- return more;
- }
-
- private void doActionUpOrCancel() {
- mCancelMethod = NO_CANCEL;
- mInTouchEvent = false;
- if (mDragState == STOPPED) {
- mDragState = IDLE;
- }
- mCurrFloatAlpha = mFloatAlpha;
- mListViewIntercepted = false;
- mChildHeightCache.clear();
- }
-
- private void saveTouchCoords(MotionEvent ev) {
- int action = ev.getAction() & MotionEvent.ACTION_MASK;
- if (action != MotionEvent.ACTION_DOWN) {
- mLastX = mX;
- mLastY = mY;
- }
- mX = (int) ev.getX();
- mY = (int) ev.getY();
- if (action == MotionEvent.ACTION_DOWN) {
- mLastX = mX;
- mLastY = mY;
- }
- mOffsetX = (int) ev.getRawX() - mX;
- mOffsetY = (int) ev.getRawY() - mY;
- }
-
- public boolean listViewIntercepted() {
- return mListViewIntercepted;
- }
-
- private boolean mListViewIntercepted = false;
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (!mDragEnabled) {
- return super.onInterceptTouchEvent(ev);
- }
-
- saveTouchCoords(ev);
- mLastCallWasIntercept = true;
-
- int action = ev.getAction() & MotionEvent.ACTION_MASK;
-
- if (action == MotionEvent.ACTION_DOWN) {
- if (mDragState != IDLE) {
- // intercept and ignore
- mIgnoreTouchEvent = true;
- return true;
- }
- mInTouchEvent = true;
- }
-
- boolean intercept = false;
-
- // the following deals with calls to super.onInterceptTouchEvent
- if (mFloatView != null) {
- // super's touch event canceled in startDrag
- intercept = true;
- } else {
- if (super.onInterceptTouchEvent(ev)) {
- mListViewIntercepted = true;
- intercept = true;
- }
-
- switch (action) {
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- doActionUpOrCancel();
- break;
- default:
- if (intercept) {
- mCancelMethod = ON_TOUCH_EVENT;
- } else {
- mCancelMethod = ON_INTERCEPT_TOUCH_EVENT;
- }
- }
- }
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- mInTouchEvent = false;
- }
-
- return intercept;
- }
-
- /**
- * Set the width of each drag scroll region by specifying a fraction of the
- * ListView height.
- *
- * @param heightFraction
- * Fraction of ListView height. Capped at 0.5f.
- *
- */
- public void setDragScrollStart(float heightFraction) {
- setDragScrollStarts(heightFraction, heightFraction);
- }
-
- /**
- * Set the width of each drag scroll region by specifying a fraction of the
- * ListView height.
- *
- * @param upperFrac
- * Fraction of ListView height for up-scroll bound. Capped at
- * 0.5f.
- * @param lowerFrac
- * Fraction of ListView height for down-scroll bound. Capped at
- * 0.5f.
- *
- */
- public void setDragScrollStarts(float upperFrac, float lowerFrac) {
- if (lowerFrac > 0.5f) {
- mDragDownScrollStartFrac = 0.5f;
- } else {
- mDragDownScrollStartFrac = lowerFrac;
- }
-
- if (upperFrac > 0.5f) {
- mDragUpScrollStartFrac = 0.5f;
- } else {
- mDragUpScrollStartFrac = upperFrac;
- }
-
- if (getHeight() != 0) {
- updateScrollStarts();
- }
- }
-
- private void continueDrag(int x, int y) {
-
- // proposed position
- mFloatLoc.x = x - mDragDeltaX;
- mFloatLoc.y = y - mDragDeltaY;
-
- doDragFloatView(true);
-
- int minY = Math.min(y, mFloatViewMid + mFloatViewHeightHalf);
- int maxY = Math.max(y, mFloatViewMid - mFloatViewHeightHalf);
-
- // get the current scroll direction
- int currentScrollDir = mDragScroller.getScrollDir();
-
- if (minY > mLastY && minY > mDownScrollStartY && currentScrollDir != DragScroller.DOWN) {
- // dragged down, it is below the down scroll start and it is not
- // scrolling up
-
- if (currentScrollDir != DragScroller.STOP) {
- // moved directly from up scroll to down scroll
- mDragScroller.stopScrolling(true);
- }
-
- // start scrolling down
- mDragScroller.startScrolling(DragScroller.DOWN);
- } else if (maxY < mLastY && maxY < mUpScrollStartY && currentScrollDir != DragScroller.UP) {
- // dragged up, it is above the up scroll start and it is not
- // scrolling up
-
- if (currentScrollDir != DragScroller.STOP) {
- // moved directly from down scroll to up scroll
- mDragScroller.stopScrolling(true);
- }
-
- // start scrolling up
- mDragScroller.startScrolling(DragScroller.UP);
- } else if (maxY >= mUpScrollStartY && minY <= mDownScrollStartY && mDragScroller.isScrolling()) {
- // not in the upper nor in the lower drag-scroll regions but it is
- // still scrolling
-
- mDragScroller.stopScrolling(true);
- }
- }
-
- private void updateScrollStarts() {
- final int padTop = getPaddingTop();
- final int listHeight = getHeight() - padTop - getPaddingBottom();
- float heightF = listHeight;
-
- mUpScrollStartYF = padTop + mDragUpScrollStartFrac * heightF;
- mDownScrollStartYF = padTop + (1.0f - mDragDownScrollStartFrac) * heightF;
-
- mUpScrollStartY = (int) mUpScrollStartYF;
- mDownScrollStartY = (int) mDownScrollStartYF;
-
- mDragUpScrollHeight = mUpScrollStartYF - padTop;
- mDragDownScrollHeight = padTop + listHeight - mDownScrollStartYF;
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- updateScrollStarts();
- }
-
- private void adjustAllItems() {
- final int first = getFirstVisiblePosition();
- final int last = getLastVisiblePosition();
-
- int begin = Math.max(0, getHeaderViewsCount() - first);
- int end = Math.min(last - first, getCount() - 1 - getFooterViewsCount() - first);
-
- for (int i = begin; i <= end; ++i) {
- View v = getChildAt(i);
- if (v != null) {
- adjustItem(first + i, v, false);
- }
- }
- }
-
- private void adjustItem(int position) {
- View v = getChildAt(position - getFirstVisiblePosition());
-
- if (v != null) {
- adjustItem(position, v, false);
- }
- }
-
- /**
- * Sets layout param height, gravity, and visibility on wrapped item.
- */
- private void adjustItem(int position, View v, boolean invalidChildHeight) {
-
- // Adjust item height
- ViewGroup.LayoutParams lp = v.getLayoutParams();
- int height;
- if (position != mSrcPos && position != mFirstExpPos && position != mSecondExpPos) {
- height = ViewGroup.LayoutParams.WRAP_CONTENT;
- } else {
- height = calcItemHeight(position, v, invalidChildHeight);
- }
-
- if (height != lp.height) {
- lp.height = height;
- v.setLayoutParams(lp);
- }
-
- // Adjust item gravity
- if (position == mFirstExpPos || position == mSecondExpPos) {
- if (position < mSrcPos) {
- ((DragSortItemView) v).setGravity(Gravity.BOTTOM);
- } else if (position > mSrcPos) {
- ((DragSortItemView) v).setGravity(Gravity.TOP);
- }
- }
-
- // Finally adjust item visibility
-
- int oldVis = v.getVisibility();
- int vis = View.VISIBLE;
-
- if (position == mSrcPos && mFloatView != null) {
- vis = View.INVISIBLE;
- }
-
- if (vis != oldVis) {
- v.setVisibility(vis);
- }
- }
-
- private int getChildHeight(int position) {
- if (position == mSrcPos) {
- return 0;
- }
-
- View v = getChildAt(position - getFirstVisiblePosition());
-
- if (v != null) {
- // item is onscreen, therefore child height is valid,
- // hence the "true"
- return getChildHeight(position, v, false);
- } else {
- // item is offscreen
- // first check cache for child height at this position
- int childHeight = mChildHeightCache.get(position);
- if (childHeight != -1) {
- // Log.d("mobeta", "found child height in cache!");
- return childHeight;
- }
-
- final ListAdapter adapter = getAdapter();
- int type = adapter.getItemViewType(position);
-
- // There might be a better place for checking for the following
- final int typeCount = adapter.getViewTypeCount();
- if (typeCount != mSampleViewTypes.length) {
- mSampleViewTypes = new View[typeCount];
- }
-
- if (type >= 0) {
- if (mSampleViewTypes[type] == null) {
- v = adapter.getView(position, null, this);
- mSampleViewTypes[type] = v;
- } else {
- v = adapter.getView(position, mSampleViewTypes[type], this);
- }
- } else {
- // type is HEADER_OR_FOOTER or IGNORE
- v = adapter.getView(position, null, this);
- }
-
- // current child height is invalid, hence "true" below
- childHeight = getChildHeight(position, v, true);
-
- // cache it because this could have been expensive
- mChildHeightCache.add(position, childHeight);
-
- return childHeight;
- }
- }
-
- private int getChildHeight(int position, View item, boolean invalidChildHeight) {
- if (position == mSrcPos) {
- return 0;
- }
-
- View child;
- if (position < getHeaderViewsCount() || position >= getCount() - getFooterViewsCount()) {
- child = item;
- } else {
- child = ((ViewGroup) item).getChildAt(0);
- }
-
- ViewGroup.LayoutParams lp = child.getLayoutParams();
-
- if (lp != null) {
- if (lp.height > 0) {
- return lp.height;
- }
- }
-
- int childHeight = child.getHeight();
-
- if (childHeight == 0 || invalidChildHeight) {
- measureItem(child);
- childHeight = child.getMeasuredHeight();
- }
-
- return childHeight;
- }
-
- private int calcItemHeight(int position, View item, boolean invalidChildHeight) {
- return calcItemHeight(position, getChildHeight(position, item, invalidChildHeight));
- }
-
- private int calcItemHeight(int position, int childHeight) {
-
- int divHeight = getDividerHeight();
-
- boolean isSliding = mAnimate && mFirstExpPos != mSecondExpPos;
- int maxNonSrcBlankHeight = mFloatViewHeight - mItemHeightCollapsed;
- int slideHeight = (int) (mSlideFrac * maxNonSrcBlankHeight);
-
- int height;
-
- if (position == mSrcPos) {
- if (mSrcPos == mFirstExpPos) {
- if (isSliding) {
- height = slideHeight + mItemHeightCollapsed;
- } else {
- height = mFloatViewHeight;
- }
- } else if (mSrcPos == mSecondExpPos) {
- // if gets here, we know an item is sliding
- height = mFloatViewHeight - slideHeight;
- } else {
- height = mItemHeightCollapsed;
- }
- } else if (position == mFirstExpPos) {
- if (isSliding) {
- height = childHeight + slideHeight;
- } else {
- height = childHeight + maxNonSrcBlankHeight;
- }
- } else if (position == mSecondExpPos) {
- // we know an item is sliding (b/c 2ndPos != 1stPos)
- height = childHeight + maxNonSrcBlankHeight - slideHeight;
- } else {
- height = childHeight;
- }
-
- return height;
- }
-
- @Override
- public void requestLayout() {
- if (!mBlockLayoutRequests) {
- super.requestLayout();
- }
- }
-
- private int adjustScroll(int movePos, View moveItem, int oldFirstExpPos, int oldSecondExpPos) {
- int adjust = 0;
-
- final int childHeight = getChildHeight(movePos);
-
- int moveHeightBefore = moveItem.getHeight();
- int moveHeightAfter = calcItemHeight(movePos, childHeight);
-
- int moveBlankBefore = moveHeightBefore;
- int moveBlankAfter = moveHeightAfter;
- if (movePos != mSrcPos) {
- moveBlankBefore -= childHeight;
- moveBlankAfter -= childHeight;
- }
-
- int maxBlank = mFloatViewHeight;
- if (mSrcPos != mFirstExpPos && mSrcPos != mSecondExpPos) {
- maxBlank -= mItemHeightCollapsed;
- }
-
- if (movePos <= oldFirstExpPos) {
- if (movePos > mFirstExpPos) {
- adjust += maxBlank - moveBlankAfter;
- }
- } else if (movePos == oldSecondExpPos) {
- if (movePos <= mFirstExpPos) {
- adjust += moveBlankBefore - maxBlank;
- } else if (movePos == mSecondExpPos) {
- adjust += moveHeightBefore - moveHeightAfter;
- } else {
- adjust += moveBlankBefore;
- }
- } else {
- if (movePos <= mFirstExpPos) {
- adjust -= maxBlank;
- } else if (movePos == mSecondExpPos) {
- adjust -= moveBlankAfter;
- }
- }
-
- return adjust;
- }
-
- private void measureItem(View item) {
- ViewGroup.LayoutParams lp = item.getLayoutParams();
- if (lp == null) {
- lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- item.setLayoutParams(lp);
- }
- int wspec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, getListPaddingLeft() + getListPaddingRight(),
- lp.width);
- int hspec;
- if (lp.height > 0) {
- hspec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
- } else {
- hspec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- }
- item.measure(wspec, hspec);
- }
-
- private void measureFloatView() {
- if (mFloatView != null) {
- measureItem(mFloatView);
- mFloatViewHeight = mFloatView.getMeasuredHeight();
- mFloatViewHeightHalf = mFloatViewHeight / 2;
- }
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- // Log.d("mobeta", "onMeasure called");
- if (mFloatView != null) {
- if (mFloatView.isLayoutRequested()) {
- measureFloatView();
- }
- mFloatViewOnMeasured = true; // set to false after layout
- }
- mWidthMeasureSpec = widthMeasureSpec;
- }
-
- @Override
- protected void layoutChildren() {
- super.layoutChildren();
-
- if (mFloatView != null) {
- if (mFloatView.isLayoutRequested() && !mFloatViewOnMeasured) {
- // Have to measure here when usual android measure
- // pass is skipped. This happens during a drag-sort
- // when layoutChildren is called directly.
- measureFloatView();
- }
- mFloatView.layout(0, 0, mFloatView.getMeasuredWidth(), mFloatView.getMeasuredHeight());
- mFloatViewOnMeasured = false;
- }
- }
-
- protected boolean onDragTouchEvent(MotionEvent ev) {
- // we are in a drag
- int action = ev.getAction() & MotionEvent.ACTION_MASK;
-
- switch (ev.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_CANCEL:
- if (mDragState == DRAGGING) {
- cancelDrag();
- }
- doActionUpOrCancel();
- break;
- case MotionEvent.ACTION_UP:
- // Log.d("mobeta", "calling stopDrag from onDragTouchEvent");
- if (mDragState == DRAGGING) {
- stopDrag(false);
- }
- doActionUpOrCancel();
- break;
- case MotionEvent.ACTION_MOVE:
- continueDrag((int) ev.getX(), (int) ev.getY());
- break;
- }
-
- return true;
- }
-
- private boolean mFloatViewInvalidated = false;
-
- private void invalidateFloatView() {
- mFloatViewInvalidated = true;
- }
-
- /**
- * Start a drag of item at position
using the registered
- * FloatViewManager. Calls through to
- * {@link #startDrag(int,View,int,int,int)} after obtaining the floating
- * View from the FloatViewManager.
- *
- * @param position
- * Item to drag.
- * @param dragFlags
- * Flags that restrict some movements of the floating View. For
- * example, set dragFlags |=
- * ~{@link #DRAG_NEG_X}
to allow dragging the floating View in all
- * directions except off the screen to the left.
- * @param deltaX
- * Offset in x of the touch coordinate from the left edge of the
- * floating View (i.e. touch-x minus float View left).
- * @param deltaY
- * Offset in y of the touch coordinate from the top edge of the
- * floating View (i.e. touch-y minus float View top).
- *
- * @return True if the drag was started, false otherwise. This
- * startDrag
will fail if we are not currently in a
- * touch event, there is no registered FloatViewManager, or the
- * FloatViewManager returns a null View.
- */
- public boolean startDrag(int position, int dragFlags, int deltaX, int deltaY) {
- if (!mInTouchEvent || mFloatViewManager == null) {
- return false;
- }
-
- View v = mFloatViewManager.onCreateFloatView(position);
-
- if (v == null) {
- return false;
- } else {
- return startDrag(position, v, dragFlags, deltaX, deltaY);
- }
-
- }
-
- /**
- * Start a drag of item at position
without using a
- * FloatViewManager.
- *
- * @param position
- * Item to drag.
- * @param floatView
- * Floating View.
- * @param dragFlags
- * Flags that restrict some movements of the floating View. For
- * example, set dragFlags |=
- * ~{@link #DRAG_NEG_X}
to allow dragging the floating View in all
- * directions except off the screen to the left.
- * @param deltaX
- * Offset in x of the touch coordinate from the left edge of the
- * floating View (i.e. touch-x minus float View left).
- * @param deltaY
- * Offset in y of the touch coordinate from the top edge of the
- * floating View (i.e. touch-y minus float View top).
- *
- * @return True if the drag was started, false otherwise. This
- * startDrag
will fail if we are not currently in a
- * touch event, floatView
is null, or there is a drag
- * in progress.
- */
- public boolean startDrag(int position, View floatView, int dragFlags, int deltaX, int deltaY) {
- if (mDragState != IDLE || !mInTouchEvent || mFloatView != null || floatView == null || !mDragEnabled) {
- return false;
- }
-
- if (getParent() != null) {
- getParent().requestDisallowInterceptTouchEvent(true);
- }
-
- int pos = position + getHeaderViewsCount();
- mFirstExpPos = pos;
- mSecondExpPos = pos;
- mSrcPos = pos;
- mFloatPos = pos;
-
- // mDragState = dragType;
- mDragState = DRAGGING;
- mDragFlags = 0;
- mDragFlags |= dragFlags;
-
- mFloatView = floatView;
- measureFloatView(); // sets mFloatViewHeight
-
- mDragDeltaX = deltaX;
- mDragDeltaY = deltaY;
- mDragStartY = mY;
-
- // updateFloatView(mX - mDragDeltaX, mY - mDragDeltaY);
- mFloatLoc.x = mX - mDragDeltaX;
- mFloatLoc.y = mY - mDragDeltaY;
-
- // set src item invisible
- final View srcItem = getChildAt(mSrcPos - getFirstVisiblePosition());
-
- if (srcItem != null) {
- srcItem.setVisibility(View.INVISIBLE);
- }
-
- if (mTrackDragSort) {
- mDragSortTracker.startTracking();
- }
-
- // once float view is created, events are no longer passed
- // to ListView
- switch (mCancelMethod) {
- case ON_TOUCH_EVENT:
- super.onTouchEvent(mCancelEvent);
- break;
- case ON_INTERCEPT_TOUCH_EVENT:
- super.onInterceptTouchEvent(mCancelEvent);
- break;
- }
-
- requestLayout();
-
- if (mLiftAnimator != null) {
- mLiftAnimator.start();
- }
-
- return true;
- }
-
- private void doDragFloatView(boolean forceInvalidate) {
- int movePos = getFirstVisiblePosition() + getChildCount() / 2;
- View moveItem = getChildAt(getChildCount() / 2);
-
- if (moveItem == null) {
- return;
- }
-
- doDragFloatView(movePos, moveItem, forceInvalidate);
- }
-
- private void doDragFloatView(int movePos, View moveItem, boolean forceInvalidate) {
- mBlockLayoutRequests = true;
-
- updateFloatView();
-
- int oldFirstExpPos = mFirstExpPos;
- int oldSecondExpPos = mSecondExpPos;
-
- boolean updated = updatePositions();
-
- if (updated) {
- adjustAllItems();
- int scroll = adjustScroll(movePos, moveItem, oldFirstExpPos, oldSecondExpPos);
- // Log.d("mobeta", " adjust scroll="+scroll);
-
- setSelectionFromTop(movePos, moveItem.getTop() + scroll - getPaddingTop());
- layoutChildren();
- }
-
- if (updated || forceInvalidate) {
- invalidate();
- }
-
- mBlockLayoutRequests = false;
- }
-
- /**
- * Sets float View location based on suggested values and constraints set in
- * mDragFlags.
- */
- private void updateFloatView() {
-
- if (mFloatViewManager != null) {
- mTouchLoc.set(mX, mY);
- mFloatViewManager.onDragFloatView(mFloatView, mFloatLoc, mTouchLoc);
- }
-
- final int floatX = mFloatLoc.x;
- final int floatY = mFloatLoc.y;
-
- // restrict x motion
- int padLeft = getPaddingLeft();
- if ((mDragFlags & DRAG_POS_X) == 0 && floatX > padLeft) {
- mFloatLoc.x = padLeft;
- } else if ((mDragFlags & DRAG_NEG_X) == 0 && floatX < padLeft) {
- mFloatLoc.x = padLeft;
- }
-
- // keep floating view from going past bottom of last header view
- final int numHeaders = getHeaderViewsCount();
- final int numFooters = getFooterViewsCount();
- final int firstPos = getFirstVisiblePosition();
- final int lastPos = getLastVisiblePosition();
-
- // Log.d("mobeta",
- // "nHead="+numHeaders+" nFoot="+numFooters+" first="+firstPos+" last="+lastPos);
- int topLimit = getPaddingTop();
- if (firstPos < numHeaders) {
- topLimit = getChildAt(numHeaders - firstPos - 1).getBottom();
- }
- if ((mDragFlags & DRAG_NEG_Y) == 0) {
- if (firstPos <= mSrcPos) {
- topLimit = Math.max(getChildAt(mSrcPos - firstPos).getTop(), topLimit);
- }
- }
- // bottom limit is top of first footer View or
- // bottom of last item in list
- int bottomLimit = getHeight() - getPaddingBottom();
- if (lastPos >= getCount() - numFooters - 1) {
- bottomLimit = getChildAt(getCount() - numFooters - 1 - firstPos).getBottom();
- }
- if ((mDragFlags & DRAG_POS_Y) == 0) {
- if (lastPos >= mSrcPos) {
- bottomLimit = Math.min(getChildAt(mSrcPos - firstPos).getBottom(), bottomLimit);
- }
- }
-
- // Log.d("mobeta", "dragView top=" + (y - mDragDeltaY));
- // Log.d("mobeta", "limit=" + limit);
- // Log.d("mobeta", "mDragDeltaY=" + mDragDeltaY);
-
- if (floatY < topLimit) {
- mFloatLoc.y = topLimit;
- } else if (floatY + mFloatViewHeight > bottomLimit) {
- mFloatLoc.y = bottomLimit - mFloatViewHeight;
- }
-
- // get y-midpoint of floating view (constrained to ListView bounds)
- mFloatViewMid = mFloatLoc.y + mFloatViewHeightHalf;
- }
-
- private void destroyFloatView() {
- if (mFloatView != null) {
- mFloatView.setVisibility(GONE);
- if (mFloatViewManager != null) {
- mFloatViewManager.onDestroyFloatView(mFloatView);
- }
- mFloatView = null;
- invalidate();
- }
- }
-
- /**
- * Interface for customization of the floating View appearance and dragging
- * behavior. Implement your own and pass it to {@link #setFloatViewManager}.
- * If your own is not passed, the default {@link SimpleFloatViewManager}
- * implementation is used.
- */
- public interface FloatViewManager {
- /**
- * Return the floating View for item at position
.
- * DragSortListView will measure and layout this View for you, so feel
- * free to just inflate it. You can help DSLV by setting some
- * {@link ViewGroup.LayoutParams} on this View; otherwise it will set
- * some for you (with a width of FILL_PARENT and a height of
- * WRAP_CONTENT).
- *
- * @param position
- * Position of item to drag (NOTE: position
- * excludes header Views; thus, if you want to call
- * {@link ListView#getChildAt(int)}, you will need to add
- * {@link ListView#getHeaderViewsCount()} to the index).
- *
- * @return The View you wish to display as the floating View.
- */
- public View onCreateFloatView(int position);
-
- /**
- * Called whenever the floating View is dragged. Float View properties
- * can be changed here. Also, the upcoming location of the float View
- * can be altered by setting location.x
and
- * location.y
.
- *
- * @param floatView
- * The floating View.
- * @param location
- * The location (top-left; relative to DSLV top-left) at
- * which the float View would like to appear, given the
- * current touch location and the offset provided in
- * {@link DragSortListView#startDrag}.
- * @param touch
- * The current touch location (relative to DSLV top-left).
- * @param pendingScroll
- */
- public void onDragFloatView(View floatView, Point location, Point touch);
-
- /**
- * Called when the float View is dropped; lets you perform any necessary
- * cleanup. The internal DSLV floating View reference is set to null
- * immediately after this is called.
- *
- * @param floatView
- * The floating View passed to
- * {@link #onCreateFloatView(int)}.
- */
- public void onDestroyFloatView(View floatView);
- }
-
- public void setFloatViewManager(FloatViewManager manager) {
- mFloatViewManager = manager;
- }
-
- public void setDragListener(DragListener l) {
- mDragListener = l;
- }
-
- /**
- * Allows for easy toggling between a DragSortListView and a regular old
- * ListView. If enabled, items are draggable, where the drag init mode
- * determines how items are lifted (see {@link setDragInitMode(int)}). If
- * disabled, items cannot be dragged.
- *
- * @param enabled
- * Set true
to enable list item dragging
- */
- public void setDragEnabled(boolean enabled) {
- mDragEnabled = enabled;
- }
-
- public boolean isDragEnabled() {
- return mDragEnabled;
- }
-
- /**
- * This better reorder your ListAdapter! DragSortListView does not do this
- * for you; doesn't make sense to. Make sure
- * {@link BaseAdapter#notifyDataSetChanged()} or something like it is called
- * in your implementation. Furthermore, if you have a choiceMode other than
- * none and the ListAdapter does not return true for
- * {@link ListAdapter#hasStableIds()}, you will need to call
- * {@link #moveCheckState(int, int)} to move the check boxes along with the
- * list items.
- *
- * @param l
- */
- public void setDropListener(DropListener l) {
- mDropListener = l;
- }
-
- /**
- * Probably a no-brainer, but make sure that your remove listener calls
- * {@link BaseAdapter#notifyDataSetChanged()} or something like it. When an
- * item removal occurs, DragSortListView relies on a redraw of all the items
- * to recover invisible views and such. Strictly speaking, if you remove
- * something, your dataset has changed...
- *
- * @param l
- */
- public void setRemoveListener(RemoveListener l) {
- mRemoveListener = l;
- }
-
- public interface DragListener {
- public void drag(int from, int to);
- }
-
- /**
- * Your implementation of this has to reorder your ListAdapter! Make sure to
- * call {@link BaseAdapter#notifyDataSetChanged()} or something like it in
- * your implementation.
- *
- * @author heycosmo
- *
- */
- public interface DropListener {
- public void drop(int from, int to);
- }
-
- /**
- * Make sure to call {@link BaseAdapter#notifyDataSetChanged()} or something
- * like it in your implementation.
- *
- * @author heycosmo
- *
- */
- public interface RemoveListener {
- public void remove(int which);
- }
-
- public interface DragSortListener extends DropListener, DragListener, RemoveListener {
- }
-
- public void setDragSortListener(DragSortListener l) {
- setDropListener(l);
- setDragListener(l);
- setRemoveListener(l);
- }
-
- /**
- * Completely custom scroll speed profile. Default increases linearly with
- * position and is constant in time. Create your own by implementing
- * {@link DragSortListView.DragScrollProfile}.
- *
- * @param ssp
- */
- public void setDragScrollProfile(DragScrollProfile ssp) {
- if (ssp != null) {
- mScrollProfile = ssp;
- }
- }
-
- /**
- * Use this to move the check state of an item from one position to another
- * in a drop operation. If you have a choiceMode which is not none, this
- * method must be called when the order of items changes in an underlying
- * adapter which does not have stable IDs (see
- * {@link ListAdapter#hasStableIds()}). This is because without IDs, the
- * ListView has no way of knowing which items have moved where, and cannot
- * update the check state accordingly.
- *
- * A word of warning about a "feature" in Android that you may run into when
- * dealing with movable list items: for an adapter that does have
- * stable IDs, ListView will attempt to locate each item based on its ID and
- * move the check state from the item's old position to the new position —
- * which is all fine and good (and removes the need for calling this
- * function), except for the half-baked approach. Apparently to save time in
- * the naive algorithm used, ListView will only search for an ID in the
- * close neighborhood of the old position. If the user moves an item too far
- * (specifically, more than 20 rows away), ListView will give up and just
- * force the item to be unchecked. So if there is a reasonable chance that
- * the user will move items more than 20 rows away from the original
- * position, you may wish to use an adapter with unstable IDs and call this
- * method manually instead.
- *
- * @param from
- * @param to
- */
- public void moveCheckState(int from, int to) {
- // This method runs in O(n log n) time (n being the number of list
- // items). The bottleneck is the call to AbsListView.setItemChecked,
- // which is O(log n) because of the binary search involved in calling
- // SparseBooleanArray.put().
- //
- // To improve on the average time, we minimize the number of calls to
- // setItemChecked by only calling it for items that actually have a
- // changed state. This is achieved by building a list containing the
- // start and end of the "runs" of checked items, and then moving the
- // runs. Note that moving an item from A to B is essentially a rotation
- // of the range of items in [A, B]. Let's say we have
- // . . U V X Y Z . .
- // and move U after Z. This is equivalent to a rotation one step to the
- // left within the range you are moving across:
- // . . V X Y Z U . .
- //
- // So, to perform the move we enumerate all the runs within the move
- // range, then rotate each run one step to the left or right (depending
- // on move direction). For example, in the list:
- // X X . X X X . X
- // we have two runs. One begins at the last item of the list and wraps
- // around to the beginning, ending at position 1. The second begins at
- // position 3 and ends at position 5. To rotate a run, regardless of
- // length, we only need to set a check mark at one end of the run, and
- // clear a check mark at the other end:
- // X . X X X . X X
- SparseBooleanArray cip = getCheckedItemPositions();
- int rangeStart = from;
- int rangeEnd = to;
- if (to < from) {
- rangeStart = to;
- rangeEnd = from;
- }
- rangeEnd += 1;
-
- int[] runStart = new int[cip.size()];
- int[] runEnd = new int[cip.size()];
- int runCount = buildRunList(cip, rangeStart, rangeEnd, runStart, runEnd);
- if (runCount == 1 && (runStart[0] == runEnd[0])) {
- // Special case where all items are checked, we can never set any
- // item to false like we do below.
- return;
- }
-
- if (from < to) {
- for (int i = 0; i != runCount; i++) {
- setItemChecked(rotate(runStart[i], -1, rangeStart, rangeEnd), true);
- setItemChecked(rotate(runEnd[i], -1, rangeStart, rangeEnd), false);
- }
-
- } else {
- for (int i = 0; i != runCount; i++) {
- setItemChecked(runStart[i], false);
- setItemChecked(runEnd[i], true);
- }
- }
- }
-
- /**
- * Use this when an item has been deleted, to move the check state of all
- * following items up one step. If you have a choiceMode which is not none,
- * this method must be called when the order of items changes in an
- * underlying adapter which does not have stable IDs (see
- * {@link ListAdapter#hasStableIds()}). This is because without IDs, the
- * ListView has no way of knowing which items have moved where, and cannot
- * update the check state accordingly.
- *
- * See also further comments on {@link #moveCheckState(int, int)}.
- *
- * @param position
- */
- public void removeCheckState(int position) {
- SparseBooleanArray cip = getCheckedItemPositions();
-
- if (cip.size() == 0)
- return;
- int[] runStart = new int[cip.size()];
- int[] runEnd = new int[cip.size()];
- int rangeStart = position;
- int rangeEnd = cip.keyAt(cip.size() - 1) + 1;
- int runCount = buildRunList(cip, rangeStart, rangeEnd, runStart, runEnd);
- for (int i = 0; i != runCount; i++) {
- if (!(runStart[i] == position || (runEnd[i] < runStart[i] && runEnd[i] > position))) {
- // Only set a new check mark in front of this run if it does
- // not contain the deleted position. If it does, we only need
- // to make it one check mark shorter at the end.
- setItemChecked(rotate(runStart[i], -1, rangeStart, rangeEnd), true);
- }
- setItemChecked(rotate(runEnd[i], -1, rangeStart, rangeEnd), false);
- }
- }
-
- private static int buildRunList(SparseBooleanArray cip, int rangeStart, int rangeEnd, int[] runStart, int[] runEnd) {
- int runCount = 0;
-
- int i = findFirstSetIndex(cip, rangeStart, rangeEnd);
- if (i == -1)
- return 0;
-
- int position = cip.keyAt(i);
- int currentRunStart = position;
- int currentRunEnd = currentRunStart + 1;
- for (i++; i < cip.size() && (position = cip.keyAt(i)) < rangeEnd; i++) {
- if (!cip.valueAt(i)) // not checked => not interesting
- continue;
- if (position == currentRunEnd) {
- currentRunEnd++;
- } else {
- runStart[runCount] = currentRunStart;
- runEnd[runCount] = currentRunEnd;
- runCount++;
- currentRunStart = position;
- currentRunEnd = position + 1;
- }
- }
-
- if (currentRunEnd == rangeEnd) {
- // rangeStart and rangeEnd are equivalent positions so to be
- // consistent we translate them to the same integer value. That way
- // we can check whether a run covers the entire range by just
- // checking if the start equals the end position.
- currentRunEnd = rangeStart;
- }
- runStart[runCount] = currentRunStart;
- runEnd[runCount] = currentRunEnd;
- runCount++;
-
- if (runCount > 1) {
- if (runStart[0] == rangeStart && runEnd[runCount - 1] == rangeStart) {
- // The last run ends at the end of the range, and the first run
- // starts at the beginning of the range. So they are actually
- // part of the same run, except they wrap around the end of the
- // range. To avoid adjacent runs, we need to merge them.
- runStart[0] = runStart[runCount - 1];
- runCount--;
- }
- }
- return runCount;
- }
-
- private static int rotate(int value, int offset, int lowerBound, int upperBound) {
- int windowSize = upperBound - lowerBound;
-
- value += offset;
- if (value < lowerBound) {
- value += windowSize;
- } else if (value >= upperBound) {
- value -= windowSize;
- }
- return value;
- }
-
- private static int findFirstSetIndex(SparseBooleanArray sba, int rangeStart, int rangeEnd) {
- int size = sba.size();
- int i = insertionIndexForKey(sba, rangeStart);
- while (i < size && sba.keyAt(i) < rangeEnd && !sba.valueAt(i))
- i++;
- if (i == size || sba.keyAt(i) >= rangeEnd)
- return -1;
- return i;
- }
-
- private static int insertionIndexForKey(SparseBooleanArray sba, int key) {
- int low = 0;
- int high = sba.size();
- while (high - low > 0) {
- int middle = (low + high) >> 1;
- if (sba.keyAt(middle) < key)
- low = middle + 1;
- else
- high = middle;
- }
- return low;
- }
-
- /**
- * Interface for controlling scroll speed as a function of touch position
- * and time. Use
- * {@link DragSortListView#setDragScrollProfile(DragScrollProfile)} to set
- * custom profile.
- *
- * @author heycosmo
- *
- */
- public interface DragScrollProfile {
- /**
- * Return a scroll speed in pixels/millisecond. Always return a positive
- * number.
- *
- * @param w
- * Normalized position in scroll region (i.e. w \in [0,1]).
- * Small w typically means slow scrolling.
- * @param t
- * Time (in milliseconds) since start of scroll (handy if you
- * want scroll acceleration).
- * @return Scroll speed at position w and time t in pixels/ms.
- */
- float getSpeed(float w, long t);
- }
-
- private class DragScroller implements Runnable {
-
- private boolean mAbort;
-
- private long mPrevTime;
- private long mCurrTime;
-
- private int dy;
- private float dt;
- private long tStart;
- private int scrollDir;
-
- public final static int STOP = -1;
- public final static int UP = 0;
- public final static int DOWN = 1;
-
- private float mScrollSpeed; // pixels per ms
-
- private boolean mScrolling = false;
-
- private int mLastHeader;
- private int mFirstFooter;
-
- public boolean isScrolling() {
- return mScrolling;
- }
-
- public int getScrollDir() {
- return mScrolling ? scrollDir : STOP;
- }
-
- public DragScroller() {
- }
-
- public void startScrolling(int dir) {
- if (!mScrolling) {
- // Debug.startMethodTracing("dslv-scroll");
- mAbort = false;
- mScrolling = true;
- tStart = SystemClock.uptimeMillis();
- mPrevTime = tStart;
- scrollDir = dir;
- post(this);
- }
- }
-
- public void stopScrolling(boolean now) {
- if (now) {
- removeCallbacks(this);
- mScrolling = false;
- } else {
- mAbort = true;
- }
-
- // Debug.stopMethodTracing();
- }
-
- @Override
- public void run() {
- if (mAbort) {
- mScrolling = false;
- return;
- }
-
- // Log.d("mobeta", "scroll");
-
- final int first = getFirstVisiblePosition();
- final int last = getLastVisiblePosition();
- final int count = getCount();
- final int padTop = getPaddingTop();
- final int listHeight = getHeight() - padTop - getPaddingBottom();
-
- int minY = Math.min(mY, mFloatViewMid + mFloatViewHeightHalf);
- int maxY = Math.max(mY, mFloatViewMid - mFloatViewHeightHalf);
-
- if (scrollDir == UP) {
- View v = getChildAt(0);
- // Log.d("mobeta", "vtop="+v.getTop()+" padtop="+padTop);
- if (v == null) {
- mScrolling = false;
- return;
- } else {
- if (first == 0 && v.getTop() == padTop) {
- mScrolling = false;
- return;
- }
- }
- mScrollSpeed = mScrollProfile.getSpeed((mUpScrollStartYF - maxY) / mDragUpScrollHeight, mPrevTime);
- } else {
- View v = getChildAt(last - first);
- if (v == null) {
- mScrolling = false;
- return;
- } else {
- if (last == count - 1 && v.getBottom() <= listHeight + padTop) {
- mScrolling = false;
- return;
- }
- }
- mScrollSpeed = -mScrollProfile.getSpeed((minY - mDownScrollStartYF) / mDragDownScrollHeight, mPrevTime);
- }
-
- mCurrTime = SystemClock.uptimeMillis();
- dt = mCurrTime - mPrevTime;
-
- // dy is change in View position of a list item; i.e. positive dy
- // means user is scrolling up (list item moves down the screen,
- // remember
- // y=0 is at top of View).
- dy = Math.round(mScrollSpeed * dt);
-
- int movePos;
- if (dy >= 0) {
- dy = Math.min(listHeight, dy);
- movePos = first;
- } else {
- dy = Math.max(-listHeight, dy);
- movePos = last;
- }
-
- final View moveItem = getChildAt(movePos - first);
- int top = moveItem.getTop() + dy;
-
- if (movePos == 0 && top > padTop) {
- top = padTop;
- }
-
- // always do scroll
- mBlockLayoutRequests = true;
-
- setSelectionFromTop(movePos, top - padTop);
- layoutChildren();
- invalidate();
-
- mBlockLayoutRequests = false;
-
- // scroll means relative float View movement
- doDragFloatView(movePos, moveItem, false);
-
- mPrevTime = mCurrTime;
- // Log.d("mobeta", " updated prevTime="+mPrevTime);
-
- post(this);
- }
- }
-
- private class DragSortTracker {
- StringBuilder mBuilder = new StringBuilder();
-
- File mFile;
-
- private int mNumInBuffer = 0;
- private int mNumFlushes = 0;
-
- private boolean mTracking = false;
-
- public DragSortTracker() {
- File root = Environment.getExternalStorageDirectory();
- mFile = new File(root, "dslv_state.txt");
-
- if (!mFile.exists()) {
- try {
- mFile.createNewFile();
- Log.d("mobeta", "file created");
- } catch (IOException e) {
- Log.w("mobeta", "Could not create dslv_state.txt");
- Log.d("mobeta", e.getMessage());
- }
- }
-
- }
-
- public void startTracking() {
- mBuilder.append("\n");
- mNumFlushes = 0;
- mTracking = true;
- }
-
- public void appendState() {
- if (!mTracking) {
- return;
- }
-
- mBuilder.append("\n");
- final int children = getChildCount();
- final int first = getFirstVisiblePosition();
- mBuilder.append(" ");
- for (int i = 0; i < children; ++i) {
- mBuilder.append(first + i).append(",");
- }
- mBuilder.append("\n");
-
- mBuilder.append(" ");
- for (int i = 0; i < children; ++i) {
- mBuilder.append(getChildAt(i).getTop()).append(",");
- }
- mBuilder.append("\n");
- mBuilder.append(" ");
- for (int i = 0; i < children; ++i) {
- mBuilder.append(getChildAt(i).getBottom()).append(",");
- }
- mBuilder.append("\n");
-
- mBuilder.append(" ").append(mFirstExpPos).append("\n");
- mBuilder.append(" ")
- .append(getItemHeight(mFirstExpPos) - getChildHeight(mFirstExpPos))
- .append("\n");
- mBuilder.append(" ").append(mSecondExpPos).append("\n");
- mBuilder.append(" ")
- .append(getItemHeight(mSecondExpPos) - getChildHeight(mSecondExpPos))
- .append("\n");
- mBuilder.append(" ").append(mSrcPos).append("\n");
- mBuilder.append(" ").append(mFloatViewHeight + getDividerHeight()).append("\n");
- mBuilder.append(" ").append(getHeight()).append("\n");
- mBuilder.append(" ").append(mLastY).append("\n");
- mBuilder.append(" ").append(mFloatViewMid).append("\n");
- mBuilder.append(" ");
- for (int i = 0; i < children; ++i) {
- mBuilder.append(getShuffleEdge(first + i, getChildAt(i).getTop())).append(",");
- }
- mBuilder.append("\n");
-
- mBuilder.append("\n");
- mNumInBuffer++;
-
- if (mNumInBuffer > 1000) {
- flush();
- mNumInBuffer = 0;
- }
- }
-
- public void flush() {
- if (!mTracking) {
- return;
- }
-
- // save to file on sdcard
- try {
- boolean append = true;
- if (mNumFlushes == 0) {
- append = false;
- }
- FileWriter writer = new FileWriter(mFile, append);
-
- writer.write(mBuilder.toString());
- mBuilder.delete(0, mBuilder.length());
-
- writer.flush();
- writer.close();
-
- mNumFlushes++;
- } catch (IOException e) {
- // do nothing
- }
- }
-
- public void stopTracking() {
- if (mTracking) {
- mBuilder.append("\n");
- flush();
- mTracking = false;
- }
- }
-
- }
-
-}
diff --git a/Clover/app/src/main/java/com/mobeta/android/dslv/ResourceDragSortCursorAdapter.java b/Clover/app/src/main/java/com/mobeta/android/dslv/ResourceDragSortCursorAdapter.java
deleted file mode 100644
index 63fc5c5a..00000000
--- a/Clover/app/src/main/java/com/mobeta/android/dslv/ResourceDragSortCursorAdapter.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.mobeta.android.dslv;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-// taken from v4 rev. 10 ResourceCursorAdapter.java
-
-/**
- * Static library support version of the framework's
- * {@link android.widget.ResourceCursorAdapter}. Used to write apps that run on
- * platforms prior to Android 3.0. When running on Android 3.0 or above, this
- * implementation is still used; it does not try to switch to the framework's
- * implementation. See the framework SDK documentation for a class overview.
- */
-public abstract class ResourceDragSortCursorAdapter extends DragSortCursorAdapter {
- private int mLayout;
-
- private int mDropDownLayout;
-
- private LayoutInflater mInflater;
-
- /**
- * Constructor the enables auto-requery.
- *
- * @deprecated This option is discouraged, as it results in Cursor queries
- * being performed on the application's UI thread and thus can
- * cause poor responsiveness or even Application Not Responding
- * errors. As an alternative, use
- * {@link android.app.LoaderManager} with a
- * {@link android.content.CursorLoader}.
- *
- * @param context
- * The context where the ListView associated with this adapter is
- * running
- * @param layout
- * resource identifier of a layout file that defines the views
- * for this list item. Unless you override them later, this will
- * define both the item views and the drop down views.
- */
- @Deprecated
- public ResourceDragSortCursorAdapter(Context context, int layout, Cursor c) {
- super(context, c);
- mLayout = mDropDownLayout = layout;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- /**
- * Constructor with default behavior as per
- * {@link CursorAdapter#CursorAdapter(Context, Cursor, boolean)}; it is
- * recommended you not use this, but instead
- * {@link #ResourceCursorAdapter(Context, int, Cursor, int)}. When using
- * this constructor, {@link #FLAG_REGISTER_CONTENT_OBSERVER} will always be
- * set.
- *
- * @param context
- * The context where the ListView associated with this adapter is
- * running
- * @param layout
- * resource identifier of a layout file that defines the views
- * for this list item. Unless you override them later, this will
- * define both the item views and the drop down views.
- * @param c
- * The cursor from which to get the data.
- * @param autoRequery
- * If true the adapter will call requery() on the cursor whenever
- * it changes so the most recent data is always displayed. Using
- * true here is discouraged.
- */
- public ResourceDragSortCursorAdapter(Context context, int layout, Cursor c, boolean autoRequery) {
- super(context, c, autoRequery);
- mLayout = mDropDownLayout = layout;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- /**
- * Standard constructor.
- *
- * @param context
- * The context where the ListView associated with this adapter is
- * running
- * @param layout
- * Resource identifier of a layout file that defines the views
- * for this list item. Unless you override them later, this will
- * define both the item views and the drop down views.
- * @param c
- * The cursor from which to get the data.
- * @param flags
- * Flags used to determine the behavior of the adapter, as per
- * {@link CursorAdapter#CursorAdapter(Context, Cursor, int)}.
- */
- public ResourceDragSortCursorAdapter(Context context, int layout, Cursor c, int flags) {
- super(context, c, flags);
- mLayout = mDropDownLayout = layout;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- /**
- * Inflates view(s) from the specified XML file.
- *
- * @see android.widget.CursorAdapter#newView(android.content.Context,
- * android.database.Cursor, ViewGroup)
- */
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(mLayout, parent, false);
- }
-
- @Override
- public View newDropDownView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(mDropDownLayout, parent, false);
- }
-
- /**
- *
- * Sets the layout resource of the item views.
- *
- *
- * @param layout
- * the layout resources used to create item views
- */
- public void setViewResource(int layout) {
- mLayout = layout;
- }
-
- /**
- *
- * Sets the layout resource of the drop down views.
- *
- *
- * @param dropDownLayout
- * the layout resources used to create drop down views
- */
- public void setDropDownViewResource(int dropDownLayout) {
- mDropDownLayout = dropDownLayout;
- }
-}
diff --git a/Clover/app/src/main/java/com/mobeta/android/dslv/SimpleDragSortCursorAdapter.java b/Clover/app/src/main/java/com/mobeta/android/dslv/SimpleDragSortCursorAdapter.java
deleted file mode 100644
index c01ecb61..00000000
--- a/Clover/app/src/main/java/com/mobeta/android/dslv/SimpleDragSortCursorAdapter.java
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright (C) 2006 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 com.mobeta.android.dslv;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-// taken from sdk/sources/android-16/android/widget/SimpleCursorAdapter.java
-
-/**
- * An easy adapter to map columns from a cursor to TextViews or ImageViews
- * defined in an XML file. You can specify which columns you want, which views
- * you want to display the columns, and the XML file that defines the appearance
- * of these views.
- *
- * Binding occurs in two phases. First, if a
- * {@link android.widget.SimpleCursorAdapter.ViewBinder} is available,
- * {@link ViewBinder#setViewValue(android.view.View, android.database.Cursor, int)}
- * is invoked. If the returned value is true, binding has occured. If the
- * returned value is false and the view to bind is a TextView,
- * {@link #setViewText(TextView, String)} is invoked. If the returned value is
- * false and the view to bind is an ImageView,
- * {@link #setViewImage(ImageView, String)} is invoked. If no appropriate
- * binding can be found, an {@link IllegalStateException} is thrown.
- *
- * If this adapter is used with filtering, for instance in an
- * {@link android.widget.AutoCompleteTextView}, you can use the
- * {@link android.widget.SimpleCursorAdapter.CursorToStringConverter} and the
- * {@link android.widget.FilterQueryProvider} interfaces to get control over the
- * filtering process. You can refer to
- * {@link #convertToString(android.database.Cursor)} and
- * {@link #runQueryOnBackgroundThread(CharSequence)} for more information.
- */
-public class SimpleDragSortCursorAdapter extends ResourceDragSortCursorAdapter {
- /**
- * A list of columns containing the data to bind to the UI. This field
- * should be made private, so it is hidden from the SDK. {@hide}
- */
- protected int[] mFrom;
- /**
- * A list of View ids representing the views to which the data must be
- * bound. This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected int[] mTo;
-
- private int mStringConversionColumn = -1;
- private CursorToStringConverter mCursorToStringConverter;
- private ViewBinder mViewBinder;
-
- String[] mOriginalFrom;
-
- /**
- * Constructor the enables auto-requery.
- *
- * @deprecated This option is discouraged, as it results in Cursor queries
- * being performed on the application's UI thread and thus can
- * cause poor responsiveness or even Application Not Responding
- * errors. As an alternative, use
- * {@link android.app.LoaderManager} with a
- * {@link android.content.CursorLoader}.
- */
- @Deprecated
- public SimpleDragSortCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
- super(context, layout, c);
- mTo = to;
- mOriginalFrom = from;
- findColumns(c, from);
- }
-
- /**
- * Standard constructor.
- *
- * @param context
- * The context where the ListView associated with this
- * SimpleListItemFactory is running
- * @param layout
- * resource identifier of a layout file that defines the views
- * for this list item. The layout file should include at least
- * those named views defined in "to"
- * @param c
- * The database cursor. Can be null if the cursor is not
- * available yet.
- * @param from
- * A list of column names representing the data to bind to the
- * UI. Can be null if the cursor is not available yet.
- * @param to
- * The views that should display column in the "from" parameter.
- * These should all be TextViews. The first N views in this list
- * are given the values of the first N columns in the from
- * parameter. Can be null if the cursor is not available yet.
- * @param flags
- * Flags used to determine the behavior of the adapter, as per
- * {@link CursorAdapter#CursorAdapter(Context, Cursor, int)}.
- */
- public SimpleDragSortCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
- super(context, layout, c, flags);
- mTo = to;
- mOriginalFrom = from;
- findColumns(c, from);
- }
-
- /**
- * Binds all of the field names passed into the "to" parameter of the
- * constructor with their corresponding cursor columns as specified in the
- * "from" parameter.
- *
- * Binding occurs in two phases. First, if a
- * {@link android.widget.SimpleCursorAdapter.ViewBinder} is available,
- * {@link ViewBinder#setViewValue(android.view.View, android.database.Cursor, int)}
- * is invoked. If the returned value is true, binding has occured. If the
- * returned value is false and the view to bind is a TextView,
- * {@link #setViewText(TextView, String)} is invoked. If the returned value
- * is false and the view to bind is an ImageView,
- * {@link #setViewImage(ImageView, String)} is invoked. If no appropriate
- * binding can be found, an {@link IllegalStateException} is thrown.
- *
- * @throws IllegalStateException
- * if binding cannot occur
- *
- * @see android.widget.CursorAdapter#bindView(android.view.View,
- * android.content.Context, android.database.Cursor)
- * @see #getViewBinder()
- * @see #setViewBinder(android.widget.SimpleCursorAdapter.ViewBinder)
- * @see #setViewImage(ImageView, String)
- * @see #setViewText(TextView, String)
- */
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- final ViewBinder binder = mViewBinder;
- final int count = mTo.length;
- final int[] from = mFrom;
- final int[] to = mTo;
-
- for (int i = 0; i < count; i++) {
- final View v = view.findViewById(to[i]);
- if (v != null) {
- boolean bound = false;
- if (binder != null) {
- bound = binder.setViewValue(v, cursor, from[i]);
- }
-
- if (!bound) {
- String text = cursor.getString(from[i]);
- if (text == null) {
- text = "";
- }
-
- if (v instanceof TextView) {
- setViewText((TextView) v, text);
- } else if (v instanceof ImageView) {
- setViewImage((ImageView) v, text);
- } else {
- throw new IllegalStateException(v.getClass().getName() + " is not a "
- + " view that can be bounds by this SimpleCursorAdapter");
- }
- }
- }
- }
- }
-
- /**
- * Returns the {@link ViewBinder} used to bind data to views.
- *
- * @return a ViewBinder or null if the binder does not exist
- *
- * @see #bindView(android.view.View, android.content.Context,
- * android.database.Cursor)
- * @see #setViewBinder(android.widget.SimpleCursorAdapter.ViewBinder)
- */
- public ViewBinder getViewBinder() {
- return mViewBinder;
- }
-
- /**
- * Sets the binder used to bind data to views.
- *
- * @param viewBinder
- * the binder used to bind data to views, can be null to remove
- * the existing binder
- *
- * @see #bindView(android.view.View, android.content.Context,
- * android.database.Cursor)
- * @see #getViewBinder()
- */
- public void setViewBinder(ViewBinder viewBinder) {
- mViewBinder = viewBinder;
- }
-
- /**
- * Called by bindView() to set the image for an ImageView but only if there
- * is no existing ViewBinder or if the existing ViewBinder cannot handle
- * binding to an ImageView.
- *
- * By default, the value will be treated as an image resource. If the value
- * cannot be used as an image resource, the value is used as an image Uri.
- *
- * Intended to be overridden by Adapters that need to setFilter strings
- * retrieved from the database.
- *
- * @param v
- * ImageView to receive an image
- * @param value
- * the value retrieved from the cursor
- */
- public void setViewImage(ImageView v, String value) {
- try {
- v.setImageResource(Integer.parseInt(value));
- } catch (NumberFormatException nfe) {
- v.setImageURI(Uri.parse(value));
- }
- }
-
- /**
- * Called by bindView() to set the text for a TextView but only if there is
- * no existing ViewBinder or if the existing ViewBinder cannot handle
- * binding to a TextView.
- *
- * Intended to be overridden by Adapters that need to setFilter strings
- * retrieved from the database.
- *
- * @param v
- * TextView to receive text
- * @param text
- * the text to be set for the TextView
- */
- public void setViewText(TextView v, String text) {
- v.setText(text);
- }
-
- /**
- * Return the index of the column used to get a String representation of the
- * Cursor.
- *
- * @return a valid index in the current Cursor or -1
- *
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- * @see #setStringConversionColumn(int)
- * @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
- * @see #getCursorToStringConverter()
- */
- public int getStringConversionColumn() {
- return mStringConversionColumn;
- }
-
- /**
- * Defines the index of the column in the Cursor used to get a String
- * representation of that Cursor. The column is used to convert the Cursor
- * to a String only when the current CursorToStringConverter is null.
- *
- * @param stringConversionColumn
- * a valid index in the current Cursor or -1 to use the default
- * conversion mechanism
- *
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- * @see #getStringConversionColumn()
- * @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
- * @see #getCursorToStringConverter()
- */
- public void setStringConversionColumn(int stringConversionColumn) {
- mStringConversionColumn = stringConversionColumn;
- }
-
- /**
- * Returns the converter used to convert the filtering Cursor into a String.
- *
- * @return null if the converter does not exist or an instance of
- * {@link android.widget.SimpleCursorAdapter.CursorToStringConverter}
- *
- * @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
- * @see #getStringConversionColumn()
- * @see #setStringConversionColumn(int)
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- */
- public CursorToStringConverter getCursorToStringConverter() {
- return mCursorToStringConverter;
- }
-
- /**
- * Sets the converter used to convert the filtering Cursor into a String.
- *
- * @param cursorToStringConverter
- * the Cursor to String converter, or null to remove the
- * converter
- *
- * @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
- * @see #getStringConversionColumn()
- * @see #setStringConversionColumn(int)
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- */
- public void setCursorToStringConverter(CursorToStringConverter cursorToStringConverter) {
- mCursorToStringConverter = cursorToStringConverter;
- }
-
- /**
- * Returns a CharSequence representation of the specified Cursor as defined
- * by the current CursorToStringConverter. If no CursorToStringConverter has
- * been set, the String conversion column is used instead. If the conversion
- * column is -1, the returned String is empty if the cursor is null or
- * Cursor.toString().
- *
- * @param cursor
- * the Cursor to convert to a CharSequence
- *
- * @return a non-null CharSequence representing the cursor
- */
- @Override
- public CharSequence convertToString(Cursor cursor) {
- if (mCursorToStringConverter != null) {
- return mCursorToStringConverter.convertToString(cursor);
- } else if (mStringConversionColumn > -1) {
- return cursor.getString(mStringConversionColumn);
- }
-
- return super.convertToString(cursor);
- }
-
- /**
- * Create a map from an array of strings to an array of column-id integers
- * in cursor c. If c is null, the array will be discarded.
- *
- * @param c
- * the cursor to find the columns from
- * @param from
- * the Strings naming the columns of interest
- */
- private void findColumns(Cursor c, String[] from) {
- if (c != null) {
- int i;
- int count = from.length;
- if (mFrom == null || mFrom.length != count) {
- mFrom = new int[count];
- }
- for (i = 0; i < count; i++) {
- mFrom[i] = c.getColumnIndexOrThrow(from[i]);
- }
- } else {
- mFrom = null;
- }
- }
-
- @Override
- public Cursor swapCursor(Cursor c) {
- // super.swapCursor() will notify observers before we have
- // a valid mapping, make sure we have a mapping before this
- // happens
- findColumns(c, mOriginalFrom);
- return super.swapCursor(c);
- }
-
- /**
- * Change the cursor and change the column-to-view mappings at the same
- * time.
- *
- * @param c
- * The database cursor. Can be null if the cursor is not
- * available yet.
- * @param from
- * A list of column names representing the data to bind to the
- * UI. Can be null if the cursor is not available yet.
- * @param to
- * The views that should display column in the "from" parameter.
- * These should all be TextViews. The first N views in this list
- * are given the values of the first N columns in the from
- * parameter. Can be null if the cursor is not available yet.
- */
- public void changeCursorAndColumns(Cursor c, String[] from, int[] to) {
- mOriginalFrom = from;
- mTo = to;
- // super.changeCursor() will notify observers before we have
- // a valid mapping, make sure we have a mapping before this
- // happens
- findColumns(c, mOriginalFrom);
- super.changeCursor(c);
- }
-
- /**
- * This class can be used by external clients of SimpleCursorAdapter to bind
- * values fom the Cursor to views.
- *
- * You should use this class to bind values from the Cursor to views that
- * are not directly supported by SimpleCursorAdapter or to change the way
- * binding occurs for views supported by SimpleCursorAdapter.
- *
- * @see SimpleCursorAdapter#bindView(android.view.View,
- * android.content.Context, android.database.Cursor)
- * @see SimpleCursorAdapter#setViewImage(ImageView, String)
- * @see SimpleCursorAdapter#setViewText(TextView, String)
- */
- public static interface ViewBinder {
- /**
- * Binds the Cursor column defined by the specified index to the
- * specified view.
- *
- * When binding is handled by this ViewBinder, this method must return
- * true. If this method returns false, SimpleCursorAdapter will attempts
- * to handle the binding on its own.
- *
- * @param view
- * the view to bind the data to
- * @param cursor
- * the cursor to get the data from
- * @param columnIndex
- * the column at which the data can be found in the cursor
- *
- * @return true if the data was bound to the view, false otherwise
- */
- boolean setViewValue(View view, Cursor cursor, int columnIndex);
- }
-
- /**
- * This class can be used by external clients of SimpleCursorAdapter to
- * define how the Cursor should be converted to a String.
- *
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- */
- public static interface CursorToStringConverter {
- /**
- * Returns a CharSequence representing the specified Cursor.
- *
- * @param cursor
- * the cursor for which a CharSequence representation is
- * requested
- *
- * @return a non-null CharSequence representing the cursor
- */
- CharSequence convertToString(Cursor cursor);
- }
-
-}
diff --git a/Clover/app/src/main/java/com/mobeta/android/dslv/SimpleFloatViewManager.java b/Clover/app/src/main/java/com/mobeta/android/dslv/SimpleFloatViewManager.java
deleted file mode 100644
index 27dd8328..00000000
--- a/Clover/app/src/main/java/com/mobeta/android/dslv/SimpleFloatViewManager.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.mobeta.android.dslv;
-
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Point;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.ListView;
-
-/**
- * Simple implementation of the FloatViewManager class. Uses list items as they
- * appear in the ListView to create the floating View.
- */
-public class SimpleFloatViewManager implements DragSortListView.FloatViewManager {
-
- private Bitmap mFloatBitmap;
-
- private ImageView mImageView;
-
- private int mFloatBGColor = Color.BLACK;
-
- private ListView mListView;
-
- public SimpleFloatViewManager(ListView lv) {
- mListView = lv;
- }
-
- public void setBackgroundColor(int color) {
- mFloatBGColor = color;
- }
-
- /**
- * This simple implementation creates a Bitmap copy of the list item
- * currently shown at ListView position
.
- */
- @Override
- public View onCreateFloatView(int position) {
- // Guaranteed that this will not be null? I think so. Nope, got
- // a NullPointerException once...
- View v = mListView.getChildAt(position + mListView.getHeaderViewsCount() - mListView.getFirstVisiblePosition());
-
- if (v == null) {
- return null;
- }
-
- v.setPressed(false);
-
- // Create a copy of the drawing cache so that it does not get
- // recycled by the framework when the list tries to clean up memory
- //v.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
- v.setDrawingCacheEnabled(true);
- mFloatBitmap = Bitmap.createBitmap(v.getDrawingCache());
- v.setDrawingCacheEnabled(false);
-
- if (mImageView == null) {
- mImageView = new ImageView(mListView.getContext());
- }
- mImageView.setBackgroundColor(mFloatBGColor);
- mImageView.setPadding(0, 0, 0, 0);
- mImageView.setImageBitmap(mFloatBitmap);
- mImageView.setLayoutParams(new ViewGroup.LayoutParams(v.getWidth(), v.getHeight()));
-
- return mImageView;
- }
-
- /**
- * This does nothing
- */
- @Override
- public void onDragFloatView(View floatView, Point position, Point touch) {
- // do nothing
- }
-
- /**
- * Removes the Bitmap from the ImageView created in onCreateFloatView() and
- * tells the system to recycle it.
- */
- @Override
- public void onDestroyFloatView(View floatView) {
- ((ImageView) floatView).setImageDrawable(null);
-
- mFloatBitmap.recycle();
- mFloatBitmap = null;
- }
-
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/Chan.java b/Clover/app/src/main/java/org/floens/chan/Chan.java
new file mode 100644
index 00000000..1c0986bd
--- /dev/null
+++ b/Clover/app/src/main/java/org/floens/chan/Chan.java
@@ -0,0 +1,220 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.floens.chan;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.StrictMode;
+import android.view.ViewConfiguration;
+
+import com.android.volley.RequestQueue;
+import com.android.volley.toolbox.ImageLoader;
+import com.android.volley.toolbox.Volley;
+import com.squareup.leakcanary.LeakCanary;
+import com.squareup.leakcanary.RefWatcher;
+
+import org.floens.chan.chan.ChanUrls;
+import org.floens.chan.core.cache.FileCache;
+import org.floens.chan.core.manager.BoardManager;
+import org.floens.chan.core.manager.WatchManager;
+import org.floens.chan.core.net.BitmapLruImageCache;
+import org.floens.chan.core.reply.ReplyManager;
+import org.floens.chan.core.settings.ChanSettings;
+import org.floens.chan.database.DatabaseManager;
+import org.floens.chan.utils.AndroidUtils;
+import org.floens.chan.utils.Logger;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.Locale;
+
+import de.greenrobot.event.EventBus;
+
+public class Chan extends Application {
+ private static final String TAG = "ChanApplication";
+
+ private static final long FILE_CACHE_DISK_SIZE = 50 * 1024 * 1024;
+ private static final String FILE_CACHE_NAME = "filecache";
+ private static final int VOLLEY_LRU_CACHE_SIZE = 8 * 1024 * 1024;
+ private static final int VOLLEY_CACHE_SIZE = 10 * 1024 * 1024;
+
+ public static Context con;
+
+ private static Chan instance;
+ private static RequestQueue volleyRequestQueue;
+ private static com.android.volley.toolbox.ImageLoader imageLoader;
+ private static BoardManager boardManager;
+ private static WatchManager watchManager;
+ private static ReplyManager replyManager;
+ private static DatabaseManager databaseManager;
+ private static FileCache fileCache;
+ private static RefWatcher refWatcher;
+
+ private String userAgent;
+ private int activityForegroundCounter = 0;
+
+ public Chan() {
+ instance = this;
+ con = this;
+ }
+
+ public static Chan getInstance() {
+ return instance;
+ }
+
+ public static RequestQueue getVolleyRequestQueue() {
+ return volleyRequestQueue;
+ }
+
+ public static ImageLoader getVolleyImageLoader() {
+ return imageLoader;
+ }
+
+ public static BoardManager getBoardManager() {
+ return boardManager;
+ }
+
+ public static WatchManager getWatchManager() {
+ return watchManager;
+ }
+
+ public static ReplyManager getReplyManager() {
+ return replyManager;
+ }
+
+ public static DatabaseManager getDatabaseManager() {
+ return databaseManager;
+ }
+
+ public static FileCache getFileCache() {
+ return fileCache;
+ }
+
+ public static RefWatcher getRefWatcher() {
+ return refWatcher;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ // Force the overflow button to show, even on devices that have a
+ // physical button.
+ try {
+ ViewConfiguration config = ViewConfiguration.get(this);
+ Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
+ if (menuKeyField != null) {
+ menuKeyField.setAccessible(true);
+ menuKeyField.setBoolean(config, false);
+ }
+ } catch (Exception e) {
+ }
+
+ if (ChanBuild.DEVELOPER_MODE) {
+ refWatcher = LeakCanary.install(this);
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
+ }
+
+ AndroidUtils.init();
+
+ ChanUrls.loadScheme(ChanSettings.networkHttps.get());
+
+ // User agent is /
+ String version = "";
+ try {
+ version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ version = version.toLowerCase(Locale.ENGLISH).replace(" ", "_");
+ userAgent = getString(R.string.app_name) + "/" + version;
+
+ cleanupOutdated();
+
+ File cacheDir = getExternalCacheDir() != null ? getExternalCacheDir() : getCacheDir();
+
+ replyManager = new ReplyManager(this);
+
+ volleyRequestQueue = Volley.newRequestQueue(this, getUserAgent(), null, new File(cacheDir, Volley.DEFAULT_CACHE_DIR), VOLLEY_CACHE_SIZE);
+ imageLoader = new ImageLoader(volleyRequestQueue, new BitmapLruImageCache(VOLLEY_LRU_CACHE_SIZE));
+
+ fileCache = new FileCache(new File(cacheDir, FILE_CACHE_NAME), FILE_CACHE_DISK_SIZE, getUserAgent());
+
+ databaseManager = new DatabaseManager(this);
+ boardManager = new BoardManager();
+ watchManager = new WatchManager(this);
+ }
+
+ public String getUserAgent() {
+ return userAgent;
+ }
+
+ public void activityEnteredForeground() {
+ boolean lastForeground = getApplicationInForeground();
+
+ activityForegroundCounter++;
+
+ if (getApplicationInForeground() != lastForeground) {
+ EventBus.getDefault().post(new ForegroundChangedMessage(getApplicationInForeground()));
+ }
+ }
+
+ public void activityEnteredBackground() {
+ boolean lastForeground = getApplicationInForeground();
+
+ activityForegroundCounter--;
+ if (activityForegroundCounter < 0) {
+ Logger.wtf(TAG, "activityForegroundCounter below 0");
+ }
+
+ if (getApplicationInForeground() != lastForeground) {
+ EventBus.getDefault().post(new ForegroundChangedMessage(getApplicationInForeground()));
+ }
+ }
+
+ public boolean getApplicationInForeground() {
+ return activityForegroundCounter > 0;
+ }
+
+ private void cleanupOutdated() {
+ File ionCacheFolder = new File(getCacheDir() + "/ion");
+ if (ionCacheFolder.exists() && ionCacheFolder.isDirectory()) {
+ Logger.i(TAG, "Clearing old ion folder");
+ for (File file : ionCacheFolder.listFiles()) {
+ if (!file.delete()) {
+ Logger.i(TAG, "Could not delete old ion file " + file.getName());
+ }
+ }
+ if (!ionCacheFolder.delete()) {
+ Logger.i(TAG, "Could not delete old ion folder");
+ } else {
+ Logger.i(TAG, "Deleted old ion folder");
+ }
+ }
+ }
+
+ public static class ForegroundChangedMessage {
+ public boolean inForeground;
+
+ public ForegroundChangedMessage(boolean inForeground) {
+ this.inForeground = inForeground;
+ }
+ }
+}
diff --git a/Clover/app/src/main/java/org/floens/chan/ChanApplication.java b/Clover/app/src/main/java/org/floens/chan/ChanApplication.java
index 2f137ced..4001cd19 100644
--- a/Clover/app/src/main/java/org/floens/chan/ChanApplication.java
+++ b/Clover/app/src/main/java/org/floens/chan/ChanApplication.java
@@ -17,207 +17,5 @@
*/
package org.floens.chan;
-import android.app.Application;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.StrictMode;
-import android.view.ViewConfiguration;
-
-import com.android.volley.RequestQueue;
-import com.android.volley.toolbox.ImageLoader;
-import com.android.volley.toolbox.Volley;
-import com.squareup.leakcanary.LeakCanary;
-import com.squareup.leakcanary.RefWatcher;
-
-import org.floens.chan.chan.ChanUrls;
-import org.floens.chan.core.manager.BoardManager;
-import org.floens.chan.core.reply.ReplyManager;
-import org.floens.chan.core.manager.WatchManager;
-import org.floens.chan.core.net.BitmapLruImageCache;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.database.DatabaseManager;
-import org.floens.chan.utils.AndroidUtils;
-import org.floens.chan.utils.FileCache;
-import org.floens.chan.utils.IconCache;
-import org.floens.chan.utils.Logger;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.util.Locale;
-
-import de.greenrobot.event.EventBus;
-
-public class ChanApplication extends Application {
- private static final String TAG = "ChanApplication";
-
- private static final long FILE_CACHE_DISK_SIZE = 50 * 1024 * 1024;
- private static final String FILE_CACHE_NAME = "filecache";
- private static final int VOLLEY_LRU_CACHE_SIZE = 8 * 1024 * 1024;
- private static final int VOLLEY_CACHE_SIZE = 10 * 1024 * 1024;
-
- public static Context con;
-
- private static ChanApplication instance;
- private static RequestQueue volleyRequestQueue;
- private static com.android.volley.toolbox.ImageLoader imageLoader;
- private static BoardManager boardManager;
- private static WatchManager watchManager;
- private static ReplyManager replyManager;
- private static DatabaseManager databaseManager;
- private static FileCache fileCache;
- private static RefWatcher refWatcher;
-
- private String userAgent;
- private int activityForegroundCounter = 0;
-
- public ChanApplication() {
- instance = this;
- con = this;
- }
-
- public static ChanApplication getInstance() {
- return instance;
- }
-
- public static RequestQueue getVolleyRequestQueue() {
- return volleyRequestQueue;
- }
-
- public static ImageLoader getVolleyImageLoader() {
- return imageLoader;
- }
-
- public static BoardManager getBoardManager() {
- return boardManager;
- }
-
- public static WatchManager getWatchManager() {
- return watchManager;
- }
-
- public static ReplyManager getReplyManager() {
- return replyManager;
- }
-
- public static DatabaseManager getDatabaseManager() {
- return databaseManager;
- }
-
- public static FileCache getFileCache() {
- return fileCache;
- }
-
- public static RefWatcher getRefWatcher() {
- return refWatcher;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
-
- // Force the overflow button to show, even on devices that have a
- // physical button.
- try {
- ViewConfiguration config = ViewConfiguration.get(this);
- Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
- if (menuKeyField != null) {
- menuKeyField.setAccessible(true);
- menuKeyField.setBoolean(config, false);
- }
- } catch (Exception e) {
- }
-
- if (ChanBuild.DEVELOPER_MODE) {
- refWatcher = LeakCanary.install(this);
- StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
- StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
- }
-
- AndroidUtils.init();
-
- ChanUrls.loadScheme(ChanSettings.getNetworkHttps());
-
- // User agent is /
- String version = "";
- try {
- version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
- version = version.toLowerCase(Locale.ENGLISH).replace(" ", "_");
- userAgent = getString(R.string.app_name) + "/" + version;
-
- IconCache.createIcons(this);
-
- cleanupOutdated();
-
- File cacheDir = getExternalCacheDir() != null ? getExternalCacheDir() : getCacheDir();
-
- replyManager = new ReplyManager(this);
-
- volleyRequestQueue = Volley.newRequestQueue(this, getUserAgent(), null, new File(cacheDir, Volley.DEFAULT_CACHE_DIR), VOLLEY_CACHE_SIZE);
- imageLoader = new ImageLoader(volleyRequestQueue, new BitmapLruImageCache(VOLLEY_LRU_CACHE_SIZE));
-
- fileCache = new FileCache(new File(cacheDir, FILE_CACHE_NAME), FILE_CACHE_DISK_SIZE, getUserAgent());
-
- databaseManager = new DatabaseManager(this);
- boardManager = new BoardManager();
- watchManager = new WatchManager(this);
- }
-
- public String getUserAgent() {
- return userAgent;
- }
-
- public void activityEnteredForeground() {
- boolean lastForeground = getApplicationInForeground();
-
- activityForegroundCounter++;
-
- if (getApplicationInForeground() != lastForeground) {
- EventBus.getDefault().post(new ForegroundChangedMessage(getApplicationInForeground()));
- }
- }
-
- public void activityEnteredBackground() {
- boolean lastForeground = getApplicationInForeground();
-
- activityForegroundCounter--;
- if (activityForegroundCounter < 0) {
- Logger.wtf(TAG, "activityForegroundCounter below 0");
- }
-
- if (getApplicationInForeground() != lastForeground) {
- EventBus.getDefault().post(new ForegroundChangedMessage(getApplicationInForeground()));
- }
- }
-
- public boolean getApplicationInForeground() {
- return activityForegroundCounter > 0;
- }
-
- private void cleanupOutdated() {
- File ionCacheFolder = new File(getCacheDir() + "/ion");
- if (ionCacheFolder.exists() && ionCacheFolder.isDirectory()) {
- Logger.i(TAG, "Clearing old ion folder");
- for (File file : ionCacheFolder.listFiles()) {
- if (!file.delete()) {
- Logger.i(TAG, "Could not delete old ion file " + file.getName());
- }
- }
- if (!ionCacheFolder.delete()) {
- Logger.i(TAG, "Could not delete old ion folder");
- } else {
- Logger.i(TAG, "Deleted old ion folder");
- }
- }
- }
-
- public static class ForegroundChangedMessage {
- public boolean inForeground;
-
- public ForegroundChangedMessage(boolean inForeground) {
- this.inForeground = inForeground;
- }
- }
+public class ChanApplication extends Chan {
}
diff --git a/Clover/app/src/main/java/org/floens/chan/chan/ImageSearch.java b/Clover/app/src/main/java/org/floens/chan/chan/ImageSearch.java
index 4c1df343..76029eb9 100644
--- a/Clover/app/src/main/java/org/floens/chan/chan/ImageSearch.java
+++ b/Clover/app/src/main/java/org/floens/chan/chan/ImageSearch.java
@@ -17,8 +17,6 @@
*/
package org.floens.chan.chan;
-import org.floens.chan.R;
-
import java.util.ArrayList;
import java.util.List;
@@ -34,7 +32,7 @@ public abstract class ImageSearch {
static {
engines.add(new ImageSearch() {
public int getId() {
- return R.id.action_0;
+ return 0;
}
public String getName() {
@@ -48,7 +46,7 @@ public abstract class ImageSearch {
engines.add(new ImageSearch() {
public int getId() {
- return R.id.action_1;
+ return 1;
}
public String getName() {
diff --git a/Clover/app/src/main/java/org/floens/chan/controller/ControllerLogic.java b/Clover/app/src/main/java/org/floens/chan/controller/ControllerLogic.java
index a1d37c8c..bc25f1ee 100644
--- a/Clover/app/src/main/java/org/floens/chan/controller/ControllerLogic.java
+++ b/Clover/app/src/main/java/org/floens/chan/controller/ControllerLogic.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.controller;
import android.view.ViewGroup;
diff --git a/Clover/app/src/main/java/org/floens/chan/controller/FadeInTransition.java b/Clover/app/src/main/java/org/floens/chan/controller/FadeInTransition.java
index 2475e711..ec3c3329 100644
--- a/Clover/app/src/main/java/org/floens/chan/controller/FadeInTransition.java
+++ b/Clover/app/src/main/java/org/floens/chan/controller/FadeInTransition.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.controller;
import android.animation.Animator;
diff --git a/Clover/app/src/main/java/org/floens/chan/controller/FadeOutTransition.java b/Clover/app/src/main/java/org/floens/chan/controller/FadeOutTransition.java
index c0ab0bed..30868e47 100644
--- a/Clover/app/src/main/java/org/floens/chan/controller/FadeOutTransition.java
+++ b/Clover/app/src/main/java/org/floens/chan/controller/FadeOutTransition.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.controller;
import android.animation.Animator;
diff --git a/Clover/app/src/main/java/org/floens/chan/utils/FileCache.java b/Clover/app/src/main/java/org/floens/chan/core/cache/FileCache.java
similarity index 98%
rename from Clover/app/src/main/java/org/floens/chan/utils/FileCache.java
rename to Clover/app/src/main/java/org/floens/chan/core/cache/FileCache.java
index 0fc17225..2b0af178 100644
--- a/Clover/app/src/main/java/org/floens/chan/utils/FileCache.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/cache/FileCache.java
@@ -15,10 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.floens.chan.utils;
-
-import android.os.Handler;
-import android.os.Looper;
+package org.floens.chan.core.cache;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.OkHttpClient;
@@ -28,6 +25,10 @@ import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;
import com.squareup.okhttp.internal.Util;
+import org.floens.chan.utils.AndroidUtils;
+import org.floens.chan.utils.Logger;
+import org.floens.chan.utils.Time;
+
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/loader/ChanLoader.java b/Clover/app/src/main/java/org/floens/chan/core/loader/ChanLoader.java
index 72f9d4af..8b8b0912 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/loader/ChanLoader.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/loader/ChanLoader.java
@@ -18,13 +18,11 @@
package org.floens.chan.core.loader;
import android.text.TextUtils;
-import android.util.SparseArray;
import com.android.volley.Response;
-import com.android.volley.ServerError;
import com.android.volley.VolleyError;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post;
@@ -48,7 +46,6 @@ public class ChanLoader {
private final List listeners = new ArrayList<>();
private final Loadable loadable;
- private final SparseArray postsById = new SparseArray<>();
private ChanThread thread;
private boolean destroyed = false;
@@ -62,6 +59,10 @@ public class ChanLoader {
public ChanLoader(Loadable loadable) {
this.loadable = loadable;
+
+ if (loadable.mode == Loadable.Mode.BOARD) {
+ loadable.mode = Loadable.Mode.CATALOG;
+ }
}
/**
@@ -129,7 +130,7 @@ public class ChanLoader {
request.cancel();
}
- if (loadable.isBoardMode() || loadable.isCatalogMode()) {
+ if (loadable.isCatalogMode()) {
loadable.no = 0;
loadable.listViewIndex = 0;
loadable.listViewTop = 0;
@@ -147,16 +148,7 @@ public class ChanLoader {
public void requestMoreData() {
clearTimer();
- if (loadable.isBoardMode()) {
- if (request != null) {
- // finish the last board load first
- return;
- }
-
- loadable.no++;
-
- request = getData();
- } else if (loadable.isThreadMode()) {
+ if (loadable.isThreadMode()) {
if (request != null) {
return;
}
@@ -180,18 +172,12 @@ public class ChanLoader {
return request != null;
}
- public Post findPostById(int id) {
- return postsById.get(id);
- }
-
public Loadable getLoadable() {
return loadable;
}
/**
* Get the time in milliseconds until another loadMore is recommended
- *
- * @return
*/
public long getTimeUntilLoadMore() {
if (request != null) {
@@ -272,7 +258,7 @@ public class ChanLoader {
}
);
- ChanApplication.getVolleyRequestQueue().add(request);
+ Chan.getVolleyRequestQueue().add(request);
return request;
}
@@ -285,31 +271,8 @@ public class ChanLoader {
thread = new ChanThread(loadable, new ArrayList());
}
- if (loadable.isThreadMode() || loadable.isCatalogMode()) {
- thread.posts.clear();
- thread.posts.addAll(result);
- postsById.clear();
- for (Post post : result) {
- postsById.append(post.no, post);
- }
- } else if (loadable.isBoardMode()) {
- // Only add new posts
- boolean flag;
- for (Post post : result) {
- flag = true;
- for (Post cached : thread.posts) {
- if (post.no == cached.no) {
- flag = false;
- break;
- }
- }
-
- if (flag) {
- thread.posts.add(post);
- postsById.append(post.no, post);
- }
- }
- }
+ thread.posts.clear();
+ thread.posts.addAll(result);
if (loadable.isThreadMode() && thread.posts.size() > 0) {
thread.op = thread.posts.get(0);
@@ -346,11 +309,6 @@ public class ChanLoader {
Logger.e(TAG, "Loading error");
- // 404 with more pages already loaded means endofline
- if ((error instanceof ServerError) && loadable.isBoardMode() && loadable.no > 0) {
- error = new EndOfLineException();
- }
-
clearTimer();
for (ChanLoaderCallback l : listeners) {
diff --git a/Clover/app/src/main/java/org/floens/chan/core/loader/ChanParser.java b/Clover/app/src/main/java/org/floens/chan/core/loader/ChanParser.java
index 27892616..d62627d0 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/loader/ChanParser.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/loader/ChanParser.java
@@ -30,11 +30,11 @@ import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
-import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.core.model.Post;
import org.floens.chan.core.model.PostLinkable;
+import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.utils.AndroidUtils;
import org.floens.chan.utils.ThemeHelper;
import org.jsoup.Jsoup;
@@ -90,11 +90,11 @@ public class ChanParser {
}
private void parseSpans(Post post) {
- boolean anonymize = ChanSettings.getAnonymize();
- boolean anonymizeIds = ChanSettings.getAnonymizeIds();
+ boolean anonymize = ChanSettings.anonymize.get();
+ boolean anonymizeIds = ChanSettings.anonymizeIds.get();
if (anonymize) {
- post.name = ChanApplication.getInstance().getString(R.string.default_name);
+ post.name = "Anonymous";
post.tripcode = "";
}
@@ -376,7 +376,7 @@ public class ChanParser {
// Append You when it's a reply to an saved reply
// todo synchronized
- if (ChanApplication.getDatabaseManager().isSavedReply(post.board, id)) {
+ if (Chan.getDatabaseManager().isSavedReply(post.board, id)) {
key += " (You)";
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/loader/EndOfLineException.java b/Clover/app/src/main/java/org/floens/chan/core/loader/EndOfLineException.java
deleted file mode 100644
index ae98a8be..00000000
--- a/Clover/app/src/main/java/org/floens/chan/core/loader/EndOfLineException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.core.loader;
-
-import com.android.volley.NetworkResponse;
-import com.android.volley.VolleyError;
-
-@SuppressWarnings("serial")
-public class EndOfLineException extends VolleyError {
- public EndOfLineException(NetworkResponse networkResponse) {
- super(networkResponse);
- }
-
- public EndOfLineException() {
- super();
- }
-
- @Override
- public String getMessage() {
- return "End of the line";
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java
index d2bf5c6f..bcd36854 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java
@@ -20,7 +20,7 @@ package org.floens.chan.core.manager;
import com.android.volley.Response;
import com.android.volley.VolleyError;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.model.Board;
import org.floens.chan.core.net.BoardsRequest;
@@ -84,7 +84,7 @@ public class BoardManager {
}
public void updateSavedBoards() {
- ChanApplication.getDatabaseManager().updateBoards(allBoards);
+ Chan.getDatabaseManager().updateBoards(allBoards);
notifyChanged();
}
@@ -103,12 +103,12 @@ public class BoardManager {
private void storeBoards() {
updateByValueMap();
- ChanApplication.getDatabaseManager().setBoards(allBoards);
+ Chan.getDatabaseManager().setBoards(allBoards);
notifyChanged();
}
private void loadBoards() {
- allBoards = ChanApplication.getDatabaseManager().getBoards();
+ allBoards = Chan.getDatabaseManager().getBoards();
if (allBoards.size() == 0) {
Logger.d(TAG, "Loading default boards");
allBoards = getDefaultBoards();
@@ -149,7 +149,7 @@ public class BoardManager {
}
private void loadFromServer() {
- ChanApplication.getVolleyRequestQueue().add(
+ Chan.getVolleyRequestQueue().add(
new BoardsRequest(ChanUrls.getBoardsUrl(), new Response.Listener>() {
@Override
public void onResponse(List data) {
diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java
deleted file mode 100644
index 5de96cfc..00000000
--- a/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.core.manager;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.FragmentTransaction;
-import android.app.ProgressDialog;
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.text.TextUtils;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.CheckBox;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-import android.widget.Toast;
-
-import com.android.volley.VolleyError;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.chan.ChanUrls;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.core.loader.ChanLoader;
-import org.floens.chan.core.loader.LoaderPool;
-import org.floens.chan.core.reply.ReplyManager.DeleteListener;
-import org.floens.chan.core.reply.ReplyManager.DeleteResponse;
-import org.floens.chan.core.model.ChanThread;
-import org.floens.chan.core.model.Loadable;
-import org.floens.chan.core.model.Pin;
-import org.floens.chan.core.model.Post;
-import org.floens.chan.core.model.PostLinkable;
-import org.floens.chan.core.model.SavedReply;
-import org.floens.chan.ui.activity.ReplyActivity;
-import org.floens.chan.ui.fragment.PostRepliesFragment;
-import org.floens.chan.ui.fragment.ReplyFragment;
-import org.floens.chan.utils.AndroidUtils;
-import org.floens.chan.utils.Logger;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.floens.chan.utils.AndroidUtils.dp;
-
-/**
- * All PostView's need to have this referenced. This manages some things like
- * pages, starting and stopping of loading, handling linkables, replies popups
- * etc. onDestroy, onStart and onStop must be called from the activity/fragment
- */
-public class ThreadManager implements ChanLoader.ChanLoaderCallback {
- public static enum ViewMode {
- LIST, GRID
- }
-
- private static final String TAG = "ThreadManager";
-
- private final Activity activity;
- private final ThreadManagerListener threadManagerListener;
- private final List popupQueue = new ArrayList<>();
- private PostRepliesFragment currentPopupFragment;
- private int highlightedPost = -1;
- private int lastPost = -1;
- private String highlightedId = null;
-
- private ChanLoader chanLoader;
-
- public ThreadManager(Activity activity, final ThreadManagerListener listener) {
- this.activity = activity;
- threadManagerListener = listener;
- }
-
- public void onDestroy() {
- unbindLoader();
- }
-
- public void onStart() {
- if (chanLoader != null) {
- if (isWatching()) {
- chanLoader.setAutoLoadMore(true);
- chanLoader.requestMoreDataAndResetTimer();
- }
- }
- }
-
- public void onStop() {
- if (chanLoader != null) {
- chanLoader.setAutoLoadMore(false);
- }
- }
-
- public void bindLoader(Loadable loadable) {
- if (chanLoader != null) {
- unbindLoader();
- }
-
- chanLoader = LoaderPool.getInstance().obtain(loadable, this);
- if (isWatching()) {
- chanLoader.setAutoLoadMore(true);
- }
- }
-
- public void unbindLoader() {
- if (chanLoader != null) {
- chanLoader.setAutoLoadMore(false);
- LoaderPool.getInstance().release(chanLoader, this);
- chanLoader = null;
- } else {
- Logger.e(TAG, "Loader already unbinded");
- }
-
- highlightedPost = -1;
- lastPost = -1;
- highlightedId = null;
- }
-
- public void bottomPostViewed() {
- if (chanLoader.getLoadable().isThreadMode() && chanLoader.getThread() != null && chanLoader.getThread().posts.size() > 0) {
- chanLoader.getLoadable().lastViewed = chanLoader.getThread().posts.get(chanLoader.getThread().posts.size() - 1).no;
- }
-
- Pin pin = ChanApplication.getWatchManager().findPinByLoadable(chanLoader.getLoadable());
- if (pin != null) {
- pin.onBottomPostViewed();
- ChanApplication.getWatchManager().onPinsChanged();
- }
- }
-
- public boolean isWatching() {
- if (!chanLoader.getLoadable().isThreadMode()) {
- return false;
- } else if (!ChanSettings.getThreadAutoRefresh()) {
- return false;
- } else if (chanLoader.getThread() != null && chanLoader.getThread().closed) {
- return false;
- } else {
- return true;
- }
- }
-
- public void requestData() {
- if (chanLoader != null) {
- chanLoader.requestData();
- } else {
- Logger.e(TAG, "Loader null in requestData");
- }
- }
-
- /**
- * Called by postadapter and threadwatchcounterview.onclick
- */
- public void requestNextData() {
- if (chanLoader != null) {
- chanLoader.requestMoreData();
- } else {
- Logger.e(TAG, "Loader null in requestData");
- }
- }
-
- @Override
- public void onChanLoaderError(VolleyError error) {
- threadManagerListener.onThreadLoadError(error);
- }
-
- @Override
- public void onChanLoaderData(ChanThread thread) {
- if (!isWatching()) {
- chanLoader.setAutoLoadMore(false);
- }
-
- if (thread.posts.size() > 0) {
- lastPost = thread.posts.get(thread.posts.size() - 1).no;
- }
-
- threadManagerListener.onThreadLoaded(thread);
- }
-
- public boolean hasLoader() {
- return chanLoader != null;
- }
-
- public Post findPostById(int id) {
- if (chanLoader == null)
- return null;
- return chanLoader.findPostById(id);
- }
-
- public Loadable getLoadable() {
- if (chanLoader == null)
- return null;
- return chanLoader.getLoadable();
- }
-
- public ChanLoader getChanLoader() {
- return chanLoader;
- }
-
- public void onThumbnailClicked(Post post) {
- threadManagerListener.onThumbnailClicked(post);
- }
-
- public void onPostClicked(Post post) {
- if (chanLoader != null) {
- threadManagerListener.onPostClicked(post);
- }
- }
-
- public void showPostOptions(final Post post, PopupMenu popupMenu) {
- Menu menu = popupMenu.getMenu();
-
- if (chanLoader.getLoadable().isBoardMode() || chanLoader.getLoadable().isCatalogMode()) {
- menu.add(Menu.NONE, 9, Menu.NONE, activity.getString(R.string.action_pin));
- }
-
-// if (chanLoader.getLoadable().isThreadMode()) {
-// menu.add(Menu.NONE, 10, Menu.NONE, activity.getString(R.string.post_quick_reply));
-// }
-
- String[] baseOptions = activity.getResources().getStringArray(R.array.post_options);
- for (int i = 0; i < baseOptions.length; i++) {
- menu.add(Menu.NONE, i, Menu.NONE, baseOptions[i]);
- }
-
- if (!TextUtils.isEmpty(post.id)) {
- menu.add(Menu.NONE, 6, Menu.NONE, activity.getString(R.string.post_highlight_id));
- }
-
- // Only add the delete option when the post is a saved reply
- if (ChanApplication.getDatabaseManager().isSavedReply(post.board, post.no)) {
- menu.add(Menu.NONE, 7, Menu.NONE, activity.getString(R.string.delete));
- }
-
- if (ChanSettings.getDeveloper()) {
- menu.add(Menu.NONE, 8, Menu.NONE, "Make this a saved reply");
- }
-
- popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(final MenuItem item) {
- switch (item.getItemId()) {
- case 10: // Quick reply
- openReply(false);
- // Pass through
- case 0: // Quote
-// ChanApplication.getReplyManager().quote(post.no);
- break;
- case 1: // Quote inline
-// ChanApplication.getReplyManager().quoteInline(post.no, post.comment.toString());
- break;
- case 2: // Info
- showPostInfo(post);
- break;
- case 3: // Show clickables
- showPostLinkables(post);
- break;
- case 4: // Copy text
- copyToClipboard(post.comment.toString());
- break;
- case 5: // Report
- AndroidUtils.openWebView(activity, "Report /" + post.board + "/" + post.no, ChanUrls.getReportUrl(post.board, post.no));
- break;
- case 6: // Id
- highlightedId = post.id;
- threadManagerListener.onRefreshView();
- break;
- case 7: // Delete
- deletePost(post);
- break;
- case 8: // Save reply
- ChanApplication.getDatabaseManager().saveReply(new SavedReply(post.board, post.no, "foo"));
- break;
- case 9: // Pin
- ChanApplication.getWatchManager().addPin(post);
- break;
- }
- return false;
- }
- });
- }
-
- public void openReply(boolean startInActivity) {
- if (chanLoader == null)
- return;
-
- if (startInActivity) {
- ReplyActivity.setLoadable(chanLoader.getLoadable());
- Intent i = new Intent(activity, ReplyActivity.class);
- activity.startActivity(i);
- } else {
- ReplyFragment reply = ReplyFragment.newInstance(chanLoader.getLoadable(), true);
- reply.show(activity.getFragmentManager(), "replyDialog");
- }
- }
-
- public void onPostLinkableClicked(PostLinkable linkable) {
- handleLinkableSelected(linkable);
- }
-
- public void scrollToPost(int post) {
- threadManagerListener.onScrollTo(post);
- }
-
- public void highlightPost(int post) {
- highlightedPost = post;
- }
-
- public boolean isPostHightlighted(Post post) {
- return (highlightedPost >= 0 && post.no == highlightedPost) || (highlightedId != null && post.id.equals(highlightedId));
- }
-
- public boolean isPostLastSeen(Post post) {
- return post.no == chanLoader.getLoadable().lastViewed && post.no != lastPost;
- }
-
- private void copyToClipboard(String comment) {
- ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
- ClipData clip = ClipData.newPlainText("Post text", comment);
- clipboard.setPrimaryClip(clip);
- Toast.makeText(activity, R.string.post_text_copied_to_clipboard, Toast.LENGTH_SHORT).show();
- }
-
- private void showPostInfo(Post post) {
- String text = "";
-
- if (post.hasImage) {
- text += "File: " + post.filename + "." + post.ext + " \nDimensions: " + post.imageWidth + "x"
- + post.imageHeight + "\nSize: " + AndroidUtils.getReadableFileSize(post.fileSize, false) + "\n\n";
- }
-
- text += "Time: " + post.date;
-
- if (!TextUtils.isEmpty(post.id)) {
- text += "\nId: " + post.id;
- }
-
- if (!TextUtils.isEmpty(post.tripcode)) {
- text += "\nTripcode: " + post.tripcode;
- }
-
- if (!TextUtils.isEmpty(post.countryName)) {
- text += "\nCountry: " + post.countryName;
- }
-
- if (!TextUtils.isEmpty(post.capcode)) {
- text += "\nCapcode: " + post.capcode;
- }
-
- AlertDialog dialog = new AlertDialog.Builder(activity).setTitle(R.string.post_info).setMessage(text)
- .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- }
- }).create();
-
- dialog.show();
- }
-
- /**
- * Show a list of things that can be clicked in a list to the user.
- *
- * @param post The post that was clicked.
- */
- public void showPostLinkables(Post post) {
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- final ArrayList linkables = post.linkables;
-
- if (linkables.size() > 0) {
- String[] keys = new String[linkables.size()];
- for (int i = 0; i < linkables.size(); i++) {
- keys[i] = linkables.get(i).key;
- }
-
- builder.setItems(keys, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- handleLinkableSelected(linkables.get(which));
- }
- });
-
- AlertDialog dialog = builder.create();
- dialog.show();
- }
- }
-
- public void showPostReplies(Post post) {
- RepliesPopup l = new RepliesPopup();
- List p = new ArrayList<>();
- for (int no : post.repliesFrom) {
- Post r = findPostById(no);
- if (r != null) {
- p.add(r);
- }
- }
- l.posts = p;
- l.forNo = post.no;
- if (p.size() > 0) {
- showPostsRepliesFragment(l);
- }
- }
-
- public ThreadManager.ViewMode getViewMode() {
- return threadManagerListener.getViewMode();
- }
-
- /**
- * Handle when a linkable has been clicked.
- *
- * @param linkable the selected linkable.
- */
- private void handleLinkableSelected(final PostLinkable linkable) {
- if (linkable.type == PostLinkable.Type.QUOTE) {
- Post post = findPostById((Integer) linkable.value);
- if (post != null) {
- RepliesPopup l = new RepliesPopup();
- l.forNo = (Integer) linkable.value;
- l.posts.add(post);
- showPostsRepliesFragment(l);
- }
- } else if (linkable.type == PostLinkable.Type.LINK) {
- if (ChanSettings.getOpenLinkConfirmation()) {
- new AlertDialog.Builder(activity)
- .setNegativeButton(R.string.cancel, null)
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- AndroidUtils.openLink((String) linkable.value);
- }
- })
- .setTitle(R.string.open_link_confirmation)
- .setMessage((String) linkable.value)
- .show();
- } else {
- AndroidUtils.openLink((String) linkable.value);
- }
- } else if (linkable.type == PostLinkable.Type.THREAD) {
- final PostLinkable.ThreadLink link = (PostLinkable.ThreadLink) linkable.value;
- final Loadable thread = new Loadable(link.board, link.threadId);
-
- new AlertDialog.Builder(activity)
- .setNegativeButton(R.string.cancel, null)
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- threadManagerListener.onOpenThread(thread, link.postId);
- }
- })
- .setTitle(R.string.open_thread_confirmation)
- .setMessage("/" + thread.board + "/" + thread.no)
- .show();
- }
- }
-
- private void showPostsRepliesFragment(RepliesPopup repliesPopup) {
- // Post popups are now queued up, more than 32 popups on top of each
- // other makes the system crash!
- popupQueue.add(repliesPopup);
-
- if (currentPopupFragment != null) {
- currentPopupFragment.dismissNoCallback();
- }
-
-// PostRepliesFragment popup = PostRepliesFragment.newInstance(repliesPopup, this);
- PostRepliesFragment popup = null;
- FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
- ft.add(popup, "postPopup");
- ft.commitAllowingStateLoss();
-
- currentPopupFragment = popup;
- }
-
- public void onPostRepliesPop() {
- if (popupQueue.size() == 0)
- return;
-
- popupQueue.remove(popupQueue.size() - 1);
-
- if (popupQueue.size() > 0) {
-// PostRepliesFragment popup = PostRepliesFragment.newInstance(popupQueue.get(popupQueue.size() - 1), this);
- PostRepliesFragment popup = null;
- FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
- ft.add(popup, "postPopup");
- ft.commit();
-
- currentPopupFragment = popup;
- } else {
- currentPopupFragment = null;
- }
- }
-
- public void closeAllPostFragments() {
- popupQueue.clear();
- currentPopupFragment = null;
- }
-
- public boolean arePostRepliesOpen() {
- return popupQueue.size() > 0;
- }
-
- private void deletePost(final Post post) {
- final CheckBox checkBox = new CheckBox(activity);
- checkBox.setText(R.string.delete_image_only);
-
- LinearLayout wrapper = new LinearLayout(activity);
- wrapper.addView(checkBox);
- int padding = dp(8f);
- wrapper.setPadding(padding, padding, padding, padding);
-
- new AlertDialog.Builder(activity).setTitle(R.string.delete_confirm).setView(wrapper)
- .setPositiveButton(R.string.delete, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- doDeletePost(post, checkBox.isChecked());
- }
- }).setNegativeButton(R.string.cancel, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- }
- }).show();
- }
-
- private void doDeletePost(Post post, boolean onlyImageDelete) {
- SavedReply reply = ChanApplication.getDatabaseManager().getSavedReply(post.board, post.no);
- if (reply == null) {
- /*
- * reply = new SavedReply(); reply.board = "g"; reply.no = 1234;
- * reply.password = "boom";
- */
- return;
- }
-
- final ProgressDialog dialog = ProgressDialog.show(activity, null, activity.getString(R.string.delete_wait));
-
- ChanApplication.getReplyManager().postDelete(reply, onlyImageDelete, new DeleteListener() {
- @Override
- public void onResponse(DeleteResponse response) {
- dialog.dismiss();
-
- if (response.isNetworkError || response.isUserError) {
- int resId;
-
- if (response.isTooSoonError) {
- resId = R.string.delete_too_soon;
- } else if (response.isInvalidPassword) {
- resId = R.string.delete_password_incorrect;
- } else if (response.isTooOldError) {
- resId = R.string.delete_too_old;
- } else {
- resId = R.string.delete_fail;
- }
-
- Toast.makeText(activity, resId, Toast.LENGTH_LONG).show();
- } else if (response.isSuccessful) {
- Toast.makeText(activity, R.string.delete_success, Toast.LENGTH_SHORT).show();
- } else {
- Toast.makeText(activity, R.string.delete_fail, Toast.LENGTH_LONG).show();
- }
- }
- });
- }
-
- public interface ThreadManagerListener {
- void onThreadLoaded(ChanThread thread);
-
- void onThreadLoadError(VolleyError error);
-
- void onPostClicked(Post post);
-
- void onThumbnailClicked(Post post);
-
- void onScrollTo(int post);
-
- void onRefreshView();
-
- void onOpenThread(Loadable thread, int highlightedPost);
-
- ThreadManager.ViewMode getViewMode();
- }
-
- public static class RepliesPopup {
- public List posts = new ArrayList<>();
- public int listViewIndex;
- public int listViewTop;
- public int forNo = -1;
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java
index ff2ba790..f019ed6d 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java
@@ -20,7 +20,7 @@ package org.floens.chan.core.manager;
import android.content.Context;
import android.content.Intent;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Pin;
import org.floens.chan.core.model.Post;
@@ -51,7 +51,7 @@ public class WatchManager {
public WatchManager(Context context) {
this.context = context;
- pins = ChanApplication.getDatabaseManager().getPinned();
+ pins = Chan.getDatabaseManager().getPinned();
EventBus.getDefault().register(this);
@@ -122,7 +122,7 @@ public class WatchManager {
}
pins.add(pin);
- ChanApplication.getDatabaseManager().addPin(pin);
+ Chan.getDatabaseManager().addPin(pin);
onPinsChanged();
@@ -161,7 +161,7 @@ public class WatchManager {
public void removePin(Pin pin) {
pins.remove(pin);
pin.destroyWatcher();
- ChanApplication.getDatabaseManager().removePin(pin);
+ Chan.getDatabaseManager().removePin(pin);
onPinsChanged();
@@ -174,7 +174,7 @@ public class WatchManager {
* @param pin
*/
public void updatePin(Pin pin) {
- ChanApplication.getDatabaseManager().updatePin(pin);
+ Chan.getDatabaseManager().updatePin(pin);
onPinsChanged();
@@ -185,15 +185,15 @@ public class WatchManager {
* Updates all the pins to the database.
*/
public void updateDatabase() {
- ChanApplication.getDatabaseManager().updatePins(pins);
+ Chan.getDatabaseManager().updatePins(pins);
}
public void toggleWatch(Pin pin) {
pin.watching = !pin.watching;
EventBus.getDefault().post(new PinChangedMessage(pin));
- ChanApplication.getWatchManager().onPinsChanged();
- ChanApplication.getWatchManager().invokeLoadNow();
+ Chan.getWatchManager().onPinsChanged();
+ Chan.getWatchManager().invokeLoadNow();
}
public void pinWatcherUpdated(Pin pin) {
@@ -231,7 +231,7 @@ public class WatchManager {
}
}
- public void onEvent(ChanApplication.ForegroundChangedMessage message) {
+ public void onEvent(Chan.ForegroundChangedMessage message) {
updateNotificationServiceState();
updateTimerState(true);
}
@@ -259,11 +259,11 @@ public class WatchManager {
}
public boolean getWatchBackgroundEnabled() {
- return ChanSettings.getWatchBackgroundEnabled();
+ return ChanSettings.watchBackground.get();
}
private void updatePinWatchers() {
- updatePinWatchers(ChanSettings.getWatchEnabled());
+ updatePinWatchers(ChanSettings.watchEnabled.get());
}
private void updatePinWatchers(boolean watchEnabled) {
@@ -294,9 +294,9 @@ public class WatchManager {
}
private void updateTimerState(boolean watchEnabled, boolean backgroundEnabled, boolean invokeLoadNow) {
- Logger.d(TAG, "updateTimerState watchEnabled=" + watchEnabled + " backgroundEnabled=" + backgroundEnabled + " invokeLoadNow=" + invokeLoadNow + " foreground=" + ChanApplication.getInstance().getApplicationInForeground());
+ Logger.d(TAG, "updateTimerState watchEnabled=" + watchEnabled + " backgroundEnabled=" + backgroundEnabled + " invokeLoadNow=" + invokeLoadNow + " foreground=" + Chan.getInstance().getApplicationInForeground());
if (watchEnabled) {
- if (ChanApplication.getInstance().getApplicationInForeground()) {
+ if (Chan.getInstance().getApplicationInForeground()) {
setTimer(invokeLoadNow ? 1 : FOREGROUND_TIME);
} else {
if (backgroundEnabled) {
diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/Loadable.java b/Clover/app/src/main/java/org/floens/chan/core/model/Loadable.java
index a20b8c23..95e44fd1 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/model/Loadable.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/model/Loadable.java
@@ -57,22 +57,14 @@ public class Loadable {
public Loadable() {
}
- /**
- * Quick constructor for a board loadable.
- *
- * @param board
- */
public Loadable(String board) {
- mode = Mode.BOARD;
+ mode = Mode.CATALOG;
this.board = board;
- no = 0;
+ this.no = 0;
}
/**
* Quick constructor for a thread loadable.
- *
- * @param board
- * @param no
*/
public Loadable(String board, int no) {
mode = Mode.THREAD;
@@ -82,10 +74,6 @@ public class Loadable {
/**
* Quick constructor for a thread loadable with an title.
- *
- * @param board
- * @param no
- * @param title
*/
public Loadable(String board, int no, String title) {
mode = Mode.THREAD;
@@ -115,10 +103,6 @@ public class Loadable {
return result;
}
- public boolean isBoardMode() {
- return mode == Mode.BOARD;
- }
-
public boolean isThreadMode() {
return mode == Mode.THREAD;
}
@@ -127,26 +111,6 @@ public class Loadable {
return mode == Mode.CATALOG;
}
- public void readFromBundle(Context context, Bundle bundle) {
- String p = context.getPackageName();
- mode = bundle.getInt(p + ".mode", Mode.INVALID);
- board = bundle.getString(p + ".board", "");
- no = bundle.getInt(p + ".no", -1);
- title = bundle.getString(p + ".subject", "");
- listViewIndex = bundle.getInt(p + ".listViewIndex");
- listViewTop = bundle.getInt(p + ".listViewTop");
- }
-
- public void writeToBundle(Context context, Bundle bundle) {
- String p = context.getPackageName();
- bundle.putInt(p + ".mode", mode);
- bundle.putString(p + ".board", board);
- bundle.putInt(p + ".no", no);
- bundle.putString(p + ".subject", title);
- bundle.putInt(p + ".listViewIndex", listViewIndex);
- bundle.putInt(p + ".listViewTop", listViewTop);
- }
-
public void readFromBundle(Context context, String tag, Bundle bundle) {
String p = context.getPackageName();
mode = bundle.getInt(p + "." + tag + ".mode", Mode.INVALID);
diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/Post.java b/Clover/app/src/main/java/org/floens/chan/core/model/Post.java
index fb355c02..65e31e93 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/model/Post.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/model/Post.java
@@ -20,7 +20,7 @@ package org.floens.chan.core.model;
import android.text.SpannableString;
import android.text.TextUtils;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.loader.ChanParser;
import org.jsoup.parser.Parser;
@@ -131,7 +131,7 @@ public class Post {
filename = Parser.unescapeEntities(filename, false);
if (spoiler) {
- Board b = ChanApplication.getBoardManager().getBoardByValue(board);
+ Board b = Chan.getBoardManager().getBoardByValue(board);
if (b != null && b.customSpoilers >= 0) {
thumbnailUrl = ChanUrls.getCustomSpoilerUrl(board, random.nextInt(b.customSpoilers) + 1);
} else {
@@ -143,7 +143,7 @@ public class Post {
}
if (!TextUtils.isEmpty(country)) {
- Board b = ChanApplication.getBoardManager().getBoardByValue(board);
+ Board b = Chan.getBoardManager().getBoardByValue(board);
countryUrl = b.trollFlags ? ChanUrls.getTrollCountryFlagUrl(country) : ChanUrls.getCountryFlagUrl(country);
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java b/Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java
index 9bb03b4b..2de647b1 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.core.model;
public class PostImage {
diff --git a/Clover/app/src/main/java/org/floens/chan/core/net/ByteArrayRequest.java b/Clover/app/src/main/java/org/floens/chan/core/net/ByteArrayRequest.java
deleted file mode 100644
index 15fffacd..00000000
--- a/Clover/app/src/main/java/org/floens/chan/core/net/ByteArrayRequest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.core.net;
-
-import com.android.volley.NetworkResponse;
-import com.android.volley.Request;
-import com.android.volley.Response;
-import com.android.volley.Response.ErrorListener;
-import com.android.volley.Response.Listener;
-
-/**
- * Request a plain byte[] Warning: no caching!
- */
-public class ByteArrayRequest extends Request {
- protected final Listener listener;
-
- public ByteArrayRequest(String url, Listener listener, ErrorListener errorListener) {
- super(Method.GET, url, errorListener);
-
- this.listener = listener;
- }
-
- @Override
- protected void deliverResponse(byte[] response) {
- listener.onResponse(response);
- }
-
- @Override
- protected Response parseNetworkResponse(NetworkResponse response) {
- return Response.success(response.data, null);
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/net/ChanReaderRequest.java b/Clover/app/src/main/java/org/floens/chan/core/net/ChanReaderRequest.java
index e8e4e27a..6ca1f964 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/net/ChanReaderRequest.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/net/ChanReaderRequest.java
@@ -22,7 +22,7 @@ import android.util.JsonReader;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post;
@@ -44,9 +44,7 @@ public class ChanReaderRequest extends JsonReaderRequest> {
public static ChanReaderRequest newInstance(Loadable loadable, List cached, Listener> listener, ErrorListener errorListener) {
String url;
- if (loadable.isBoardMode()) {
- url = ChanUrls.getPageUrl(loadable.board, loadable.no);
- } else if (loadable.isThreadMode()) {
+ if (loadable.isThreadMode()) {
url = ChanUrls.getThreadUrl(loadable.board, loadable.no);
} else if (loadable.isCatalogMode()) {
url = ChanUrls.getCatalogUrl(loadable.board);
@@ -72,9 +70,7 @@ public class ChanReaderRequest extends JsonReaderRequest> {
public List readJson(JsonReader reader) throws Exception {
List list;
- if (loadable.isBoardMode()) {
- list = loadBoard(reader);
- } else if (loadable.isThreadMode()) {
+ if (loadable.isThreadMode()) {
list = loadThread(reader);
} else if (loadable.isCatalogMode()) {
list = loadCatalog(reader);
@@ -177,7 +173,7 @@ public class ChanReaderRequest extends JsonReaderRequest> {
}
for (Post post : totalList) {
- post.isSavedReply = ChanApplication.getDatabaseManager().isSavedReply(post.board, post.no);
+ post.isSavedReply = Chan.getDatabaseManager().isSavedReply(post.board, post.no);
}
return totalList;
@@ -207,44 +203,6 @@ public class ChanReaderRequest extends JsonReaderRequest> {
return list;
}
- private List loadBoard(JsonReader reader) throws Exception {
- ArrayList list = new ArrayList<>();
-
- reader.beginObject(); // Threads array
-
- if (reader.nextName().equals("threads")) {
- reader.beginArray();
-
- while (reader.hasNext()) {
- reader.beginObject(); // Thread object
-
- if (reader.nextName().equals("posts")) {
- reader.beginArray();
-
- list.add(readPostObject(reader));
-
- // Only consume one post
- while (reader.hasNext())
- reader.skipValue();
-
- reader.endArray();
- } else {
- reader.skipValue();
- }
-
- reader.endObject();
- }
-
- reader.endArray();
- } else {
- reader.skipValue();
- }
-
- reader.endObject();
-
- return list;
- }
-
private List loadCatalog(JsonReader reader) throws Exception {
ArrayList list = new ArrayList<>();
diff --git a/Clover/app/src/main/java/org/floens/chan/core/net/FileRequest.java b/Clover/app/src/main/java/org/floens/chan/core/net/FileRequest.java
deleted file mode 100644
index b3421aa7..00000000
--- a/Clover/app/src/main/java/org/floens/chan/core/net/FileRequest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.core.net;
-
-import com.android.volley.NetworkResponse;
-import com.android.volley.Request;
-import com.android.volley.Response;
-import com.android.volley.Response.ErrorListener;
-import com.android.volley.Response.Listener;
-import com.android.volley.toolbox.DiskBasedCache;
-import com.android.volley.toolbox.HttpHeaderParser;
-
-import org.floens.chan.ChanApplication;
-
-import java.io.File;
-
-public class FileRequest extends Request {
- protected final Listener listener;
-
- public FileRequest(String url, Listener listener, ErrorListener errorListener) {
- super(Method.GET, url, errorListener);
- this.listener = listener;
-
- setShouldCache(true);
- }
-
- @Override
- protected Response parseNetworkResponse(NetworkResponse response) {
- return Response.success(null, HttpHeaderParser.parseCacheHeaders(response));
- }
-
- @Override
- protected void deliverResponse(Void response) {
- DiskBasedCache cache = (DiskBasedCache) ChanApplication.getVolleyRequestQueue().getCache();
- File file = cache.getFileForKey(getCacheKey());
-
- if (file.exists()) {
- listener.onResponse(file);
- } else {
- listener.onResponse(null);
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/net/JsonReaderRequest.java b/Clover/app/src/main/java/org/floens/chan/core/net/JsonReaderRequest.java
index 095e7636..f32e1032 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/net/JsonReaderRequest.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/net/JsonReaderRequest.java
@@ -27,8 +27,9 @@ import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
+import org.floens.chan.utils.IOUtils;
+
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
@@ -65,13 +66,7 @@ public abstract class JsonReaderRequest extends Request {
exception = e;
}
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
+ IOUtils.closeQuietly(reader);
if (read == null) {
if (exception != null) {
diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java
index 7b7c8803..b8237af0 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.core.presenter;
import android.support.v4.view.ViewPager;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
index 03abce65..9756ebb6 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
@@ -1,8 +1,25 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.core.presenter;
import android.text.TextUtils;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.manager.BoardManager;
@@ -55,10 +72,10 @@ public class ReplyPresenter implements ReplyManager.FileListener, ReplyManager.H
public ReplyPresenter(ReplyPresenterCallback callback) {
this.callback = callback;
- replyManager = ChanApplication.getReplyManager();
- boardManager = ChanApplication.getBoardManager();
- watchManager = ChanApplication.getWatchManager();
- databaseManager = ChanApplication.getDatabaseManager();
+ replyManager = Chan.getReplyManager();
+ boardManager = Chan.getBoardManager();
+ watchManager = Chan.getWatchManager();
+ databaseManager = Chan.getDatabaseManager();
}
public void bindLoadable(Loadable loadable) {
@@ -144,7 +161,7 @@ public class ReplyPresenter implements ReplyManager.FileListener, ReplyManager.H
}
previewOpen = false;
} else {
- ChanApplication.getReplyManager().pickFile(this);
+ Chan.getReplyManager().pickFile(this);
pickingFile = true;
}
}
@@ -313,7 +330,7 @@ public class ReplyPresenter implements ReplyManager.FileListener, ReplyManager.H
String baseUrl = loadable.isThreadMode() ?
ChanUrls.getThreadUrlDesktop(loadable.board, loadable.no) :
ChanUrls.getBoardUrlDesktop(loadable.board);
- callback.initCaptcha(baseUrl, ChanUrls.getCaptchaSiteKey(), ChanApplication.getInstance().getUserAgent(), this);
+ callback.initCaptcha(baseUrl, ChanUrls.getCaptchaSiteKey(), Chan.getInstance().getUserAgent(), this);
}
break;
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
index 54e6b206..f0e65ee5 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
@@ -21,7 +21,7 @@ import android.text.TextUtils;
import com.android.volley.VolleyError;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.loader.ChanLoader;
@@ -72,8 +72,8 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
public ThreadPresenter(ThreadPresenterCallback threadPresenterCallback) {
this.threadPresenterCallback = threadPresenterCallback;
- watchManager = ChanApplication.getWatchManager();
- databaseManager = ChanApplication.getDatabaseManager();
+ watchManager = Chan.getWatchManager();
+ databaseManager = Chan.getDatabaseManager();
}
public void bindLoadable(Loadable loadable) {
@@ -287,7 +287,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
menu.add(new FloatingMenuItem(POST_OPTION_DELETE, R.string.delete));
}
- if (ChanSettings.getDeveloper()) {
+ if (ChanSettings.developer.get()) {
menu.add(new FloatingMenuItem(POST_OPTION_SAVE, "Save"));
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/reply/HttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/reply/HttpCall.java
index fb359b57..c3d67922 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/reply/HttpCall.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/reply/HttpCall.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.core.reply;
import com.squareup.okhttp.Callback;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyHttpCall.java
index 21642ac2..8fc369ee 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyHttpCall.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyHttpCall.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.core.reply;
import android.text.TextUtils;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyManager.java b/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyManager.java
index 533c801e..7468d996 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyManager.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyManager.java
@@ -19,18 +19,14 @@ package org.floens.chan.core.reply;
import android.content.Context;
import android.content.Intent;
-import android.text.TextUtils;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
-import com.squareup.okhttp.MediaType;
-import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
-import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.model.Loadable;
@@ -38,18 +34,14 @@ import org.floens.chan.core.model.Reply;
import org.floens.chan.core.model.SavedReply;
import org.floens.chan.ui.activity.ImagePickActivity;
import org.floens.chan.utils.AndroidUtils;
-import org.floens.chan.utils.Logger;
import java.io.File;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.HashMap;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
-import java.util.Random;
import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -63,7 +55,6 @@ public class ReplyManager {
private final Context context;
private FileListener fileListener;
- private final Random random = new Random();
private OkHttpClient client;
private Map drafts = new HashMap<>();
@@ -169,7 +160,7 @@ public class ReplyManager {
public void onFailure(Request request, IOException e) {
final PassResponse res = new PassResponse();
res.isError = true;
- res.message = context.getString(R.string.pass_error);
+ res.message = context.getString(R.string.setting_pass_error);
runUI(new Runnable() {
public void run() {
passListener.onResponse(res);
@@ -317,131 +308,6 @@ public class ReplyManager {
public String responseData = "";
}
- public void postReply(Reply reply, ReplyListener replyListener) {
- if (reply.usePass) {
- postReplyInternal(reply, replyListener, null);
- } else {
- postReplyInternal(reply, replyListener, reply.captchaResponse);
- }
- }
-
- private void postReplyInternal(final Reply reply, final ReplyListener replyListener, String captchaHash) {
-// reply.password = Long.toHexString(random.nextLong());
-
- MultipartBuilder formBuilder = new MultipartBuilder();
- formBuilder.type(MultipartBuilder.FORM);
-
- formBuilder.addFormDataPart("mode", "regist");
-// formBuilder.addFormDataPart("pwd", reply.password);
-
- if (reply.resto >= 0) {
- formBuilder.addFormDataPart("resto", String.valueOf(reply.resto));
- }
-
- formBuilder.addFormDataPart("name", reply.name);
- formBuilder.addFormDataPart("email", reply.options);
-
- if (reply.resto >= 0 && !TextUtils.isEmpty(reply.subject)) {
- formBuilder.addFormDataPart("sub", reply.subject);
- }
-
- formBuilder.addFormDataPart("com", reply.comment);
-
- if (captchaHash != null) {
- formBuilder.addFormDataPart("g-recaptcha-response", captchaHash);
- }
-
- if (reply.file != null) {
- formBuilder.addFormDataPart("upfile", reply.fileName, RequestBody.create(
- MediaType.parse("application/octet-stream"), reply.file
- ));
- }
-
- if (reply.spoilerImage) {
- formBuilder.addFormDataPart("spoiler", "on");
- }
-
- Request.Builder request = new Request.Builder()
- .url(ChanUrls.getReplyUrl(reply.board))
- .post(formBuilder.build());
-
- if (reply.usePass) {
- request.addHeader("Cookie", "pass_id=" + reply.passId);
- }
-
- makeOkHttpCall(request, new Callback() {
- @Override
- public void onFailure(Request request, IOException e) {
- final ReplyResponse res = new ReplyResponse();
- res.isNetworkError = true;
-
- runUI(new Runnable() {
- public void run() {
- replyListener.onResponse(res);
- }
- });
- }
-
- @Override
- public void onResponse(Response response) throws IOException {
- final ReplyResponse res = new ReplyResponse();
- if (response.isSuccessful()) {
- onReplyPosted(response.body().string(), reply, res);
- response.body().close();
- } else {
- res.isNetworkError = true;
- }
-
- runUI(new Runnable() {
- public void run() {
- replyListener.onResponse(res);
- }
- });
- }
- });
- }
-
- private ReplyResponse onReplyPosted(String responseString, Reply reply, ReplyResponse res) {
- res.responseData = responseString;
-
- if (res.responseData.contains("No file selected")) {
- res.isUserError = true;
- res.isFileError = true;
- } else if (res.responseData.contains("You forgot to solve the CAPTCHA") || res.responseData.contains("You seem to have mistyped the CAPTCHA")) {
- res.isUserError = true;
- res.isCaptchaError = true;
- } else if (res.responseData.toLowerCase(Locale.ENGLISH).contains("post successful")) {
- res.isSuccessful = true;
-
- Matcher matcher = POST_THREAD_NO_PATTERN.matcher(res.responseData);
- int threadNo = -1;
- int no = -1;
- if (matcher.find()) {
- try {
- threadNo = Integer.parseInt(matcher.group(1));
- no = Integer.parseInt(matcher.group(2));
- } catch (NumberFormatException err) {
- err.printStackTrace();
- }
- }
-
- if (threadNo >= 0 && no >= 0) {
- SavedReply savedReply = new SavedReply();
- savedReply.board = reply.board;
- savedReply.no = no;
-// savedReply.password = reply.password;
-
- ChanApplication.getDatabaseManager().saveReply(savedReply);
-
- res.threadNo = threadNo;
- res.no = no;
- } else {
- Logger.w(TAG, "No thread & no in the response");
- }
- }
- return res;
- }
-
public void makeHttpCall(HttpCall httpCall, HttpCallback callback) {
//noinspection unchecked
httpCall.setCallback(callback);
@@ -450,7 +316,7 @@ public class ReplyManager {
httpCall.setup(requestBuilder);
- requestBuilder.header("User-Agent", ChanApplication.getInstance().getUserAgent());
+ requestBuilder.header("User-Agent", Chan.getInstance().getUserAgent());
Request request = requestBuilder.build();
client.newCall(request).enqueue(httpCall);
@@ -463,7 +329,7 @@ public class ReplyManager {
}
private void makeOkHttpCall(Request.Builder requestBuilder, Callback callback) {
- requestBuilder.header("User-Agent", ChanApplication.getInstance().getUserAgent());
+ requestBuilder.header("User-Agent", Chan.getInstance().getUserAgent());
Request request = requestBuilder.build();
client.newCall(request).enqueue(callback);
}
@@ -471,51 +337,4 @@ public class ReplyManager {
private void runUI(Runnable runnable) {
AndroidUtils.runOnUiThread(runnable);
}
-
- public interface ReplyListener {
- void onResponse(ReplyResponse response);
- }
-
- public static class ReplyResponse {
- /**
- * No response from server.
- */
- public boolean isNetworkError = false;
-
- /**
- * Some user error, like no file or captcha wrong.
- */
- public boolean isUserError = false;
-
- /**
- * The userError was an fileError
- */
- public boolean isFileError = false;
-
- /**
- * The userError was an captchaError
- */
- public boolean isCaptchaError = false;
-
- /**
- * Received 'post successful'
- */
- public boolean isSuccessful = false;
-
- /**
- * Raw html from the response. Used to set html in an WebView to the
- * client, when the error was not recognized by Clover.
- */
- public String responseData = "";
-
- /**
- * The no the post has
- */
- public int no = -1;
-
- /**
- * The thread no the post has
- */
- public int threadNo = -1;
- }
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/BooleanSetting.java b/Clover/app/src/main/java/org/floens/chan/core/settings/BooleanSetting.java
index 31e82dea..fa17f65c 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/settings/BooleanSetting.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/settings/BooleanSetting.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.core.settings;
import android.content.SharedPreferences;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java
index 8ea4078f..3763cb1a 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java
@@ -20,7 +20,7 @@ package org.floens.chan.core.settings;
import android.content.SharedPreferences;
import android.os.Environment;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.utils.AndroidUtils;
@@ -98,217 +98,32 @@ public class ChanSettings {
watchEnabled = new BooleanSetting(p, "preference_watch_enabled", false, new Setting.SettingCallback() {
@Override
public void onValueChange(Setting setting, Boolean value) {
- ChanApplication.getWatchManager().onWatchEnabledChanged(value);
+ Chan.getWatchManager().onWatchEnabledChanged(value);
}
});
watchCountdown = new BooleanSetting(p, "preference_watch_countdown", false);
watchBackground = new BooleanSetting(p, "preference_watch_background_enabled", false, new Setting.SettingCallback() {
@Override
public void onValueChange(Setting setting, Boolean value) {
- ChanApplication.getWatchManager().onBackgroundWatchingChanged(value);
+ Chan.getWatchManager().onBackgroundWatchingChanged(value);
}
});
watchBackgroundTimeout = new StringSetting(p, "preference_watch_background_timeout", "60");
watchNotifyMode = new StringSetting(p, "preference_watch_notify_mode", "all");
- watchSound = new StringSetting(p, "preference_watch_sound", "all");
+ watchSound = new StringSetting(p, "preference_watch_sound", "quotes");
watchLed = new StringSetting(p, "preference_watch_led", "ffffffff");
passToken = new StringSetting(p, "preference_pass_token", "");
passPin = new StringSetting(p, "preference_pass_pin", "");
passId = new StringSetting(p, "preference_pass_id", "");
- }
- private static SharedPreferences p() {
- return AndroidUtils.getPreferences();
+ // Old (but possibly still in some users phone)
+ // preference_board_view_mode default "list"
+ // preference_board_editor_filler default false
+ // preference_pass_enabled default false
}
public static boolean passLoggedIn() {
return passId.get().length() > 0;
}
-
- public static boolean getOpenLinkConfirmation() {
- return p().getBoolean("preference_open_link_confirmation", true);
- }
-
- public static String getDefaultName() {
- return p().getString("preference_default_name", "");
- }
-
- public static boolean getPinOnPost() {
- return p().getBoolean("preference_pin_on_post", false);
- }
-
- public static boolean getDeveloper() {
- return p().getBoolean("preference_developer", false);
- }
-
- public static void setDeveloper(boolean developer) {
- p().edit().putBoolean("preference_developer", developer).commit();
- }
-
- public static File getImageSaveDirectory() {
- String path = p().getString("preference_image_save_location", null);
- File file;
- if (path == null) {
- file = new File(Environment.getExternalStorageDirectory() + File.separator + "Clover");
- } else {
- file = new File(path);
- }
-
- return file;
- }
-
- public static void setImageSaveDirectory(File file) {
- p().edit().putString("preference_image_save_location", file.getAbsolutePath()).commit();
- }
-
- public static boolean getImageSaveOriginalFilename() {
- return p().getBoolean("preference_image_save_original", false);
- }
-
- public static boolean getImageShareUrl() {
- return p().getBoolean("preference_image_share_url", false);
- }
-
- public static boolean getWatchEnabled() {
- return p().getBoolean("preference_watch_enabled", false);
- }
-
- /**
- * This also calls updateRunningState on the PinnedService to start/stop the
- * service as needed.
- *
- * @param enabled
- */
- public static void setWatchEnabled(boolean enabled) {
- if (getWatchEnabled() != enabled) {
- p().edit().putBoolean("preference_watch_enabled", enabled).commit();
- ChanApplication.getWatchManager().onWatchEnabledChanged(enabled);
- }
- }
-
- public static boolean getWatchCountdownVisibleEnabled() {
- return p().getBoolean("preference_watch_countdown", false);
- }
-
- public static boolean getWatchBackgroundEnabled() {
- return p().getBoolean("preference_watch_background_enabled", false);
- }
-
- public static int getWatchBackgroundTimeout() {
- String number = p().getString("preference_watch_background_timeout", "60");
- return Integer.parseInt(number);
- }
-
- public static String getWatchNotifyMode() {
- return p().getString("preference_watch_notify_mode", "all");
- }
-
- public static String getWatchSound() {
- return p().getString("preference_watch_sound", "quotes");
- }
-
- public static long getWatchLed() {
- String raw = p().getString("preference_watch_led", "ffffffff");
- return Long.parseLong(raw, 16);
- }
-
- public static boolean getVideoAutoPlay() {
- return getImageAutoLoad() && !getVideoExternal() && p().getBoolean("preference_autoplay", false);
- }
-
- public static boolean getThreadAutoRefresh() {
- return p().getBoolean("preference_auto_refresh_thread", true);
- }
-
- public static boolean getImageAutoLoad() {
- return p().getBoolean("preference_image_auto_load", true);
- }
-
- public static boolean getPassEnabled() {
- return p().getBoolean("preference_pass_enabled", false);
- }
-
- public static void setPassEnabled(boolean enabled) {
- if (getPassEnabled() != enabled) {
- p().edit().putBoolean("preference_pass_enabled", enabled).commit();
- }
- }
-
- public static String getPassToken() {
- return p().getString("preference_pass_token", "");
- }
-
- public static String getPassPin() {
- return p().getString("preference_pass_pin", "");
- }
-
- public static void setPassId(String id) {
- p().edit().putString("preference_pass_id", id).commit();
- }
-
- public static String getPassId() {
- return p().getString("preference_pass_id", "");
- }
-
- public static String getTheme() {
- return p().getString("preference_theme", "light");
- }
-
- public static boolean getForcePhoneLayout() {
- return p().getBoolean("preference_force_phone_layout", false);
- }
-
- public static boolean getBoardEditorFillerEnabled() {
- return p().getBoolean("preference_board_editor_filler", false);
- }
-
- public static boolean setBoardEditorFillerEnabled(boolean enabled) {
- return p().edit().putBoolean("preference_board_editor_filler", enabled).commit();
- }
-
- public static String getBoardViewMode() {
- return p().getString("preference_board_view_mode", "list");
- }
-
- public static void setBoardViewMode(String mode) {
- p().edit().putString("preference_board_view_mode", mode).commit();
- }
-
- public static boolean getAnonymize() {
- return p().getBoolean("preference_anonymize", false);
- }
-
- public static boolean getAnonymizeIds() {
- return p().getBoolean("preference_anonymize_ids", false);
- }
-
- public static boolean getReplyButtonsBottom() {
- return p().getBoolean("preference_buttons_bottom", false);
- }
-
- public static String getBoardMode() {
- return p().getString("preference_board_mode", "catalog");
- }
-
- public static boolean getVideoErrorIgnore() {
- return p().getBoolean("preference_video_error_ignore", false);
- }
-
- public static void setVideoErrorIgnore(boolean show) {
- p().edit().putBoolean("preference_video_error_ignore", show).commit();
- }
-
- public static boolean getVideoExternal() {
- return p().getBoolean("preference_video_external", false);
- }
-
- public static int getFontSize() {
- String font = p().getString("preference_font", null);
- return font == null ? 14 : Integer.parseInt(font);
- }
-
- public static boolean getNetworkHttps() {
- return p().getBoolean("preference_network_https", true);
- }
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/Setting.java b/Clover/app/src/main/java/org/floens/chan/core/settings/Setting.java
index e7c2c4f7..a2bf9cde 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/settings/Setting.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/settings/Setting.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.core.settings;
import android.content.SharedPreferences;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/StringSetting.java b/Clover/app/src/main/java/org/floens/chan/core/settings/StringSetting.java
index df699062..bd507c82 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/settings/StringSetting.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/settings/StringSetting.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.core.settings;
import android.content.SharedPreferences;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/watch/PinWatcher.java b/Clover/app/src/main/java/org/floens/chan/core/watch/PinWatcher.java
index cef5a8d8..56712a92 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/watch/PinWatcher.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/watch/PinWatcher.java
@@ -19,7 +19,7 @@ package org.floens.chan.core.watch;
import com.android.volley.VolleyError;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.core.loader.ChanLoader;
import org.floens.chan.core.loader.LoaderPool;
import org.floens.chan.core.model.ChanThread;
@@ -122,7 +122,7 @@ public class PinWatcher implements ChanLoader.ChanLoaderCallback {
AndroidUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
- ChanApplication.getWatchManager().onPinsChanged();
+ Chan.getWatchManager().onPinsChanged();
}
});
}
@@ -195,7 +195,7 @@ public class PinWatcher implements ChanLoader.ChanLoaderCallback {
AndroidUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
- ChanApplication.getWatchManager().pinWatcherUpdated(pin);
+ Chan.getWatchManager().pinWatcherUpdated(pin);
}
});
}
diff --git a/Clover/app/src/main/java/org/floens/chan/test/TestActivity.java b/Clover/app/src/main/java/org/floens/chan/test/TestActivity.java
index 136a8013..d34ed167 100644
--- a/Clover/app/src/main/java/org/floens/chan/test/TestActivity.java
+++ b/Clover/app/src/main/java/org/floens/chan/test/TestActivity.java
@@ -27,12 +27,12 @@ import android.widget.LinearLayout;
import com.android.volley.VolleyError;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
+import org.floens.chan.core.cache.FileCache;
import org.floens.chan.core.loader.ChanLoader;
import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post;
-import org.floens.chan.utils.FileCache;
import org.floens.chan.utils.Logger;
import org.floens.chan.utils.ThemeHelper;
@@ -90,7 +90,7 @@ public class TestActivity extends Activity implements View.OnClickListener {
File cacheDir = getExternalCacheDir() != null ? getExternalCacheDir() : getCacheDir();
File fileCacheDir = new File(cacheDir, "filecache");
- fileCache = new FileCache(fileCacheDir, 50 * 1024 * 1024, ChanApplication.getInstance().getUserAgent());
+ fileCache = new FileCache(fileCacheDir, 50 * 1024 * 1024, Chan.getInstance().getUserAgent());
}
@Override
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/ThemeActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/ThemeActivity.java
deleted file mode 100644
index 8e987953..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/ThemeActivity.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui;
-
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.MenuItem;
-
-import org.floens.chan.R;
-import org.floens.chan.utils.ThemeHelper;
-
-public class ThemeActivity extends AppCompatActivity {
- private Toolbar toolbar;
-
- public void setTheme() {
- setTheme(ThemeHelper.getInstance().getTheme().resValue);
- }
-
- public void setToolbar() {
- toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- }
-
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- if (item.getItemId() == android.R.id.home) {
- finish();
- return true;
- } else {
- return super.onOptionsItemSelected(item);
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/AboutActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/AboutActivity.java
deleted file mode 100644
index 10f4c897..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/AboutActivity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.os.Bundle;
-import android.webkit.WebView;
-
-import org.floens.chan.R;
-import org.floens.chan.ui.ThemeActivity;
-
-public class AboutActivity extends ThemeActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.toolbar_activity);
- setToolbar();
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- WebView webView = new WebView(this);
- webView.loadUrl("file:///android_asset/html/licenses.html");
-
- setContentView(webView);
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/AdvancedSettingsActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/AdvancedSettingsActivity.java
deleted file mode 100644
index 3bf2cab9..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/AdvancedSettingsActivity.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.os.Bundle;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
-
-import org.floens.chan.R;
-import org.floens.chan.chan.ChanUrls;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.ui.ThemeActivity;
-import org.floens.chan.ui.fragment.FolderPickFragment;
-
-import java.io.File;
-
-public class AdvancedSettingsActivity extends ThemeActivity {
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.toolbar_activity);
- setToolbar();
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- getFragmentManager().beginTransaction().replace(R.id.content, new AdvancedSettingsFragment()).commit();
- }
-
- public static class AdvancedSettingsFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preference_advanced);
-
- findPreference("preference_force_phone_layout").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(final Preference preference, final Object newValue) {
- BaseActivity.doRestartOnResume = true;
- return true;
- }
- });
-
- findPreference("preference_anonymize").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(final Preference preference, final Object newValue) {
- BaseActivity.doRestartOnResume = true;
- return true;
- }
- });
-
- findPreference("preference_anonymize_ids").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(final Preference preference, final Object newValue) {
- BaseActivity.doRestartOnResume = true;
- return true;
- }
- });
-
- final ListPreference boardMode = (ListPreference) findPreference("preference_board_mode");
- String currentModeValue = boardMode.getValue();
- if (currentModeValue == null) {
- boardMode.setValue((String) boardMode.getEntryValues()[0]);
- currentModeValue = boardMode.getValue();
- }
- updateSummary(boardMode, currentModeValue);
- boardMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- updateSummary(boardMode, newValue.toString());
- BaseActivity.doRestartOnResume = true;
- return true;
- }
- });
-
- reloadSavePath();
- final Preference saveLocation = findPreference("preference_image_save_location");
- saveLocation.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- File dir = ChanSettings.getImageSaveDirectory();
- dir.mkdirs();
-
- FolderPickFragment frag = FolderPickFragment.newInstance(new FolderPickFragment.FolderPickListener() {
- @Override
- public void folderPicked(File path) {
- ChanSettings.setImageSaveDirectory(path);
- reloadSavePath();
- }
- }, dir);
- getActivity().getFragmentManager().beginTransaction().add(frag, null).commit();
-
- return true;
- }
- });
-
- findPreference("preference_network_https").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- ChanUrls.loadScheme((Boolean) newValue);
-
- return true;
- }
- });
- }
-
- private void reloadSavePath() {
- Preference saveLocation = findPreference("preference_image_save_location");
- saveLocation.setSummary(ChanSettings.getImageSaveDirectory().getAbsolutePath());
- }
-
- private void updateSummary(ListPreference list, String value) {
- int index = list.findIndexOfValue(value);
- list.setSummary(list.getEntries()[index]);
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java
deleted file mode 100644
index b7e8497a..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.TypedArray;
-import android.net.Uri;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.nfc.NfcAdapter;
-import android.os.Bundle;
-import android.support.v4.view.GravityCompat;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v4.widget.SlidingPaneLayout;
-import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
-import android.support.v7.app.ActionBarDrawerToggle;
-import android.support.v7.widget.ShareActionProvider;
-import android.text.TextUtils;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView.OnItemLongClickListener;
-import android.widget.EditText;
-import android.widget.ListView;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.core.model.ChanThread;
-import org.floens.chan.core.model.Loadable;
-import org.floens.chan.core.model.Pin;
-import org.floens.chan.core.model.Post;
-import org.floens.chan.ui.ThemeActivity;
-import org.floens.chan.ui.adapter.PinnedAdapter;
-import org.floens.chan.ui.animation.SwipeDismissListViewTouchListener;
-import org.floens.chan.ui.animation.SwipeDismissListViewTouchListener.DismissCallbacks;
-import org.floens.chan.utils.AndroidUtils;
-import org.floens.chan.utils.ThemeHelper;
-
-import static org.floens.chan.utils.AndroidUtils.dp;
-
-public abstract class BaseActivity extends ThemeActivity implements PanelSlideListener {
- public static boolean doRestartOnResume = false;
-
- private final static int ACTION_OPEN_URL = 1;
-
- protected PinnedAdapter pinnedAdapter;
- protected DrawerLayout pinDrawer;
- protected ListView pinDrawerView;
- protected ActionBarDrawerToggle pinDrawerListener;
-
- protected SlidingPaneLayout threadPane;
-
- private String shareUrl;
- private ShareActionProvider shareActionProvider;
- private Intent pendingShareActionProviderIntent;
-
- /**
- * Called when a post has been clicked in the pinned drawer
- *
- * @param post
- */
- abstract public void openPin(Pin post);
-
- /**
- * Called when a post has been clicked in the listview
- *
- * @param post
- */
- abstract public void onOPClicked(Post post);
-
- abstract public void onOpenThread(Loadable thread);
-
- abstract public void onThreadLoaded(ChanThread thread);
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- ThemeHelper.getInstance().reloadPostViewColors(this);
-
- setContentView(R.layout.activity_base);
-
- setTheme();
- setToolbar();
-
- pinDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
- initDrawer();
-
- threadPane = (SlidingPaneLayout) findViewById(R.id.pane_container);
- initPane();
-
- updateIcon();
- }
-
- @Override
- public void onBackPressed() {
- if (pinDrawer.isDrawerOpen(pinDrawerView)) {
- pinDrawer.closeDrawer(pinDrawerView);
- } else {
- super.onBackPressed();
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- if (doRestartOnResume) {
- doRestartOnResume = false;
- recreate();
- }
- }
-
- private void initPane() {
- threadPane.setPanelSlideListener(this);
- threadPane.setParallaxDistance(dp(100));
- threadPane.setShadowResource(R.drawable.panel_shadow);
-
- TypedArray ta = obtainStyledAttributes(null, R.styleable.BoardPane, R.attr.board_pane_style, 0);
- int color = ta.getColor(R.styleable.BoardPane_fade_color, 0);
- ta.recycle();
-
- threadPane.setSliderFadeColor(color);
- threadPane.openPane();
- }
-
- protected void initDrawer() {
- if (pinDrawerListener == null) {
- return;
- }
-
- pinDrawer.setDrawerListener(pinDrawerListener);
- pinDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
-
- pinDrawerView = (ListView) findViewById(R.id.left_drawer);
-
- pinnedAdapter = new PinnedAdapter(getSupportActionBar().getThemedContext(), pinDrawerView); // Get the dark theme, not the light one
- pinnedAdapter.reload();
- pinDrawerView.setAdapter(pinnedAdapter);
-
- pinDrawerView.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- Pin pin = pinnedAdapter.getItem(position);
- if (pin == null)
- return;
- openPin(pin);
- }
- });
-
- pinDrawerView.setOnItemLongClickListener(new OnItemLongClickListener() {
- @Override
- public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
- Pin post = pinnedAdapter.getItem(position);
- if (post == null)
- return false;
-
- onPinLongPress(post);
-
- return true;
- }
- });
-
- SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(pinDrawerView,
- new DismissCallbacks() {
- @Override
- public void onDismiss(ListView listView, int[] reverseSortedPositions) {
- for (int position : reverseSortedPositions) {
- removePin(pinnedAdapter.getItem(position));
- }
- }
-
- @Override
- public boolean canDismiss(int position) {
- return pinnedAdapter.getItem(position) != null;
- }
- }
- );
-
- pinDrawerView.setOnTouchListener(touchListener);
- pinDrawerView.setOnScrollListener(touchListener.makeScrollListener());
- pinDrawerView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- }
-
- private void updateIcon() {
- /*List list = ChanApplication.getWatchManager().getWatchingPins();
- if (list.size() > 0) {
- int count = 0;
- boolean color = false;
- for (Pin p : list) {
- count += p.getNewPostCount();
- if (p.getNewQuoteCount() > 0) {
- color = true;
- }
- }
-
- if (count > 0) {
- Drawable icon = BadgeDrawable.get(getResources(), R.drawable.ic_launcher, count, color);
- getSupportActionBar().setIcon(icon);
- } else {
- getSupportActionBar().setIcon(R.drawable.ic_launcher);
- }
- } else {
- getSupportActionBar().setIcon(R.drawable.ic_launcher);
- }*/
- }
-
- public void removePin(Pin pin) {
- ChanApplication.getWatchManager().removePin(pin);
- }
-
- public void updatePin(Pin pin) {
- ChanApplication.getWatchManager().updatePin(pin);
- }
-
- private void onPinLongPress(final Pin pin) {
- new AlertDialog.Builder(this)
- .setNegativeButton(R.string.drawer_pinned_delete, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Delete pin
- removePin(pin);
- }
- }).setPositiveButton(R.string.drawer_pinned_change_title, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Change pin title
- final EditText text = new EditText(BaseActivity.this);
- text.setSingleLine();
- text.setText(pin.loadable.title);
- text.setSelectAllOnFocus(true);
-
- AlertDialog titleDialog = new AlertDialog.Builder(BaseActivity.this)
- .setPositiveButton(R.string.change, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface d, int which) {
- String value = text.getText().toString();
-
- if (!TextUtils.isEmpty(value)) {
- pin.loadable.title = value;
- updatePin(pin);
- }
- }
- }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface d, int which) {
- }
- }).setTitle(R.string.drawer_pinned_change_title).setView(text).create();
-
- AndroidUtils.requestKeyboardFocus(titleDialog, text);
-
- titleDialog.show();
- }
- }).show();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_settings:
- startActivity(new Intent(this, SettingsActivity.class));
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.base, menu);
- /*shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.action_share));
- if (pendingShareActionProviderIntent != null) {
- shareActionProvider.setShareIntent(pendingShareActionProviderIntent);
- pendingShareActionProviderIntent = null;
- }*/
-
- return true;
- }
-
- @Override
- public void onPanelClosed(View view) {
- }
-
- @Override
- public void onPanelOpened(View view) {
- }
-
- @Override
- public void onPanelSlide(View view, float offset) {
- }
-
- /**
- * Set the url that Android Beam and the share action will send.
- *
- * @param url
- */
- public void setShareUrl(String url) {
- shareUrl = url;
-
- NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
-
- if (adapter != null) {
- NdefRecord record = null;
- try {
- record = NdefRecord.createUri(url);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- return;
- }
-
- NdefMessage message = new NdefMessage(new NdefRecord[]{record});
- try {
- adapter.setNdefPushMessage(message, this);
- } catch (Exception e) {
- }
- }
-
- Intent share = new Intent(android.content.Intent.ACTION_SEND);
- share.putExtra(android.content.Intent.EXTRA_TEXT, url);
- share.setType("text/plain");
-
- if (shareActionProvider != null) {
- shareActionProvider.setShareIntent(share);
- } else {
- pendingShareActionProviderIntent = share;
- }
- }
-
- public void openInBrowser() {
- if (shareUrl != null) {
- showUrlOpenPicker(shareUrl);
- }
- }
-
- /**
- * Let the user choose between all activities that can open the url. This is
- * done to prevent "open in browser" opening the url in our own app.
- *
- * @param url
- */
- public void showUrlOpenPicker(String url) {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- startActivity(intent);
- }
-
- /**
- * Used for showUrlOpenPicker
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- if (requestCode == ACTION_OPEN_URL && resultCode == RESULT_OK && data != null) {
- data.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(data);
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardEditor.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardEditor.java
deleted file mode 100644
index 20666d98..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardEditor.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.graphics.Color;
-import android.graphics.Point;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.AutoCompleteTextView;
-import android.widget.Filter;
-import android.widget.Filterable;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.mobeta.android.dslv.DragSortController;
-import com.mobeta.android.dslv.DragSortListView;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.core.manager.BoardManager;
-import org.floens.chan.core.model.Board;
-import org.floens.chan.ui.animation.SwipeDismissListViewTouchListener;
-import org.floens.chan.ui.ThemeActivity;
-import org.floens.chan.utils.AndroidUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-public class BoardEditor extends ThemeActivity {
- private final BoardManager boardManager = ChanApplication.getBoardManager();
-
- private List list;
- private DragSortListView listView;
- private BoardEditAdapter adapter;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.toolbar_activity);
- setToolbar();
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- list = boardManager.getSavedBoards();
-
- adapter = new BoardEditAdapter(this, 0, list);
-
- listView = new DragSortListView(this, null);
- listView.setAdapter(adapter);
- listView.setDivider(new ColorDrawable(Color.TRANSPARENT));
-
- final DragSortController controller = new NiceDragSortController(listView, adapter);
-
- listView.setFloatViewManager(controller);
- listView.setOnTouchListener(controller);
- listView.setDragEnabled(true);
- listView.setDropListener(new DragSortListView.DropListener() {
- @Override
- public void drop(int from, int to) {
- if (from != to) {
- Board board = list.remove(from);
- list.add(to, board);
- adapter.notifyDataSetChanged();
- }
- }
- });
-
- final SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(listView,
- new SwipeDismissListViewTouchListener.DismissCallbacks() {
- @Override
- public void onDismiss(ListView listView, int[] reverseSortedPositions) {
- for (int position : reverseSortedPositions) {
- if (position >= 0 && position < adapter.getCount()) {
- Board b = adapter.getItem(position);
- adapter.remove(b);
- b.saved = false;
- }
- }
-
- adapter.notifyDataSetChanged();
- }
-
- @Override
- public boolean canDismiss(int position) {
- return list.size() > 1;
- }
- }
- );
-
- listView.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View view, MotionEvent motionEvent) {
- return controller.onTouch(view, motionEvent)
- || (!listView.isDragging() && touchListener.onTouch(view, motionEvent));
- }
- });
-
- listView.setOnScrollListener(touchListener.makeScrollListener());
-
- listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
- @Override
- public boolean onItemLongClick(AdapterView> parent, View view, final int position, long id) {
- new AlertDialog.Builder(BoardEditor.this)
- .setNegativeButton(R.string.cancel, null)
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (position >= 0 && position < adapter.getCount()) {
- Board b = adapter.getItem(position);
- adapter.remove(b);
- b.saved = false;
- adapter.notifyDataSetChanged();
- }
- }
- })
- .setMessage(R.string.board_delete)
- .show();
- return true;
- }
- });
-
- ((ViewGroup) findViewById(R.id.content)).addView(listView);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- if (list.size() > 0) {
- // Order
- for (int i = 0; i < list.size(); i++) {
- list.get(i).order = i;
- }
-
- boardManager.updateSavedBoards();
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.board_edit, menu);
-
- menu.findItem(R.id.action_show_filler).setChecked(ChanSettings.getBoardEditorFillerEnabled());
-
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_add_board:
- showAddBoardDialog();
- return true;
- case R.id.action_show_filler:
- ChanSettings.setBoardEditorFillerEnabled(!ChanSettings.getBoardEditorFillerEnabled());
- item.setChecked(ChanSettings.getBoardEditorFillerEnabled());
- return true;
- case android.R.id.home:
- finish();
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- private void addBoard(String value) {
- value = value.trim();
- value = value.replace("/", "");
- value = value.replace("\\", ""); // what are you doing?!
-
- // Duplicate
- for (Board board : list) {
- if (board.value.equals(value)) {
- Toast.makeText(this, R.string.board_add_duplicate, Toast.LENGTH_LONG).show();
-
- return;
- }
- }
-
- // Normal add
- List all = ChanApplication.getBoardManager().getAllBoards();
- for (Board board : all) {
- if (board.value.equals(value)) {
- board.saved = true;
- list.add(board);
- adapter.notifyDataSetChanged();
-
- Toast.makeText(this, getString(R.string.board_add_success) + " " + board.key, Toast.LENGTH_LONG).show();
-
- return;
- }
- }
-
- // Unknown
- new AlertDialog.Builder(this)
- .setTitle(R.string.board_add_unknown_title)
- .setMessage(getString(R.string.board_add_unknown, value))
- .setPositiveButton(R.string.ok, null)
- .show();
- }
-
- private void showAddBoardDialog() {
- final AutoCompleteTextView text = new AutoCompleteTextView(this);
- text.setSingleLine();
-
- FillAdapter fillAdapter = new FillAdapter(this, 0);
- fillAdapter.setEditingList(list);
- fillAdapter.setAutoCompleteView(text);
- text.setAdapter(fillAdapter);
- text.setThreshold(1);
- text.setDropDownHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
- text.setHint(R.string.board_add_hint);
- text.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
-
- AlertDialog dialog = new AlertDialog.Builder(this)
- .setPositiveButton(R.string.add, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface d, int which) {
- String value = text.getText().toString();
-
- if (!TextUtils.isEmpty(value)) {
- addBoard(value.toLowerCase(Locale.ENGLISH));
- }
- }
- }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface d, int which) {
- }
- }).setTitle(R.string.board_add).setView(text).create();
-
- AndroidUtils.requestKeyboardFocus(dialog, text);
-
- dialog.show();
- }
-
- private static class FillAdapter extends ArrayAdapter implements Filterable {
- private List currentlyEditing;
- private View autoCompleteView;
- private final Filter filter;
- private final List filtered = new ArrayList<>();
-
- public FillAdapter(Context context, int resource) {
- super(context, resource);
-
- filter = new Filter() {
- @Override
- protected synchronized FilterResults performFiltering(CharSequence constraint) {
- FilterResults results = new FilterResults();
-
- if (TextUtils.isEmpty(constraint) || (constraint.toString().startsWith(" "))) {
- results.values = null;
- results.count = 0;
- } else {
- List keys = getFiltered(constraint.toString());
- results.values = keys;
- results.count = keys.size();
- }
-
- return results;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected void publishResults(CharSequence constraint, FilterResults results) {
- filtered.clear();
-
- if (ChanSettings.getBoardEditorFillerEnabled()) {
- if (results.values != null) {
- filtered.addAll((List) results.values);
- } else {
- filtered.addAll(getBoards());
- }
- }
-
- notifyDataSetChanged();
- }
- };
- }
-
- public void setEditingList(List list) {
- currentlyEditing = list;
- }
-
- public void setAutoCompleteView(View autoCompleteView) {
- this.autoCompleteView = autoCompleteView;
- }
-
- @Override
- public int getCount() {
- return filtered.size();
- }
-
- @Override
- public String getItem(int position) {
- return filtered.get(position).value;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- TextView view = (TextView) inflater.inflate(android.R.layout.simple_list_item_1, null);
- Board b = filtered.get(position);
- view.setText(b.value + " - " + b.key);
-
- view.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
- Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(autoCompleteView.getWindowToken(), 0);
- }
-
- return false;
- }
- });
-
- return view;
- }
-
- @Override
- public Filter getFilter() {
- return filter;
- }
-
- private List getFiltered(String filter) {
- String lowered = filter.toLowerCase(Locale.ENGLISH);
- List list = new ArrayList<>();
- for (Board b : getBoards()) {
- if ((b.key.toLowerCase(Locale.ENGLISH).contains(lowered) || b.value.toLowerCase(Locale.ENGLISH)
- .contains(lowered))) {
- list.add(b);
- }
- }
- return list;
- }
-
- private boolean haveBoard(String value) {
- for (Board b : currentlyEditing) {
- if (b.value.equals(value))
- return true;
- }
- return false;
- }
-
- private List getBoards() {
- // Lets be cheaty here: if the user has nsfw boards in the list,
- // show them in the autofiller.
- boolean showUnsafe = false;
- for (Board has : currentlyEditing) {
- if (!has.workSafe) {
- showUnsafe = true;
- break;
- }
- }
-
- List s = new ArrayList<>();
- for (Board b : ChanApplication.getBoardManager().getAllBoards()) {
- if (!haveBoard(b.value) && (showUnsafe || b.workSafe))
- s.add(b);
- }
- return s;
- }
- }
-
- private class NiceDragSortController extends DragSortController {
- private final ListView listView;
- private final ArrayAdapter adapter;
-
- public NiceDragSortController(DragSortListView listView, ArrayAdapter adapter) {
- super(listView, R.id.drag_handle, DragSortController.ON_DOWN, 0);
- this.listView = listView;
- this.adapter = adapter;
- setSortEnabled(true);
- setRemoveEnabled(false);
- }
-
- @Override
- public View onCreateFloatView(int position) {
- return adapter.getView(position, null, listView);
- }
-
- @Override
- public void onDragFloatView(View floatView, Point floatPoint, Point touchPoint) {
- }
-
- @Override
- public void onDestroyFloatView(View floatView) {
- }
- }
-
- private class BoardEditAdapter extends ArrayAdapter {
- public BoardEditAdapter(Context context, int textViewResourceId, List objects) {
- super(context, textViewResourceId, objects);
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public long getItemId(int position) {
- return getItem(position).hashCode();
- }
-
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- View inflated = LayoutInflater.from(getContext()).inflate(R.layout.board_edit_item, null);
- TextView text = (TextView) inflated.findViewById(R.id.text);
- Board b = getItem(position);
- text.setText(b.value + " - " + b.key);
-
- return inflated;
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java
deleted file mode 100644
index 053b4f84..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.app.AlertDialog;
-import android.app.FragmentTransaction;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarDrawerToggle;
-import android.util.DisplayMetrics;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.chan.ChanUrls;
-import org.floens.chan.core.loader.ChanLoader;
-import org.floens.chan.core.manager.ThreadManager;
-import org.floens.chan.core.model.Board;
-import org.floens.chan.core.model.ChanThread;
-import org.floens.chan.core.model.Loadable;
-import org.floens.chan.core.model.Pin;
-import org.floens.chan.core.model.Post;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.ui.fragment.ThreadFragment;
-import org.floens.chan.utils.Logger;
-
-import java.util.List;
-
-import static org.floens.chan.utils.AndroidUtils.dp;
-
-public class ChanActivity extends BaseActivity implements AdapterView.OnItemSelectedListener {
- private static final String TAG = "ChanActivity";
-
- private Loadable boardLoadable;
- private Loadable threadLoadable;
- private ThreadFragment boardFragment;
- private ThreadFragment threadFragment;
-
- private boolean ignoreNextOnItemSelected = false;
- private Spinner boardSpinner;
- private BoardSpinnerAdapter spinnerAdapter;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- boardLoadable = new Loadable();
- threadLoadable = new Loadable();
-
- boardFragment = ThreadFragment.newInstance(this);
- setBoardFragmentViewMode();
-
- threadFragment = ThreadFragment.newInstance(this);
-
- FragmentTransaction ft = getFragmentManager().beginTransaction();
- ft.replace(R.id.left_pane, boardFragment);
- ft.replace(R.id.right_pane, threadFragment);
- ft.commitAllowingStateLoss();
-
- final ActionBar actionBar = getSupportActionBar();
-
- boardSpinner = new Spinner(this);
- spinnerAdapter = new BoardSpinnerAdapter(this, boardSpinner);
- boardSpinner.setAdapter(spinnerAdapter);
- boardSpinner.setOnItemSelectedListener(this);
-
- actionBar.setCustomView(boardSpinner);
- actionBar.setDisplayShowCustomEnabled(true);
-
- updatePaneState();
-
- Intent startIntent = getIntent();
- Uri startUri = startIntent.getData();
-
- if (savedInstanceState != null) {
- Loadable threadTmp = new Loadable();
- threadTmp.readFromBundle(this, "thread", savedInstanceState);
- startLoadingThread(threadTmp);
-
- // Reset page etc.
- Loadable tmp = new Loadable();
- tmp.readFromBundle(this, "board", savedInstanceState);
- startLoadingBoard(new Loadable(tmp.board));
- } else {
- if (startUri != null) {
- handleIntentURI(startUri);
- }
-
- if (boardLoadable.mode == Loadable.Mode.INVALID) {
- List savedValues = ChanApplication.getBoardManager().getSavedBoards();
- if (savedValues.size() > 0) {
- startLoadingBoard(new Loadable(savedValues.get(0).value));
- }
- }
- }
-
- if (startIntent.getExtras() != null) {
- handleExtraBundle(startIntent.getExtras());
- }
-
- ignoreNextOnItemSelected = true;
- }
-
- @Override
- protected void onNewIntent(final Intent intent) {
- super.onNewIntent(intent);
-
- if (intent.getExtras() != null) {
- handleExtraBundle(intent.getExtras());
- }
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- boardLoadable.writeToBundle(this, "board", outState);
- threadLoadable.writeToBundle(this, "thread", outState);
- }
-
- @Override
- protected void onStart() {
- super.onStart();
-
- ChanApplication.getInstance().activityEnteredForeground();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
-
- ChanApplication.getInstance().activityEnteredBackground();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- ChanApplication.getWatchManager().updateDatabase();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
-// ChanApplication.getBoardManager().removeListener(this);
- }
-
- @Override
- protected void initDrawer() {
- pinDrawerListener = new ActionBarDrawerToggle(this, pinDrawer, R.string.drawer_open, R.string.drawer_close);
-
- super.initDrawer();
- }
-
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- pinDrawerListener.syncState();
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- pinDrawerListener.onConfigurationChanged(newConfig);
-
- updatePaneState();
- }
-
- @Override
- public void onBackPressed() {
- if (pinDrawer.isDrawerOpen(pinDrawerView)) {
- pinDrawer.closeDrawer(pinDrawerView);
- } else {
- if (threadPane.isOpen()) {
- super.onBackPressed();
- } else {
- threadPane.openPane();
- }
- }
- }
-
- @Override
- public void openPin(Pin pin) {
- startLoadingThread(pin.loadable);
-
- pinDrawer.closeDrawer(pinDrawerView);
- }
-
- @Override
- public void onOPClicked(Post post) {
- Loadable l = new Loadable(post.board, post.no);
- l.generateTitle(post);
- startLoadingThread(l);
- }
-
- @Override
- public void onOpenThread(Loadable thread) {
- startLoadingThread(thread);
- }
-
- @Override
- public void onThreadLoaded(ChanThread thread) {
- updateActionBarState();
- pinnedAdapter.notifyDataSetChanged();
- }
-
- @Override
- public void updatePin(Pin pin) {
- super.updatePin(pin);
- updateActionBarState();
- }
-
- @Override
- public void removePin(Pin pin) {
- super.removePin(pin);
- updateActionBarState();
- }
-
- @Override
- public void onNothingSelected(final AdapterView> parent) {
- }
-
- @Override
- public void onPanelClosed(View view) {
- updateActionBarState();
- }
-
- @Override
- public void onPanelOpened(View view) {
- updateActionBarState();
- }
-
-// @Override
-// public void onBoardsChanged() {
-// spinnerAdapter.setBoards();
-// spinnerAdapter.notifyDataSetChanged();
-// }
-
- private void handleExtraBundle(Bundle extras) {
- int pinId = extras.getInt("pin_id", -2);
- if (pinId != -2) {
- if (pinId == -1) {
- pinDrawer.openDrawer(pinDrawerView);
- } else {
- Pin pin = ChanApplication.getWatchManager().findPinById(pinId);
- if (pin != null) {
- startLoadingThread(pin.loadable);
- }
- }
- }
- }
-
- private void updatePaneState() {
- DisplayMetrics metrics = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(metrics);
- int width = metrics.widthPixels;
-
- FrameLayout left = (FrameLayout) findViewById(R.id.left_pane);
- FrameLayout right = (FrameLayout) findViewById(R.id.right_pane);
-
- LayoutParams leftParams = left.getLayoutParams();
- LayoutParams rightParams = right.getLayoutParams();
-
- boolean wasSlidable = threadPane.isSlideable();
- boolean isSlidable;
-
- // Content view dp's:
- // Nexus 4 is 384 x 640 dp
- // Nexus 7 is 600 x 960 dp
- // Nexus 10 is 800 x 1280 dp
-
- if (ChanSettings.getForcePhoneLayout()) {
- leftParams.width = width - dp(30);
- rightParams.width = width;
- isSlidable = true;
- } else {
- if (width < dp(400)) {
- leftParams.width = width - dp(30);
- rightParams.width = width;
- isSlidable = true;
- } else if (width < dp(800)) {
- leftParams.width = width - dp(60);
- rightParams.width = width;
- isSlidable = true;
- } else if (width < dp(1000)) {
- leftParams.width = dp(300);
- rightParams.width = width - dp(300);
- isSlidable = false;
- } else {
- leftParams.width = dp(400);
- rightParams.width = width - dp(400);
- isSlidable = false;
- }
- }
-
- left.setLayoutParams(leftParams);
- right.setLayoutParams(rightParams);
-
- threadPane.requestLayout();
- left.requestLayout();
- right.requestLayout();
-
- LayoutParams drawerParams = pinDrawerView.getLayoutParams();
-
- if (width < dp(340)) {
- drawerParams.width = dp(280);
- } else {
- drawerParams.width = dp(320);
- }
-
- pinDrawerView.setLayoutParams(drawerParams);
-
- updateActionBarState();
-
- if (isSlidable != wasSlidable) {
- // Terrible hack to sync state for some devices when it changes slidable mode
- threadPane.postDelayed(new Runnable() {
- @Override
- public void run() {
- updateActionBarState();
- }
- }, 1000);
- }
- }
-
- private void updateActionBarState() {
- // Force the actionbar state after the ThreadPane layout,
- // otherwise the ThreadPane incorrectly reports that it's not slidable.
- threadPane.post(new Runnable() {
- @Override
- public void run() {
- updateActionBarStateCallback();
- }
- });
- }
-
- private void updateActionBarStateCallback() {
- final ActionBar actionBar = getSupportActionBar();
-
- if (threadPane.isSlideable()) {
- if (threadPane.isOpen()) {
- actionBar.setDisplayShowCustomEnabled(true);
- spinnerAdapter.setBoard(boardLoadable.board);
- actionBar.setTitle("");
- pinDrawerListener.setDrawerIndicatorEnabled(true);
-
- if (boardLoadable.isBoardMode()) {
- setShareUrl(ChanUrls.getBoardUrlDesktop(boardLoadable.board));
- } else if (boardLoadable.isCatalogMode()) {
- setShareUrl(ChanUrls.getCatalogUrlDesktop(boardLoadable.board));
- }
- } else {
- actionBar.setDisplayShowCustomEnabled(false);
- actionBar.setTitle(threadLoadable.title);
- pinDrawerListener.setDrawerIndicatorEnabled(false);
-
- if (threadLoadable.isThreadMode())
- setShareUrl(ChanUrls.getThreadUrlDesktop(threadLoadable.board, threadLoadable.no));
- }
- } else {
- actionBar.setDisplayShowCustomEnabled(true);
- pinDrawerListener.setDrawerIndicatorEnabled(true);
- actionBar.setTitle(threadLoadable.title);
-
- if (threadLoadable.isThreadMode()) {
- setShareUrl(ChanUrls.getThreadUrlDesktop(threadLoadable.board, threadLoadable.no));
- }
- }
-
- actionBar.setHomeButtonEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowTitleEnabled(true);
-
- invalidateOptionsMenu();
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- boolean open = threadPane.isOpen();
- boolean slidable = threadPane.isSlideable();
-
- setMenuItemEnabled(menu.findItem(R.id.action_reload_board), slidable && open);
- setMenuItemEnabled(menu.findItem(R.id.action_reload_thread), slidable && !open);
- setMenuItemEnabled(menu.findItem(R.id.action_reload_tablet), !slidable);
-
- setMenuItemEnabled(menu.findItem(R.id.action_pin), !slidable || !open);
- setMenuItemEnabled(menu.findItem(R.id.action_download_album), !slidable || !open);
-
- setMenuItemEnabled(menu.findItem(R.id.action_reply), slidable);
- setMenuItemEnabled(menu.findItem(R.id.action_reply_tablet), !slidable);
-
- setMenuItemEnabled(menu.findItem(R.id.action_board_view_mode), !slidable || open);
-
- if (ChanSettings.getBoardViewMode().equals("list")) {
- menu.findItem(R.id.action_board_view_mode_list).setChecked(true);
- } else if (ChanSettings.getBoardViewMode().equals("grid")) {
- menu.findItem(R.id.action_board_view_mode_grid).setChecked(true);
- }
-
- setMenuItemEnabled(menu.findItem(R.id.action_search), slidable);
- setMenuItemEnabled(menu.findItem(R.id.action_search_tablet), !slidable);
-
- boolean bookmarkedFilled = false;
- if (threadLoadable.mode == Loadable.Mode.THREAD) {
- Pin pin = ChanApplication.getWatchManager().findPinByLoadable(threadLoadable);
- if (pin != null) {
- bookmarkedFilled = true;
- }
- }
-
- menu.findItem(R.id.action_pin).setIcon(bookmarkedFilled ? R.drawable.ic_bookmark_filled : R.drawable.ic_bookmark);
-
- return super.onPrepareOptionsMenu(menu);
- }
-
- private void setMenuItemEnabled(MenuItem item, boolean enabled) {
- if (item != null) {
- item.setVisible(enabled);
- item.setEnabled(enabled);
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (pinDrawerListener.onOptionsItemSelected(item)) {
- return true;
- }
-
- switch (item.getItemId()) {
- case R.id.action_reload_board:
- case R.id.action_reload_tablet_board:
- boardFragment.reload();
- return true;
- case R.id.action_reload_thread:
- case R.id.action_reload_tablet_thread:
- threadFragment.reload();
- return true;
- case R.id.action_reply:
- if (threadPane.isOpen()) {
- boardFragment.openReply();
- } else {
- threadFragment.openReply();
- }
- return true;
- case R.id.action_reply_board:
- boardFragment.openReply();
-
- return true;
- case R.id.action_reply_thread:
- threadFragment.openReply();
-
- return true;
- case R.id.action_pin:
- if (threadFragment.hasLoader()) {
- ChanLoader chanLoader = threadFragment.getLoader();
- if (chanLoader != null && chanLoader.getLoadable().isThreadMode() && chanLoader.getThread() != null) {
- Pin pin = ChanApplication.getWatchManager().findPinByLoadable(threadLoadable);
- if (pin != null) {
- ChanApplication.getWatchManager().removePin(pin);
- } else {
- ChanApplication.getWatchManager().addPin(chanLoader.getLoadable(), chanLoader.getThread().op);
- }
- updateActionBarState();
- }
- }
-
- return true;
- case R.id.action_open_browser:
- openInBrowser();
-
- return true;
- case R.id.action_board_view_mode_grid:
- if (!ChanSettings.getBoardViewMode().equals("grid")) {
- ChanSettings.setBoardViewMode("grid");
- setBoardFragmentViewMode();
- startLoadingBoard(boardLoadable);
- }
- return true;
- case R.id.action_board_view_mode_list:
- if (!ChanSettings.getBoardViewMode().equals("list")) {
- ChanSettings.setBoardViewMode("list");
- setBoardFragmentViewMode();
- startLoadingBoard(boardLoadable);
- }
- return true;
- case R.id.action_search:
- if (threadPane.isOpen()) {
- boardFragment.startFiltering();
- } else {
- threadFragment.startFiltering();
- }
- return true;
- case R.id.action_search_board:
- boardFragment.startFiltering();
- return true;
- case R.id.action_search_thread:
- threadFragment.startFiltering();
- return true;
- case android.R.id.home:
- threadPane.openPane();
-
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onItemSelected(final AdapterView> parent, final View view, final int position, final long id) {
- if (ignoreNextOnItemSelected) {
- Logger.d(TAG, "Ignoring onItemSelected");
- ignoreNextOnItemSelected = false;
- return;
- }
-
- spinnerAdapter.onItemSelected(position);
- }
-
- private void startLoadingBoard(Loadable loadable) {
- if (loadable.mode == Loadable.Mode.INVALID)
- return;
-
- boardLoadable = loadable;
-
- if (ChanSettings.getBoardMode().equals("catalog")) {
- boardLoadable.mode = Loadable.Mode.CATALOG;
- } else if (ChanSettings.getBoardMode().equals("pages")) {
- boardLoadable.mode = Loadable.Mode.BOARD;
- }
-
- // Force catalog mode when using grid
- if (boardFragment.getViewMode() == ThreadManager.ViewMode.GRID) {
- boardLoadable.mode = Loadable.Mode.CATALOG;
- }
-
- boardFragment.bindLoadable(boardLoadable);
- boardFragment.requestData();
-
- updateActionBarState();
- }
-
- private void startLoadingThread(Loadable loadable) {
- if (loadable.mode == Loadable.Mode.INVALID)
- return;
-
- Pin pin = ChanApplication.getWatchManager().findPinByLoadable(loadable);
- if (pin != null) {
- // Use the loadable from the pin.
- // This way we can store the listview position in the pin loadable,
- // and not in a separate loadable instance.
- loadable = pin.loadable;
- }
-
- if (threadLoadable.equals(loadable)) {
- threadFragment.requestNextData();
- } else {
- threadLoadable = loadable;
- threadFragment.bindLoadable(loadable);
- threadFragment.requestData();
- }
-
- threadPane.closePane();
-
- updateActionBarState();
- }
-
- /**
- * Handle opening from an external url.
- *
- * @param startUri
- */
- private void handleIntentURI(Uri startUri) {
- Logger.d(TAG, "Opening " + startUri.getPath());
-
- List parts = startUri.getPathSegments();
-
- if (parts.size() == 1) {
- // Board mode
- String rawBoard = parts.get(0);
- if (ChanApplication.getBoardManager().getBoardExists(rawBoard)) {
- startLoadingBoard(new Loadable(rawBoard));
- } else {
- handleIntentURIFallback(startUri.toString());
- }
- } else if (parts.size() >= 3) {
- // Thread mode
- String rawBoard = parts.get(0);
- int no = -1;
-
- try {
- no = Integer.parseInt(parts.get(2));
- } catch (NumberFormatException e) {
- }
-
- int post = -1;
- String fragment = startUri.getFragment();
- if (fragment != null) {
- int index = fragment.indexOf("p");
- if (index >= 0) {
- try {
- post = Integer.parseInt(fragment.substring(index + 1));
- } catch (NumberFormatException e) {
- }
- }
- }
-
- if (no >= 0 && ChanApplication.getBoardManager().getBoardExists(rawBoard)) {
- startLoadingThread(new Loadable(rawBoard, no));
- if (post >= 0) {
- threadFragment.highlightPost(post);
- }
- } else {
- handleIntentURIFallback(startUri.toString());
- }
- } else {
- showUrlOpenPicker(startUri.toString());
- }
- }
-
- private void handleIntentURIFallback(final String url) {
- new AlertDialog.Builder(this).setTitle(R.string.open_unknown_title).setMessage(R.string.open_unknown)
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- finish();
- }
- }).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- showUrlOpenPicker(url);
- }
- }).setCancelable(false).create().show();
- }
-
- private void setBoardFragmentViewMode() {
- if (ChanSettings.getBoardViewMode().equals("list")) {
- boardFragment.setViewMode(ThreadManager.ViewMode.LIST);
- } else if (ChanSettings.getBoardViewMode().equals("grid")) {
- boardFragment.setViewMode(ThreadManager.ViewMode.GRID);
- }
- }
-
- private class BoardSpinnerAdapter extends BaseAdapter {
- private Context context;
- private Spinner spinner;
- private List boards;
- private int lastSelectedPosition = 0;
-
- public BoardSpinnerAdapter(Context context, Spinner spinner) {
- this.context = context;
- this.spinner = spinner;
- setBoards();
- }
-
- public void setBoards() {
- boards = ChanApplication.getBoardManager().getSavedBoards();
- }
-
- public void setBoard(String boardValue) {
- for (int i = 0; i < boards.size(); i++) {
- if (boards.get(i).value.equals(boardValue)) {
- spinner.setSelection(i);
- return;
- }
- }
- }
-
- public void onItemSelected(int position) {
- if (position >= 0 && position < boards.size()) {
- Loadable board = new Loadable(boards.get(position).value);
-
- // onItemSelected is called after the view initializes,
- // ignore if it's the same board
- if (boardLoadable.equals(board))
- return;
-
- startLoadingBoard(board);
-
- lastSelectedPosition = position;
- } else {
- startActivity(new Intent(context, BoardEditor.class));
- spinner.setSelection(lastSelectedPosition);
- }
- }
-
- @Override
- public int getCount() {
- return boards.size() + 1;
- }
-
- @Override
- public long getItemId(final int position) {
- return position;
- }
-
- @Override
- public String getItem(final int position) {
- if (position == getCount() - 1) {
- return context.getString(R.string.board_select_add);
- } else {
- return boards.get(position).key;
- }
- }
-
- @Override
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return createView(position, convertView, parent, true);
- }
-
- @Override
- public View getView(final int position, View convertView, final ViewGroup parent) {
- return createView(position, convertView, parent, false);
- }
-
- private View createView(int position, View convertView, ViewGroup parent, boolean dropDown) {
- if (position == getCount() - 1) {
- TextView textView = (TextView) LayoutInflater.from(context).inflate(R.layout.board_select_add, parent, false);
- textView.setText(getItem(position));
- return textView;
- } else {
- TextView textView = (TextView) LayoutInflater.from(context).inflate(
- dropDown ? R.layout.board_select_spinner_dropdown : R.layout.board_select_spinner, parent, false);
- textView.setText(getItem(position));
- return textView;
- }
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/DeveloperActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/DeveloperActivity.java
deleted file mode 100644
index 39d6c15d..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/DeveloperActivity.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.os.Bundle;
-import android.view.View;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.core.model.SavedReply;
-import org.floens.chan.ui.ThemeActivity;
-
-import java.util.Random;
-
-public class DeveloperActivity extends ThemeActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.toolbar_activity);
- setToolbar();
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- LinearLayout wrapper = new LinearLayout(this);
- wrapper.setOrientation(LinearLayout.VERTICAL);
-
- Button crashButton = new Button(this);
-
- crashButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- @SuppressWarnings({"unused", "NumericOverflow"})
- int i = 1 / 0;
- }
- });
- crashButton.setText("Crash the app");
-
- wrapper.addView(crashButton);
-
- String dbSummary = "";
-
- dbSummary += "Database summary:\n";
- dbSummary += ChanApplication.getDatabaseManager().getSummary();
-
- TextView db = new TextView(this);
- db.setPadding(0, 25, 0, 0);
- db.setText(dbSummary);
- wrapper.addView(db);
-
- Button resetDbButton = new Button(this);
- resetDbButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ChanApplication.getDatabaseManager().reset();
- System.exit(0);
- }
- });
- resetDbButton.setText("Delete database");
- wrapper.addView(resetDbButton);
-
- Button savedReplyDummyAdd = new Button(this);
- savedReplyDummyAdd.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(final View v) {
- Random r = new Random();
- int j = 0;
- for (int i = 0; i < 100; i++) {
- j += r.nextInt(10000);
- ChanApplication.getDatabaseManager().saveReply(new SavedReply("g", j, "pass"));
- }
- recreate();
- }
- });
- savedReplyDummyAdd.setText("Add test rows to savedReply");
- wrapper.addView(savedReplyDummyAdd);
-
- Button trimSavedReply = new Button(this);
- trimSavedReply.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(final View v) {
- ChanApplication.getDatabaseManager().trimSavedRepliesTable(10);
- recreate();
- }
- });
- trimSavedReply.setText("Trim savedreply table");
- wrapper.addView(trimSavedReply);
-
- setContentView(wrapper);
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java
index e99e01f5..055eaf1a 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java
@@ -25,7 +25,7 @@ import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.core.reply.ReplyManager;
import org.floens.chan.utils.IOUtils;
import org.floens.chan.utils.Logger;
@@ -53,7 +53,7 @@ public class ImagePickActivity extends Activity implements Runnable {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- replyManager = ChanApplication.getReplyManager();
+ replyManager = Chan.getReplyManager();
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/ImageViewActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/ImageViewActivity.java
deleted file mode 100644
index c8d9202c..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/ImageViewActivity.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.view.ViewPager;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.SubMenu;
-import android.view.View;
-import android.widget.ProgressBar;
-
-import org.floens.chan.R;
-import org.floens.chan.chan.ImageSearch;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.core.manager.ThreadManager;
-import org.floens.chan.core.model.Post;
-import org.floens.chan.ui.ThemeActivity;
-import org.floens.chan.ui.adapter.ImageViewAdapter;
-import org.floens.chan.ui.adapter.PostAdapter;
-import org.floens.chan.ui.fragment.ImageViewFragment;
-import org.floens.chan.utils.ImageSaver;
-import org.floens.chan.utils.Logger;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * An fragment pager that contains images. Call setPosts first, and then start
- * the activity with startActivity()
- */
-public class ImageViewActivity extends ThemeActivity implements ViewPager.OnPageChangeListener {
- private static final String TAG = "ImageViewActivity";
-
- private static PostAdapter postAdapterStatic;
- private static int selectedNoStatic = -1;
- private static ThreadManager threadManagerStatic;
-
- private PostAdapter postAdapter;
- private ThreadManager threadManager;
- private int selectedNo;
-
- private ImageViewAdapter adapter;
- private ViewPager viewPager;
- private ProgressBar progressBar;
- private int currentPosition;
-
- /**
- * Set the posts to show
- *
- * @param adapter the adapter to get image data from
- * @param selected the no that the user clicked on
- */
- public static void launch(Activity activity, PostAdapter adapter, int selected, ThreadManager threadManager) {
- postAdapterStatic = adapter;
- selectedNoStatic = selected;
- threadManagerStatic = threadManager;
-
- Intent intent = new Intent(activity, ImageViewActivity.class);
- activity.startActivity(intent);
- activity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- if (postAdapterStatic == null || threadManagerStatic == null) {
- Logger.e(TAG, "postadapter or threadmanager null");
- finish();
- return;
- }
-
- super.onCreate(savedInstanceState);
-
- threadManager = threadManagerStatic;
- threadManagerStatic = null;
- postAdapter = postAdapterStatic;
- postAdapterStatic = null;
- selectedNo = selectedNoStatic;
- selectedNoStatic = -1;
-
- setContentView(R.layout.image_view);
- setToolbar();
-
- initProgressBar();
- initPager();
- }
-
- private void initProgressBar() {
- progressBar = (ProgressBar) findViewById(R.id.progress_bar);
-// progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.progressbar_no_bg));
- progressBar.setIndeterminate(false);
- progressBar.setMax(1000000);
- }
-
- private void initPager() {
- // Get the posts with images
- ArrayList imagePosts = new ArrayList<>();
-// for (Post post : postAdapter.getList()) {
-// if (post.hasImage) {
-// imagePosts.add(post);
-// }
-// }
-
- // Setup our pages and adapter
- viewPager = (ViewPager) findViewById(R.id.image_pager);
- adapter = new ImageViewAdapter(getFragmentManager(), this);
- adapter.setList(imagePosts);
- viewPager.setAdapter(adapter);
- viewPager.setOnPageChangeListener(this);
-
- // Select the right image
- for (int i = 0; i < imagePosts.size(); i++) {
- if (imagePosts.get(i).no == selectedNo) {
- viewPager.setCurrentItem(i);
- onPageSelected(i);
- break;
- }
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
-
- // Avoid things like out of sync, since this is an activity.
- finish();
- }
-
- @Override
- public void finish() {
- super.finish();
- overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
- }
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- }
-
- @Override
- public void onPageSelected(int position) {
- currentPosition = position;
-
- for (int i = -1; i <= 1; i++) {
- ImageViewFragment fragment = getFragment(position + i);
- if (fragment != null) {
- fragment.onDeselected();
- }
- }
-
- ImageViewFragment fragment = getFragment(currentPosition);
- if (fragment != null) {
- fragment.onSelected(adapter, position);
- }
-
- Post post = adapter.getPost(position);
- if (!threadManager.arePostRepliesOpen()) {
-// postAdapter.scrollToPost(post.no); //TODO
- }
- }
-
- public void invalidateActionBar() {
- invalidateOptionsMenu();
- }
-
- public void updateActionBarIfSelected(ImageViewFragment targetFragment) {
- ImageViewFragment fragment = getFragment(currentPosition);
- if (fragment != null && fragment == targetFragment) {
- fragment.onSelected(adapter, currentPosition);
- }
- }
-
- public void setProgressBar(long current, long total, boolean done) {
- if (done) {
- progressBar.setVisibility(View.GONE);
- } else {
- progressBar.setVisibility(View.VISIBLE);
- progressBar.setProgress((int) (((double) current / total) * progressBar.getMax()));
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- finish();
- return true;
- case R.id.action_download_album:
- if (adapter.getList().size() > 0) {
- List list = new ArrayList<>();
-
- String folderName = Post.generateTitle(adapter.getList().get(0), 10);
-
- String filename;
- for (Post post : adapter.getList()) {
- filename = (ChanSettings.getImageSaveOriginalFilename() ? post.tim : post.filename) + "." + post.ext;
- list.add(new ImageSaver.DownloadPair(post.imageUrl, filename));
- }
-
- ImageSaver.getInstance().saveAll(this, folderName, list);
- }
-
- return true;
- default:
- ImageViewFragment fragment = getFragment(currentPosition);
- if (fragment != null) {
- fragment.customOnOptionsItemSelected(item);
- }
-
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.image_view, menu);
-
- MenuItem imageSearch = menu.findItem(R.id.action_image_search);
- SubMenu subMenu = imageSearch.getSubMenu();
- for (ImageSearch engine : ImageSearch.engines) {
- subMenu.add(Menu.NONE, engine.getId(), Menu.NONE, engine.getName());
- }
-
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- ImageViewFragment fragment = getFragment(currentPosition);
- if (fragment != null) {
- fragment.onPrepareOptionsMenu(menu);
- }
-
- return super.onPrepareOptionsMenu(menu);
- }
-
- private ImageViewFragment getFragment(int i) {
- if (adapter == null) {
- return null;
- } else if (i >= 0 && i < adapter.getCount()) {
- Object o = adapter.instantiateItem(viewPager, i);
- if (o instanceof ImageViewFragment) {
- return (ImageViewFragment) o;
- } else {
- return null;
- }
- } else {
- return null;
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/LicenseActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/LicenseActivity.java
deleted file mode 100644
index f427a29f..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/LicenseActivity.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.webkit.WebView;
-
-import org.floens.chan.utils.ThemeHelper;
-
-public class LicenseActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- ThemeHelper.setTheme(this);
-
- WebView webView = new WebView(this);
- webView.loadUrl("file:///android_asset/html/license.html");
-
- setContentView(webView);
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/PassSettingsActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/PassSettingsActivity.java
deleted file mode 100644
index a1770d0b..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/PassSettingsActivity.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.app.AlertDialog;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.app.ProgressDialog;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
-import android.support.v7.widget.SwitchCompat;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.TextView;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.core.reply.ReplyManager;
-import org.floens.chan.core.reply.ReplyManager.PassResponse;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.ui.ThemeActivity;
-import org.floens.chan.utils.AndroidUtils;
-
-public class PassSettingsActivity extends ThemeActivity implements OnCheckedChangeListener {
- private SwitchCompat onSwitch;
- private TextView toggleStatus;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.header_switch_layout);
- setToolbar();
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- findViewById(R.id.toggle_bar).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- onSwitch.toggle();
- }
- });
-
- toggleStatus = (TextView) findViewById(R.id.toggle_status);
- onSwitch = (SwitchCompat) findViewById(R.id.toggle);
- onSwitch.setOnCheckedChangeListener(this);
- setSwitch(ChanSettings.getPassEnabled());
-
- setFragment(ChanSettings.getPassEnabled());
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- if (TextUtils.isEmpty(ChanSettings.getPassId())) {
- ChanSettings.setPassEnabled(false);
- setSwitch(false);
- }
- }
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- setFragment(isChecked);
- setSwitch(isChecked);
- }
-
- private void setSwitch(boolean enabled) {
- onSwitch.setChecked(enabled);
- toggleStatus.setText(enabled ? R.string.on : R.string.off);
-
- ChanSettings.setPassEnabled(enabled);
- }
-
- private void setFragment(boolean enabled) {
- if (enabled) {
- FragmentTransaction t = getFragmentManager().beginTransaction();
- t.replace(R.id.content, new PassSettingsFragment());
- t.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
- t.commit();
- } else {
- FragmentTransaction t = getFragmentManager().beginTransaction();
- t.replace(R.id.content, new TextFragment());
- t.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
- t.commit();
- }
- }
-
- public static class TextFragment extends Fragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle savedInstanceState) {
- View container = inflater.inflate(R.layout.preference_pass, null);
-
- TextView link = (TextView) container.findViewById(R.id.pass_link);
- link.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- AndroidUtils.openLink(v.getContext().getString(R.string.pass_info_link));
- }
- });
-
- return container;
- }
- }
-
- public static class PassSettingsFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preference_pass);
-
- Preference login = findPreference("preference_pass_login");
- login.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- onLoginClick(ChanSettings.getPassToken(), ChanSettings.getPassPin());
- return true;
- }
- });
-
- updateLoginButton();
- }
-
- private void updateLoginButton() {
- findPreference("preference_pass_login").setTitle(TextUtils.isEmpty(ChanSettings.getPassId()) ? R.string.pass_login : R.string.pass_logout);
- }
-
- private void onLoginClick(String token, String pin) {
- if (TextUtils.isEmpty(ChanSettings.getPassId())) {
- // Login
- final ProgressDialog dialog = ProgressDialog.show(getActivity(), null, "Logging in");
-
- ChanApplication.getReplyManager().postPass(token, pin, new ReplyManager.PassListener() {
- @Override
- public void onResponse(PassResponse response) {
- dialog.dismiss();
-
- if (getActivity() == null)
- return;
-
- if (response.unknownError) {
- WebView webView = new WebView(getActivity());
- WebSettings settings = webView.getSettings();
- settings.setSupportZoom(true);
-
- webView.loadData(response.responseData, "text/html", null);
-
- new AlertDialog.Builder(getActivity()).setView(webView).setNeutralButton(R.string.ok, null).show();
- } else {
- new AlertDialog.Builder(getActivity()).setMessage(response.message)
- .setNeutralButton(R.string.ok, null).show();
- ChanSettings.setPassId(response.passId);
- }
-
- updateLoginButton();
- }
- });
- } else {
- // Logout
- ChanSettings.setPassId("");
- updateLoginButton();
- }
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/ReplyActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/ReplyActivity.java
deleted file mode 100644
index 04d43ecf..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/ReplyActivity.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.os.Bundle;
-import android.view.MenuItem;
-
-import org.floens.chan.R;
-import org.floens.chan.core.model.Loadable;
-import org.floens.chan.ui.ThemeActivity;
-import org.floens.chan.ui.fragment.ReplyFragment;
-import org.floens.chan.utils.Logger;
-
-public class ReplyActivity extends ThemeActivity {
- private static final String TAG = "ReplyActivity";
-
- private static Loadable staticLoadable;
-
- public static void setLoadable(Loadable l) {
- staticLoadable = l;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Loadable loadable = staticLoadable;
- staticLoadable = null;
-
- if (loadable != null && savedInstanceState == null) {
- setTheme();
- setContentView(R.layout.toolbar_activity);
- setToolbar();
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- FragmentTransaction ft = getFragmentManager().beginTransaction();
- ft.replace(R.id.content, ReplyFragment.newInstance(loadable, false), "reply");
- ft.commitAllowingStateLoss();
- } else if (savedInstanceState == null) {
- Logger.e(TAG, "Loadable was null, exiting!");
- finish();
- }
- }
-
- @Override
- public void onBackPressed() {
- Fragment f = getFragmentManager().findFragmentByTag("reply");
- if (f != null && ((ReplyFragment) f).onBackPressed()) {
- super.onBackPressed();
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- finish();
-
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/SettingsActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/SettingsActivity.java
deleted file mode 100644
index 8dd80be0..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/SettingsActivity.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import org.floens.chan.R;
-import org.floens.chan.ui.ThemeActivity;
-import org.floens.chan.ui.fragment.SettingsFragment;
-import org.floens.chan.utils.ThemeHelper;
-
-public class SettingsActivity extends ThemeActivity {
- private static boolean doingThemeRestart = false;
- private static ThemeHelper.Theme lastTheme;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.toolbar_activity);
- setToolbar();
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- if (!doingThemeRestart) {
- lastTheme = ThemeHelper.getInstance().getTheme();
- }
-
- SettingsFragment frag = new SettingsFragment();
- frag.setArguments(getIntent().getExtras());
- getFragmentManager().beginTransaction().replace(R.id.content, frag).commit();
- }
-
- public void restart(Intent intent) {
- doingThemeRestart = true;
- startActivity(intent);
- finish();
- doingThemeRestart = false;
- overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- if (ThemeHelper.getInstance().getTheme() != lastTheme) {
- lastTheme = ThemeHelper.getInstance().getTheme();
-
- BaseActivity.doRestartOnResume = true;
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(final Menu menu) {
- getMenuInflater().inflate(R.menu.settings, menu);
-
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- if (item.getItemId() == R.id.action_settings_advanced) {
- startActivity(new Intent(this, AdvancedSettingsActivity.class));
- return true;
- } else if (item.getItemId() == android.R.id.home) {
- finish();
- return true;
- } else {
- return super.onOptionsItemSelected(item);
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java
index a2013473..41789331 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.activity;
import android.app.AlertDialog;
@@ -7,7 +24,7 @@ import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.ViewGroup;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.core.settings.ChanSettings;
@@ -103,21 +120,21 @@ public class StartActivity extends AppCompatActivity {
protected void onStart() {
super.onStart();
- ChanApplication.getInstance().activityEnteredForeground();
+ Chan.getInstance().activityEnteredForeground();
}
@Override
protected void onStop() {
super.onStop();
- ChanApplication.getInstance().activityEnteredBackground();
+ Chan.getInstance().activityEnteredBackground();
}
@Override
protected void onPause() {
super.onPause();
- ChanApplication.getWatchManager().updateDatabase();
+ Chan.getWatchManager().updateDatabase();
}
private Controller stackTop() {
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/WatchSettingsActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/WatchSettingsActivity.java
deleted file mode 100644
index 591e889b..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/WatchSettingsActivity.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.activity;
-
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.os.Bundle;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.PreferenceFragment;
-import android.support.v7.widget.SwitchCompat;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.TextView;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.ui.ThemeActivity;
-
-public class WatchSettingsActivity extends ThemeActivity implements OnCheckedChangeListener {
- private SwitchCompat watchSwitch;
- private TextView toggleStatus;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.header_switch_layout);
- setToolbar();
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- findViewById(R.id.toggle_bar).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- watchSwitch.toggle();
- }
- });
-
- toggleStatus = (TextView) findViewById(R.id.toggle_status);
- watchSwitch = (SwitchCompat) findViewById(R.id.toggle);
- watchSwitch.setOnCheckedChangeListener(this);
- setSwitch(ChanSettings.getWatchEnabled());
-
- setFragment(ChanSettings.getWatchEnabled());
- }
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- setFragment(isChecked);
- setSwitch(isChecked);
- }
-
- private void setSwitch(boolean enabled) {
- watchSwitch.setChecked(enabled);
- toggleStatus.setText(enabled ? R.string.on : R.string.off);
-
- ChanSettings.setWatchEnabled(enabled);
- }
-
- private void setFragment(boolean enabled) {
- FragmentTransaction t = getFragmentManager().beginTransaction();
- if (enabled) {
- t.replace(R.id.content, new WatchSettingsFragment());
- } else {
- t.replace(R.id.content, TextFragment.newInstance(R.string.watch_info_text));
- }
- t.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
- t.commit();
- }
-
- public static class TextFragment extends Fragment {
- public static TextFragment newInstance(int textResource) {
- TextFragment f = new TextFragment();
- Bundle bundle = new Bundle();
- bundle.putInt("text_resource", textResource);
- f.setArguments(bundle);
- return f;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle savedInstanceState) {
- ViewGroup container = (ViewGroup) inflater.inflate(R.layout.watch_description, null);
-
- TextView text = (TextView) container.findViewById(R.id.text);
- text.setText(getArguments().getInt("text_resource"));
-
- return container;
- }
- }
-
- public static class WatchSettingsFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preference_watch);
-
- final ListPreference backgroundTimeout = (ListPreference) findPreference("preference_watch_background_timeout");
- String currentValue = backgroundTimeout.getValue();
- if (currentValue == null) {
- backgroundTimeout.setValue((String) backgroundTimeout.getEntryValues()[0]);
- currentValue = backgroundTimeout.getValue();
- }
- updateListSummary(backgroundTimeout, currentValue);
-
- backgroundTimeout.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- updateListSummary(backgroundTimeout, newValue.toString());
- return true;
- }
- });
-
- final ListPreference notifyMode = (ListPreference) findPreference("preference_watch_notify_mode");
- String currentNotifyMode = notifyMode.getValue();
- if (currentNotifyMode == null) {
- notifyMode.setValue((String) notifyMode.getEntryValues()[0]);
- currentNotifyMode = notifyMode.getValue();
- }
- updateListSummary(notifyMode, currentNotifyMode);
-
- notifyMode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- updateListSummary(notifyMode, newValue.toString());
- return true;
- }
- });
-
- final ListPreference sound = (ListPreference) findPreference("preference_watch_sound");
- String currentSound = sound.getValue();
- if (currentSound == null) {
- sound.setValue((String) sound.getEntryValues()[0]);
- currentSound = sound.getValue();
- }
- updateListSummary(sound, currentSound);
-
- sound.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- updateListSummary(sound, newValue.toString());
- return true;
- }
- });
-
- final ListPreference led = (ListPreference) findPreference("preference_watch_led");
- String currentLed = led.getValue();
- if (currentLed == null) {
- led.setValue((String) led.getEntryValues()[0]);
- currentLed = led.getValue();
- }
- updateListSummary(led, currentLed);
-
- led.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- updateListSummary(led, newValue.toString());
- return true;
- }
- });
-
- findPreference("preference_watch_background_enabled").setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(final Preference preference, final Object newValue) {
- ChanApplication.getWatchManager().onBackgroundWatchingChanged((Boolean) newValue);
-
- return true;
- }
- });
- }
-
- private void updateListSummary(ListPreference backgroundTimeout, String value) {
- int index = backgroundTimeout.findIndexOfValue(value);
- backgroundTimeout.setSummary(backgroundTimeout.getEntries()[index]);
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewAdapter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewAdapter.java
deleted file mode 100644
index 09f90d44..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewAdapter.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.adapter;
-
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.support.v13.app.FragmentStatePagerAdapter;
-
-import org.floens.chan.core.model.Post;
-import org.floens.chan.ui.activity.ImageViewActivity;
-import org.floens.chan.ui.fragment.ImageViewFragment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ImageViewAdapter extends FragmentStatePagerAdapter {
- private final ImageViewActivity activity;
- private final ArrayList postList = new ArrayList<>();
-
- public ImageViewAdapter(FragmentManager fragmentManager, ImageViewActivity activity) {
- super(fragmentManager);
- this.activity = activity;
- }
-
- @Override
- public int getCount() {
- return postList.size();
- }
-
- @Override
- public Fragment getItem(int position) {
- return ImageViewFragment.newInstance(postList.get(position), activity, position);
- }
-
- public Post getPost(int position) {
- if (position < 0 || position >= getCount())
- return null;
-
- return postList.get(position);
- }
-
- public void setList(ArrayList list) {
- postList.clear();
- postList.addAll(list);
-
- notifyDataSetChanged();
- }
-
- public List getList() {
- return postList;
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewerAdapter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewerAdapter.java
index 66e314bc..5fb6f653 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewerAdapter.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/adapter/ImageViewerAdapter.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.adapter;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java
index ab20dde1..9c4e56e0 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java
@@ -1,6 +1,22 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.adapter;
-import android.os.Build;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@@ -8,7 +24,7 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.core.model.Pin;
import org.floens.chan.core.settings.ChanSettings;
@@ -21,7 +37,7 @@ import java.util.List;
import static org.floens.chan.utils.AndroidUtils.ROBOTO_MEDIUM;
import static org.floens.chan.utils.AndroidUtils.dp;
-import static org.floens.chan.utils.AndroidUtils.getAttrDrawable;
+import static org.floens.chan.utils.AndroidUtils.setRoundItemBackground;
public class PinAdapter extends RecyclerView.Adapter implements SwipeListener.Callback {
private static final int PIN_OFFSET = 3;
@@ -156,7 +172,7 @@ public class PinAdapter extends RecyclerView.Adapter im
@Override
public void removeItem(int position) {
- ChanApplication.getWatchManager().removePin(pins.get(position - PIN_OFFSET));
+ Chan.getWatchManager().removePin(pins.get(position - PIN_OFFSET));
}
@Override
@@ -240,11 +256,7 @@ public class PinAdapter extends RecyclerView.Adapter im
watchCountText = (TextView) itemView.findViewById(R.id.watch_count);
watchCountText.setTypeface(ROBOTO_MEDIUM);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- watchCountText.setBackground(getAttrDrawable(itemView.getContext(), android.R.attr.selectableItemBackgroundBorderless));
- } else {
- watchCountText.setBackgroundResource(R.drawable.item_background);
- }
+ setRoundItemBackground(watchCountText);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
@@ -271,11 +283,7 @@ public class PinAdapter extends RecyclerView.Adapter im
text = (TextView) itemView.findViewById(R.id.text);
text.setTypeface(ROBOTO_MEDIUM);
image = (ImageView) itemView.findViewById(R.id.image);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- image.setBackground(getAttrDrawable(itemView.getContext(), android.R.attr.selectableItemBackgroundBorderless));
- } else {
- image.setBackgroundResource(R.drawable.item_background);
- }
+ setRoundItemBackground(image);
image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java
deleted file mode 100644
index ad464dd1..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.adapter;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.core.model.Pin;
-import org.floens.chan.ui.view.CustomNetworkImageView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.floens.chan.utils.AndroidUtils.dp;
-
-public class PinnedAdapter extends BaseAdapter {
- private final static int VIEW_TYPE_ITEM = 0;
- private final static int VIEW_TYPE_HEADER = 1;
-
- private Context context;
- private ListView listView;
- private List pins = new ArrayList<>();
- private boolean postInvalidated = false;
-
- public PinnedAdapter(Context context, ListView listView) {
- this.context = context;
- this.listView = listView;
- }
-
- @Override
- public int getCount() {
- return pins.size() + 1;
- }
-
- @Override
- public int getViewTypeCount() {
- return 2;
- }
-
- @Override
- public int getItemViewType(final int position) {
- return position == 0 ? VIEW_TYPE_HEADER : VIEW_TYPE_ITEM;
- }
-
- @Override
- public Pin getItem(final int position) {
- switch (getItemViewType(position)) {
- case VIEW_TYPE_ITEM:
- int itemPosition = position - 1;
- if (itemPosition >= 0 && itemPosition < pins.size()) {
- return pins.get(itemPosition);
- } else {
- return null;
- }
- case VIEW_TYPE_HEADER:
- return null;
- default:
- return null;
- }
- }
-
- @Override
- public long getItemId(int position) {
- switch (getItemViewType(position)) {
- case VIEW_TYPE_ITEM:
- int itemPosition = position - 1;
- if (itemPosition >= 0 && itemPosition < pins.size()) {
- return pins.get(itemPosition).id;
- } else {
- return -1;
- }
- case VIEW_TYPE_HEADER:
- return -1;
- default:
- return -1;
- }
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- switch (getItemViewType(position)) {
- case VIEW_TYPE_ITEM: {
- final Pin pin = getItem(position);
-
- if (convertView == null) {
- convertView = LayoutInflater.from(context).inflate(R.layout.pin_item, null);
- }
-
- CustomNetworkImageView imageView = (CustomNetworkImageView) convertView.findViewById(R.id.image);
- if (pin.thumbnailUrl != null) {
- imageView.setVisibility(View.VISIBLE);
- imageView.setFadeIn(0);
- imageView.forceImageDimensions(dp(48), dp(48));
- imageView.setImageUrl(pin.thumbnailUrl, ChanApplication.getVolleyImageLoader());
- } else {
- imageView.setVisibility(View.GONE);
- }
-
- ((TextView) convertView.findViewById(R.id.text)).setText(pin.loadable.title);
-
- FrameLayout timeContainer = (FrameLayout) convertView.findViewById(R.id.time_container);
- FrameLayout countContainer = (FrameLayout) convertView.findViewById(R.id.pin_count_container);
- if (ChanSettings.getWatchEnabled()) {
- countContainer.setVisibility(View.VISIBLE);
-
- TextView timeView = (TextView) convertView.findViewById(R.id.time);
- if (pin.watching && pin.getPinWatcher() != null && ChanSettings.getWatchCountdownVisibleEnabled()) {
- timeContainer.setVisibility(View.VISIBLE);
- long timeRaw = pin.getPinWatcher().getTimeUntilNextLoad();
- long time = 0;
- if (timeRaw > 0) {
- time = timeRaw / 1000L;
- time = Math.min(9999, time);
- }
-
- timeView.setText(Long.toString(time));
-
- postInvalidate();
- } else {
- timeContainer.setVisibility(View.GONE);
- }
-
- TextView countView = (TextView) convertView.findViewById(R.id.pin_count);
- ProgressBar loadView = (ProgressBar) convertView.findViewById(R.id.pin_load);
-
- if (pin.isError) {
- countView.setText("Err");
- } else {
- int count = pin.getNewPostCount();
- String total = Integer.toString(count);
- if (count > 999) {
- total = "1k+";
- }
- countView.setText(total);
- }
-
- if (pin.getPinWatcher() != null && pin.getPinWatcher().isLoading()) {
- countView.setVisibility(View.GONE);
- loadView.setVisibility(View.VISIBLE);
- } else {
- loadView.setVisibility(View.GONE);
- countView.setVisibility(View.VISIBLE);
- }
-
- countContainer.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
-// pin.toggleWatch();
- }
- });
-
- if (!pin.watching) {
- countContainer.setBackgroundResource(R.drawable.pin_icon_gray);
- } else if (pin.getNewQuoteCount() > 0) {
- countContainer.setBackgroundResource(R.drawable.pin_icon_red);
- } else {
- countContainer.setBackgroundResource(R.drawable.pin_icon_blue);
- }
- } else {
- timeContainer.setVisibility(View.GONE);
- countContainer.setVisibility(View.GONE);
- }
-
- return convertView;
- }
- case VIEW_TYPE_HEADER: {
- if (convertView == null) {
- convertView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.pin_item_header, null);
- ((TextView) convertView.findViewById(R.id.pin_header)).setText(R.string.drawer_pinned);
- }
-
- return convertView;
- }
- default:
- return null;
- }
- }
-
- public void reload() {
- pins.clear();
- pins.addAll(ChanApplication.getWatchManager().getPins());
-
- notifyDataSetChanged();
- }
-
- private void postInvalidate() {
- if (!postInvalidated) {
- postInvalidated = true;
- new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
- @Override
- public void run() {
- postInvalidated = false;
- listView.invalidateViews();
- }
- }, 1000);
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/animation/ScrollerRunnable.java b/Clover/app/src/main/java/org/floens/chan/ui/animation/ScrollerRunnable.java
deleted file mode 100644
index 3e984f6e..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/animation/ScrollerRunnable.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.animation;
-
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.widget.AbsListView;
-import android.widget.ListView;
-
-public class ScrollerRunnable implements Runnable {
- private static final int SCROLL_DURATION = 300;
-
- private static final int MOVE_DOWN_POS = 1;
- private static final int MOVE_UP_POS = 2;
-
- private final AbsListView mList;
-
- private int mMode;
- private int mTargetPos;
- private int mLastSeenPos;
- private int mScrollDuration;
- private final int mExtraScroll;
-
- public ScrollerRunnable(AbsListView listView) {
- mList = listView;
- mExtraScroll = ViewConfiguration.get(mList.getContext()).getScaledFadingEdgeLength();
- }
-
- public void start(int position) {
- stop();
-
- final int firstPos = mList.getFirstVisiblePosition();
- final int lastPos = firstPos + mList.getChildCount() - 1;
-
- int viewTravelCount;
- if (position <= firstPos) {
- viewTravelCount = firstPos - position + 1;
- mMode = MOVE_UP_POS;
- } else if (position >= lastPos) {
- viewTravelCount = position - lastPos + 1;
- mMode = MOVE_DOWN_POS;
- } else {
- // Already on screen, nothing to do
- return;
- }
-
- if (viewTravelCount > 0) {
- mScrollDuration = SCROLL_DURATION / viewTravelCount;
- } else {
- mScrollDuration = SCROLL_DURATION;
- }
- mTargetPos = position;
- mLastSeenPos = ListView.INVALID_POSITION;
-
- mList.post(this);
- }
-
- void stop() {
- mList.removeCallbacks(this);
- }
-
- @Override
- public void run() {
- final int listHeight = mList.getHeight();
- final int firstPos = mList.getFirstVisiblePosition();
-
- switch (mMode) {
- case MOVE_DOWN_POS: {
- final int lastViewIndex = mList.getChildCount() - 1;
- final int lastPos = firstPos + lastViewIndex;
-
- if (lastViewIndex < 0) {
- return;
- }
-
- if (lastPos == mLastSeenPos) {
- // No new views, let things keep going.
- mList.post(this);
- return;
- }
-
- final View lastView = mList.getChildAt(lastViewIndex);
- final int lastViewHeight = lastView.getHeight();
- final int lastViewTop = lastView.getTop();
- final int lastViewPixelsShowing = listHeight - lastViewTop;
- final int extraScroll = lastPos < mList.getCount() - 1 ? mExtraScroll : mList.getPaddingBottom();
-
- mList.smoothScrollBy(lastViewHeight - lastViewPixelsShowing + extraScroll, mScrollDuration);
-
- mLastSeenPos = lastPos;
- if (lastPos < mTargetPos) {
- mList.post(this);
- }
- break;
- }
-
- case MOVE_UP_POS: {
- if (firstPos == mLastSeenPos) {
- // No new views, let things keep going.
- mList.post(this);
- return;
- }
-
- final View firstView = mList.getChildAt(0);
- if (firstView == null) {
- return;
- }
- final int firstViewTop = firstView.getTop();
- final int extraScroll = firstPos > 0 ? mExtraScroll : mList.getPaddingTop();
-
- mList.smoothScrollBy(firstViewTop - extraScroll, mScrollDuration);
-
- mLastSeenPos = firstPos;
-
- if (firstPos > mTargetPos) {
- mList.post(this);
- }
- break;
- }
-
- default:
- break;
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/animation/SwipeDismissListViewTouchListener.java b/Clover/app/src/main/java/org/floens/chan/ui/animation/SwipeDismissListViewTouchListener.java
deleted file mode 100644
index 367d1e1f..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/animation/SwipeDismissListViewTouchListener.java
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.floens.chan.ui.animation;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.graphics.Rect;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.ListView;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A {@link android.view.View.OnTouchListener} that makes the list items in a
- * {@link ListView} dismissable. {@link ListView} is given special treatment
- * because by default it handles touches for its list items... i.e. it's in
- * charge of drawing the pressed state (the list selector), handling list item
- * clicks, etc.
- *
- *
- * After creating the listener, the caller should also call
- * {@link ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)}
- * , passing in the scroll listener returned by {@link #makeScrollListener()}.
- * If a scroll listener is already assigned, the caller should still pass scroll
- * changes through to this listener. This will ensure that this
- * {@link SwipeDismissListViewTouchListener} is paused during list view
- * scrolling.
- *
- *
- *
- * Example usage:
- *
- *
- *
- * SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(listView,
- * new SwipeDismissListViewTouchListener.OnDismissCallback() {
- * public void onDismiss(ListView listView, int[] reverseSortedPositions) {
- * for (int position : reverseSortedPositions) {
- * adapter.remove(adapter.getItem(position));
- * }
- * adapter.notifyDataSetChanged();
- * }
- * });
- * listView.setOnTouchListener(touchListener);
- * listView.setOnScrollListener(touchListener.makeScrollListener());
- *
- *
- *
- * This class Requires API level 12 or later due to use of
- * {@link android.view.ViewPropertyAnimator}.
- *
- */
-public class SwipeDismissListViewTouchListener implements View.OnTouchListener {
- // Cached ViewConfiguration and system-wide constant values
- private int mSlop;
- private final int mMinFlingVelocity;
- private final int mMaxFlingVelocity;
- private final long mAnimationTime;
-
- // Fixed properties
- private final ListView mListView;
- private final DismissCallbacks mCallbacks;
- private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
-
- // Transient properties
- private final List mPendingDismisses = new ArrayList<>();
- private int mDismissAnimationRefCount = 0;
- private float mDownX;
- private boolean mSwiping;
- private VelocityTracker mVelocityTracker;
- private int mDownPosition;
- private View mDownView;
- private boolean mPaused;
-
- /**
- * The callback interface used by {@link SwipeDismissListViewTouchListener}
- * to inform its client about a successful dismissal of one or more list
- * item positions.
- */
- public interface DismissCallbacks {
- /**
- * Called to determine whether the given position can be dismissed.
- */
- boolean canDismiss(int position);
-
- /**
- * Called when the user has indicated they she would like to dismiss one
- * or more list item positions.
- *
- * @param listView The originating {@link ListView}.
- * @param reverseSortedPositions An array of positions to dismiss, sorted in descending
- * order for convenience.
- */
- void onDismiss(ListView listView, int[] reverseSortedPositions);
- }
-
- /**
- * Constructs a new swipe-to-dismiss touch listener for the given list view.
- *
- * @param listView The list view whose items should be dismissable.
- * @param callbacks The callback to trigger when the user has indicated that she
- * would like to dismiss one or more list items.
- */
- public SwipeDismissListViewTouchListener(ListView listView, DismissCallbacks callbacks) {
- ViewConfiguration vc = ViewConfiguration.get(listView.getContext());
- mSlop = vc.getScaledTouchSlop();
- mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * 16;
- mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
- mAnimationTime = listView.getContext().getResources().getInteger(android.R.integer.config_shortAnimTime);
- mListView = listView;
- mCallbacks = callbacks;
- }
-
- public int getSlop() {
- return mSlop;
- }
-
- public void setSlop(int slop) {
- mSlop = slop;
- }
-
- /**
- * Enables or disables (pauses or resumes) watching for swipe-to-dismiss
- * gestures.
- *
- * @param enabled Whether or not to watch for gestures.
- */
- public void setEnabled(boolean enabled) {
- mPaused = !enabled;
- }
-
- /**
- * Returns an {@link android.widget.AbsListView.OnScrollListener} to be
- * added to the {@link ListView} using
- * {@link ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)}
- * . If a scroll listener is already assigned, the caller should still pass
- * scroll changes through to this listener. This will ensure that this
- * {@link SwipeDismissListViewTouchListener} is paused during list view
- * scrolling.
- *
- * @see SwipeDismissListViewTouchListener
- */
- public AbsListView.OnScrollListener makeScrollListener() {
- return new AbsListView.OnScrollListener() {
- @Override
- public void onScrollStateChanged(AbsListView absListView, int scrollState) {
- setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
- }
-
- @Override
- public void onScroll(AbsListView absListView, int i, int i1, int i2) {
- }
- };
- }
-
- /**
- * Manually cause the item at the given position to be dismissed (trigger
- * the dismiss animation).
- */
- public void dismiss(int position) {
- dismiss(getViewForPosition(position), position, true);
- }
-
- @Override
- public boolean onTouch(View view, MotionEvent motionEvent) {
- if (mViewWidth < 2) {
- mViewWidth = mListView.getWidth();
- }
-
- mListView.requestDisallowInterceptTouchEvent(true);
-
- switch (motionEvent.getActionMasked()) {
- case MotionEvent.ACTION_DOWN: {
- if (mPaused) {
- return false;
- }
-
- // TODO: ensure this is a finger, and set a flag
-
- // Find the child view that was touched (perform a hit test)
- Rect rect = new Rect();
- int childCount = mListView.getChildCount();
- int[] listViewCoords = new int[2];
- mListView.getLocationOnScreen(listViewCoords);
- int x = (int) motionEvent.getRawX() - listViewCoords[0];
- int y = (int) motionEvent.getRawY() - listViewCoords[1];
- View child;
- for (int i = 0; i < childCount; i++) {
- child = mListView.getChildAt(i);
- child.getHitRect(rect);
- if (rect.contains(x, y)) {
- mDownView = child;
- break;
- }
- }
-
- if (mDownView != null) {
- mDownX = motionEvent.getRawX();
- mDownPosition = mListView.getPositionForView(mDownView);
- if (mCallbacks.canDismiss(mDownPosition)) {
- mVelocityTracker = VelocityTracker.obtain();
- mVelocityTracker.addMovement(motionEvent);
- } else {
- mDownView = null;
- }
- }
- view.onTouchEvent(motionEvent);
- return true;
- }
-
- case MotionEvent.ACTION_UP: {
- if (mVelocityTracker == null) {
- break;
- }
-
- float deltaX = motionEvent.getRawX() - mDownX;
- mVelocityTracker.addMovement(motionEvent);
- mVelocityTracker.computeCurrentVelocity(1000);
- float velocityX = mVelocityTracker.getXVelocity();
- float absVelocityX = Math.abs(velocityX);
- float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
- boolean dismiss = false;
- boolean dismissRight = false;
- if (Math.abs(deltaX) > mViewWidth / 2) {
- dismiss = true;
- dismissRight = deltaX > 0;
- } else if (mMinFlingVelocity <= absVelocityX && absVelocityX <= mMaxFlingVelocity
- && absVelocityY < absVelocityX) {
- // dismiss only if flinging in the same direction as dragging
- dismiss = (velocityX < 0) == (deltaX < 0);
- dismissRight = mVelocityTracker.getXVelocity() > 0;
- }
- if (dismiss) {
- // dismiss
- dismiss(mDownView, mDownPosition, dismissRight);
- } else {
- // cancel
- mDownView.animate().translationX(0).alpha(1).setDuration(mAnimationTime).setListener(null);
- }
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mDownX = 0;
- mDownView = null;
- mDownPosition = ListView.INVALID_POSITION;
- mSwiping = false;
- break;
- }
-
- case MotionEvent.ACTION_CANCEL: {
- if (mVelocityTracker == null) {
- break;
- }
-
- if (mDownView != null) {
- // cancel
- mDownView.animate().translationX(0).alpha(1).setDuration(mAnimationTime).setListener(null);
- }
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mDownX = 0;
- mDownView = null;
- mDownPosition = ListView.INVALID_POSITION;
- mSwiping = false;
- break;
- }
-
- case MotionEvent.ACTION_MOVE: {
- if (mVelocityTracker == null || mPaused) {
- break;
- }
-
- mVelocityTracker.addMovement(motionEvent);
- float deltaX = motionEvent.getRawX() - mDownX;
- if (Math.abs(deltaX) > mSlop) {
- mSwiping = true;
- mListView.requestDisallowInterceptTouchEvent(true);
-
- // Cancel ListView's touch (un-highlighting the item)
- MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
- cancelEvent.setAction(MotionEvent.ACTION_CANCEL
- | (motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
- mListView.onTouchEvent(cancelEvent);
- cancelEvent.recycle();
- }
-
- if (mSwiping) {
- mDownView.setTranslationX(deltaX);
- mDownView.setAlpha(Math.max(0.15f, Math.min(1f, 1f - 2f * Math.abs(deltaX) / mViewWidth)));
- return true;
- }
- break;
- }
- }
- return false;
- }
-
- private void dismiss(final View view, final int position, boolean dismissRight) {
- ++mDismissAnimationRefCount;
- if (view == null) {
- // No view, shortcut to calling onDismiss to let it deal with adapter
- // updates and all that.
- mCallbacks.onDismiss(mListView, new int[]{position});
- return;
- }
-
- view.animate().translationX(dismissRight ? mViewWidth : -mViewWidth).alpha(0).setDuration(mAnimationTime)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- performDismiss(view, position);
- }
- });
- }
-
- private View getViewForPosition(int position) {
- int index = position - (mListView.getFirstVisiblePosition() - mListView.getHeaderViewsCount());
- return (index >= 0 && index < mListView.getChildCount()) ? mListView.getChildAt(index) : null;
- }
-
- class PendingDismissData implements Comparable {
- public int position;
- public View view;
-
- public PendingDismissData(int position, View view) {
- this.position = position;
- this.view = view;
- }
-
- @Override
- public int compareTo(PendingDismissData other) {
- // Sort by descending position
- return other.position - position;
- }
- }
-
- private void performDismiss(final View dismissView, final int dismissPosition) {
- // Animate the dismissed list item to zero-height and fire the dismiss callback when
- // all dismissed list item animations have completed. This triggers layout on each animation
- // frame; in the future we may want to do something smarter and more performant.
-
- final ViewGroup.LayoutParams lp = dismissView.getLayoutParams();
- final int originalHeight = dismissView.getHeight();
-
- ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime);
-
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- --mDismissAnimationRefCount;
- if (mDismissAnimationRefCount == 0) {
- // No active animations, process all pending dismisses.
- // Sort by descending position
- Collections.sort(mPendingDismisses);
-
- int[] dismissPositions = new int[mPendingDismisses.size()];
- for (int i = mPendingDismisses.size() - 1; i >= 0; i--) {
- dismissPositions[i] = mPendingDismisses.get(i).position;
- }
- mCallbacks.onDismiss(mListView, dismissPositions);
-
- ViewGroup.LayoutParams lp;
- for (PendingDismissData pendingDismiss : mPendingDismisses) {
- // Reset view presentation
- pendingDismiss.view.setAlpha(1f);
- pendingDismiss.view.setTranslationX(0);
- lp = pendingDismiss.view.getLayoutParams();
- lp.height = originalHeight;
- pendingDismiss.view.setLayoutParams(lp);
- }
-
- mPendingDismisses.clear();
- }
- }
- });
-
- animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator valueAnimator) {
- lp.height = (Integer) valueAnimator.getAnimatedValue();
- dismissView.setLayoutParams(lp);
- }
- });
-
- mPendingDismisses.add(new PendingDismissData(dismissPosition, dismissView));
- animator.start();
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/animation/ViewFlipperAnimations.java b/Clover/app/src/main/java/org/floens/chan/ui/animation/ViewFlipperAnimations.java
deleted file mode 100644
index 54e7a0cf..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/animation/ViewFlipperAnimations.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.animation;
-
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.Animation;
-import android.view.animation.TranslateAnimation;
-
-/**
- * Contains the TranslateAnimation's for a horizontal scrolling ViewFlipper.
- */
-public class ViewFlipperAnimations {
- public static TranslateAnimation BACK_IN;
- public static TranslateAnimation BACK_OUT;
- public static TranslateAnimation NEXT_IN;
- public static TranslateAnimation NEXT_OUT;
-
- static {
- // Setup the static TranslateAnimations for the ViewFlipper
- BACK_IN = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -1f, Animation.RELATIVE_TO_PARENT, 0f, 0, 0f, 0,
- 0f);
- BACK_IN.setInterpolator(new AccelerateDecelerateInterpolator());
- BACK_IN.setDuration(300);
-
- BACK_OUT = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 1f, 0, 0f, 0,
- 0f);
- BACK_OUT.setInterpolator(new AccelerateDecelerateInterpolator());
- BACK_OUT.setDuration(300);
-
- NEXT_IN = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 1f, Animation.RELATIVE_TO_PARENT, 0f, 0, 0f, 0,
- 0f);
- NEXT_IN.setInterpolator(new AccelerateDecelerateInterpolator());
- NEXT_IN.setDuration(300);
-
- NEXT_OUT = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, -1f, 0, 0f,
- 0, 0f);
- NEXT_OUT.setInterpolator(new AccelerateDecelerateInterpolator());
- NEXT_OUT.setDuration(300);
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java b/Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java
index bcfa5d8e..2780f159 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java
@@ -1,10 +1,26 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.cell;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
-import android.os.Build;
import android.support.annotation.NonNull;
import android.text.Layout;
import android.text.Spannable;
@@ -29,7 +45,7 @@ import android.widget.TextView;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post;
@@ -46,8 +62,8 @@ import java.util.ArrayList;
import java.util.List;
import static org.floens.chan.utils.AndroidUtils.dp;
-import static org.floens.chan.utils.AndroidUtils.getAttrDrawable;
import static org.floens.chan.utils.AndroidUtils.getRes;
+import static org.floens.chan.utils.AndroidUtils.setRoundItemBackground;
import static org.floens.chan.utils.AndroidUtils.sp;
public class PostCell extends RelativeLayout implements PostLinkable.Callback {
@@ -132,17 +148,9 @@ public class PostCell extends RelativeLayout implements PostLinkable.Callback {
replies.setTextSize(textSizeSp);
replies.setPadding(paddingPx, 0, paddingPx, paddingPx);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- replies.setBackground(getAttrDrawable(getContext(), android.R.attr.selectableItemBackgroundBorderless));
- } else {
- replies.setBackgroundResource(R.drawable.item_background);
- }
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- options.setBackground(getAttrDrawable(getContext(), android.R.attr.selectableItemBackgroundBorderless));
- } else {
- options.setBackgroundResource(R.drawable.item_background);
- }
+ setRoundItemBackground(replies);
+ setRoundItemBackground(options);
RelativeLayout.LayoutParams dividerParams = (LayoutParams) divider.getLayoutParams();
dividerParams.leftMargin = paddingPx;
@@ -382,7 +390,7 @@ public class PostCell extends RelativeLayout implements PostLinkable.Callback {
private void loadCountryIcon() {
final Post requestedPost = post;
- ChanApplication.getVolleyImageLoader().get(post.countryUrl, new ImageLoader.ImageListener() {
+ Chan.getVolleyImageLoader().get(post.countryUrl, new ImageLoader.ImageListener() {
@Override
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
if (response.getBitmap() != null && PostCell.this.post == requestedPost) {
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java b/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java
index 162879df..a1172287 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java
@@ -1,7 +1,23 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.cell;
import android.content.Context;
-import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
@@ -14,7 +30,6 @@ import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Post;
import static org.floens.chan.utils.AndroidUtils.ROBOTO_MEDIUM;
-import static org.floens.chan.utils.AndroidUtils.getAttrDrawable;
public class ThreadStatusCell extends LinearLayout implements View.OnClickListener {
private static final int UPDATE_INTERVAL = 1000;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java
index f0b861a4..38c880bb 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.app.Activity;
@@ -42,10 +59,11 @@ public class AdvancedSettingsController extends SettingsController {
private void populatePreferences() {
SettingsGroup settings = new SettingsGroup(string(R.string.settings_group_advanced));
+ // TODO change this to a presenting controller
saveLocation = (LinkSettingView) settings.add(new LinkSettingView(this, string(R.string.setting_save_folder), null, new View.OnClickListener() {
@Override
public void onClick(View v) {
- File dir = ChanSettings.getImageSaveDirectory();
+ File dir = new File(ChanSettings.saveLocation.get());
if (!dir.mkdirs() && !dir.isDirectory()) {
new AlertDialog.Builder(context).setMessage(R.string.setting_save_folder_error_create_folder).show();
} else {
@@ -66,8 +84,8 @@ public class AdvancedSettingsController extends SettingsController {
settings.add(new BooleanSettingView(this, ChanSettings.shareUrl, string(R.string.setting_share_url), string(R.string.setting_share_url_description)));
settings.add(new BooleanSettingView(this, ChanSettings.networkHttps, string(R.string.setting_network_https), string(R.string.setting_network_https_description)));
settings.add(new BooleanSettingView(this, ChanSettings.forcePhoneLayout, string(R.string.setting_force_phone_layout), null));
- settings.add(new BooleanSettingView(this, ChanSettings.anonymize, string(R.string.preference_anonymize), null));
- settings.add(new BooleanSettingView(this, ChanSettings.anonymizeIds, string(R.string.preference_anonymize_ids), null));
+ settings.add(new BooleanSettingView(this, ChanSettings.anonymize, string(R.string.setting_anonymize), null));
+ settings.add(new BooleanSettingView(this, ChanSettings.anonymizeIds, string(R.string.setting_anonymize_ids), null));
settings.add(new BooleanSettingView(this, ChanSettings.repliesButtonsBottom, string(R.string.setting_buttons_bottom), null));
settings.add(new BooleanSettingView(this, ChanSettings.confirmExit, string(R.string.setting_confirm_exit), null));
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardEditController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardEditController.java
index fdd7a4b8..b0c0f310 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardEditController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/BoardEditController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.app.AlertDialog;
@@ -19,7 +36,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.core.manager.BoardManager;
@@ -40,7 +57,7 @@ import static org.floens.chan.utils.AndroidUtils.dp;
public class BoardEditController extends Controller implements SwipeListener.Callback, ToolbarMenuItem.ToolbarMenuItemCallback {
private static final int ADD_ID = 1;
- private final BoardManager boardManager = ChanApplication.getBoardManager();
+ private final BoardManager boardManager = Chan.getBoardManager();
private RecyclerView recyclerView;
private BoardEditAdapter adapter;
@@ -173,7 +190,7 @@ public class BoardEditController extends Controller implements SwipeListener.Cal
}
// Normal add
- List all = ChanApplication.getBoardManager().getAllBoards();
+ List all = Chan.getBoardManager().getAllBoards();
for (Board board : all) {
if (board.value.equals(value)) {
board.saved = true;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java
index 1fa42095..a4b164c4 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java
@@ -25,7 +25,7 @@ import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.manager.BoardManager;
@@ -68,8 +68,8 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte
navigationItem.menu = menu;
navigationItem.hasBack = false;
- menu.addItem(new ToolbarMenuItem(context, this, REFRESH_ID, R.drawable.ic_action_refresh));
- menu.addItem(new ToolbarMenuItem(context, this, POST_ID, R.drawable.ic_action_write));
+ menu.addItem(new ToolbarMenuItem(context, this, REFRESH_ID, R.drawable.ic_refresh_white_24dp));
+ menu.addItem(new ToolbarMenuItem(context, this, POST_ID, R.drawable.ic_create_white_24dp));
ToolbarMenuItem overflow = menu.createOverflow(this);
@@ -80,7 +80,7 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte
overflow.setSubMenu(new FloatingMenu(context, overflow.getView(), items));
- loadBoard(ChanApplication.getBoardManager().getSavedBoards().get(0));
+ loadBoard(Chan.getBoardManager().getSavedBoards().get(0));
}
@Override
@@ -168,7 +168,7 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte
}
private void loadBoards() {
- List boards = ChanApplication.getBoardManager().getSavedBoards();
+ List boards = Chan.getBoardManager().getSavedBoards();
boardItems = new ArrayList<>();
for (Board board : boards) {
FloatingMenuItem item = new FloatingMenuItemBoard(board);
@@ -222,7 +222,7 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte
if (position >= 0 && position < items.size()) {
return items.get(position).getText();
} else {
- return context.getString(R.string.board_select_add);
+ return context.getString(R.string.thread_board_select_add);
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/DeveloperSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/DeveloperSettingsController.java
index 2b4e27e6..6164e112 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/DeveloperSettingsController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/DeveloperSettingsController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.content.Context;
@@ -7,7 +24,7 @@ import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.core.model.SavedReply;
@@ -53,7 +70,7 @@ public class DeveloperSettingsController extends Controller {
resetDbButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- ChanApplication.getDatabaseManager().reset();
+ Chan.getDatabaseManager().reset();
System.exit(0);
}
});
@@ -68,7 +85,7 @@ public class DeveloperSettingsController extends Controller {
int j = 0;
for (int i = 0; i < 100; i++) {
j += r.nextInt(10000);
- ChanApplication.getDatabaseManager().saveReply(new SavedReply("g", j, "pass"));
+ Chan.getDatabaseManager().saveReply(new SavedReply("g", j, "pass"));
}
setDbSummary();
}
@@ -80,7 +97,7 @@ public class DeveloperSettingsController extends Controller {
trimSavedReply.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
- ChanApplication.getDatabaseManager().trimSavedRepliesTable(10);
+ Chan.getDatabaseManager().trimSavedRepliesTable(10);
setDbSummary();
}
});
@@ -95,7 +112,7 @@ public class DeveloperSettingsController extends Controller {
private void setDbSummary() {
String dbSummary = "";
dbSummary += "Database summary:\n";
- dbSummary += ChanApplication.getDatabaseManager().getSummary();
+ dbSummary += Chan.getDatabaseManager().getSummary();
summaryText.setText(dbSummary);
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java
index 651e01ed..e7db17f7 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.animation.Animator;
@@ -5,6 +22,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
@@ -28,7 +46,7 @@ import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.davemorrissey.labs.subscaleview.ImageViewState;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.chan.ImageSearch;
import org.floens.chan.controller.Controller;
@@ -249,6 +267,7 @@ public class ImageViewerController extends Controller implements View.OnClickLis
if (ChanSettings.videoErrorIgnore.get()) {
Toast.makeText(context, R.string.image_open_failed, Toast.LENGTH_SHORT).show();
} else {
+ @SuppressLint("InflateParams")
View notice = LayoutInflater.from(context).inflate(R.layout.dialog_video_error, null);
final CheckBox dontShowAgain = (CheckBox) notice.findViewById(R.id.checkbox);
@@ -309,7 +328,7 @@ public class ImageViewerController extends Controller implements View.OnClickLis
}
});
- ChanApplication.getVolleyImageLoader().get(postImage.thumbnailUrl, new ImageLoader.ImageListener() {
+ Chan.getVolleyImageLoader().get(postImage.thumbnailUrl, new ImageLoader.ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "onErrorResponse for preview in transition in ImageViewerController, cannot show correct transition bitmap");
@@ -331,7 +350,7 @@ public class ImageViewerController extends Controller implements View.OnClickLis
return;
}
- ChanApplication.getVolleyImageLoader().get(postImage.thumbnailUrl, new ImageLoader.ImageListener() {
+ Chan.getVolleyImageLoader().get(postImage.thumbnailUrl, new ImageLoader.ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "onErrorResponse for preview out transition in ImageViewerController, cannot show correct transition bitmap");
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerNavigationController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerNavigationController.java
index 0e89789a..d9008412 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerNavigationController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerNavigationController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/LicensesController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/LicensesController.java
index 257864f6..baaa1e58 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/LicensesController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/LicensesController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java
index d0432671..6ffcec71 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.app.AlertDialog;
@@ -12,7 +29,7 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.core.reply.ReplyManager;
@@ -100,7 +117,7 @@ public class PassSettingsController extends Controller implements View.OnClickLi
ChanSettings.passToken.set(inputToken.getText().toString());
ChanSettings.passPin.set(inputPin.getText().toString());
- ChanApplication.getReplyManager().postPass(ChanSettings.passToken.get(), ChanSettings.passPin.get(), new ReplyManager.PassListener() {
+ Chan.getReplyManager().postPass(ChanSettings.passToken.get(), ChanSettings.passPin.get(), new ReplyManager.PassListener() {
@Override
public void onResponse(ReplyManager.PassResponse response) {
if (response.isError) {
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/PostRepliesController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/PostRepliesController.java
index 896d652d..bdf7a4f1 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/PostRepliesController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/PostRepliesController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.animation.ValueAnimator;
@@ -24,7 +41,6 @@ import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.cell.PostCell;
import org.floens.chan.ui.helper.PostPopupHelper;
import org.floens.chan.ui.view.LoadView;
-import org.floens.chan.ui.view.PostView;
import org.floens.chan.ui.view.ThumbnailView;
import org.floens.chan.utils.ThemeHelper;
@@ -133,8 +149,8 @@ public class PostRepliesController extends Controller {
});
if (!ThemeHelper.getInstance().getTheme().isLightTheme) {
- ((TextView) dataView.findViewById(R.id.replies_back_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_action_back_dark, 0, 0, 0);
- ((TextView) dataView.findViewById(R.id.replies_close_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_action_done_dark, 0, 0, 0);
+ ((TextView) dataView.findViewById(R.id.replies_back_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_arrow_back_white_24dp, 0, 0, 0);
+ ((TextView) dataView.findViewById(R.id.replies_close_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_done_white_24dp, 0, 0, 0);
dataView.findViewById(R.id.container).setBackgroundResource(R.drawable.dialog_full_dark);
}
@@ -142,24 +158,15 @@ public class PostRepliesController extends Controller {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
PostCell postCell;
- if (convertView instanceof PostView) {
+ if (convertView instanceof PostCell) {
postCell = (PostCell) convertView;
} else {
- postCell = (PostCell) LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_post, parent, false);
+ postCell = (PostCell) LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_post, parent, false);
}
final Post p = getItem(position);
postCell.setPost(p, presenter, false, data.forPost.no);
-// postView.setPost(p, presenter, false);
-// postView.setHighlightQuotesWithNo(data.forPost.no);
- /*postCell.setOnClickListeners(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- postPopupHelper.postClicked(p);
- }
- });*/
-
return postCell;
}
};
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java
index f4d1e67b..21c9d13e 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java
@@ -25,7 +25,7 @@ import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
import org.floens.chan.controller.ControllerTransition;
@@ -72,7 +72,7 @@ public class RootNavigationController extends NavigationController implements Pi
new SwipeListener(context, recyclerView, pinAdapter);
- pinAdapter.onPinsChanged(ChanApplication.getWatchManager().getPins());
+ pinAdapter.onPinsChanged(Chan.getWatchManager().getPins());
toolbar.setCallback(this);
@@ -162,7 +162,7 @@ public class RootNavigationController extends NavigationController implements Pi
@Override
public void onWatchCountClicked(Pin pin) {
- ChanApplication.getWatchManager().toggleWatch(pin);
+ Chan.getWatchManager().toggleWatch(pin);
}
@Override
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java
index 1813a228..245c8662 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java
@@ -1,8 +1,25 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.content.Context;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.controller.Controller;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.PostImage;
@@ -45,7 +62,7 @@ public abstract class ThreadController extends Controller implements ThreadLayou
return threadLayout.onBack();
}
- public void onEvent(ChanApplication.ForegroundChangedMessage message) {
+ public void onEvent(Chan.ForegroundChangedMessage message) {
threadLayout.getPresenter().onForegroundChanged(message.inForeground);
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java
index 32ba1bcc..81c50347 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java
@@ -21,7 +21,7 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.manager.WatchManager;
@@ -62,8 +62,8 @@ public class ViewThreadController extends ThreadController implements ThreadLayo
navigationItem.hasDrawer = true;
navigationItem.menu = new ToolbarMenu(context);
- navigationItem.menu.addItem(new ToolbarMenuItem(context, this, POST_ID, R.drawable.ic_action_write));
- pinItem = navigationItem.menu.addItem(new ToolbarMenuItem(context, this, PIN_ID, R.drawable.ic_bookmark));
+ navigationItem.menu.addItem(new ToolbarMenuItem(context, this, POST_ID, R.drawable.ic_create_white_24dp));
+ pinItem = navigationItem.menu.addItem(new ToolbarMenuItem(context, this, PIN_ID, R.drawable.ic_bookmark_outline_white_24dp));
navigationItem.createOverflow(context, this, Arrays.asList(
new FloatingMenuItem(REFRESH_ID, context.getString(R.string.action_reload)),
new FloatingMenuItem(SEARCH_ID, context.getString(R.string.action_search)),
@@ -177,11 +177,11 @@ public class ViewThreadController extends ThreadController implements ThreadLayo
}
private void setPinIconState() {
- WatchManager wm = ChanApplication.getWatchManager();
+ WatchManager wm = Chan.getWatchManager();
setPinIconState(wm.findPinByLoadable(loadable) != null);
}
private void setPinIconState(boolean pinned) {
- pinItem.setImage(pinned ? R.drawable.ic_bookmark_filled : R.drawable.ic_bookmark);
+ pinItem.setImage(pinned ? R.drawable.ic_bookmark_white_24dp : R.drawable.ic_bookmark_outline_white_24dp);
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java
index 7592c710..3398f629 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.controller;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/drawable/DropdownArrowDrawable.java b/Clover/app/src/main/java/org/floens/chan/ui/drawable/DropdownArrowDrawable.java
index 37e05f8b..49a5f1cb 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/drawable/DropdownArrowDrawable.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/drawable/DropdownArrowDrawable.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.drawable;
import android.graphics.Canvas;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/drawable/ThumbDrawable.java b/Clover/app/src/main/java/org/floens/chan/ui/drawable/ThumbDrawable.java
index 5f6c1031..1e97c808 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/drawable/ThumbDrawable.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/drawable/ThumbDrawable.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.drawable;
import android.graphics.Canvas;
@@ -9,7 +26,6 @@ import android.graphics.drawable.Drawable;
import static org.floens.chan.utils.AndroidUtils.dp;
-
public class ThumbDrawable extends Drawable {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Path path = new Path();
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/FolderPickFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/FolderPickFragment.java
index 1e02bd84..2f7dbe0f 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/FolderPickFragment.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/fragment/FolderPickFragment.java
@@ -71,7 +71,7 @@ public class FolderPickFragment extends DialogFragment {
return null;
}
- View container = inflater.inflate(R.layout.folder_pick, parent);
+ View container = inflater.inflate(R.layout.fragment_folder_pick, parent);
statusPath = (TextView) container.findViewById(R.id.folder_status);
listView = (ListView) container.findViewById(R.id.folder_list);
@@ -94,8 +94,8 @@ public class FolderPickFragment extends DialogFragment {
});
if (!ThemeHelper.getInstance().getTheme().isLightTheme) {
- ((TextView) container.findViewById(R.id.pick_back_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_action_cancel_dark, 0, 0, 0);
- ((TextView) container.findViewById(R.id.pick_ok_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_action_done_dark, 0, 0, 0);
+ ((TextView) container.findViewById(R.id.pick_back_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_arrow_back_white_24dp, 0, 0, 0);
+ ((TextView) container.findViewById(R.id.pick_ok_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_done_white_24dp, 0, 0, 0);
}
adapter = new ArrayAdapter(inflater.getContext(), 0) {
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ImageViewFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ImageViewFragment.java
deleted file mode 100644
index 35434b4a..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ImageViewFragment.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.fragment;
-
-import android.app.AlertDialog;
-import android.app.Fragment;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CheckBox;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import android.widget.Toast;
-import android.widget.VideoView;
-
-import org.floens.chan.R;
-import org.floens.chan.chan.ImageSearch;
-import org.floens.chan.core.model.Post;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.ui.activity.ImageViewActivity;
-import org.floens.chan.ui.adapter.ImageViewAdapter;
-import org.floens.chan.ui.view.MultiImageView;
-import org.floens.chan.ui.view.MultiImageView.Callback;
-import org.floens.chan.utils.AndroidUtils;
-import org.floens.chan.utils.ImageSaver;
-
-import static org.floens.chan.utils.AndroidUtils.dp;
-
-public class ImageViewFragment extends Fragment implements Callback {
- private Context context;
- private ImageViewActivity activity;
-
- private MultiImageView imageView;
-
- private Post post;
- private boolean showProgressBar = true;
- private boolean isVideo = false;
- private boolean videoVisible = false;
- private boolean videoSetIconToPause = false;
- private boolean tapToLoad = false;
- private boolean loaded = false;
-
- private long progressCurrent;
- private long progressTotal;
- private boolean progressDone;
-
- public static ImageViewFragment newInstance(Post post, ImageViewActivity activity, int index) {
- ImageViewFragment imageViewFragment = new ImageViewFragment();
- imageViewFragment.post = post;
- imageViewFragment.activity = activity;
-
- return imageViewFragment;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- if (post == null) {
- // No restoring
- return null;
- } else {
- context = inflater.getContext();
-
- imageView = new MultiImageView(context);
- imageView.setCallback(this);
- int padding = getResources().getDimensionPixelSize(R.dimen.image_view_padding);
- imageView.setPadding(padding, padding, padding, padding);
-
- return imageView;
- }
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- // No restoring
- if (post != null) {
- if (!post.hasImage) {
- throw new IllegalArgumentException("Post has no image");
- }
-
- // After layout has been done so getWidth & getHeight don't return 0
- imageView.post(new Runnable() {
- @Override
- public void run() {
- // When the viewpager is created, it starts loading the first two views,
- // then we set a position to the viewpager and it loads three more views!
- // Check for these unused views here to avoid unnecessary loads
- if (imageView.getWidth() == 0 || imageView.getHeight() == 0)
- return;
-
- imageView.setThumbnail(post.thumbnailUrl);
-
- if (ChanSettings.getImageAutoLoad() && !post.spoiler) {
- load();
- } else {
- tapToLoad = true;
- showProgressBar(false);
-
- if (post.ext.equals("webm")) {
- isVideo = true;
- activity.invalidateActionBar();
- }
- }
- }
- });
- }
- }
-
- private void load() {
- if (loaded) return;
- loaded = true;
-
- switch (post.ext) {
- case "gif":
- imageView.setGif(post.imageUrl);
- break;
- case "webm":
- isVideo = true;
- activity.invalidateActionBar();
- showProgressBar(false);
-
- if (tapToLoad) {
- if (!videoVisible) {
- startVideo();
- } else {
- if (imageView.getVideoView() != null) {
- imageView.getVideoView().start();
- }
- }
- }
- break;
- default:
- imageView.setBigImage(post.imageUrl);
- break;
- }
-
- }
-
- @Override
- public void onSaveInstanceState(Bundle bundle) {
- // https://code.google.com/p/android/issues/detail?id=19917
- bundle.putString("bug_19917", "bug_19917");
- super.onSaveInstanceState(bundle);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
-
- if (imageView != null) {
- imageView.cancelLoad();
- }
- }
-
- public void onSelected(ImageViewAdapter adapter, int position) {
- activity.setProgressBarIndeterminateVisibility(showProgressBar);
-
- String filename = post.filename + "." + post.ext;
- activity.getSupportActionBar().setTitle(filename);
-
- String text = (position + 1) + "/" + adapter.getCount();
- activity.getSupportActionBar().setSubtitle(text);
-
- activity.invalidateActionBar();
-
- if (isVideo && ChanSettings.getVideoAutoPlay() && imageView != null) {
- if (!videoVisible) {
- startVideo();
- } else {
- if (imageView.getVideoView() != null) {
- imageView.getVideoView().start();
- }
- }
- }
-
- activity.setProgressBar(progressCurrent, progressTotal, progressDone);
- }
-
- public void onDeselected() {
- if (imageView != null && imageView.getVideoView() != null) {
- imageView.getVideoView().pause();
- }
- }
-
- public void onPrepareOptionsMenu(Menu menu) {
- MenuItem item = menu.findItem(R.id.action_image_play_state);
- item.setVisible(isVideo);
- item.setEnabled(isVideo);
-
- if (imageView != null) {
- VideoView view = imageView.getVideoView();
- if (view != null) {
- item.setIcon((videoSetIconToPause || view.isPlaying()) ? R.drawable.ic_action_pause
- : R.drawable.ic_action_play);
- videoSetIconToPause = false;
- }
- }
- }
-
- public void customOnOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_image_play_state:
- if (!videoVisible) {
- startVideo();
- } else {
- VideoView view = imageView.getVideoView();
- if (view != null) {
- if (!view.isPlaying()) {
- view.start();
- } else {
- view.pause();
- }
- }
- }
-
- activity.invalidateActionBar();
- break;
- case R.id.action_open_browser:
- AndroidUtils.openLink(post.imageUrl);
- break;
- case R.id.action_image_save:
- case R.id.action_share:
- if (ChanSettings.getImageShareUrl()) {
- shareImageUrl(post.imageUrl);
- } else {
- ImageSaver.getInstance().saveImage(context, post.imageUrl,
- ChanSettings.getImageSaveOriginalFilename() ? Long.toString(post.tim) : post.filename, post.ext,
- item.getItemId() == R.id.action_share);
- }
- break;
- default:
- // Search if it was an ImageSearch item
- for (ImageSearch engine : ImageSearch.engines) {
- if (item.getItemId() == engine.getId()) {
- AndroidUtils.openLink(engine.getUrl(post.imageUrl));
- break;
- }
- }
-
- break;
- }
- }
-
- private void shareImageUrl(String url) {
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType("text/plain");
- intent.putExtra(Intent.EXTRA_TEXT, url);
- context.startActivity(Intent.createChooser(intent, context.getString(R.string.action_share)));
- }
-
- public void onVideoError(MultiImageView view) {
- if (ChanSettings.getVideoErrorIgnore()) {
- Toast.makeText(context, R.string.image_open_failed, Toast.LENGTH_SHORT).show();
- } else {
- showVideoWarning();
- }
- }
-
- @Override
- public void onModeLoaded(MultiImageView multiImageView, MultiImageView.Mode mode) {
-
- }
-
- private void showVideoWarning() {
- LinearLayout notice = new LinearLayout(context);
- notice.setOrientation(LinearLayout.VERTICAL);
-
- TextView noticeText = new TextView(context);
- noticeText.setText(R.string.video_playback_warning);
- noticeText.setTextSize(16f);
- notice.addView(noticeText, AndroidUtils.MATCH_WRAP_PARAMS);
-
- final CheckBox dontShowAgain = new CheckBox(context);
- dontShowAgain.setText(R.string.video_playback_ignore);
- notice.addView(dontShowAgain, AndroidUtils.MATCH_WRAP_PARAMS);
-
- int padding = dp(16f);
- notice.setPadding(padding, padding, padding, padding);
-
- new AlertDialog.Builder(context)
- .setTitle(R.string.video_playback_warning_title)
- .setView(notice)
- .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (dontShowAgain.isChecked()) {
- ChanSettings.setVideoErrorIgnore(true);
- }
- }
- })
- .setCancelable(false)
- .show();
- }
-
- private void startVideo() {
- if (videoVisible) return;
- videoVisible = true;
-
- imageView.setVideo(post.imageUrl);
- }
-
- public void showProgressBar(boolean e) {
- showProgressBar = e;
- activity.updateActionBarIfSelected(this);
- }
-
- @Override
- public void onTap(MultiImageView view) {
- if (tapToLoad) {
- if (loaded) {
- activity.finish();
- } else {
- load();
- }
- } else {
- activity.finish();
- }
- }
-
- @Override
- public void showProgress(MultiImageView view, boolean progress) {
- showProgressBar(progress);
- }
-
- @Override
- public void onProgress(MultiImageView view, long current, long total) {
- progressCurrent = current;
- progressTotal = total;
- progressDone = true;
- activity.updateActionBarIfSelected(this);
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/PostRepliesFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/PostRepliesFragment.java
deleted file mode 100644
index 3ca1aafe..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/PostRepliesFragment.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.fragment;
-
-import android.app.Activity;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import org.floens.chan.R;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.core.model.Post;
-import org.floens.chan.core.presenter.ThreadPresenter;
-import org.floens.chan.ui.helper.PostPopupHelper;
-import org.floens.chan.ui.view.PostView;
-import org.floens.chan.utils.ThemeHelper;
-
-/**
- * A DialogFragment that shows a list of posts. Use the newInstance method for
- * instantiating.
- */
-public class PostRepliesFragment extends DialogFragment {
- private ListView listView;
-
- private Activity activity;
- private PostPopupHelper.RepliesData repliesData;
- private PostPopupHelper postPopupHelper;
- private ThreadPresenter presenter;
-
- public static PostRepliesFragment newInstance(PostPopupHelper.RepliesData repliesData, PostPopupHelper postPopupHelper, ThreadPresenter presenter) {
- PostRepliesFragment fragment = new PostRepliesFragment();
-
- fragment.repliesData = repliesData;
- fragment.postPopupHelper = postPopupHelper;
- fragment.presenter = presenter;
- return fragment;
- }
-
- public void dismissNoCallback() {
- postPopupHelper = null;
- dismiss();
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setStyle(STYLE_NO_TITLE, 0);
- }
-
- @Override
- public void onDismiss(DialogInterface dialog) {
- super.onDismiss(dialog);
-
- if (postPopupHelper != null) {
-// postPopupHelper.onPostRepliesPop();
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup unused, Bundle savedInstanceState) {
- View container;
- if (ChanSettings.getReplyButtonsBottom()) {
- container = inflater.inflate(R.layout.post_replies_bottombuttons, null);
- } else {
- container = inflater.inflate(R.layout.post_replies, null);
- }
-
- listView = (ListView) container.findViewById(R.id.post_list);
-
- container.findViewById(R.id.replies_back).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dismiss();
- }
- });
-
- container.findViewById(R.id.replies_close).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (postPopupHelper != null) {
-// postPopupHelper.closeAllPostFragments();
- }
- }
- });
-
- if (!ThemeHelper.getInstance().getTheme().isLightTheme) {
- ((TextView) container.findViewById(R.id.replies_back_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_action_back_dark, 0, 0, 0);
- ((TextView) container.findViewById(R.id.replies_close_icon)).setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_action_done_dark, 0, 0, 0);
- }
-
- return container;
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- activity = getActivity();
-
- if (repliesData == null) {
- // Restoring from background.
- dismiss();
- } else {
- ArrayAdapter adapter = new ArrayAdapter(activity, 0) {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- PostView postView;
- if (convertView instanceof PostView) {
- postView = (PostView) convertView;
- } else {
- postView = new PostView(activity);
- }
-
- final Post p = getItem(position);
-
-// postView.setPost(p, presenter, false);
-// postView.setHighlightQuotesWithNo(repliesData.forPost.no);
- postView.setOnClickListeners(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (postPopupHelper != null) {
- postPopupHelper.postClicked(p);
- }
- dismiss();
- }
- });
-
- return postView;
- }
- };
-
- adapter.addAll(repliesData.posts);
- listView.setAdapter(adapter);
-
- listView.setSelectionFromTop(repliesData.listViewIndex, repliesData.listViewTop);
- listView.setOnScrollListener(new AbsListView.OnScrollListener() {
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- }
-
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- if (repliesData != null) {
- repliesData.listViewIndex = view.getFirstVisiblePosition();
- View v = view.getChildAt(0);
- repliesData.listViewTop = (v == null) ? 0 : v.getTop();
- }
- }
- });
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ReplyFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ReplyFragment.java
deleted file mode 100644
index 2f1c0368..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ReplyFragment.java
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.fragment;
-
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
-import android.widget.ViewFlipper;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.chan.ChanUrls;
-import org.floens.chan.core.reply.ReplyManager;
-import org.floens.chan.core.model.Board;
-import org.floens.chan.core.model.Loadable;
-import org.floens.chan.core.model.Reply;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.ui.animation.ViewFlipperAnimations;
-import org.floens.chan.ui.layout.CaptchaLayout;
-import org.floens.chan.ui.view.LoadView;
-import org.floens.chan.utils.AndroidUtils;
-import org.floens.chan.utils.ImageDecoder;
-import org.floens.chan.utils.Logger;
-import org.floens.chan.utils.ThemeHelper;
-
-import java.io.File;
-
-import static org.floens.chan.utils.AndroidUtils.dp;
-
-public class ReplyFragment extends DialogFragment implements CaptchaLayout.CaptchaCallback {
- private static final String TAG = "ReplyFragment";
-
- private int page = 0;
-
- private Loadable loadable;
- private boolean quickMode = false;
-
- private final Reply draft = new Reply();
- private boolean shouldSaveDraft = true;
-
- private String captchaResponse;
-
- private int defaultTextColor;
- private int maxCommentCount;
-
- // Views
- private View container;
- private ViewFlipper flipper;
- private Button cancelButton;
- private ImageButton fileButton;
- private Button submitButton;
- private EditText nameView;
- private EditText emailView;
- private EditText subjectView;
- private EditText commentView;
- private EditText fileNameView;
- private CheckBox spoilerImageView;
- private LoadView imageViewContainer;
- private CaptchaLayout captchaLayout;
- private LoadView responseContainer;
- private Button insertSpoiler;
- private Button insertCode;
- private TextView commentCountView;
- private TextView fileStatusView;
-
- private AppCompatActivity context;
-
- public static ReplyFragment newInstance(Loadable loadable, boolean quickMode) {
- ReplyFragment reply = new ReplyFragment();
- reply.loadable = loadable;
- reply.quickMode = quickMode;
- return reply;
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- loadable.writeToBundle(context, outState);
- outState.putBoolean(context.getPackageName() + ".quickmode", quickMode);
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- context = (AppCompatActivity) getActivity();
-
- if (loadable == null && savedInstanceState != null) {
- loadable = new Loadable();
- loadable.readFromBundle(context, savedInstanceState);
- quickMode = savedInstanceState.getBoolean(context.getPackageName() + ".quickmode");
- }
-
- if (loadable != null) {
- setClosable(true);
-
- Dialog dialog = getDialog();
- String title = (loadable.isThreadMode() ? context.getString(R.string.reply_to_board) : context.getString(R.string.reply_to_board)) + " " + loadable.title;
-
- if (dialog == null) {
- context.getSupportActionBar().setTitle(title);
- } else {
- dialog.setTitle(title);
- // todo move elsewhere
- dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
- dialog.setOnKeyListener(new Dialog.OnKeyListener() {
- @Override
- public boolean onKey(DialogInterface dialogInterface, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- onBackPressed();
- return true;
- } else
- return false;
- }
- });
- }
-
- Reply draft = null;
-
- if (TextUtils.isEmpty(draft.name)) {
- draft.name = ChanSettings.getDefaultName();
- }
-
- nameView.setText(draft.name);
- emailView.setText(draft.options);
- subjectView.setText(draft.subject);
- commentView.setText(draft.comment);
- commentView.setSelection(draft.selection);
-
- setFile(draft.fileName, draft.file);
- spoilerImageView.setChecked(draft.spoilerImage);
-
- if (loadable.isThreadMode()) {
- subjectView.setVisibility(View.GONE);
- }
-
- if (quickMode) {
- nameView.setVisibility(View.GONE);
- emailView.setVisibility(View.GONE);
- subjectView.setVisibility(View.GONE);
- }
-
- defaultTextColor = commentView.getCurrentTextColor();
-
- Board b = ChanApplication.getBoardManager().getBoardByValue(loadable.board);
- if (b != null) {
- insertSpoiler.setVisibility(b.spoilers ? View.VISIBLE : View.GONE);
- insertCode.setVisibility(b.codeTags ? View.VISIBLE : View.GONE);
- maxCommentCount = b.maxCommentChars;
- }
-
- commentView.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- showCommentCount();
- }
- });
- showCommentCount();
-
- String baseUrl = loadable.isThreadMode() ? ChanUrls.getThreadUrlDesktop(loadable.board, loadable.no) : ChanUrls.getBoardUrlDesktop(loadable.board);
- captchaLayout.initCaptcha(baseUrl, ChanUrls.getCaptchaSiteKey(),
- ThemeHelper.getInstance().getTheme().isLightTheme, ChanApplication.getInstance().getUserAgent(), this);
- } else {
- Logger.e(TAG, "Loadable in ReplyFragment was null");
- closeReply();
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- ReplyManager replyManager = ChanApplication.getReplyManager();
-
- if (shouldSaveDraft) {
- draft.name = nameView.getText().toString();
- draft.options = emailView.getText().toString();
- draft.subject = subjectView.getText().toString();
- draft.comment = commentView.getText().toString();
- draft.fileName = fileNameView.getText().toString();
- draft.spoilerImage = spoilerImageView.isChecked();
- draft.selection = commentView.getSelectionStart();
-
-// replyManager.setReplyDraft(draft);
- } else {
-// replyManager.removeReplyDraft();
- setFile(null, null);
- }
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
-
- ReplyManager replyManager = ChanApplication.getReplyManager();
- replyManager.removeFileListener();
-
- context = null;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
- // Setup the views with listeners
- container = inflater.inflate(R.layout.reply_view, null);
- flipper = (ViewFlipper) container.findViewById(R.id.reply_flipper);
-
- nameView = (EditText) container.findViewById(R.id.reply_name);
- emailView = (EditText) container.findViewById(R.id.reply_email);
- subjectView = (EditText) container.findViewById(R.id.reply_subject);
- commentView = (EditText) container.findViewById(R.id.reply_comment);
- commentView.requestFocus();
- fileNameView = (EditText) container.findViewById(R.id.reply_file_name);
- spoilerImageView = (CheckBox) container.findViewById(R.id.reply_spoiler_image);
-
- imageViewContainer = (LoadView) container.findViewById(R.id.reply_image);
- responseContainer = (LoadView) container.findViewById(R.id.reply_response);
- captchaLayout = (CaptchaLayout) container.findViewById(R.id.captcha_layout);
-
- cancelButton = (Button) container.findViewById(R.id.reply_cancel);
- cancelButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (page == 1) {
- flipPage(0);
- } else {
- closeReply();
- }
- }
- });
-
- fileButton = (ImageButton) container.findViewById(R.id.reply_file);
- fileButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (draft.file == null) {
- /*ChanApplication.getReplyManager().pickFile(new ReplyManager.FileListener() {
- @Override
- public void onFile(String name, File file) {
- setFile(name, file);
- }
-
- @Override
- public void onFileLoading() {
- imageViewContainer.setVisibility(View.VISIBLE);
- imageViewContainer.setView(null);
- }
- });*/
- } else {
- setFile(null, null);
- }
- }
- });
-
- submitButton = (Button) container.findViewById(R.id.reply_submit);
- submitButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (page == 1 || ChanSettings.passLoggedIn()) {
- flipPage(2);
- submit();
- } else {
- flipPage(1);
- }
- }
- });
-
- insertSpoiler = (Button) container.findViewById(R.id.insert_spoiler);
- insertSpoiler.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- insertAtCursor("[spoiler]", "[/spoiler]");
- }
- });
-
- insertCode = (Button) container.findViewById(R.id.insert_code);
- insertCode.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- insertAtCursor("[code]", "[/code]");
- }
- });
-
- commentCountView = (TextView) container.findViewById(R.id.reply_comment_counter);
-
- fileStatusView = (TextView) container.findViewById(R.id.reply_file_status);
-
- return container;
- }
-
- public boolean onBackPressed() {
- if (page == 1) {
- flipPage(0);
- return false;
- } else {
- return true;
- }
- }
-
- @Override
- public void captchaLoaded(CaptchaLayout captchaLayout) {
- }
-
- @Override
- public void captchaEntered(CaptchaLayout captchaLayout, String response) {
- captchaResponse = response;
- if (page == 1) {
- flipPage(2);
- submit();
- }
- }
-
- private void insertAtCursor(String before, String after) {
- int pos = commentView.getSelectionStart();
- String text = commentView.getText().toString();
- text = new StringBuilder(text).insert(pos, before + after).toString();
- commentView.setText(text);
- commentView.setSelection(pos + before.length());
- }
-
- private void showCommentCount() {
- int count = commentView.getText().length();
- commentCountView.setText(count + "/" + maxCommentCount);
- if (count > maxCommentCount) {
- commentCountView.setTextColor(0xffff0000);
- } else {
- commentCountView.setTextColor(defaultTextColor);
- }
- }
-
- private void closeReply() {
- if (getDialog() != null) {
- dismissAllowingStateLoss();
- } else {
- context.finish();
- }
- }
-
- /**
- * Set if the dialog is able to be closed, by pressing outside of the
- * dialog, or something else.
- */
- private void setClosable(boolean e) {
- if (getDialog() != null) {
- getDialog().setCanceledOnTouchOutside(e);
- setCancelable(e);
- }
- }
-
- /**
- * Flip to an page with an animation. Sets the correct text on the
- * cancelButton:
- *
- * @param position 0-2
- */
- private void flipPage(int position) {
- boolean flipBack = position < page;
-
- page = position;
-
- if (flipBack) {
- flipper.setInAnimation(ViewFlipperAnimations.BACK_IN);
- flipper.setOutAnimation(ViewFlipperAnimations.BACK_OUT);
- } else {
- flipper.setInAnimation(ViewFlipperAnimations.NEXT_IN);
- flipper.setOutAnimation(ViewFlipperAnimations.NEXT_OUT);
- }
- flipper.setDisplayedChild(position);
-
- if (page == 0) {
- cancelButton.setText(R.string.cancel);
- } else if (page == 1) {
- cancelButton.setText(R.string.back);
- } else if (page == 2) {
- cancelButton.setText(R.string.close);
- }
-
- if (page == 1) {
- captchaLayout.load();
- submitButton.setEnabled(captchaResponse != null);
- } else if (page == 0) {
- submitButton.setEnabled(true);
- }
- }
-
- /**
- * Set the picked image in the imageView. Sets the file in the draft. Call
- * null on the file to empty the imageView.
- *
- * @param name the filename
- * @param file the file
- */
- private void setFile(final String name, final File file) {
- draft.file = file;
- draft.fileName = name;
-
- if (file == null) {
- fileButton.setImageResource(ThemeHelper.getInstance().getTheme().isLightTheme ? R.drawable.ic_action_attachment : R.drawable.ic_action_attachment_dark);
- imageViewContainer.removeAllViews();
- imageViewContainer.setVisibility(View.GONE);
- fileNameView.setText("");
- fileNameView.setVisibility(View.GONE);
- spoilerImageView.setVisibility(View.GONE);
- spoilerImageView.setChecked(false);
- fileStatusView.setVisibility(View.GONE);
- } else {
- fileButton.setImageResource(ThemeHelper.getInstance().getTheme().isLightTheme ? R.drawable.ic_action_cancel : R.drawable.ic_action_cancel_dark);
- fileNameView.setVisibility(View.VISIBLE);
- fileNameView.setText(name);
-
- Board b = ChanApplication.getBoardManager().getBoardByValue(loadable.board);
- spoilerImageView.setVisibility(b != null && b.spoilers ? View.VISIBLE : View.GONE);
-
- if (b != null) {
- boolean probablyWebm = name.endsWith(".webm");
- int maxSize = probablyWebm ? b.maxWebmSize : b.maxFileSize;
- if (file.length() > maxSize) {
- String fileSize = AndroidUtils.getReadableFileSize((int) file.length(), false);
- String maxSizeString = AndroidUtils.getReadableFileSize(maxSize, false);
- String text = getString(probablyWebm ? R.string.reply_webm_too_big : R.string.reply_file_too_big, fileSize, maxSizeString);
- fileStatusView.setVisibility(View.VISIBLE);
- fileStatusView.setText(text);
- } else {
- fileStatusView.setVisibility(View.GONE);
- }
- }
-
- imageViewContainer.setVisibility(View.VISIBLE);
- imageViewContainer.setView(null);
- imageViewContainer.post(new Runnable() {
- public void run() {
- if (file.length() < 10 * 1024 * 1024) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- if (context == null)
- return;
-
- final Bitmap bitmap = ImageDecoder.decodeFile(file, imageViewContainer.getWidth(), imageViewContainer.getWidth());
-
- context.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (context != null) {
- if (bitmap != null) {
- ImageView imageView = new ImageView(context);
- imageViewContainer.setView(imageView);
- imageView.setAdjustViewBounds(true);
- imageView.setMaxWidth(imageViewContainer.getWidth());
- imageView.setMaxHeight(imageViewContainer.getWidth());
- imageView.setImageBitmap(bitmap);
- } else {
- noPreview(imageViewContainer);
- }
- }
- }
- });
- }
- }).start();
- } else {
- noPreview(imageViewContainer);
- }
- }
- });
- }
- }
-
- private void noPreview(LoadView loadView) {
- TextView text = new TextView(context);
- text.setLayoutParams(AndroidUtils.MATCH_WRAP_PARAMS);
- text.setGravity(Gravity.CENTER);
- text.setText(R.string.reply_no_preview);
- text.setTextSize(16f);
- int padding = dp(16);
- text.setPadding(padding, padding, padding, padding);
- loadView.setView(text);
- }
-
- /**
- * Submit button clicked at page 1
- */
- private void submit() {
- submitButton.setEnabled(false);
- cancelButton.setEnabled(false);
- setClosable(false);
-
- responseContainer.setView(null);
-
- draft.name = nameView.getText().toString();
- draft.options = emailView.getText().toString();
- draft.subject = subjectView.getText().toString();
- draft.comment = commentView.getText().toString();
- draft.captchaResponse = captchaResponse;
-
- draft.fileName = "image";
- String n = fileNameView.getText().toString();
- if (!TextUtils.isEmpty(n)) {
- draft.fileName = n;
- }
-
- draft.resto = loadable.isThreadMode() ? loadable.no : -1;
- draft.board = loadable.board;
-
- if (ChanSettings.getPassEnabled()) {
- draft.usePass = true;
- draft.passId = ChanSettings.getPassId();
- }
-
- Board b = ChanApplication.getBoardManager().getBoardByValue(loadable.board);
- draft.spoilerImage = b != null && b.spoilers && spoilerImageView.isChecked();
-
- ChanApplication.getReplyManager().postReply(draft, new ReplyManager.ReplyListener() {
- @Override
- public void onResponse(ReplyManager.ReplyResponse response) {
- handleSubmitResponse(response);
- }
- });
- }
-
- /**
- * Got response about or reply from ReplyManager
- *
- * @param response
- */
- private void handleSubmitResponse(ReplyManager.ReplyResponse response) {
- if (context == null)
- return;
-
- if (response.isNetworkError || response.isUserError) {
- int resId = R.string.reply_error;
- Toast.makeText(context, resId, Toast.LENGTH_LONG).show();
- submitButton.setEnabled(true);
- cancelButton.setEnabled(true);
- setClosable(true);
- captchaResponse = null;
- if (ChanSettings.passLoggedIn()) {
- flipPage(0);
- } else {
- flipPage(1);
- captchaLayout.reset();
- }
- } else if (response.isSuccessful) {
- shouldSaveDraft = false;
- Toast.makeText(context, R.string.reply_success, Toast.LENGTH_SHORT).show();
-
- // Pin thread on successful post
- if (ChanSettings.getPinOnPost() && loadable.isThreadMode()) {
- ChanApplication.getWatchManager().addPin(loadable);
- }
-
- closeReply();
- } else {
- cancelButton.setEnabled(true);
- setClosable(true);
-
- WebView webView = new WebView(context);
- WebSettings settings = webView.getSettings();
- settings.setSupportZoom(true);
-
- webView.loadData(response.responseData, "text/html", null);
-
- responseContainer.setView(webView);
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/SettingsFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/SettingsFragment.java
deleted file mode 100644
index e80c6af3..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/SettingsFragment.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.fragment;
-
-import android.content.Intent;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Bundle;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceGroup;
-import android.view.View;
-import android.widget.ListView;
-import android.widget.Toast;
-
-import org.floens.chan.R;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.ui.activity.AboutActivity;
-import org.floens.chan.ui.activity.BaseActivity;
-import org.floens.chan.ui.activity.LicenseActivity;
-import org.floens.chan.ui.activity.SettingsActivity;
-import org.floens.chan.utils.ThemeHelper;
-
-public class SettingsFragment extends PreferenceFragment {
- private int clickCount = 0;
- private boolean argumentsRead = false;
-
- private Preference developerPreference;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preference);
-
- Preference aboutLicences = findPreference("about_licenses");
- if (aboutLicences != null) {
- aboutLicences.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- startActivity(new Intent(getActivity(), AboutActivity.class));
-
- return true;
- }
- });
- }
-
- Preference aboutLicence = findPreference("about_license");
- if (aboutLicence != null) {
- aboutLicence.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- startActivity(new Intent(getActivity(), LicenseActivity.class));
-
- return true;
- }
- });
- }
-
- Preference aboutVersion = findPreference("about_version");
- if (aboutVersion != null) {
- aboutVersion.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- if (++clickCount >= 5) {
- clickCount = 0;
-
- boolean enabled = !ChanSettings.getDeveloper();
- ChanSettings.setDeveloper(enabled);
- updateDeveloperPreference();
-
- Toast.makeText(getActivity(), (enabled ? "Enabled " : "Disabled ") + "developer options",
- Toast.LENGTH_LONG).show();
- }
-
- return true;
- }
- });
-
- String version = "";
- try {
- version = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0).versionName;
- } catch (NameNotFoundException e) {
- e.printStackTrace();
- }
-
- aboutVersion.setTitle(R.string.app_name);
- aboutVersion.setSummary(version);
- }
-
- developerPreference = findPreference("about_developer");
- ((PreferenceGroup) findPreference("group_about")).removePreference(developerPreference);
- updateDeveloperPreference();
-
- final ListPreference theme = (ListPreference) findPreference("preference_theme");
- String currentValue = theme.getValue();
- if (currentValue == null) {
- theme.setValue((String) theme.getEntryValues()[0]);
- currentValue = theme.getValue();
- }
- updateSummary(theme, currentValue);
-
- theme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- updateSummary(theme, newValue.toString());
-
- // Thanks! https://github.com/CyanogenMod/android_packages_apps_Calculator/blob/cm-10.2/src/com/android/calculator2/view/PreferencesFragment.java
- if (!newValue.toString().equals(ThemeHelper.getInstance().getTheme().name)) {
- Intent intent = new Intent(getActivity(), SettingsActivity.class);
-
- intent.putExtra("pos", getListView().getFirstVisiblePosition());
- View child = getListView().getChildAt(0);
- intent.putExtra("off", child != null ? child.getTop() : 0);
-
- ((SettingsActivity) getActivity()).restart(intent);
- }
-
- return true;
- }
- });
-
- final ListPreference font = (ListPreference) findPreference("preference_font");
- String currentFontValue = font.getValue();
- if (currentFontValue == null) {
- font.setValue((String) font.getEntryValues()[0]);
- currentFontValue = font.getValue();
- }
- updateSummary(font, currentFontValue);
-
- font.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- updateSummary(font, newValue.toString());
- BaseActivity.doRestartOnResume = true;
-
- return true;
- }
- });
- }
-
- public void onStart() {
- super.onStart();
-
- final Bundle args = getArguments();
- if (args != null && !argumentsRead) {
- argumentsRead = true;
- getListView().setSelectionFromTop(args.getInt("pos", 0), args.getInt("off", 0));
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- final Preference watchPreference = findPreference("watch_settings");
- if (watchPreference != null) {
- watchPreference.setSummary(ChanSettings.getWatchEnabled() ? R.string.watch_summary_enabled
- : R.string.watch_summary_disabled);
- }
-
- final Preference passPreference = findPreference("pass_settings");
- if (passPreference != null) {
- passPreference.setSummary(ChanSettings.getPassEnabled() ? R.string.pass_summary_enabled
- : R.string.pass_summary_disabled);
- }
- }
-
- private ListView getListView() {
- return (ListView) getView().findViewById(android.R.id.list);
- }
-
- private void updateDeveloperPreference() {
- if (ChanSettings.getDeveloper()) {
- ((PreferenceGroup) findPreference("group_about")).addPreference(developerPreference);
- } else {
- ((PreferenceGroup) findPreference("group_about")).removePreference(developerPreference);
- }
- }
-
- private void updateSummary(ListPreference list, String value) {
- int index = list.findIndexOfValue(value);
- list.setSummary(list.getEntries()[index]);
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java
deleted file mode 100644
index 810eab92..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.fragment;
-
-import android.app.Fragment;
-import android.content.Context;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
-import android.widget.AbsListView;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.Button;
-import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.RelativeLayout;
-import android.widget.SearchView;
-import android.widget.TextView;
-
-import com.android.volley.NetworkError;
-import com.android.volley.NoConnectionError;
-import com.android.volley.ServerError;
-import com.android.volley.VolleyError;
-
-import org.floens.chan.R;
-import org.floens.chan.core.settings.ChanSettings;
-import org.floens.chan.core.loader.ChanLoader;
-import org.floens.chan.core.loader.EndOfLineException;
-import org.floens.chan.core.manager.ThreadManager;
-import org.floens.chan.core.model.ChanThread;
-import org.floens.chan.core.model.Loadable;
-import org.floens.chan.core.model.Post;
-import org.floens.chan.ui.activity.BaseActivity;
-import org.floens.chan.ui.activity.ImageViewActivity;
-import org.floens.chan.ui.adapter.PostAdapter;
-import org.floens.chan.ui.view.LoadView;
-import org.floens.chan.utils.AndroidUtils;
-import org.floens.chan.utils.ImageSaver;
-import org.floens.chan.utils.ThemeHelper;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.net.ssl.SSLException;
-
-import static org.floens.chan.utils.AndroidUtils.dp;
-import static org.floens.chan.utils.AndroidUtils.setItemBackground;
-
-public class ThreadFragment extends Fragment implements ThreadManager.ThreadManagerListener, PostAdapter.PostAdapterCallback {
- private ThreadManager threadManager;
- private Loadable loadable;
-
- private PostAdapter postAdapter;
- private LoadView container;
- private AbsListView listView;
- private ImageView skip;
- private FilterView filterView;
-
- private SkipLogic skipLogic;
- private int highlightedPost = -1;
- private ThreadManager.ViewMode viewMode = ThreadManager.ViewMode.LIST;
- private boolean isFiltering = false;
-
- public static ThreadFragment newInstance(BaseActivity activity) {
- ThreadFragment fragment = new ThreadFragment();
- fragment.threadManager = new ThreadManager(activity, fragment);
-
- return fragment;
- }
-
- public void bindLoadable(Loadable l) {
- if (loadable != null) {
- threadManager.unbindLoader();
- }
-
- setEmpty();
-
- loadable = l;
- threadManager.bindLoader(loadable);
- }
-
- public void requestData() {
- threadManager.requestData();
- }
-
- public void requestNextData() {
- threadManager.requestNextData();
- }
-
- public void reload() {
- setEmpty();
-
- threadManager.requestData();
- }
-
- public void openReply() {
- if (threadManager.hasLoader()) {
- threadManager.openReply(true);
- }
- }
-
- public boolean hasLoader() {
- return threadManager.hasLoader();
- }
-
- public void setViewMode(ThreadManager.ViewMode viewMode) {
- this.viewMode = viewMode;
- }
-
- public ChanLoader getLoader() {
- return threadManager.getChanLoader();
- }
-
- public void startFiltering() {
- if (filterView != null) {
- isFiltering = true;
- filterView.setVisibility(View.VISIBLE);
- filterView.focusSearch();
- }
- }
-
- public void highlightPost(int no) {
- highlightedPost = no;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
-
- if (threadManager != null) {
- threadManager.onDestroy();
- }
- threadManager = null;
- loadable = null;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onStart() {
- super.onStart();
-
- if (threadManager != null) {
- threadManager.onStart();
- }
- }
-
- @Override
- public void onStop() {
- super.onStop();
-
- if (threadManager != null) {
- threadManager.onStop();
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
- container = new LoadView(inflater.getContext());
- if (loadable == null) {
- container.setView(getCenteredMessageView(R.string.thread_not_specified));
- }
-
- return container;
- }
-
- @Override
- public void onPostClicked(Post post) {
- if (loadable.isBoardMode() || loadable.isCatalogMode()) {
- ((BaseActivity) getActivity()).onOPClicked(post);
- } else if (loadable.isThreadMode() && isFiltering) {
- filterView.clearSearch();
-// postAdapter.scrollToPost(post.no);
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (loadable.isThreadMode()) {
- switch (item.getItemId()) {
- case R.id.action_download_album:
- // Get the posts with images
- ArrayList imagePosts = new ArrayList<>();
-// for (Post post : postAdapter.getList()) {
-// if (post.hasImage) {
-// imagePosts.add(post);
-// }
-// }
- if (imagePosts.size() > 0) {
- List list = new ArrayList<>();
-
- String folderName = Post.generateTitle(imagePosts.get(0), 10);
-
- String filename;
- for (Post post : imagePosts) {
- filename = (ChanSettings.getImageSaveOriginalFilename() ? post.tim : post.filename) + "." + post.ext;
- list.add(new ImageSaver.DownloadPair(post.imageUrl, filename));
- }
-
- ImageSaver.getInstance().saveAll(getActivity(), folderName, list);
- }
-
- return true;
- }
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onThumbnailClicked(Post source) {
- if (postAdapter != null) {
- ImageViewActivity.launch(getActivity(), postAdapter, source.no, threadManager);
- }
- }
-
- @Override
- public void onScrollTo(int post) {
- if (postAdapter != null) {
-// postAdapter.scrollToPost(post);
- }
- }
-
- @Override
- public void onRefreshView() {
- if (postAdapter != null) {
- postAdapter.notifyDataSetChanged();
- }
- }
-
- @Override
- public void onOpenThread(final Loadable thread, int highlightedPost) {
- ((BaseActivity) getActivity()).onOpenThread(thread);
- this.highlightedPost = highlightedPost;
- }
-
- @Override
- public ThreadManager.ViewMode getViewMode() {
- return viewMode;
- }
-
- @Override
- public void onThreadLoaded(ChanThread thread) {
- if (postAdapter == null) {
- if (container != null) {
- container.setView(createView());
- }
- }
-
-// postAdapter.setError(null);
- postAdapter.setThread(thread);
-
- if (highlightedPost >= 0) {
- threadManager.highlightPost(highlightedPost);
-// postAdapter.scrollToPost(highlightedPost);
- highlightedPost = -1;
- }
-
- ((BaseActivity) getActivity()).onThreadLoaded(thread);
- }
-
- @Override
- public void onThreadLoadError(VolleyError error) {
- if (error instanceof EndOfLineException) {
-// postAdapter.setEndOfLine(true);
- } else {
- if (postAdapter == null) {
- if (container != null) {
- container.setView(getLoadErrorView(error));
- }
- } else {
-// postAdapter.setError(getLoadErrorText(error));
- }
- }
-
- highlightedPost = -1;
- }
-
- public void onFilteredResults(String filter, int count, boolean all) {
- isFiltering = !all;
-
- if (filterView != null) {
- filterView.setText(filter, count, all);
- }
- }
-
- @Override
- public Loadable getLoadable() {
- return loadable;
- }
-
- @Override
- public void onListScrolledToBottom() {
-
- }
-
- private RelativeLayout createView() {
- RelativeLayout compound = new RelativeLayout(getActivity());
-
- LinearLayout listViewContainer = new LinearLayout(getActivity());
- listViewContainer.setOrientation(LinearLayout.VERTICAL);
-
- filterView = new FilterView(getActivity());
- filterView.setVisibility(View.GONE);
- listViewContainer.addView(filterView, AndroidUtils.MATCH_WRAP_PARAMS);
-
- if (viewMode == ThreadManager.ViewMode.LIST) {
- ListView list = new ListView(getActivity());
- listView = list;
-// postAdapter = new PostAdapter(getActivity(), threadManager, listView, this);
-// listView.setAdapter(postAdapter);
- list.setSelectionFromTop(loadable.listViewIndex, loadable.listViewTop);
- } else if (viewMode == ThreadManager.ViewMode.GRID) {
- GridView grid = new GridView(getActivity());
- grid.setNumColumns(GridView.AUTO_FIT);
- int postGridWidth = getActivity().getResources().getDimensionPixelSize(R.dimen.post_grid_width);
- grid.setColumnWidth(postGridWidth);
- listView = grid;
-// postAdapter = new PostAdapter(getActivity(), threadManager, listView, this);
-// listView.setAdapter(postAdapter);
- listView.setSelection(loadable.listViewIndex);
- }
-
- listView.setOnScrollListener(new OnScrollListener() {
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- if (!isFiltering) {
- if (skipLogic != null) {
- skipLogic.onScrollStateChanged(view, scrollState);
- }
- }
- }
-
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- if (!isFiltering) {
- if (loadable != null) {
- int index = view.getFirstVisiblePosition();
- View v = view.getChildAt(0);
- int top = v == null ? 0 : v.getTop();
- if (index != 0 || top != 0) {
- loadable.listViewIndex = index;
- loadable.listViewTop = top;
- }
- }
- if (skipLogic != null) {
- skipLogic.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
- }
- }
- }
- });
-
- listViewContainer.addView(listView, AndroidUtils.MATCH_PARAMS);
-
- compound.addView(listViewContainer, AndroidUtils.MATCH_PARAMS);
-
- if (loadable.isThreadMode()) {
- skip = new ImageView(getActivity());
- skip.setImageResource(R.drawable.skip_arrow_down);
- skip.setVisibility(View.GONE);
- compound.addView(skip, AndroidUtils.WRAP_PARAMS);
-
- RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) skip.getLayoutParams();
- params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
- params.setMargins(0, 0, dp(8), dp(8));
- skip.setLayoutParams(params);
-
- skipLogic = new SkipLogic(skip, listView);
- }
-
- return compound;
- }
-
- private void setEmpty() {
- postAdapter = null;
-
- if (container != null) {
- container.setView(null);
- }
-
- if (listView != null) {
- listView.setOnScrollListener(null);
- listView = null;
- }
-
- skip = null;
- skipLogic = null;
- filterView = null;
- }
-
- private void doFilter(String filter) {
- if (postAdapter != null) {
-// postAdapter.setFilter(filter);
- }
- }
-
- /**
- * Returns an TextView containing the appropriate error message
- *
- * @param error
- * @return
- */
- private View getLoadErrorView(VolleyError error) {
- String errorMessage = getLoadErrorText(error);
-
- LinearLayout wrapper = new LinearLayout(getActivity());
- wrapper.setLayoutParams(AndroidUtils.MATCH_PARAMS);
- wrapper.setGravity(Gravity.CENTER);
- wrapper.setOrientation(LinearLayout.VERTICAL);
-
- TextView text = new TextView(getActivity());
- text.setLayoutParams(AndroidUtils.WRAP_PARAMS);
- text.setText(errorMessage);
- text.setTextSize(24f);
- wrapper.addView(text);
-
- Button retry = new Button(getActivity());
- retry.setText(R.string.thread_load_failed_retry);
- retry.setLayoutParams(AndroidUtils.WRAP_PARAMS);
- retry.setGravity(Gravity.CENTER);
- retry.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (threadManager != null) {
- reload();
- }
- }
- });
-
- wrapper.addView(retry);
-
- LinearLayout.LayoutParams retryParams = (LinearLayout.LayoutParams) retry.getLayoutParams();
- retryParams.topMargin = dp(12);
- retry.setLayoutParams(retryParams);
-
- return wrapper;
- }
-
- private String getLoadErrorText(VolleyError error) {
- String errorMessage;
-
- if (error.getCause() instanceof SSLException) {
- errorMessage = getString(R.string.thread_load_failed_ssl);
- } else if ((error instanceof NoConnectionError) || (error instanceof NetworkError)) {
- errorMessage = getString(R.string.thread_load_failed_network);
- } else if (error instanceof ServerError) {
- errorMessage = getString(R.string.thread_load_failed_server);
- } else {
- errorMessage = getString(R.string.thread_load_failed_parsing);
- }
-
- return errorMessage;
- }
-
- private View getCenteredMessageView(int stringResourceId) {
- LinearLayout layout = new LinearLayout(getActivity());
- layout.setGravity(Gravity.CENTER);
- TextView messageView = new TextView(getActivity());
- messageView.setText(getString(stringResourceId));
- layout.addView(messageView);
-
- return layout;
- }
-
- private static class SkipLogic {
- private final ImageView skip;
- private int lastFirstVisibleItem;
- private int lastTop;
- private boolean up = false;
- private final AbsListView listView;
-
- public SkipLogic(ImageView skipView, AbsListView list) {
- skip = skipView;
- listView = list;
- skip.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (up) {
- listView.setSelection(0);
- } else {
- listView.setSelection(listView.getCount() - 1);
- }
- skip.setVisibility(View.GONE);
- }
- });
- }
-
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- if (scrollState != AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
- skip.setVisibility(View.VISIBLE);
- }
- }
-
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- View v = view.getChildAt(0);
- int top = (v == null) ? 0 : v.getTop();
-
- if (firstVisibleItem == lastFirstVisibleItem) {
- if (top > lastTop) {
- onUp();
- } else if (top < lastTop) {
- onDown();
- }
- } else {
- if (firstVisibleItem > lastFirstVisibleItem) {
- onDown();
- } else {
- onUp();
- }
- }
- lastFirstVisibleItem = firstVisibleItem;
- lastTop = top;
- }
-
- private void onUp() {
- skip.setImageResource(R.drawable.skip_arrow_up);
- up = true;
- }
-
- private void onDown() {
- skip.setImageResource(R.drawable.skip_arrow_down);
- up = false;
- }
- }
-
- public class FilterView extends LinearLayout {
- private SearchView searchView;
- private TextView textView;
-
- public FilterView(Context activity) {
- super(activity);
- init();
- }
-
- public FilterView(Context activity, AttributeSet attr) {
- super(activity, attr);
- init();
- }
-
- public FilterView(Context activity, AttributeSet attr, int style) {
- super(activity, attr, style);
- init();
- }
-
- public void focusSearch() {
- searchView.requestFocus();
- }
-
- public void clearSearch() {
- searchView.setQuery("", false);
- doFilter("");
- setVisibility(View.GONE);
- }
-
- private void init() {
- setOrientation(LinearLayout.VERTICAL);
-
- LinearLayout searchViewContainer = new LinearLayout(getContext());
- searchViewContainer.setOrientation(LinearLayout.HORIZONTAL);
-
- searchView = new SearchView(getContext());
- searchView.setIconifiedByDefault(false);
- searchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
- searchViewContainer.addView(searchView);
- LinearLayout.LayoutParams searchViewParams = (LinearLayout.LayoutParams) searchView.getLayoutParams();
- searchViewParams.weight = 1f;
- searchViewParams.width = 0;
- searchViewParams.height = LayoutParams.MATCH_PARENT;
- searchView.setLayoutParams(searchViewParams);
-
- ImageView closeButton = new ImageView(getContext());
- searchViewContainer.addView(closeButton);
- closeButton.setImageResource(ThemeHelper.getInstance().getTheme().isLightTheme ? R.drawable.ic_action_cancel : R.drawable.ic_action_cancel_dark);
- LinearLayout.LayoutParams closeButtonParams = (LinearLayout.LayoutParams) closeButton.getLayoutParams();
- searchViewParams.width = dp(48);
- searchViewParams.height = LayoutParams.MATCH_PARENT;
- closeButton.setLayoutParams(closeButtonParams);
- setItemBackground(closeButton);
- int padding = dp(8);
- closeButton.setPadding(padding, padding, padding, padding);
-
- closeButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- clearSearch();
- }
- });
-
- addView(searchViewContainer, new LayoutParams(LayoutParams.MATCH_PARENT, dp(48)));
-
- searchView.setQueryHint(getString(R.string.search_hint));
- searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String query) {
- doFilter(query);
- return false;
- }
-
- @Override
- public boolean onQueryTextChange(String newText) {
- doFilter(newText);
- return false;
- }
- });
-
- textView = new TextView(getContext());
- textView.setGravity(Gravity.CENTER);
- addView(textView, new LayoutParams(LayoutParams.MATCH_PARENT, dp(28)));
- }
-
- private void setText(String filter, int count, boolean all) {
- if (all) {
- textView.setText("");
- } else {
-// String posts = getContext().getString(count == 1 ? R.string.one_post : R.string.multiple_posts);
-// String text = getContext().getString(R.string.search_results, Integer.toString(count), posts, filter);
-// textView.setText(text);
- }
- }
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/helper/PostHelper.java b/Clover/app/src/main/java/org/floens/chan/ui/helper/PostHelper.java
index 26961bcd..1bff0825 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/helper/PostHelper.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/helper/PostHelper.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.helper;
import android.content.res.Resources;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/helper/SwipeItemAnimator.java b/Clover/app/src/main/java/org/floens/chan/ui/helper/SwipeItemAnimator.java
index 64a94ee4..6f7f6e79 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/helper/SwipeItemAnimator.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/helper/SwipeItemAnimator.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.helper;
import android.support.v4.view.ViewCompat;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/helper/SwipeListener.java b/Clover/app/src/main/java/org/floens/chan/ui/helper/SwipeListener.java
index ef7c7f28..96f698b3 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/helper/SwipeListener.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/helper/SwipeListener.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.helper;
import android.content.Context;
@@ -35,7 +52,6 @@ public class SwipeListener extends RecyclerView.ItemDecoration implements Recycl
private final int flingPixels;
private final int maxFlingPixels;
- private final Context context;
private Callback callback;
private final RecyclerView recyclerView;
private final LinearLayoutManager layoutManager;
@@ -83,7 +99,6 @@ public class SwipeListener extends RecyclerView.ItemDecoration implements Recycl
};
public SwipeListener(Context context, RecyclerView rv, Callback callback) {
- this.context = context;
recyclerView = rv;
this.callback = callback;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java
index d7b7e388..9fbe21a3 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.layout;
import android.content.Context;
@@ -326,7 +343,7 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima
@Override
public void onFilePickError() {
- Toast.makeText(getContext(), R.string.file_open_failed, Toast.LENGTH_LONG).show();
+ Toast.makeText(getContext(), R.string.reply_file_open_failed, Toast.LENGTH_LONG).show();
}
@Override
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
index 3b6d6a49..4ebd5dde 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
@@ -199,12 +199,12 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
ClipboardManager clipboard = (ClipboardManager) AndroidUtils.getAppRes().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Post text", post.comment.toString());
clipboard.setPrimaryClip(clip);
- Toast.makeText(getContext(), R.string.post_text_copied_to_clipboard, Toast.LENGTH_SHORT).show();
+ Toast.makeText(getContext(), R.string.post_text_copied, Toast.LENGTH_SHORT).show();
}
@Override
public void openLink(final String link) {
- if (ChanSettings.getOpenLinkConfirmation()) {
+ if (ChanSettings.openLinkConfirmation.get()) {
new AlertDialog.Builder(getContext())
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@@ -223,7 +223,7 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
@Override
public void openWebView(String title, String link) {
- AndroidUtils.openWebView((Activity)getContext(), title, link);
+ AndroidUtils.openWebView((Activity) getContext(), title, link);
}
@Override
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java b/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java
index 836d0ca0..20c5a9e8 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java
@@ -26,16 +26,14 @@ import android.content.Intent;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
-import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.core.manager.WatchManager;
import org.floens.chan.core.model.Pin;
import org.floens.chan.core.model.Post;
+import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.core.watch.PinWatcher;
import org.floens.chan.ui.activity.BoardActivity;
-import org.floens.chan.ui.activity.ChanActivity;
-import org.floens.chan.ui.activity.StartActivity;
import org.floens.chan.utils.AndroidUtils;
import java.util.ArrayList;
@@ -61,7 +59,7 @@ public class WatchNotifier extends Service {
super.onCreate();
nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- wm = ChanApplication.getWatchManager();
+ wm = Chan.getWatchManager();
startForeground(NOTIFICATION_ID, createNotification());
}
@@ -92,8 +90,8 @@ public class WatchNotifier extends Service {
}
private Notification createNotification() {
- boolean notifyQuotesOnly = ChanSettings.getWatchNotifyMode().equals("quotes");
- boolean soundQuotesOnly = ChanSettings.getWatchSound().equals("quotes");
+ boolean notifyQuotesOnly = ChanSettings.watchNotifyMode.get().equals("quotes");
+ boolean soundQuotesOnly = ChanSettings.watchSound.get().equals("quotes");
List list = new ArrayList<>();
List listQuoting = new ArrayList<>();
@@ -138,7 +136,7 @@ public class WatchNotifier extends Service {
}
}
- if (ChanApplication.getInstance().getApplicationInForeground()) {
+ if (Chan.getInstance().getApplicationInForeground()) {
ticker = false;
sound = false;
}
@@ -210,7 +208,6 @@ public class WatchNotifier extends Service {
* @param expandedLines A list of lines for the big notification, or null if not shown
* @param makeSound Should the notification make a sound
* @param target The target pin, or null to open the pinned pane on tap
- * @return
*/
@SuppressWarnings("deprecation")
private Notification getNotificationFor(String tickerText, String contentTitle, String contentText, int contentNumber,
@@ -231,7 +228,7 @@ public class WatchNotifier extends Service {
}
if (light) {
- long watchLed = ChanSettings.getWatchLed();
+ long watchLed = Long.parseLong(ChanSettings.watchLed.get(), 16);
if (watchLed >= 0) {
builder.setLights((int) watchLed, 1000, 1000);
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/settings/BooleanSettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/settings/BooleanSettingView.java
index bf9b180e..8612dd67 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/settings/BooleanSettingView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/settings/BooleanSettingView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.settings;
import android.support.v7.widget.SwitchCompat;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/settings/LinkSettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/settings/LinkSettingView.java
index b0a4e1d6..5bdb0af8 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/settings/LinkSettingView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/settings/LinkSettingView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.settings;
import android.view.View;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/settings/ListSettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/settings/ListSettingView.java
index 022b5cac..2a485ff0 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/settings/ListSettingView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/settings/ListSettingView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.settings;
import android.view.Gravity;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingView.java
index 5bb66e7f..9d4593de 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.settings;
import android.view.View;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsController.java
index d0ac8c34..3b525b2f 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsController.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.settings;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsGroup.java b/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsGroup.java
index 10352e81..3a69a21c 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsGroup.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsGroup.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.settings;
import java.util.ArrayList;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/settings/StringSettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/settings/StringSettingView.java
index 5edbb1b6..d94a740c 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/settings/StringSettingView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/settings/StringSettingView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.settings;
import android.app.AlertDialog;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java
index 6255663e..1ecfc495 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java
@@ -20,9 +20,7 @@ package org.floens.chan.ui.toolbar;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
-import android.widget.TextView;
-import org.floens.chan.R;
import org.floens.chan.ui.view.FloatingMenu;
import org.floens.chan.ui.view.FloatingMenuItem;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java
index 66780594..c606e906 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java
@@ -22,9 +22,9 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -54,7 +54,7 @@ import java.util.List;
import static org.floens.chan.utils.AndroidUtils.dp;
import static org.floens.chan.utils.AndroidUtils.getAttrColor;
-import static org.floens.chan.utils.AndroidUtils.getAttrDrawable;
+import static org.floens.chan.utils.AndroidUtils.setRoundItemBackground;
public class Toolbar extends LinearLayout implements View.OnClickListener, LoadView.Listener {
private ImageView arrowMenuView;
@@ -150,11 +150,7 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV
arrowMenuDrawable = new ArrowMenuDrawable();
arrowMenuView.setImageDrawable(arrowMenuDrawable);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- arrowMenuView.setBackground(getAttrDrawable(getContext(), android.R.attr.selectableItemBackgroundBorderless));
- } else {
- arrowMenuView.setBackgroundResource(R.drawable.item_background);
- }
+ setRoundItemBackground(arrowMenuView);
leftButtonContainer.addView(arrowMenuView, new FrameLayout.LayoutParams(dp(56), FrameLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER_VERTICAL));
@@ -352,6 +348,7 @@ public class Toolbar extends LinearLayout implements View.OnClickListener, LoadV
return searchViewWrapper;
} else {
+ @SuppressLint("InflateParams")
LinearLayout menu = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.toolbar_menu, null);
menu.setGravity(Gravity.CENTER_VERTICAL);
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenu.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenu.java
index 75778ba9..fb74a947 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenu.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenu.java
@@ -64,7 +64,7 @@ public class ToolbarMenu extends LinearLayout {
}
public ToolbarMenuItem createOverflow(ToolbarMenuItem.ToolbarMenuItemCallback callback) {
- ToolbarMenuItem overflow = addItem(new ToolbarMenuItem(getContext(), callback, 100, 100, R.drawable.ic_more));
+ ToolbarMenuItem overflow = addItem(new ToolbarMenuItem(getContext(), callback, 100, 100, R.drawable.ic_more_vert_white_24dp));
ImageView overflowImage = overflow.getView();
overflowImage.setLayoutParams(new LinearLayout.LayoutParams(dp(36), dp(54)));
overflowImage.setPadding(0, 0, dp(16), 0);
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java
index 361f6bd5..a85fb303 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java
@@ -19,17 +19,15 @@ package org.floens.chan.ui.toolbar;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import org.floens.chan.R;
import org.floens.chan.ui.view.FloatingMenu;
import org.floens.chan.ui.view.FloatingMenuItem;
import static org.floens.chan.utils.AndroidUtils.dp;
-import static org.floens.chan.utils.AndroidUtils.getAttrDrawable;
+import static org.floens.chan.utils.AndroidUtils.setRoundItemBackground;
public class ToolbarMenuItem implements View.OnClickListener, FloatingMenu.FloatingMenuCallback {
private ToolbarMenuItemCallback callback;
@@ -63,11 +61,7 @@ public class ToolbarMenuItem implements View.OnClickListener, FloatingMenu.Float
imageView.setImageDrawable(drawable);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- imageView.setBackground(getAttrDrawable(context, android.R.attr.selectableItemBackgroundBorderless));
- } else {
- imageView.setBackgroundResource(R.drawable.item_background);
- }
+ setRoundItemBackground(imageView);
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/transition/ImageTransition.java b/Clover/app/src/main/java/org/floens/chan/ui/transition/ImageTransition.java
deleted file mode 100644
index e92fd6aa..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/transition/ImageTransition.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.floens.chan.ui.transition;
-
-import org.floens.chan.controller.ControllerTransition;
-
-public class ImageTransition extends ControllerTransition {
- @Override
- public void perform() {
-
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/CrossfadeView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/CrossfadeView.java
index e1465362..72d03af5 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/CrossfadeView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/CrossfadeView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.animation.Animator;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/CustomNetworkImageView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/CustomNetworkImageView.java
deleted file mode 100644
index 224f96cb..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/CustomNetworkImageView.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/**
- * 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.floens.chan.ui.view;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ImageView;
-
-import com.android.volley.VolleyError;
-import com.android.volley.toolbox.ImageLoader;
-import com.android.volley.toolbox.ImageLoader.ImageContainer;
-import com.android.volley.toolbox.ImageLoader.ImageListener;
-
-/**
- * Custom version of NetworkImageView
- *
- * Handles fetching an image from a URL as well as the life-cycle of the
- * associated request.
- */
-public class CustomNetworkImageView extends ImageView {
- /**
- * The URL of the network image to load
- */
- private String mUrl;
-
- /**
- * Resource ID of the image to be used as a placeholder until the network
- * image is loaded.
- */
- private int mDefaultImageId;
-
- /**
- * Resource ID of the image to be used if the network response fails.
- */
- private int mErrorImageId;
-
- /**
- * Local copy of the ImageLoader.
- */
- private ImageLoader mImageLoader;
-
- /**
- * Current ImageContainer. (either in-flight or finished)
- */
- private ImageContainer mImageContainer;
-
- /**
- * Max amount to scale the image inside the view
- */
- private float mMaxScale = 1;
-
- private int mFadeTime;
-
- private int mForcedWidth = -1;
- private int mForcedHeight = -1;
-
- public CustomNetworkImageView(Context context) {
- this(context, null);
- }
-
- public CustomNetworkImageView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CustomNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- /**
- * How larger the inner bitmap is to the defined view size.
- *
- * @param amount
- */
- public void setMaxScale(float amount) {
- mMaxScale = amount;
- }
-
- public float getMaxScale() {
- return mMaxScale;
- }
-
- public void forceImageDimensions(int w, int h) {
- mForcedWidth = w;
- mForcedHeight = h;
- }
-
- public String getUrl() {
- return mUrl;
- }
-
- /**
- * Animate the image fading in.
- *
- * @param time duration of the fade animation in milliseconds
- */
- public void setFadeIn(int time) {
- mFadeTime = time;
- }
-
- /**
- * Sets URL of the image that should be loaded into this view. Note that
- * calling this will immediately either set the cached image (if available)
- * or the default image specified by
- * {@link CustomNetworkImageView#setDefaultImageResId(int)} on the view.
- *
- * NOTE: If applicable,
- * {@link CustomNetworkImageView#setDefaultImageResId(int)} and
- * {@link CustomNetworkImageView#setErrorImageResId(int)} should be called
- * prior to calling this function.
- *
- * @param url The URL that should be loaded into this ImageView.
- * @param imageLoader ImageLoader that will be used to make the request.
- */
- public void setImageUrl(String url, ImageLoader imageLoader) {
- mUrl = url;
- mImageLoader = imageLoader;
- // The URL has potentially changed. See if we need to load it.
- loadImageIfNecessary(false);
- }
-
- /**
- * Sets the default image resource ID to be used for this view until the
- * attempt to load it completes.
- */
- public void setDefaultImageResId(int defaultImage) {
- mDefaultImageId = defaultImage;
- }
-
- /**
- * Sets the error image resource ID to be used for this view in the event
- * that the image requested fails to load.
- */
- public void setErrorImageResId(int errorImage) {
- mErrorImageId = errorImage;
- }
-
- public void onErrorResponse(VolleyError error) {
- }
-
- /**
- * Loads the image for the view if it isn't already loaded.
- *
- * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.
- */
- void loadImageIfNecessary(final boolean isInLayoutPass) {
- int width;
- int height;
- boolean wrapWidth = false, wrapHeight = false;
-
- if (mForcedWidth < 0 || mForcedHeight < 0) {
- width = getWidth();
- height = getHeight();
-
- if (getLayoutParams() != null) {
- wrapWidth = getLayoutParams().width == LayoutParams.WRAP_CONTENT;
- wrapHeight = getLayoutParams().height == LayoutParams.WRAP_CONTENT;
- }
-
- // if the view's bounds aren't known yet, and this is not a
- // wrap-content/wrap-content
- // view, hold off on loading the image.
- boolean isFullyWrapContent = wrapWidth && wrapHeight;
- if (width == 0 && height == 0 && !isFullyWrapContent) {
- return;
- }
- } else {
- width = mForcedWidth;
- height = mForcedHeight;
- }
-
- // if the URL to be loaded in this view is empty, cancel any old
- // requests and clear the
- // currently loaded image.
- if (TextUtils.isEmpty(mUrl)) {
- if (mImageContainer != null) {
- mImageContainer.cancelRequest();
- mImageContainer = null;
- }
- setDefaultImageOrNull();
- return;
- }
-
- // if there was an old request in this view, check if it needs to be
- // canceled.
- if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
- if (mImageContainer.getRequestUrl().equals(mUrl)) {
- // if the request is from the same URL, return.
- return;
- } else {
- // if there is a pre-existing request, cancel it if it's
- // fetching a different URL.
- mImageContainer.cancelRequest();
- setDefaultImageOrNull();
- }
- }
-
- // Calculate the max image width / height to use while ignoring
- // WRAP_CONTENT dimens.
- int maxWidth = wrapWidth ? 0 : width;
- int maxHeight = wrapHeight ? 0 : height;
-
- // The pre-existing content of this view didn't match the current URL.
- // Load the new image
- // from the network.
- ImageContainer newContainer = mImageLoader.get(mUrl, new ImageListener() {
- @Override
- public void onErrorResponse(VolleyError error) {
- if (mErrorImageId != 0) {
- setImageResource(mErrorImageId);
- }
-
- CustomNetworkImageView.this.onErrorResponse(error);
- }
-
- @Override
- public void onResponse(final ImageContainer response, boolean isImmediate) {
- // If this was an immediate response that was delivered inside of a layout
- // pass do not set the image immediately as it will trigger a requestLayout
- // inside of a layout. Instead, defer setting the image by posting back to
- // the main thread.
- if (isImmediate && isInLayoutPass) {
- post(new Runnable() {
- @Override
- public void run() {
- onResponse(response, false);
- }
- });
- return;
- }
-
- if (response.getBitmap() != null) {
- setImageBitmap(response.getBitmap());
-
- if (mFadeTime > 0 && !isImmediate) {
- setAlpha(0f);
- animate().alpha(1f).setDuration(mFadeTime);
- }
- } else if (mDefaultImageId != 0) {
- setImageResource(mDefaultImageId);
- }
- }
- }, (int) (maxWidth * mMaxScale), (int) (maxHeight * mMaxScale));
-
- // update the ImageContainer to be the new bitmap container.
- mImageContainer = newContainer;
- }
-
- private void setDefaultImageOrNull() {
- if (mDefaultImageId != 0) {
- setImageResource(mDefaultImageId);
- } else {
- setImageBitmap(null);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- loadImageIfNecessary(true);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- if (mImageContainer != null) {
- // If the view was bound to an image request, cancel it and clear
- // out the image from the view.
- mImageContainer.cancelRequest();
- setImageBitmap(null);
- // also clear out the container so we can reload the image if
- // necessary.
- mImageContainer = null;
- }
- super.onDetachedFromWindow();
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- invalidate();
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/CustomScaleImageView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/CustomScaleImageView.java
index c9e02cf7..51ab9e81 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/CustomScaleImageView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/CustomScaleImageView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.content.Context;
@@ -71,6 +88,7 @@ public class CustomScaleImageView extends SubsamplingScaleImageView {
public interface Callback {
void onReady();
+
void onError(boolean wasInitial);
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/DragGripView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/DragGripView.java
deleted file mode 100644
index 41660c5e..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/DragGripView.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.floens.chan.ui.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.View;
-
-public class DragGripView extends View {
- private static final int[] ATTRS = new int[]{
- android.R.attr.gravity,
- android.R.attr.color,
- };
-
- private static final int HORIZ_RIDGES = 2;
-
- private int mGravity = Gravity.START;
- private int mColor = 0xff666666;
-
- private final Paint mRidgePaint;
- private final RectF mTempRectF = new RectF();
-
- private final float mRidgeSize;
- private final float mRidgeGap;
-
- // private int mWidth;
- private int mHeight;
-
- public DragGripView(Context context) {
- this(context, null, 0);
- }
-
- public DragGripView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public DragGripView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
- mGravity = a.getInteger(0, mGravity);
- mColor = a.getColor(1, mColor);
- a.recycle();
-
- final DisplayMetrics res = getResources().getDisplayMetrics();
- mRidgeSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, res);
- mRidgeGap = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, res);
-
- mRidgePaint = new Paint();
- mRidgePaint.setColor(mColor);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(
- View.resolveSize(
- (int) (HORIZ_RIDGES * (mRidgeSize + mRidgeGap) - mRidgeGap)
- + getPaddingLeft() + getPaddingRight(),
- widthMeasureSpec
- ),
- View.resolveSize(
- (int) mRidgeSize,
- heightMeasureSpec)
- );
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
-// float drawWidth = HORIZ_RIDGES * (mRidgeSize + mRidgeGap) - mRidgeGap;
- float drawLeft = getPaddingLeft();
-
- int vertRidges = (int) ((mHeight - getPaddingTop() - getPaddingBottom() + mRidgeGap)
- / (mRidgeSize + mRidgeGap));
- float drawHeight = vertRidges * (mRidgeSize + mRidgeGap) - mRidgeGap;
- float drawTop = getPaddingTop()
- + ((mHeight - getPaddingTop() - getPaddingBottom()) - drawHeight) / 2;
-
- for (int y = 0; y < vertRidges; y++) {
- for (int x = 0; x < HORIZ_RIDGES; x++) {
- mTempRectF.set(
- drawLeft + x * (mRidgeSize + mRidgeGap),
- drawTop + y * (mRidgeSize + mRidgeGap),
- drawLeft + x * (mRidgeSize + mRidgeGap) + mRidgeSize,
- drawTop + y * (mRidgeSize + mRidgeGap) + mRidgeSize);
- canvas.drawOval(mTempRectF, mRidgePaint);
- }
- }
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- mHeight = h;
-// mWidth = w;
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/FloatingMenu.java b/Clover/app/src/main/java/org/floens/chan/ui/view/FloatingMenu.java
index 13393927..c3105fdd 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/FloatingMenu.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/FloatingMenu.java
@@ -34,7 +34,6 @@ import org.floens.chan.R;
import org.floens.chan.utils.AndroidUtils;
import org.floens.chan.utils.Logger;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/HackyViewPager.java b/Clover/app/src/main/java/org/floens/chan/ui/view/HackyViewPager.java
deleted file mode 100644
index 71b870e1..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/HackyViewPager.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.view;
-
-import android.content.Context;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-/**
- * Hacky fix for Issue #4 and
- * http://code.google.com/p/android/issues/detail?id=18990
- *
- * ScaleGestureDetector seems to mess up the touch events, which means that
- * ViewGroups which make use of onInterceptTouchEvent throw a lot of
- * IllegalArgumentException: pointerIndex out of range.
- *
- * There's not much I can do in my code for now, but we can mask the result by
- * just catching the problem and ignoring it.
- *
- * @author Chris Banes
- */
-public class HackyViewPager extends ViewPager {
-
- public HackyViewPager(Context context) {
- super(context);
- }
-
- public HackyViewPager(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- try {
- return super.onInterceptTouchEvent(ev);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- return false;
- }
- }
-
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/LoadingBar.java b/Clover/app/src/main/java/org/floens/chan/ui/view/LoadingBar.java
index a3af7010..471e5bda 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/LoadingBar.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/LoadingBar.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java
index aa26bf96..e1dcc1d3 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java
@@ -25,7 +25,6 @@ import android.net.Uri;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.MediaController;
@@ -36,12 +35,12 @@ import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.davemorrissey.labs.subscaleview.ImageSource;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
+import org.floens.chan.core.cache.FileCache;
import org.floens.chan.core.model.PostImage;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.utils.AndroidUtils;
-import org.floens.chan.utils.FileCache;
import org.floens.chan.utils.Logger;
import java.io.File;
@@ -161,7 +160,7 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
}
// Also use volley for the thumbnails
- thumbnailRequest = ChanApplication.getVolleyImageLoader().get(thumbnailUrl, new com.android.volley.toolbox.ImageLoader.ImageListener() {
+ thumbnailRequest = Chan.getVolleyImageLoader().get(thumbnailUrl, new com.android.volley.toolbox.ImageLoader.ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
thumbnailRequest = null;
@@ -188,7 +187,7 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
}
callback.showProgress(this, true);
- bigImageRequest = ChanApplication.getFileCache().downloadFile(imageUrl, new FileCache.DownloadedCallback() {
+ bigImageRequest = Chan.getFileCache().downloadFile(imageUrl, new FileCache.DownloadedCallback() {
@Override
public void onProgress(long downloaded, long total, boolean done) {
callback.onProgress(MultiImageView.this, downloaded, total);
@@ -245,7 +244,7 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
}
callback.showProgress(this, true);
- gifRequest = ChanApplication.getFileCache().downloadFile(gifUrl, new FileCache.DownloadedCallback() {
+ gifRequest = Chan.getFileCache().downloadFile(gifUrl, new FileCache.DownloadedCallback() {
@Override
public void onProgress(long downloaded, long total, boolean done) {
callback.onProgress(MultiImageView.this, downloaded, total);
@@ -296,7 +295,7 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
public void setVideo(String videoUrl) {
callback.showProgress(this, true);
- videoRequest = ChanApplication.getFileCache().downloadFile(videoUrl, new FileCache.DownloadedCallback() {
+ videoRequest = Chan.getFileCache().downloadFile(videoUrl, new FileCache.DownloadedCallback() {
@Override
public void onProgress(long downloaded, long total, boolean done) {
callback.onProgress(MultiImageView.this, downloaded, total);
@@ -326,7 +325,7 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
}
public void setVideoFile(final File file) {
- if (ChanSettings.getVideoExternal()) {
+ if (ChanSettings.videoOpenExternal.get()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "video/*");
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/OptionalSwipeViewPager.java b/Clover/app/src/main/java/org/floens/chan/ui/view/OptionalSwipeViewPager.java
index ded4fde1..24a5009c 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/OptionalSwipeViewPager.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/OptionalSwipeViewPager.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java
deleted file mode 100644
index 88f62311..00000000
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.ui.view;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.text.Layout;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.SpannedString;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.text.method.LinkMovementMethod;
-import android.text.style.AbsoluteSizeSpan;
-import android.text.style.BackgroundColorSpan;
-import android.text.style.ClickableSpan;
-import android.text.style.ForegroundColorSpan;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.PopupMenu;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import com.android.volley.toolbox.NetworkImageView;
-
-import org.floens.chan.ChanApplication;
-import org.floens.chan.R;
-import org.floens.chan.core.model.Loadable;
-import org.floens.chan.core.model.Post;
-import org.floens.chan.core.model.PostLinkable;
-import org.floens.chan.utils.IconCache;
-import org.floens.chan.utils.ThemeHelper;
-import org.floens.chan.utils.Time;
-
-import static org.floens.chan.utils.AndroidUtils.setItemBackground;
-
-public class PostView extends LinearLayout implements View.OnClickListener, PostLinkable.Callback {
- private final static LinearLayout.LayoutParams matchParams = new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
- private final static LinearLayout.LayoutParams wrapParams = new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- private final static LinearLayout.LayoutParams matchWrapParams = new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
- private final static LinearLayout.LayoutParams wrapMatchParams = new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
-
- private final Activity context;
-
- private Post post;
- private PostViewCallback callback;
- private Loadable loadable;
- private int highlightQuotesNo = -1;
-
- private boolean ignoreNextOnClick = false;
-
- private boolean isBuild = false;
- private LinearLayout full;
- private LinearLayout contentContainer;
- private int imageSize;
- private ThumbnailView thumbnailView;
- private TextView titleView;
- private TextView commentView;
- private TextView repliesCountView;
- private LinearLayout iconsView;
- private ImageView stickyView;
- private ImageView closedView;
- private ImageView deletedView;
- private ImageView archivedView;
- private NetworkImageView countryView;
- private ImageView optionsView;
- private View lastSeen;
-
- /**
- * Represents a post. Use setPost(Post ThreadManager) to fill it with data.
- * setPost can be called multiple times (useful for ListView).
- *
- * @param activity
- */
- public PostView(Context activity) {
- super(activity);
- context = (Activity) activity;
- }
-
- public PostView(Context activity, AttributeSet attbs) {
- super(activity, attbs);
- context = (Activity) activity;
- }
-
- public PostView(Context activity, AttributeSet attbs, int style) {
- super(activity, attbs, style);
- context = (Activity) activity;
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- if (this.post != null) {
- setPostLinkableListener(null);
- }
- }
-
- public void setPost(final Post post, final PostViewCallback callback, boolean highlighted) {
- if (this.post != null) {
- // Remove callbacks from the old post while it is still set
- setPostLinkableListener(null);
- }
-
- this.post = post;
- this.callback = callback;
- this.loadable = callback.getLoadable();
-
- highlightQuotesNo = -1;
- setPostLinkableListener(this);
-
- boolean boardCatalogMode = loadable.isBoardMode() || loadable.isCatalogMode();
-
- TypedArray ta = context.obtainStyledAttributes(null, R.styleable.PostView, R.attr.post_style, 0);
-
- if (!isBuild) {
- buildView(context, ta);
- isBuild = true;
- }
-
- int dateColor = ta.getColor(R.styleable.PostView_date_color, 0);
- int savedReplyColor = ta.getColor(R.styleable.PostView_saved_reply_color, 0);
- int highlightedColor = ta.getColor(R.styleable.PostView_highlighted_color, 0);
- int detailSize = ta.getDimensionPixelSize(R.styleable.PostView_detail_size, 0);
-
- ta.recycle();
-
- if (post.hasImage) {
- thumbnailView.setVisibility(View.VISIBLE);
- thumbnailView.setUrl(post.thumbnailUrl, imageSize, imageSize);
- } else {
- thumbnailView.setVisibility(View.GONE);
- thumbnailView.setUrl(null, 0, 0);
- }
-
- CharSequence total = new SpannableString("");
-
- if (post.subjectSpan != null) {
- total = TextUtils.concat(total, post.subjectSpan);
- }
-
- if (isList()) {
- CharSequence relativeTime = DateUtils.getRelativeTimeSpanString(post.time * 1000L, Time.get(), DateUtils.SECOND_IN_MILLIS, 0);
- SpannableString date = new SpannableString("No." + post.no + " " + relativeTime);
- date.setSpan(new ForegroundColorSpan(dateColor), 0, date.length(), 0);
- date.setSpan(new AbsoluteSizeSpan(detailSize), 0, date.length(), 0);
-
- total = TextUtils.concat(total, post.subjectSpan == null ? "" : "\n", post.nameTripcodeIdCapcodeSpan, date, " ");
- }
-
- if (!TextUtils.isEmpty(total)) {
- titleView.setText(total);
- titleView.setVisibility(View.VISIBLE);
- } else {
- titleView.setVisibility(View.GONE);
- }
-
- commentView.setText(post.comment);
-
- if (loadable.isThreadMode()) {
- commentView.setMovementMethod(new PostViewMovementMethod());
- commentView.setOnClickListener(this);
- } else {
- commentView.setOnClickListener(null);
- commentView.setClickable(false);
- commentView.setMovementMethod(null);
- }
-
- if (isGrid() || ((post.isOP && boardCatalogMode && post.replies > 0) || (post.repliesFrom.size() > 0))) {
- repliesCountView.setVisibility(View.VISIBLE);
-
- String text = "";
-
- int count = boardCatalogMode ? post.replies : post.repliesFrom.size();
-
- if (count != 1) {
- text = count + " " + context.getString(R.string.multiple_replies);
- } else if (count == 1) {
- text = count + " " + context.getString(R.string.one_reply);
- }
-
- if (boardCatalogMode && post.images > 0) {
- if (post.images != 1) {
- text += ", " + post.images + " " + context.getString(R.string.multiple_images);
- } else {
- text += ", " + post.images + " " + context.getString(R.string.one_image);
- }
- }
-
- if (loadable.isThreadMode()) {
- repliesCountView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- callback.onShowPostReplies(post);
- }
- });
- }
-
- repliesCountView.setText(text);
- } else {
- repliesCountView.setVisibility(View.GONE);
- repliesCountView.setOnClickListener(null);
- }
-
- boolean showCountryFlag = isList() && !TextUtils.isEmpty(post.country) && !TextUtils.isEmpty(post.countryUrl);
- boolean showStickyIcon = isList() && post.sticky;
- boolean showDeletedIcon = isList() && post.deleted;
- boolean showArchivedIcon = isList() && post.archived;
- boolean showClosedIcon = isList() && post.closed && !showArchivedIcon;
-
- iconsView.setVisibility((showCountryFlag || showStickyIcon || showClosedIcon || showDeletedIcon || showArchivedIcon) ? View.VISIBLE : View.GONE);
-
- stickyView.setVisibility(showStickyIcon ? View.VISIBLE : View.GONE);
- closedView.setVisibility(showClosedIcon ? View.VISIBLE : View.GONE);
- deletedView.setVisibility(showDeletedIcon ? View.VISIBLE : View.GONE);
- archivedView.setVisibility(showArchivedIcon ? View.VISIBLE : View.GONE);
- if (showCountryFlag) {
- countryView.setVisibility(View.VISIBLE);
- countryView.setImageUrl(post.countryUrl, ChanApplication.getVolleyImageLoader());
- } else {
- countryView.setVisibility(View.GONE);
- countryView.setImageUrl(null, null);
- }
-
- if (post.isSavedReply) {
- full.setBackgroundColor(savedReplyColor);
- } else if (highlighted) {
- full.setBackgroundColor(highlightedColor);
- } else {
- full.setBackgroundColor(0x00000000);
- }
-
- if (callback.isPostLastSeen(post)) {
- lastSeen.setVisibility(View.VISIBLE);
- } else {
- lastSeen.setVisibility(View.GONE);
- }
- }
-
- public Post getPost() {
- return post;
- }
-
- public ThumbnailView getThumbnail() {
- return thumbnailView;
- }
-
- public void setHighlightQuotesWithNo(int no) {
- highlightQuotesNo = no;
- }
-
- private void setPostLinkableListener(PostLinkable.Callback callback) {
- if (post.comment instanceof SpannedString) {
- SpannedString commentSpannable = (SpannedString) post.comment;
- PostLinkable[] linkables = commentSpannable.getSpans(0, commentSpannable.length(), PostLinkable.class);
- for (PostLinkable linkable : linkables) {
- if (callback == null) {
- if (linkable.hasCallback(this)) {
- linkable.removeCallback(this);
- }
- } else {
- linkable.addCallback(callback);
- }
- }
- }
- }
-
- private void buildView(final Context context, TypedArray ta) {
- int thumbnailBackground = ta.getColor(R.styleable.PostView_thumbnail_background, 0);
- int replyCountColor = ta.getColor(R.styleable.PostView_reply_count_color, 0);
-
- int iconPadding = ta.getDimensionPixelSize(R.styleable.PostView_icon_padding, 0);
- int iconWidth = ta.getDimensionPixelSize(R.styleable.PostView_icon_width, 0);
- int iconHeight = ta.getDimensionPixelSize(R.styleable.PostView_icon_height, 0);
- int gridHeight = ta.getDimensionPixelSize(R.styleable.PostView_grid_height, 0);
- int optionsSpacing = ta.getDimensionPixelSize(R.styleable.PostView_options_spacing, 0);
- int titleSize = ta.getDimensionPixelSize(R.styleable.PostView_title_size, 0);
- int optionsLeftPadding = ta.getDimensionPixelSize(R.styleable.PostView_options_left_padding, 0);
- int optionsTopPadding = ta.getDimensionPixelSize(R.styleable.PostView_options_top_padding, 0);
- int optionsRightPadding = ta.getDimensionPixelSize(R.styleable.PostView_options_right_padding, 0);
- int optionsBottomPadding = ta.getDimensionPixelSize(R.styleable.PostView_options_bottom_padding, 0);
- int lastSeenHeight = ta.getDimensionPixelSize(R.styleable.PostView_last_seen_height, 0);
-
- int postListMaxHeight = ta.getDimensionPixelSize(R.styleable.PostView_list_comment_max_height, 0);
-
- int postCommentSize = 0;
- int commentPadding = 0;
- int postPadding = 0;
- imageSize = 0;
- int repliesCountSize = 0;
- if (isList()) {
- postCommentSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());
- commentPadding = ta.getDimensionPixelSize(R.styleable.PostView_list_comment_padding, 0);
- postPadding = ta.getDimensionPixelSize(R.styleable.PostView_list_padding, 0);
- imageSize = ta.getDimensionPixelSize(R.styleable.PostView_list_image_size, 0);
- repliesCountSize = ta.getDimensionPixelSize(R.styleable.PostView_list_replies_count_size, 0);
- } else if (isGrid()) {
- postCommentSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12 - 1, getResources().getDisplayMetrics());
- commentPadding = ta.getDimensionPixelSize(R.styleable.PostView_grid_comment_padding, 0);
- postPadding = ta.getDimensionPixelSize(R.styleable.PostView_grid_padding, 0);
- imageSize = ta.getDimensionPixelSize(R.styleable.PostView_grid_image_size, 0);
- repliesCountSize = ta.getDimensionPixelSize(R.styleable.PostView_grid_replies_count_size, 0);
- }
-
- RelativeLayout wrapper = new RelativeLayout(context);
- wrapper.setLayoutParams(matchParams);
-
- full = new LinearLayout(context);
- if (isList()) {
- full.setOrientation(HORIZONTAL);
- wrapper.addView(full, matchParams);
- } else if (isGrid()) {
- full.setOrientation(VERTICAL);
- wrapper.addView(full, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, gridHeight));
- }
-
- LinearLayout imageContainer = new LinearLayout(context);
- imageContainer.setOrientation(VERTICAL);
- imageContainer.setBackgroundColor(thumbnailBackground);
-
- // Create thumbnail
- thumbnailView = new ThumbnailView(context);
- thumbnailView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- callback.onThumbnailClicked(post, thumbnailView);
- }
- });
-
- if (isList()) {
- imageContainer.addView(thumbnailView, new LinearLayout.LayoutParams(imageSize, imageSize));
- full.addView(imageContainer, wrapMatchParams);
- full.setMinimumHeight(imageSize);
- } else if (isGrid()) {
- imageContainer.addView(thumbnailView, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, imageSize));
- full.addView(imageContainer, matchWrapParams);
- }
-
- contentContainer = new LinearLayout(context);
- contentContainer.setOrientation(VERTICAL);
-
- LinearLayout titleContainer = new LinearLayout(context);
- titleContainer.setOrientation(HORIZONTAL);
-
- if (isList()) {
- // 25 padding to give optionsView some space
- titleContainer.setPadding(0, 0, optionsSpacing, 0);
- }
-
- titleView = new TextView(context);
- titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize);
- titleView.setPadding(postPadding, postPadding, postPadding, 0);
-
- titleContainer.addView(titleView, wrapParams);
-
- contentContainer.addView(titleContainer, matchWrapParams);
-
- iconsView = new LinearLayout(context);
- iconsView.setOrientation(HORIZONTAL);
- iconsView.setPadding(postPadding, iconPadding, postPadding, 0);
-
- stickyView = new ImageView(context);
- stickyView.setImageDrawable(IconCache.stickyIcon);
- iconsView.addView(stickyView, new LinearLayout.LayoutParams(iconWidth, iconHeight));
-
- closedView = new ImageView(context);
- closedView.setImageDrawable(IconCache.closedIcon);
- iconsView.addView(closedView, new LinearLayout.LayoutParams(iconWidth, iconHeight));
-
- deletedView = new ImageView(context);
- deletedView.setImageDrawable(IconCache.trashIcon);
- iconsView.addView(deletedView, new LinearLayout.LayoutParams(iconWidth, iconHeight));
-
- archivedView = new ImageView(context);
- archivedView.setImageDrawable(IconCache.archivedIcon);
- iconsView.addView(archivedView, new LinearLayout.LayoutParams(iconWidth, iconHeight));
-
- countryView = new NetworkImageView(context);
- countryView.setScaleType(ImageView.ScaleType.FIT_CENTER);
- iconsView.addView(countryView, new LinearLayout.LayoutParams(iconWidth, iconHeight));
-
- contentContainer.addView(iconsView, matchWrapParams);
-
- commentView = new TextView(context);
- commentView.setTextSize(TypedValue.COMPLEX_UNIT_PX, postCommentSize);
-
- if (isList()) {
- commentView.setPadding(postPadding, commentPadding, postPadding, commentPadding);
-
- if (loadable.isBoardMode() || loadable.isCatalogMode()) {
- commentView.setMaxHeight(postListMaxHeight);
- }
- } else if (isGrid()) {
- commentView.setPadding(postPadding, commentPadding, postPadding, 0);
- // So that is fills up all the height using weight later on
- commentView.setMinHeight(10000);
- }
-
- if (isList()) {
- contentContainer.addView(commentView, matchWrapParams);
- } else if (isGrid()) {
- contentContainer.addView(commentView, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, 1f));
- }
-
- repliesCountView = new TextView(context);
- setItemBackground(repliesCountView);
- repliesCountView.setTextColor(replyCountColor);
- repliesCountView.setPadding(postPadding, postPadding, postPadding, postPadding);
- repliesCountView.setTextSize(TypedValue.COMPLEX_UNIT_PX, repliesCountSize);
- repliesCountView.setSingleLine();
-
- contentContainer.addView(repliesCountView, wrapParams);
-
- lastSeen = new View(context);
- lastSeen.setBackgroundColor(0xffff0000);
- contentContainer.addView(lastSeen, new LayoutParams(LayoutParams.MATCH_PARENT, lastSeenHeight));
-
- if (!loadable.isThreadMode()) {
- setItemBackground(contentContainer);
- }
-
- full.addView(contentContainer, matchWrapParams);
-
- optionsView = new ImageView(context);
- optionsView.setImageResource(R.drawable.ic_overflow);
- setItemBackground(optionsView);
- optionsView.setPadding(optionsLeftPadding, optionsTopPadding, optionsRightPadding, optionsBottomPadding);
- optionsView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(final View v) {
- PopupMenu popupMenu = new PopupMenu(context, v);
- callback.onPopulatePostOptions(post, popupMenu.getMenu());
- popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- callback.onPostOptionClicked(post, item.getItemId());
- return true;
- }
- });
- popupMenu.show();
- if (ThemeHelper.getInstance().getTheme().isLightTheme) {
- optionsView.setImageResource(R.drawable.ic_overflow_black);
- popupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() {
- @Override
- public void onDismiss(final PopupMenu menu) {
- optionsView.setImageResource(R.drawable.ic_overflow);
- }
- });
- }
- }
- });
- wrapper.addView(optionsView, wrapParams);
- RelativeLayout.LayoutParams optionsParams = (RelativeLayout.LayoutParams) optionsView.getLayoutParams();
- optionsParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- optionsParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
- optionsView.setLayoutParams(optionsParams);
-
- addView(wrapper, matchParams);
-
- wrapper.setOnClickListener(this);
- }
-
- public void setOnClickListeners(final View.OnClickListener listener) {
- commentView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (ignoreNextOnClick) {
- ignoreNextOnClick = false;
- } else {
- listener.onClick(v);
- }
- }
- });
- }
-
- public void onLinkableClick(PostLinkable linkable) {
- callback.onPostLinkableClicked(linkable);
- }
-
- @Override
- public int getMarkedNo(PostLinkable postLinkable) {
- return highlightQuotesNo;
- }
-
- @Override
- public void onClick(View v) {
- if (ignoreNextOnClick) {
- ignoreNextOnClick = false;
- } else {
- callback.onPostClicked(post);
- }
- }
-
- private boolean isList() {
- return true;
- // TODO
-// return callback.getViewMode() == ThreadManager.ViewMode.LIST;
- }
-
- private boolean isGrid() {
- return false;
- // TODO
-// return callback.getViewMode() == ThreadManager.ViewMode.GRID;
- }
-
- public interface PostViewCallback {
- Loadable getLoadable();
-
- void onPostClicked(Post post);
-
- void onThumbnailClicked(Post post, ThumbnailView thumbnail);
-
- void onShowPostReplies(Post post);
-
- void onPopulatePostOptions(Post post, Menu menu);
-
- void onPostOptionClicked(Post post, int id);
-
- void onPostLinkableClicked(PostLinkable linkable);
-
- boolean isPostLastSeen(Post post);
- }
-
- private static BackgroundColorSpan BACKGROUND_SPAN = new BackgroundColorSpan(0x6633B5E5);
-
- private class PostViewMovementMethod extends LinkMovementMethod {
- @Override
- public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
- int action = event.getActionMasked();
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_DOWN) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
-
- if (link.length != 0) {
- if (action == MotionEvent.ACTION_UP) {
- ignoreNextOnClick = true;
- link[0].onClick(widget);
- buffer.removeSpan(BACKGROUND_SPAN);
- } else if (action == MotionEvent.ACTION_DOWN) {
- buffer.setSpan(BACKGROUND_SPAN, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]), 0);
- } else if (action == MotionEvent.ACTION_CANCEL) {
- buffer.removeSpan(BACKGROUND_SPAN);
- }
-
- return true;
- } else {
- buffer.removeSpan(BACKGROUND_SPAN);
- }
- }
-
- return true;
- }
- }
-
- /*private class PostViewMovementMethod extends LinkMovementMethod {
- @Override
- public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
- int action = event.getAction();
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
-
- if (link.length != 0) {
- if (action == MotionEvent.ACTION_UP) {
- link[0].onClick(widget);
- }
-
- commentView.invalidate();
-
- return true;
- } else {
- // Changed this to propagate events
- PostView.this.onTouchEvent(event);
- return true;
- }
- } else {
- PostView.this.onTouchEvent(event);
- return true;
- }
- }
- }*/
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/SelectionListeningEditText.java b/Clover/app/src/main/java/org/floens/chan/ui/view/SelectionListeningEditText.java
index 6bbb3a7b..7aa28973 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/SelectionListeningEditText.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/SelectionListeningEditText.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/ThumbnailView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/ThumbnailView.java
index f73ddeb4..35b80c46 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/ThumbnailView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/ThumbnailView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.content.Context;
@@ -18,7 +35,7 @@ import com.android.volley.NoConnectionError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import static org.floens.chan.utils.AndroidUtils.getString;
@@ -78,7 +95,7 @@ public class ThumbnailView extends View implements ImageLoader.ImageListener {
}
if (!TextUtils.isEmpty(url)) {
- container = ChanApplication.getVolleyImageLoader().get(url, this, width, height);
+ container = Chan.getVolleyImageLoader().get(url, this, width, height);
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/TouchBlockingFrameLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/view/TouchBlockingFrameLayout.java
index da899715..5f08bacb 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/TouchBlockingFrameLayout.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/TouchBlockingFrameLayout.java
@@ -1,6 +1,24 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.content.Context;
+import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
@@ -19,7 +37,7 @@ public class TouchBlockingFrameLayout extends FrameLayout {
}
@Override
- public boolean onTouchEvent(MotionEvent event) {
+ public boolean onTouchEvent(@NonNull MotionEvent event) {
return true;
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/TransitionImageView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/TransitionImageView.java
index f32eaee8..090a7bf0 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/TransitionImageView.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/TransitionImageView.java
@@ -1,3 +1,20 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.content.Context;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/ViewPagerAdapter.java b/Clover/app/src/main/java/org/floens/chan/ui/view/ViewPagerAdapter.java
index 2575f617..4318d76c 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/view/ViewPagerAdapter.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/view/ViewPagerAdapter.java
@@ -1,11 +1,26 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.floens.chan.ui.view;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
-import org.floens.chan.utils.AndroidUtils;
-
public abstract class ViewPagerAdapter extends PagerAdapter {
@Override
public Object instantiateItem(ViewGroup container, int position) {
@@ -18,7 +33,7 @@ public abstract class ViewPagerAdapter extends PagerAdapter {
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
- container.removeView((View)object);
+ container.removeView((View) object);
}
public boolean isViewFromObject(View view, Object object) {
diff --git a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java
index 82f0e231..5271c584 100644
--- a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java
+++ b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java
@@ -18,6 +18,7 @@
package org.floens.chan.utils;
import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
@@ -41,22 +42,15 @@ import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
import android.widget.Toast;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
public class AndroidUtils {
- public final static ViewGroup.LayoutParams MATCH_PARAMS = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- public final static ViewGroup.LayoutParams WRAP_PARAMS = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- public final static ViewGroup.LayoutParams MATCH_WRAP_PARAMS = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- public final static ViewGroup.LayoutParams WRAP_MATCH_PARAMS = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
private static HashMap typefaceCache = new HashMap<>();
public static Typeface ROBOTO_MEDIUM;
@@ -68,11 +62,11 @@ public class AndroidUtils {
}
public static Resources getRes() {
- return ChanApplication.con.getResources();
+ return Chan.con.getResources();
}
public static Context getAppRes() {
- return ChanApplication.con;
+ return Chan.con;
}
public static String getString(int res) {
@@ -80,13 +74,13 @@ public class AndroidUtils {
}
public static SharedPreferences getPreferences() {
- return PreferenceManager.getDefaultSharedPreferences(ChanApplication.con);
+ return PreferenceManager.getDefaultSharedPreferences(Chan.con);
}
@SuppressLint("SetJavaScriptEnabled")
public static void openWebView(Activity activity, String title, String link) {
Dialog dialog = new Dialog(activity);
- dialog.setContentView(R.layout.web_dialog);
+ dialog.setContentView(R.layout.dialog_web);
WebView wb = (WebView) dialog.findViewById(R.id.web_view);
wb.getSettings().setJavaScriptEnabled(true);
wb.loadUrl(link);
@@ -162,8 +156,6 @@ public class AndroidUtils {
/**
* Causes the runnable to be added to the message queue. The runnable will
* be run on the ui thread.
- *
- * @param runnable
*/
public static void runOnUiThread(Runnable runnable) {
new Handler(Looper.getMainLooper()).post(runnable);
@@ -199,7 +191,7 @@ public class AndroidUtils {
return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
- return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
+ return String.format(Locale.US, "%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
public static CharSequence ellipsize(CharSequence text, int max) {
@@ -256,13 +248,9 @@ public class AndroidUtils {
}
}
- public static void setItemBackground(View view) {
- view.setBackgroundResource(R.drawable.item_background);
- }
-
public static void setRoundItemBackground(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- view.setBackground(getAttrDrawable(view.getContext(), android.R.attr.selectableItemBackgroundBorderless));
+ setRoundItemBackgroundLollipop(view);
} else {
view.setBackgroundResource(R.drawable.item_background);
}
@@ -293,4 +281,9 @@ public class AndroidUtils {
return false;
}
}
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private static void setRoundItemBackgroundLollipop(View view) {
+ view.setBackground(getAttrDrawable(view.getContext(), android.R.attr.selectableItemBackgroundBorderless));
+ }
}
diff --git a/Clover/app/src/main/java/org/floens/chan/utils/IconCache.java b/Clover/app/src/main/java/org/floens/chan/utils/IconCache.java
deleted file mode 100644
index a59a46ad..00000000
--- a/Clover/app/src/main/java/org/floens/chan/utils/IconCache.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Clover - 4chan browser https://github.com/Floens/Clover/
- * Copyright (C) 2014 Floens
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.floens.chan.utils;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-
-import org.floens.chan.R;
-
-public class IconCache {
- public static BitmapDrawable stickyIcon;
- public static BitmapDrawable closedIcon;
- public static BitmapDrawable trashIcon;
- public static BitmapDrawable archivedIcon;
-
- public static void createIcons(final Context context) {
- Resources res = context.getResources();
- stickyIcon = new BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.sticky_icon));
- closedIcon = new BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.closed_icon));
- trashIcon = new BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.trash_icon));
- archivedIcon = new BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.archived_icon));
- }
-}
diff --git a/Clover/app/src/main/java/org/floens/chan/utils/ImageSaver.java b/Clover/app/src/main/java/org/floens/chan/utils/ImageSaver.java
index 940a29b1..ea361bb7 100644
--- a/Clover/app/src/main/java/org/floens/chan/utils/ImageSaver.java
+++ b/Clover/app/src/main/java/org/floens/chan/utils/ImageSaver.java
@@ -28,8 +28,9 @@ import android.media.MediaScannerConnection;
import android.net.Uri;
import android.widget.Toast;
-import org.floens.chan.ChanApplication;
+import org.floens.chan.Chan;
import org.floens.chan.R;
+import org.floens.chan.core.cache.FileCache;
import org.floens.chan.core.settings.ChanSettings;
import java.io.File;
@@ -53,9 +54,9 @@ public class ImageSaver {
private BroadcastReceiver receiver;
public void saveAll(final Context context, String folderName, final List list) {
- final File subFolder = new File(ChanSettings.getImageSaveDirectory() + File.separator + filterName(folderName));
+ final File subFolder = new File(ChanSettings.saveLocation.get() + File.separator + filterName(folderName));
- String text = context.getString(R.string.download_confirm, Integer.toString(list.size()), subFolder.getAbsolutePath());
+ String text = context.getString(R.string.image_download_confirm, Integer.toString(list.size()), subFolder.getAbsolutePath());
new AlertDialog.Builder(context).setMessage(text).setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@@ -67,7 +68,7 @@ public class ImageSaver {
}
public void saveImage(final Context context, String imageUrl, final String name, final String extension, final boolean share) {
- ChanApplication.getFileCache().downloadFile(imageUrl, new FileCache.DownloadedCallback() {
+ Chan.getFileCache().downloadFile(imageUrl, new FileCache.DownloadedCallback() {
@Override
@SuppressWarnings("deprecation")
public void onProgress(long downloaded, long total, boolean done) {
@@ -97,7 +98,7 @@ public class ImageSaver {
new Thread(new Runnable() {
@Override
public void run() {
- File saveDir = ChanSettings.getImageSaveDirectory();
+ File saveDir = new File(ChanSettings.saveLocation.get());
if (!saveDir.isDirectory() && !saveDir.mkdirs()) {
showToast(context, context.getString(R.string.image_save_directory_error));
diff --git a/Clover/app/src/main/java/org/floens/chan/utils/ThemeHelper.java b/Clover/app/src/main/java/org/floens/chan/utils/ThemeHelper.java
index 99ccbb15..e69227f8 100644
--- a/Clover/app/src/main/java/org/floens/chan/utils/ThemeHelper.java
+++ b/Clover/app/src/main/java/org/floens/chan/utils/ThemeHelper.java
@@ -26,15 +26,15 @@ import org.floens.chan.core.settings.ChanSettings;
public class ThemeHelper {
public enum Theme {
- LIGHT("light", R.style.AppTheme, true),
- DARK("dark", R.style.AppTheme_Dark, false),
- BLACK("black", R.style.AppTheme_Dark_Black, false);
+ LIGHT("light", R.style.Chan_Theme, true),
+ DARK("dark", R.style.Chan_Theme_Dark, false),
+ BLACK("black", R.style.Chan_Theme_Black, false);
public String name;
public int resValue;
public boolean isLightTheme;
- private Theme(String name, int resValue, boolean isLightTheme) {
+ Theme(String name, int resValue, boolean isLightTheme) {
this.name = name;
this.resValue = resValue;
this.isLightTheme = isLightTheme;
@@ -65,7 +65,7 @@ public class ThemeHelper {
}
public Theme getTheme() {
- String themeName = ChanSettings.getTheme();
+ String themeName = ChanSettings.theme.get();
Theme theme = null;
switch (themeName) {
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_action_attachment.png b/Clover/app/src/main/res/drawable-hdpi/ic_action_attachment.png
deleted file mode 100644
index 175adeb4c46628209078396ccacbd4d1b2485f11..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 509
zcmVO87>ZXr=q1ZddatBhAHAVG@@{$WVZguIXSpO+OKXx?vYLL0b9
zBQ0eDn;P&)XVdD_fi}=vcUT93wyicsz@}J*wmWrY{BQA+roBxB_GEx5R(DsSBiruE
z9SeH%j(qS)MijQ&Xrgu>p^V&B6P)le)RWOh_riI9
zffH|0GvPoE`Lyx@$%Y6!^vA
zRbZhTulA&p$st+G4I9#RbR3xaKPG_**KSm#)V6HAyiF=~c3!{f3}s;IOqQbWE@Za3
zU59;;d0A@AKpC-a>g`Tl8E^DFI$!CS3}|P81)_Tt>hi&U-eBCaBOhi?Md;8rssyhO
zHp&$yt%T?lef5E59XgQ{p=tJ)!vuyt3kyC;P2RzEVkKQCVozdIGOs^0_4qDxcB?GB
zhSfb>CAJ7u^=Aj1Oypyzb%~_u5P_`CqPE^O|A7!f2qAYB9Dd`$Re@cH@UwGnffkSo-$Xz%e6@gd_$mQ}@Wlcs;fn;2
z!e6>iAVqd002ovPDHLkV1i#FjE?{S
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_action_back_dark.png b/Clover/app/src/main/res/drawable-hdpi/ic_action_back_dark.png
deleted file mode 100644
index 6bb7a0b061abac0a78af841c3306ff270ca5d83f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 296
zcmV+@0oVSCP)1kobz)zBFlf)!!^P@
zzMiDnqbLADelMU)!QuW2QT&K0{zfTYWE7(W#V|)PPE#ysD3+8Ii+YM}m6j2=4s+}F
u;rQpHKGcL*b92`_BBs0$LWnSY1sDMQ)T=Bp-p}m-0000uR$+`ZL}CL9iu4pv&~TPqL?R?{{9XWYPqIRgeD^;8#3vi0QmIrbmFkC-
z=lNP%LWrBV*rEMwV3MsoHqsVpnjWjFdZ5h9V<&ATapw~E1PAb=v+=Jp6hzH@=Ksnh
z?p@-Z`}Cg%jQ{`u07*qoM6N<$g0AVdX8-^I
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_action_cancel_dark.png b/Clover/app/src/main/res/drawable-hdpi/ic_action_cancel_dark.png
deleted file mode 100644
index e206f296c2535b11a2243ae93a31b2957f42ab7d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 353
zcmV-n0iOPeP)l3^w)^1&PVosU-?Y
zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP
zs8ErclUHn2VXFi-*9yo63F|8hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83
zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s00+w{G(#^lGsVi#&Ct}+$imdr$-u?X(ACh=#L&{!#L3yw
z&D7A`#K{n**Cju>G&eP`1g19yq1OzjUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+d7PlC?
zn3-5OIXVK(v%u~ah~5<3ZZW~>7JZ;&^g&UJ6xA>xVEO?u;RzSWfhYacJYae+0w(OB
zPunsW7#L@Hx;TbZ+F}XRH$BVJ_~tbB>ux&w{i&Jpl6k3-y`NvKHk21q
zV1%GG?pIzqOj6l*_t-(U9qjp;vo`HwN=}ep)5vUa_N7?Rr}hN4ng+Fwoh&_BpW+wD
z&uL8OV?3O|erD1ih8>LjGWVRk>cn-L{3q>ay)F~Cc;}xn`8m#J@(k
z@^-_wj*fK>KI!`&dhL6Y6
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_action_done_dark.png b/Clover/app/src/main/res/drawable-hdpi/ic_action_done_dark.png
deleted file mode 100644
index 4c2e84446bf23f041b76357c44fa8f37298ce7e7..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 392
zcmV;30eAk1P)zqoZ*u&U;`iBfGvDf
z11{jB8E^$3#ehrr;09d7uWn>KV70cD$AlLK@SRCNVgk?6OztPc3Akx1@p*cCO!$8C
zv^EQzPLo3eN6mx3Qdu@+vXu6i2({+Pv>vvY2wAYSrKn9zXyBiGUhU&$WBfh904=A>
zQekW0rNN`Gy@htXRc2>`qu0R8SsIctuwbGO4R6&-%$N|N;jMcijfr6JK3a}O6>@g}
majINHe1sDLV`TCKJ?i2R_0000~)nSPMBK|z4!;0>128*SSfO(WZG({C@e<@zQ{J^CA$J^9^h-4+HW
z4uu9V;m}>FaPIT6gtre({HFI@`KRUogk{zopr05h*#
A?EnA(
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_action_play.png b/Clover/app/src/main/res/drawable-hdpi/ic_action_play.png
deleted file mode 100644
index 9a2147eccf47037a214ad4588856e2af4f4af166..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 437
zcmV;m0ZRUfP){!L~L2Tc?gmY>W|{>{TYnE5-bgMmt=QmNWj
zRaG-MVg`ue8@z=leX4Ev32!fmy!0H0;
z08;k7g+6Hxp9Gc?;58qBIGgBY1h5*zCUO&a$_QW;Nm{MiirryHt-6%?Sh51x`B=$(
zM2rCS`AA%?B|ZS^Ysu-~wZtcYRV*M2RscI6Yd{=-oe!6*giBpyzq+%$fyN4ZR!<=d
zVa^6%HrPE1KQq386waEi;XVPb^3?BaGw^^nuD;;Hj{Dq1W5$?5nH2B*bF*!LTw<|c
zI|m+8_?7J-DSWA*uZ{aXO;KR8q>
fl}hzVPXPu1yws;8#Piok00000NkvXXu0mjfk6gL~
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_action_refresh.png b/Clover/app/src/main/res/drawable-hdpi/ic_action_refresh.png
deleted file mode 100644
index cd16fdd5080541f0e67ebf3bfc97a50ac2beda79..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 531
zcmV+u0_^>XP)004R>
z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN
zS#tmY3ljhU3ljkVnw%H_00E0hL_t(Y$L*H8N&`U@hX07hLJ8QYpqOmZ*^79od;tp^
zb%|K|0D_Rp=xbQncq^;|UIV^E2ncpc1O*Y)CMNkT9HN`dY$94Hc&1o(=bUfn%$f5u
z5%e?Gp?}b?040^tsY)uVqFbFQBQG$Y4ZL9=9tTuuv?@EqjmHLjj<93Wyx_7Y77&}z
z8nk9YYUJ?o=%SMZKF4*~iFt;C(#EO4Skv4zSAo@qfIO4b89mmd`?zTjv~O0^<0!&r
zdn-y(1!|V0J}T7~C<8#wfyp*i&bA9ge9pQ2f
VFoeR4ydnSq002ovPDHLkV1j|y+zbE!
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_action_write.png b/Clover/app/src/main/res/drawable-hdpi/ic_action_write.png
deleted file mode 100644
index 3ee3e1720bd76cac1d0ba20d1315af562512663d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 351
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;Lb6AYF9SoB8UsT^3j@P1pisjL
z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?xq+X@R~r-W;^-qY;7chg60
z?&cYx!Ygtoy_Mwg^>;29~AGdj*J
sn^^*T|k0wldT1B8K8l&6bhNCo5D3%fZR5_nu6GTXnn
z)U>ihPJZ*vEHjU;Xpa-Nf7v`z+Pb!Kg%oSBYR+9u6~
vKeotrpR%h~+rO+U*x6Z^BW=wWuXoIeu2U7w-_4f;+QQ)J>gTe~DWM4f-d!_!
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_arrow_back_white_24dp.png b/Clover/app/src/main/res/drawable-hdpi/ic_arrow_back_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..a2051cef9e8fac97f1259be5c8091d6ab8e2a9d9
GIT binary patch
literal 152
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K8yr+v}h{y5d1PRu|LVxmq+;@;o
zc39A8b?ndo{U7a(OM4O*w;9f6n`$__eX(KmisUof|K~0c>6I5UYx8iZZVuRU&9CwL
y1*X|^qa;hOtXP;Y0@Si|k0wldT1B8K;Lb6AYF9SoB8UsT^3j@P1pisjL
z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?v6yN*e2orR
zA?WO2{V8r{`Te`zMfx8<{F{7lmV#rKi{vMtt{F`%s%C+&rtmGjaqJwACxcdUwkX3T
z9!-WRg~{&OGEWrPEnidzI()DeDO|k#vDX%nPnHGs((6R4|5OH?>r5*NGM72|c47J#
z5fv4YFSkzdta$oq(^bP0l+XkKLQ-}(
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_bookmark_filled.png b/Clover/app/src/main/res/drawable-hdpi/ic_bookmark_filled.png
deleted file mode 100644
index 66d4223d1e24c034a977d635c77ef2a81c835fab..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 273
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;Lb6AYF9SoB8UsT^3j@P1pisjL
z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?Tk)5S5w?TEnA$d
zw!d9S`0U0)mrKPNsS9>ZNk4l)tMyy5*VjGrRm@v00|k0wldT1B8LpHcuDF5Rc<;uk7Y+HV|H>P~`P0WERgjW%5sur%i}4*z7Y7{qty
zep~kWc_utr7KZ=kTv2wHs?RuiAt>lllARyZg3i;Q&U%;xTbKlF{%LhL$oPj-+q6qn
m&wmE6hbXkVdvFPIzhPv4=E1zK!Qw8^2MnIBelF{r5}E)FXjvx!
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_bookmark_white_24dp.png b/Clover/app/src/main/res/drawable-hdpi/ic_bookmark_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..9de15c51a92bbc29536fc7a8e34da51f1b6961de
GIT binary patch
literal 185
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K8gQtsQh{y4_*EaGtCXxw1
zJlv$4!kF$T**4E|&JoEK`&v7DIc1K0vU?gE=foPj+|<4QurOEp;fvR2wk!!*Sl|(T
zYJ#})J|0#>5s@Gd#a5AD?5A9Grg{A1oBPJ+{1E|*+Y6hgJ~Wk$v|JLPmeg(i-BtTS
ikD%?Fw#fbFYh(9%S-#0z*fJ0376wmOKbLh*2~7a_ZbD%I
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_create_white_24dp.png b/Clover/app/src/main/res/drawable-hdpi/ic_create_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3ff58dccd3c40504d3f55a4be8e0b79e3bde9d2
GIT binary patch
literal 214
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8LpTu&Fr5Rc<;uUK<67znUjnB%lT
zoOSjO>jray$uJw$FFVMU;3(SEsNVV`
zY0pZ=3oE8p__*1#52{6WCQLy}71A
z^UjP{%xC@x1hXWnn6M?T5oq1$VC;1(TE5wU%_Uvsiq|WdbN}v4kacX7_2athUkr38
NgQu&X%Q~loCIIWZPKE#g
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_done_black_24dp.png b/Clover/app/src/main/res/drawable-hdpi/ic_done_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d4c06072b56dace7da1ab5fcfc5cb0a494adc5cf
GIT binary patch
literal 177
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K8g{O;SNCo5DGlpDEh5{}R!&SuQ
zX|-?oV07r-F(+5sYxQj19uA4F0*7@nHs;@YsQf$gW>+px@zP|&GZEd1Z}?}-I>Y|V
z=y1-BV5J$-bD3R}6Ta_|*W@zZWWK6sUb;=`BCRvpTf-#$b)_C_PW(7UG2P#7{m0nI
aGWJPksgEnI&wc~Cfx*+&&t;ucLK6Uc3_uP5
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_done_white_24dp.png b/Clover/app/src/main/res/drawable-hdpi/ic_done_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..c278b6c2b30ba9bb52391af71120270e908a7502
GIT binary patch
literal 188
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K8v!{z=h{y4_R}8rt40u`}^1XVn
zvWkOUU-^j{pVq65HqD1Oi)r3+T*LWdLcQO)Q$gY0SWi#
mI0*h{o5b;0Guz~Cq_l|d_dwzLnQwv4VeoYIb6Mw<&;$SqxI>Tt
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_drawer.png b/Clover/app/src/main/res/drawable-hdpi/ic_drawer.png
deleted file mode 100644
index 6614ea4f4da2ffd9534f0ef5f20bcb00194005b2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 2826
zcmV+l3-$DgP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T
zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p
z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&nehQ1i
z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW
zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X
zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4
zfg=2N-7=cNnjjOr{yriy6mMFgG#l
znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U
zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya?
z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y
zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB
zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt
z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C
z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB
zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe
zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0
z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$
z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4
z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu
zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu
z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E
ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw
zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX
z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&
z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01
z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R
z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw
zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD
zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3|
zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy
zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z
zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}
z0000rNkl|k0wldT1B8K;Lb6AYF9SoB8UsT^3j@P1pisjL
z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?$M34UQE3J=p25@A
K&t;ucLK6TzyF#4+
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_more_vert_white_24dp.png b/Clover/app/src/main/res/drawable-hdpi/ic_more_vert_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..67f07e473442d1f5bd5dc486a42ce4bedf40b425
GIT binary patch
literal 134
zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;ucwP+h{y4_mv-_VP!M4WR9aA@
zB9L2TV$k7bqBi~Tf{Y7K)@EPe&B(sMnUQ&cV?}1b!p)H;o34MJ
iAa}{R%7g#se7OLo1Hz}Zd6xqXX7F_Nb6Mw<&;$T!hAw^p
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png b/Clover/app/src/main/res/drawable-hdpi/ic_refresh_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ffa7be9337df524557807b421e8f0c5a5f53ed08
GIT binary patch
literal 387
zcmV-}0et?6P)Nkl9LM4B;APNAOe8{k>Ka6ZdoY+NjnQBvqLY`~Fj)kHsiE3P+(RRg*h+08!O+I(
zho6SjasKC2x=Ei$>e7EgnjA%{)Oq895;;7zU`O%rIKd~#=a8g6u?vdBGOxHivmmj@
z2SsC(rUrR3c=XakiVOw5T<}RzSf;7Wqym`bmKJiu;}uh4Kp`07j&E|~7*l3Iq1dB^
zTu9>s4JH+eU4D=YIZR%m*dahJ6fqfvV4Gj$LKWkwQ`9lN>J)WMpE|`oCaq3U#4ITW
zE0|Ncu!T8O42qaFxsbxgOeq30m^#C9;|Oz2LJkaagV|RUlDuFpNhkz^Twxv=Q8Y3%
zT{Eo!X1Kxl%qbr0d^sn}1pV|eL6!nd4OZ127J0_yiFvh;aSrhbdgFjm{S`?zDNvzC
hjS6RMFs3g3C-2Jk?*l<_)DHjv002ovPDHLkV1oL9pSu76
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-hdpi/panel_shadow.9.png b/Clover/app/src/main/res/drawable-hdpi/panel_shadow.9.png
deleted file mode 100644
index 19ae66300e97a8927517c073f6ce04eefc05e79e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 111
zcmeAS@N?(olHy`uVBq!ia0vp^`asOe!3HF+3T*uYq|7{B978H@B_}jA{CDO#%*d5K
zfx%57jVVb?A&oi7PvIG35~G3`TTDaJY4;Tc>`U@6@Fr2>`Sdx1t5d?E(BnvfCzDRGF6gF4csf$in%H4Xw827`PE6p
zqeuCAn1O%?;7&EP$#lkYy<|0Z);ThuFh}CN%NA<4lv+~3Q;3EH14|d9S(1s_O@-$m
zPs-+yQzn`vx4i-WpD*9O)t?U?7nkCBV
z^b8Bia#|S-T}U!VKp;FoIgoT0gV72Q1e9fVM&YDb^%1b>nGe4|_-SF;A`S_FM}mb2
z0`P>EDZ&t84p;(=gek)W8W7Fs1|$<`Mi~SGFad@v5->?i`;Zx6PVt9Jm>Woo1p1fA
z|FF)M<}Sv--+T3=i;sJwzQDA=l}+C)p6BHgc-~~NrMP%^fCS|fP3J#O2jl?H$An36
z0tUh%89={Ue_4bGU=H#zfbXt3+5)}>A8x>=ue`9jh-^;iDa@_ry2a31?eH#lUI^Yr
zy2D)|dlrMiJRv(^0hAMRWCoFeLJ;J%oRBynY!u6I{Oc#1r`I$vfqm)mD)N1MQ)|yg
zJbUA1UQ1+pP4rpC({^TE67QC<*_1ou@2!z(A7OqsVE<
zaq_!Xnk!pws@>m+-5p>Xzz{_B9NX)Twj47)E7;5`ZrD2O=_zGow-VW=72cg@&db)K
z)5^9Zib_?bbS!nVJ#`0PZDj!ZZ!kC2V3Btlz$Uo!1e~X*z$52+V_Pc@sji2
zhj%~T(FD;p>1-3nuY2!G~@g|f6dXbm5Ocer70icBh+e9-T6hLqB
z`~nN?d^QYY?|I(mC9@oBa&4mB=r#JI9Jy~1X>ux6rBfOzsH&hXCDfl0Ls8Kq)*qXu
zDLS1_;`7yNC6>!2Ehqr$_xp*@XR{d^6!$5HVkm}UD28GvhGHm&`hQE0ZnrBe%gR+T
zMDW+5c+g}r5w7dr$5T)dREVjpK)IS9CRiSz+h(H)L;<@M@NxfM+HSY_P_R>hwOhd}UxuQqqY5e{
z4i%`NHc?t)3LVGU|A0E5###_k}@P)WGTdQA{hJ^ZmZ;~wAP55H`+jK+
zTr3tWNfNs#01b!3(opO5+CB&Lv6QP`@?UwS{+lK=yW=4GMTXHbjsp5#{Z%K
z&}=qiuInCiI7f{-gIcZD@f`9pV7x5QIm&=pLG}B6BPa`ldMHqX!GMj&R|>F
zMNyv1QYmG6cTd@PV--0HF6(|_70fhdEP)Qsy(YKK#
zNsMLVsZIwgi=t>p383&AO9qR6aN!3?#QME*2eEYGjVrDo$kZS~z8Gs{`XRKMj?iGUvyz$O
z_bCcEd`sIAGKLjMID=RxzotmQE*0n>MLpK?-(WvMO+nO*BpLH7t-{$uGv-bOn8fr2
zGmyA4rshyIa~4o@mt%9_$ljcSo0&I$x(3kTBm{{)`?qsJN>-CcvBz;dsDMBq5C}d3
Z3;?KqV7eI%afAQ>002ovPDHLkV1hxPpUnUO
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_action_attachment_dark.png b/Clover/app/src/main/res/drawable-mdpi/ic_action_attachment_dark.png
deleted file mode 100644
index d0d8051af57606f0265789a0e60c803a6c6bf246..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 379
zcmV->0fhdEP)p5$jBPJ*
zC^7OR=)%I*qQf1<=y5M92l8jD15B>D1SVn@um!d0AV?dCpj?FYIP`-*YC1xLO+C77
zAb)Ogz>@oN&^Hv;5aG?(toc=|VLWPZH{{Z^QzdBV5Y>w;Gx8<7kU40^bn+X5_=M%b
z_T2}i+=TJYuc^7YtED-R7&Wihl|3kJ188;#ZQ#IiamK`rr(jXxlP^(co
i;9#_4GU@<;00RI{VT;Q4srPFD0000<|{Ln>}1B}lL?PFT_O|NsBbOog``qW1B0oM$LxR!uXU
zm~1&=7Uz+y0LAJBGelx#8jgNC?=a`wi4#A1V%QCW4t|QB;==gYAGPbXFRCwBAU>F6XU=$26V8kbBY;0@^
zq{4u>@9f#Lk4Z5Ys8<$96#?-opx)!S)G-k-2V^-H$RMbJq*~4eHG_d%2lN5)H&Psd
zX8AX$88`tmKFR0LpMR2)lDYX-@nh*(FEV>wX{AjT2oT23$*
zkPyFQSx&M8a5#d2T+4}$0s_&&O0MO^WJ8(*W-3I%Z(_12RUCjL5gsSDoS?`7xUw3l
zg%w#2Ae7H3aRf7^mQ(5oW@=bYi6aPQLy}84s2Y@7l#+5_6*+|rnj=YcL
aAiw|+C&DJQP0oz~0000<|{Ln>}1B}pV4FnQGw$lhbcF#pN_|NmTvlOA(yaXHp7=YfQzWd6l13QbWBbF5EntH}^M8nLKhNl}v$
z`vZ-XOPZxe9-MDujuPO_2=wV|3@K%?U6t&_#+%cevc=Z|mdKI;Vst0JaBXn*aa+
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_action_done.png b/Clover/app/src/main/res/drawable-mdpi/ic_action_done.png
deleted file mode 100644
index cf5fab3adf243318d11ec95448c6deae3f52d9b1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1197
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O`
z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y
zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP
zs8ErclUHn2VXFi-*9yo63F|8hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83
zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s00+w{G(#^lGsVi#&Ct}+$imXp$-u?X(ACh=#L&{!#L3yw
z&D7A`#K{n**Cju>G&eP`1g19yq1O?oUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnv1@
zG!Lpb1-Dx)aO%|uIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1z*4|&C&cMJZ@9E+g
zQgQ3ebbs!H2{Omc#n}0tv`#21C~#0@f8W4;a{i~dB^meHw?8lo^y+Np_VX($n(_YC
z@+E&a+Mh40ocC+XEx!5ZZ+*78?c#g6#lYQ#qw)iToIq8>mujbJsbce3PBczkwdxup
zkDJUF2f-x=jZU}=Fgph@h!N>j@?Pr!beU|A1vJvL35&6;ySFy-J4wL_Ed=se(2D>)PC;-R9y
zdup`rq1*C;xs&W09=YXh=ju@sDp||AN+rHQcJ=j-`9~Vw?O~j!62JMM+>gE!%~B^t
z*B7ZvUsQj@6<2p>=j`nZ}1B}lL?P7vu~`SAaLeVl@yw8!b`j2|Tx@*Jk8
zFWUOlAxlkQwPWi!zA5J&Ze6VcFTPZtRc}1?JvSDAtwC4+o{u&F|yKCK+mXwquU}R%>+m>-ZX1@3)pc@%HUHx3vIVCg!05Z{8^0$x%HC5M
zDbb1y96PG#E}b*crF~7D(!F;|OdJXg4Qn5Lbvcy#A}ws*s|Kr{TRL)zK;aKt8+M77
g+o>-wVv%4tbz9`!VZkj~Kx-I0UHx3vIVCg!07CUbG5`Po
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_action_play.png b/Clover/app/src/main/res/drawable-mdpi/ic_action_play.png
deleted file mode 100644
index b94fbe6e38881055417b18ebbefc00a6479b799d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 339
zcmV-Z0j&OsP)wy3N|ML!X
z2=o9Q(Lig55Q+jHAl?LYMA|^60Z<5}0Ufa!h>Zs_5lRB_OrRq`SZW}1fiW~%im8!4
zD9MJAP=`bgWH|r|0Z>RRBR73es~}Q?rjH&{(+9OnLI+s3B{qG~swf7P8=z?M9mu)>
zlx^#w+17Z_Rz@r|H2XOa&tha`+&mBtm<7bkftG)!cL*E+;y$3o&*&Wmw}7}8Xz^Kk
zr-9GVcwRmbiEug8^3U|n1)yMVBqg4yO=~G=WkKx
z$X}z-W_$b!{UqMfxgg+Y2*GnN7D4e#B!a-54~*{Z!wwfd3NoTilU2CuZ0B6Z_UsBP`#&E
m+Is1!bIblNdm{hmW&YvE^KNo&|F$0JI|ffzKbLh*2~7YK7l&a0
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_action_write.png b/Clover/app/src/main/res/drawable-mdpi/ic_action_write.png
deleted file mode 100644
index 85cff0b919dd765d6aa45557d1b47e081d447a4b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 272
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1g=CK)Uj~LMH3o);76yi2K%s^g
z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tWO=~G=WkL+
z;pyTSVsZNH<-NQO3IYy^(>_m^EaBrW-%#LZt!(xzl0(q2DqVfcdvCoK;~Dwa|1d2t?+KF{Qd1XyO;N07-#Y)VLhOn84k!38d7PJee$l{xLDlK^
z4`%H)@o$_F->B5@xbmd`gl9XyL{I(6IpwFU1=n3B&Cm63N{Y&-Y+m_udZ|Cq3k(dN
Lu6{1-oD!M`PlZt94B=K^nw>~a9bmGDy*ICncJ)B+6c;%K;px=~btUyB;
NJYD@<);T3K0RZi>C3pY;
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_arrow_back_white_24dp.png b/Clover/app/src/main/res/drawable-mdpi/ic_arrow_back_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d571552fb9c5a5e47b5494f52a5cfab771d5435b
GIT binary patch
literal 118
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1TTd6q5R22v2@=~L)F1xOc4^B0
z|NnpQ7t1{5>=7*I75p@DiN=5DSw%JtMZ5*-t&^n^4|{iuWk$Vf%YVkoprJSQ@Ah{}
Rw}A#Rc)I$ztaD0e0sv~HDc}GA
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_bookmark.png b/Clover/app/src/main/res/drawable-mdpi/ic_bookmark.png
deleted file mode 100644
index ec69d41f25b6c71e2e7e1a9b98cd4023dee5a633..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 262
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1g=CK)Uj~LMH3o);76yi2K%s^g
z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tWO=~G=WkKR
z=jq}YVsSe8$9V^-lm)BX4*b{upUk}e-|yt>4Y8ISdycGQWZ7WJ>{=6Y*x>R3))trS
z2|w@u{D1fV_W#xmI!#hK|JMKcFFo%?-T!z-k%OxlS?d19f4a}ZF`XgOpdtA1=l@^-
zAAP7K^k2F`$-;EbANjxYMU{JQG%QkQ*YX!;WmM;1y-t1khFG9W7(8A5T-G@yGywom
CnO#r-
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_bookmark_filled.png b/Clover/app/src/main/res/drawable-mdpi/ic_bookmark_filled.png
deleted file mode 100644
index 7b4e65d71c7d51f99689f455a53152d47c367adf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 223
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1g=CK)Uj~LMH3o);76yi2K%s^g
z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tWO=~G=WkJm
z?&;zfVsSe8$9V^-lm)BX4*b{upUk}e-|yt>4Y8ISdycGQl$W?_u&Pl{s_tL>r~5n{
z(-|UJOl|(h|Bsi^Q~J1{QKKpN@X7xd|3?~rl8_Gg^2Fh3<{|}#8T?8C`rSuf01
MboFyt=akR{0Q!$eEC2ui
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_bookmark_outline_white_24dp.png b/Clover/app/src/main/res/drawable-mdpi/ic_bookmark_outline_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..9842707619fe6f65f85b06fc20691ec855339a42
GIT binary patch
literal 176
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_+ia!(h>5DWjer#JF8C5W^JO6f*8
za6ePXNn9i8=6$!>$vsi1sq|5-M0WrH
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_bookmark_white_24dp.png b/Clover/app/src/main/res/drawable-mdpi/ic_bookmark_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..84f16627dc7fef320a96a0950ebe50cb09f6c21a
GIT binary patch
literal 139
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_+iAWs*^5R22v2@+=>)Iaz?{r|?s
z@c(}|W*=B5!xEQty@9ueD%XLiQ|9%%Clen^me~?-P5>$?ao_51Xjx|Qk^y-
zdBRlThZ6o?Q|jd-p2|(pELRqpvP6?TOTpK2Qrr9gcRRh0Ezy*ZVPIH1?c-DthJyV-
Pdl@`k{an^LB{Ts5yXZdH
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_done_black_24dp.png b/Clover/app/src/main/res/drawable-mdpi/ic_done_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e5e7cf2b14732802095661e2de6a8c6eac3e8b5
GIT binary patch
literal 130
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1Pfr)ekP61+1H5jHVwtC$CF+b#
zCM^47?|k?}@VQePx)djfTvl$Fv|pmhqkt#ilYKy-z^-GeF>qN`e$
mOkm7ZjI#{k);#6T#=sC9S)hEq`Oa^k=?tE(elF{r5}E+GHZxWL
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_drawer.png b/Clover/app/src/main/res/drawable-mdpi/ic_drawer.png
deleted file mode 100644
index b05c026c18ac30b1852ca8fd2a3e3efb42369bc8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 2816
zcmV+b3;*KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T
zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p
z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&nehQ1i
z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW
zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X
zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4
zfg=2N-7=cNnjjOr{yriy6mMFgG#l
znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U
zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya?
z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y
zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB
zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt
z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C
z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB
zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe
zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0
z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$
z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4
z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu
zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu
z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E
ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw
zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX
z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&
z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01
z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R
z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw
zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD
zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3|
zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy
zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z
zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}
z0000hNklO=~G=WkM1
zMTcj-fMuPav=7~~Ah7&(%{n}Mb=c)I$ztaD0e0st7?IAs6;
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_more_vert_white_24dp.png b/Clover/app/src/main/res/drawable-mdpi/ic_more_vert_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..017e45edec435f227c0fadfa13a4a27353acafd0
GIT binary patch
literal 112
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1b59q?5R22v2@=a5)L;02{eS%5
z@9J@fU;kJ5AT(P>xJ=eVCD820|N5W*kJjJ67$C*FG*QAUgq7iWp7Wo)^m*JsBN#kg
L{an^LB{Ts5on9xv
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png b/Clover/app/src/main/res/drawable-mdpi/ic_refresh_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..97e42b5251a984f151a3fc469c583c360763aa17
GIT binary patch
literal 254
zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_+iqn<8~Ar^vn58C=20?J;<7d+)D
z!|^{xU``;1V%Y-~zhmA4){=|W3l^Ae^mp#jTxxh`k9c8Y&l00n|Cv_|_|7cq>|2|>
zG$hGy&ZUnnds{bdo7Op%Nx$xhX7rv{ZmkRX*#pyC_U6eHJ`TU)xv@j}**}-LJdalx
z1PhjOZFyV+!t)F}KkqyqYqH^3?iERmr&WQ;3qCxx^7H(-OkVWYy^TF;Lj5OneM?oA
zg%#QC=t>h>85EkiR`kE&hK-Z8-{gFG#8k`7Qt>7y-mx$k=phDAS3j3^P6}J2i$Slg5aGLRnlYQ1*o}Lh(HU>{uKbLh*2~7a(i5&<4
diff --git a/Clover/app/src/main/res/drawable-mdpi/progress_primary_holo_light.9.png b/Clover/app/src/main/res/drawable-mdpi/progress_primary_holo_light.9.png
deleted file mode 100644
index 6fb9445773467ceda7aadacfb9754f2d347c7779..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 561
zcmV-10?z%3P)jls#*dQ4ocnnYs5(Ho`86
zCc27}|9XYy`m~5+%ukhBcc__T#ZfXox%C31axTjJ6sxguHmyGJ_SSf)K5>aisqkD^7-ItXY*uv(G^APB_+!~MbG
zVC&iKbjHE@E0@iO2R8oRSCxhtJ*~$Y;;Mw@dKh{tv1AQac}ya)aw3!}h(^V$f)uj%
z)~i-$3kU!Y-t2q;^n|;T5~hej(mcW-8-ispa8ng?+{95%Vk(X~D7XNc@Li@2<{fAb
z%Vf1v{+XYy{Th?0|Awi^tk~(?tXp}Rm00000NkvXXu0mjf_HqHy
diff --git a/Clover/app/src/main/res/drawable-mdpi/skip_arrow_down.png b/Clover/app/src/main/res/drawable-mdpi/skip_arrow_down.png
deleted file mode 100644
index 3fc47b1b084678aefbb6fce6f7bdf364da603116..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 452
zcmV;#0XzPQP)50000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzW=TXrRCwC#m?3Y3FcimoWG60=nI&)*
zG|BWdnh$`-1BusX#0sOuLB$#0tW^wOgPp%LeV>d!EMxGD~M5U>JrS5Y*tW@~77t0OWZ-
z%F?gEfWACx$1{WJA!!v!Z-_8a6d^@XX1{e+Rr51LD|CPEt9=m(=G+{@*RU%-_@6tN
u=33&k0uWq_eExJl^U8~)&4`e86JP-C5t}4L$+dF;0000`@o$5
diff --git a/Clover/app/src/main/res/drawable-mdpi/skip_arrow_up.png b/Clover/app/src/main/res/drawable-mdpi/skip_arrow_up.png
deleted file mode 100644
index d98671e0ce1a79caf1cb150ae1ea84231f1db790..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 424
zcmV;Z0ayNsP)50000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzN=ZaPRCwC#*uAQQFcbjb)6fn@xJyC0
zx+{0??Cb;h6z)3f?o;>x&dwb=>g;?Mmx6TY(j3te?oVrbf=O>Z5W*2nK0}Ne0F7cH
zCZ6Z5c(vtaJwe|mUcT}?KmWjR2qHdtSxq2-$Pc5fdhi$kY(%``Zl(>+7uo$Q8r~
zVV45bmqpGT)EK54Zwrw&d%Q8A93_}
z3=xtcrnwk^l<(6c*h3G$PxFTI2FkB!%pFs>NyF3ThBi+qrzn3(j|*)&lI}Hg@yJQ$
zo(xs>pl(Rsm1%v|@*xrH1A|M2i^by8Ri7u>-W!dE$N|2bs?+$U`N*`sX8Bf6dmp96
z6B*5u`?h^Uyx3$BzmY6wiX5jj9<}<4_A(kE
zE>d&p!2!pEYbmGxtCWcCw6b!p@0V2hU!kxklS=Tev5JfSw
zU73{>h5p=IR)rK-{
zxpp%olgX`a(X=*G?rU?eqAgsJ5y{9(#GGzWBSU^Zb+VbF@dYdv3Y<5UL)&Hv@kxmj*|Y|=T{{$z4t6Mq+-6*U
zIn%FyMwF35tyk90pjV$Cu^Dvj59oH=u;G?KeoDt-S00B``7bB-T{v8BmmiR>5g(|{
zwrs<_S&G%$%PN~bY0STpHaokaX>2p%zX0FZBzcT5`+FO1mi_21S4cYczFEZM>
zdD*_;<2Ksg{vO^w|3$x(@w)dsAD>Qg{qMGE$ut?OhWEFn63*Sp&=+{~)$66}QMrK2kwPEjvW|t=YKC+DYMIozEOyP!1808KDD+3(
zzrp-WM^EIDE>Ka@*%eQ@zRqM#3fnCbYqMa>luOmO!^6bFcsx8i_8ixJptSOI!dh;{
zFve+5M7bRW?(l5T(eU_oTrcv#xy=(-&-ihAFSAbXR`$GDSv9`aqG|cYMos!>ZMloT
zm|iHd`RP@r%AxlD%p&XihL?N1m#kc|+?vtznb2Ie*Wb$WydFCn6fODAxQ?Oxb@InZ
z^~>ALon}k#+-m%8M#a_6&Kp7d-|aJLU!?UzeZ@LvUpEh_yhOLntndf{G9Ik^A(+5$
Wx_6(-zl0<4AQ?|rKbLh*2~7akB1Xyams|L+}iAArccq*H-e>r2{iJ5=aOk)lIH_eeCl|mNR6?`SK_G-lidh5JCtc
zBq@F0-{x=~ol*F;OpngFd++^wRRX@lKgd|gSc`-^O9`D}_#aFqbjIO-OE`&yV`>3y
z2H{6`!!YbDo`6Lr;h(L(0gIZ$M-_k&KAHfO@KFRHg;y7V7G6~VVt6$HsNq!vAcvnV
z06qLH0VRZ=ETEL|lLV9${%QdM;YaqFWP1%+VcsZ*AK7FgAm~Q4%HiQ?o5~3iAn(#a
zrY9Mnr3tA1BUt@!@akP*@BP_1_aTQ{8Owi8G2iQtDxfq8lj{PdNSIX^DM7;Q$`HB)
zmC_ip1hv{Assz>ID53=Q>M)vwDCKb^3DNokP$WcckU)?Sy+b5-2}xRH0wtKV$Rz6#
zx*%a(LcbLI1YD3{x_^+oPwAxIRdQ*SC4>+{2qCrdCBOixs1U1hHqUwh0000<
KMNUMnLSTY5^23t=
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_action_back_dark.png b/Clover/app/src/main/res/drawable-xhdpi/ic_action_back_dark.png
deleted file mode 100644
index d5760406180becfb647bc7ed6f6f40ce2517e738..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 401
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=k|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+7>zw$978H@y_t2Ex5+`kE%MP-Hk|`(InJ*a@ZR3QxA%5~
zSpu_I0;9$3jHEplhu*yVQ=@;gKtZvR-!Wp_YoH}Su;P?O-|7>evZd0cexLX>{d$I!
z;?-%(&o&vmxI#!2k_e+#d8wP<;#n7FSnQam)n|HEFFHo=8Ag=W6W
sh*rC92M=_pR@i*
zPEjZcR^hV+AS76ZFCxHFf_3;}0xTpT!WR`#QUWS`aRDVHAj6vo$dP~!Zzf=k1ds5h
z0`8IE6+U}6SYkz=AE7zA$Wy1p8|=~!7V&gK%#^meXz0%8wWZ964n9e$r4n+
z9g84Tf;flor_-F)OM-ZYj|(39WCq}AtQYDUDT$39RD*!28&48mq(Bf4M
z*efW9cy$A|3d4V1o%z@v+C@zkpMKi=gq(
z;I)vA(3}bH@|rvKM#%J5*z{q@^l{j9LBw=P%yd!IbXnZ=#fa&vu^iuQjhHdV;Tpbc
z`@Fl|n2Wjr5BGg7jj7@Nn$Qio;4%G+3?YONLI@#*kQ4I~U;up6U|mr}u3rEE002ov
JPDHLkV1oU%v4;Qv
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_action_done.png b/Clover/app/src/main/res/drawable-xhdpi/ic_action_done.png
deleted file mode 100644
index b8915716e06792d926f397a7b17346f656c86aa1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1546
zcmaJ>eM}Q~7(NOZ>jx?|Mx7)_1qW{Q?n+DPg;FVn(PM_rcwjwgk7z
zaExq;FcCM$1T(WNW-4=WI(1VrnIo~NbIM>M*htY0#}vP^FxeFW{X=%i-TV8!d7tO~
zdUEwS*{>~}w{ji;01FLSdXr$+1>d=Igzo{O;<{i~@EK-4moDL57>fgGHrj%N1`;d9
zO*m%rRCM7f01z5Ogb|R~a#dE8&^Q=`4tJ)^jrh+MMR3IR69s}KEImMxFjdYS170y97Bn2l!
zc!x&%v?#MN2TZ3~98}8S1S_0`fJq7&qJY&3^{b#9Mqmh$L$E3Vfl;Ljg%NP-kqX&Z
zTM25?XHMl3ZW^hb=NS}&TrQW)l_;axQV3D2)etO)%@DX$DNsRmu?1h*=3L=$S+q
zji`a*c#N{*2E9fqaL5S4h9>Hh6v?`@WTg&HMvx3dtw7Wn3SD|yrV>#pbjUPTPg|WN
zPVv)N+cT_sR%}oVBqLvOnw4(~Yn#0m)vQ=ZC?~O*G{jdJEH8vU^=Avr+i|X?`*2LY9
z7jHvHE29PrBH!kINN(*uSt$Oev6h7iu1N7t^Bcq8%eH4kerw;l_*m?|A2AK`y6?34
zP`@{J#lYB+FlJ}1sp{bG{!_iCO_Q1c_7CzZkyMzhv`>@qo7TfY@Gmt3uSG*tgxNWQc=v|JYQSD*fn7li5
z#PB$#i7UEVf00h?$hp1uLQj2zQtZFGsWX7jD_#?wJrFj3Z4#6Vd{fyGdK_MQaQVc!
gtQRZb>MZ20@IqqOj{Uq9k@3ze9U9M
z)lmL*9cu(5Z$ty@gS0m0_72Y*2ipFaZ*FFOJmGtrEg@N+t&rB
zf~VDorivcQ(D+nh5!jo(T)d>t_y-MR|LI)6<2eD96V+>(Eu1DOz27U4CETR)GfdlY
zzQB@`+vB))w~)xp|PcL4n61(4g;$56@AbHzE3QUk+_FtgUDK
zp!zi+YO;!F=<7&!_ahatOTI_)Ce$*l>#3Hx>JBsk12iP%PG5BXTiKs4zn|sZ&S7Er
w!T#h);t>uEg+PG`7iU&{%bBF&*?E_Vhhc@a;7?}nD~uqOp00i_>zopr0NlMvD*ylh
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_action_play.png b/Clover/app/src/main/res/drawable-xhdpi/ic_action_play.png
deleted file mode 100644
index e01a8445e46def02cebb461969284f628f6d2af2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 522
zcmV+l0`>igP)j!c
zl}e>j{ZC!jl~c;c^mt|t5Ka&asQ{ebAoc*^2r-ig;GqiQ8z5}BwuTAxo)v;vNd@5K
zD!^4j15rr?@H9yX=M8%f{$L`$dx34SrtA-9gfrF%Vks5C!ymSIZB`Ni_}8X`u%qG+
zCegX?5MLDh!6ZDpM1N>fj@5=h75ZcKTp|G99~$(BQX&A~AO7YCsQ{k-fNOUp5rFRx
z$Czt3bpX-VZY}^`*Y2fM0RC7VWbNh%An4l789Z&-u=tCgB(^{cQA6@png_Tt|LEK2oB`Y+c0>D|BLIt~-b%a%&*<)UjKd0IeeM#!
zN*jdknD|B7BxvzkYsV^gN&wDia<|mwS0w23I_9-T6+qDOl^cLMb)TmKFlbHX3?Rsw
z$`Qb5<10k~!PitS0HUp_WaYlaPwB6+eE^i1N~Kb%R4SE004R>
z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN
zS#tmY3ljhU3ljkVnw%H_00H$$L_t(o!|j(%ZxT@yh7oM#OB;7Zi7_}Pu8cndb<-t~
zYFzM7gw|H5E=*jYR5pz+OkDLxXiCzi!L==Zpkg#GG&D?`Jl$MwX2NjqolzE=IkSPx
zd*5g7aL&1h2$AVtkq{69{ujV$Zm~|A@7NsigKb*e=8T83;vaCC76ZIuz%wkDwhI0L
z2_ABYDs0w>3-uEC16aJpBs%1Xuq?hA1Fq3`n7m_!JQ-$*G0%1Ce01FH)0CeL0hYsl
zj{?y##YxJ1@z{?MAVEhi*dRG^muJ}w2B=GUO_O6$cKrh^Z29!MBwh}(gQk4a6+h+iscd#ng}h73
z$bOEVSnIcIL}S$4s-a-l_0ZeZtOt!jvX!p
z9e(4~F}I4okhJ31{w9syt6I
zFaG|YeX_TQR>*0;&<3U_XZZMQ3J+&VE^urAXCk)nG&@J?Jr#=wJpV0Ns$IpKcW5<8
zwJUsl)+i-wXTjEC&HYDyt?!nI;sXW6HH(h6-Bv0$Jl-;WKG%G-7RFl{?y;ytFI
zpSs^u)z9s2uzAn)X%F{_&pQuf=h^Wqe6nPi>d%~F$9e&zY5M*%Od8MF#f4XFO!+Mg
P3LpkgS3j3^P6U%rc>gQAlyI{<}N(MZ=^SI_8AdKR>jhetYHDLjKeOh)ZGy)Se>sD~
ti7V97rYdY)!O$66q*f-$Da+KL#xIf1*}haLNFQhkgQu&X%Q~loCIFndEw%sv
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_arrow_back_white_24dp.png b/Clover/app/src/main/res/drawable-xhdpi/ic_arrow_back_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce5b878b0fa37a263da66cfe403868fef2d4357c
GIT binary patch
literal 151
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}b0DI8PVHkch)?FCOG
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_bookmark.png b/Clover/app/src/main/res/drawable-xhdpi/ic_bookmark.png
deleted file mode 100644
index f9f17801b76cc1275fa46e9dac720fef79ae4aa3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 401
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}tg=CK)Uj~LMH3o);76yi2K%s^g
z3=E|}g|8AA7_4S6Fo+k-*%fF5lweBoc6VX;-`;;_Kaj^+;1OBOz`!jG!i)^F=14Fw
zFmigjIEF+VemmWki^))+RlTdJwRP&DYyajr>}iNQbT2#OxhspVPRIv=+tuvSffI9G
zK1xP}JnB>Yt;}(5cG^sp&j-0T`-r^QeQF}ZKd}o-Sm$!|30~-mlGoa(E@h#xt}ml-
zYsCQ>&n-`~G`C&+7UG#u?(j5Y5_^oM{5q>?bs~Z5rmtDT&!WKal9`di;n#!XjJ&Ik
z+Z;US%0Kg_+_fDqBNo5ja^I+8ue?TLL$6^FVdQ&MBb@06#mE)c^nh
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_bookmark_filled.png b/Clover/app/src/main/res/drawable-xhdpi/ic_bookmark_filled.png
deleted file mode 100644
index c5698328908edbf984c6f7dd32e133b34957828a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 341
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}tg=CK)Uj~LMH3o);76yi2K%s^g
z3=E|}g|8AA7_4S6Fo+k-*%fF5lweBoc6VX;-`;;_Kaj^+;1OBOz`!jG!i)^F=12eq
z&w9EzhD01r{&U_T`hZ2&!4q2@<}RFku(NTxNANzQH^~~wI~@10X7Q*?vUrrda%bbt
z2}{_X!0T)vxo~6W!TAx~_Y65EB_0&daqPO=WY2Tv$x)4sVt-N-q_!qpX%fsoXrJTd
zt}C%Mp(WBGFF5&1Qy{mS?t&Xl@jR;~)fivev<0x4Wkr8zN@Nq**YZh4!bsv$qsmkr
z3)YhFT5b0;vTii|JCSU#_zaWBf;oqTU!`d{{=zd+mqy@&U*ubk`V*qRa8*k15n_Kt_^R>9Nyj$8{J)oPtC)ck*1{h_(=T3qCu
zqT}4R?o}up^DOr0u6VTFR`_*e^tF=p>~fKpSIbqTpVIt3RqDq924)@!10ZSefS*}V
z{Wqid6rRUk=W3Z5B~3qP88O*Ac=&aPc>C?(_1Lj6edWCDNudn^?gww~XyRL#>u^}r
z{r>yoF&BR@YX$Mu{jpS8dW*})y^wphybnKzyP%qk4>yEj`}1}_6I%_FcVkPt%N{XT
QpdT4LUHx3vIVCg!03d8-Q~&?~
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_bookmark_white_24dp.png b/Clover/app/src/main/res/drawable-xhdpi/ic_bookmark_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..872349cca6ffc150af47fddd05a5cd9648619c1f
GIT binary patch
literal 213
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}b0DIi4<#ArXh)Uf9Tc$Uww3&^)Ep
zfYG3F`bPtU9&fG$ZvRPo3JW%}#O(4AJh91FX;%5|n&%$pC6=ajnX<2YQuh4FvM1lQ
z&rK=QRJaj**--w)>V{~$4=b2Xu+L*+;dr3x(7+&|;Ba7nL&x!?k4IiM_UXR;PzWCs&hKm{}Ung#;dGK1}q&RP1!jxG{&BN`jM9sN0LV@mN
N@O1TaS?83{1OP}SQ~Ce^
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_create_white_24dp.png b/Clover/app/src/main/res/drawable-xhdpi/ic_create_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a06bff5a2fc95d5117ce9880821384626d8864d
GIT binary patch
literal 239
zcmV+mP(MLbxIU@tZx11_<06E_Cm;EuJEI5KzuPNK$?!{-w<
zW;{Mke9afh-**!m1^<@N@NHtL5K^$DhZ|FM=P=&qvIgiFq?I{~>Up@NR&`
pI{_Y_4KVpkfXgQVHXn-(+!KC0r!M+UZ~XuO002ovPDHLkV1hXhU+Vw>
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_done_black_24dp.png b/Clover/app/src/main/res/drawable-xhdpi/ic_done_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..64a4944f7531ab9fb745fd34dd00c778cff1573f
GIT binary patch
literal 188
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}b0DW=|K#kP61P7xwZt8HzYxyd7xd
z_anOJT=vF;=6o%TO%qmB2=N*^J(z8E{F3t0DRy@o7f;`BG-3LF`^uk20(J8L%76ab
z`e&B#*^~M_=S=wbCso$$yluDh-ek*SNjhm@r
zV_;&2g`J8435fwA#K6YFz(2r-U|?WD;+({Vp(+xV?Yn#TzVH2hxVCa*W_o@a05H>B
zwpx6J**7)G|4G09gD)3Yy~Eb&ChIvd0j5Vc2y6z<7HJX3+rR&TECMjm_1hiRv2S6Q
z2BMSch-naUGyscBY2>)uguxB6<%fpw?e!Z0`ko=&Rc+ahYNYEg_hYi&UunDjZCCe%
zrE738#hf4@%z4XMOc!0y`I=BiZtGmkgn?)hoTg?
zMj_b`nUfa6WFcp;NaDtR#C#gUjM3SkyUY-{r^66}$hMD&!(@~wo-!$QA_#@0zgL&>wHk2uHZ}4jD^P)IA7Ik+660)Xc2>eF$
zd=J+()v{F7D9Q@bDhO5NN>Mk9W(ldPrZ&`^<2bBVDwlOd*7b&FB2-r@wNkyRTUte_
zmdz@%a%?k9m=n4rx9fAeBW&eFEUv}GVKi=2x|4UnT9-1KbZG=@>l(adJFXvQg3DQf
zhVfb?_V3e=mU3>1=b9@{%=^O5ariISQh`ZfrR?hxs_miKSeSdnFZM>z<
zz59>q{f@@!IrskAElpYJq&KPiiPBCFhMgWj))Fp8FZP&!(u-Yx-6=N#I*7s3)z4*}
HQ$iB}uzOqu
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_more_vert_white_24dp.png b/Clover/app/src/main/res/drawable-xhdpi/ic_more_vert_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..efab8a74f794c2931d4cedf69cd30895801c4df0
GIT binary patch
literal 158
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}b0DR8JSjkch)?rx_g|6%VwoI2{_d>%srJ7&|&vk-TbVh<5S;l;%8hhyk$Kc9U$ho
zN!;a@as7tMKN^!>mP|UmC!qU^(pC>$p{$8fOT;)oR_iUC=UG0_`?VR+LIzJ)KbLh*
G2~7aOZ8w1c
literal 0
HcmV?d00001
diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png b/Clover/app/src/main/res/drawable-xhdpi/ic_refresh_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..1989184b14751617cf6e19e833810f91563f7522
GIT binary patch
literal 509
zcmV(sT0)b>h9b-n(poNi8
zG-zQY6b*JU4l5e0V&oJJDj3%k4Q4T3VPt|orM3o^7Z9?FUlo?v_>EjL`pcT=Gl;SRnlaz&CFzDJ}KfN37%TVq`A$WX`kh6{M=
z!6=v6#el|o1bhI``@OGFc)X9DQvEsOU$8q^tdCHMdU
diff --git a/Clover/app/src/main/res/drawable-xhdpi/progress_primary_holo_light.9.png b/Clover/app/src/main/res/drawable-xhdpi/progress_primary_holo_light.9.png
deleted file mode 100644
index e62123c4d45d4de95b73db947f09cbb7edc4113c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1285
zcmV+g1^W7lP)w-zSTJ4{Ou>Y1deZ-!OP+`@z;1hy!P?u
zgkjs@C*+1<$HFIaO`2)AU`o
z3QxzAVcgE^t-TNH-X_WQ>)AXv;T_->Vi#Sy_zoA}*;3!YFx!U*CDuBTtBM@W>6#)>
z4>>G-r0z4DSn7|YQB#J34u_e7LE}`U5TTH&6dBH5jY3LWQJh4!-E1y1Y_T=Z!{8pz
za+Ph1U%|UKQM36kWmltUkn6gJS*P*2Mq`Eg>eAFuUx&yN8oQM0R5lc+!tM%^N<>LV
z7(%KctFdd4Q5+$P8`}|bktHY=)TB;>oT;+!n9M);#peFgPy8;t{Q+Eg6YY;TbpPN$
ztLM+DxQWTAQH)ZkM&A)`i8_xGNPT1h2SEYCb^(R$Mjj%GLJ&ZMA|x8ilGR{G5UoMT
zcG}3rL=&Nok^*P|-uu%he?6h9$K_K2+%>@$XtgatXI18^AdU$@1;V6ak)>oWGc!^umr$V$hO713sb-fBTa73*a=W#p9jii|RaCBObAfhxnj_=3W9YulCR=ajQmk=!ly0UgM+P67|`xa*EUD>Nh9zfB&&A|F^IkKPJ{#z{~b
zLe&tpmuB+Ne>Q67cbYA8UHOV_tzjGZ!_vWrYrl^!ufWDG9CwHf$OrrMS3<+*()SOF
zI(6}*OT1Gjg9k4`tV
z4nGFwXyf0gA5Y0+!FSdf))syF{FB~wH1(Yy{UG_{t1lXO_5ZBk4@}xo!OqnrV0ATB6K?00000NkvXXu0mjfl%{@_
diff --git a/Clover/app/src/main/res/drawable-xhdpi/skip_arrow_down.png b/Clover/app/src/main/res/drawable-xhdpi/skip_arrow_down.png
deleted file mode 100644
index b8105c86e43367734a53e3541d6f400362b9187f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 705
zcmV;y0zUnTP)|rT1)vVv`v4e#G4O3y+9*NiHAX
zy~{oBWDJ5J0m{V{HX4ml;g|a=DziZmZQ|tJNxT{qcCbu~dMehE%K7gWx2U
zZQIJB2<=M!eqUIlj{R|{4XKPVy5NY0A|?2$h9d)tv{8u~IvS0nL!o=ffFgCc9t;N3
z8oh;2_c+V<7+G$vqPt$4TMSSY!<4-Fih`puuq&GqoC-(vXs2|pbSxYl??=j)fzSie
z+^5}cvqGT|TbJtfdOdTNflMY7*6DO&Cx=u({qA5lO>5V6-y*>T
z|8?LS23nqZ`M%()N$D61+S?E68p2DDza{JB>
ncCcs7d%kvK3Ist?^drCkyh#BCaTah{00000NkvXXu0mjf;^{j<
diff --git a/Clover/app/src/main/res/drawable-xhdpi/skip_arrow_up.png b/Clover/app/src/main/res/drawable-xhdpi/skip_arrow_up.png
deleted file mode 100644
index 5d40a66d51ff913158d450553c703414b8794f26..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 690
zcmV;j0!{siP)m;+8qJ?g_WNMiura&q
z&zVhj$jTT5K>;Y^b+X-V=S5KwRuYy=$#*^o+X!3ex_I|V^81suca
zq~>zbXUd^4I|Ay$2|k=ozBqWxyC|v(O(#Xp`Oz?pUssQ@=ad>#PxV`&R8jOMloL)-
z^#W5;_zqq40+VBq=UoY4fB;|sCJ1GpZJ^WXSSFMD{XUz`X7Ct
zO2jlxc+6RiMuQE9L(AwGV1!z&78?u(tWYReM#ogAG#CQV>-DbcsV;6fnru*HfuqR?
zMFu#UtWe^Hqsa^8i00v+HCR%0V=ybJO-JJ&A?RM&b
znNFvcA(Sx301UtY%t;3zaR#$dn8nr$%z~YEu&btnuIo!zF!p~PmoP_978H@y_uz$bK60r?Q#k$x8#chDY{D(Sd}L>1>LyN
zBi7zGtw&@UTR%@pf{MvPMQM)6B|IgUoPsqqQWmf(SFf*{yy)GXIp@DcS>IQmD`ffc
z=D+)QtKZ+-8N>*51QyV+X!G!ojLht&bGP`=8g|qzoIkQ
zt*ttiUusM0nEgMCK`@T>{rdwM-yM(sS8$6^vE4ZB(A_=Lzj3{Ne`9)?jO)d!tx>Vh
zvlxW``$Wm!{l8Gt?T4bE`EY8fHIqCE!%^WEc`HpI-Df%_Zhc>rd
zum9fgV`Wod;D$Bs^Gmgky@-Ccy;EwbcJ7pw+>^R9mmfD|e6jh?jfiFU-p772|FoyL
z&{ALb>%AviW&Xcf>~4DSYn9>g(kuSuS6`mq96#&!%_Z+&wiXw?5@j
zxKI0nNiFLcV_sgfF=%}~%|vF6?D^Y1xeU=2JJ;;v*l{wf^KoH-?iqD9oAV#kq$95d
z&b#nv%{!xp^Tt1SEQmh7F|}>+li-O*&373xYuEC0XsV|~R_T2?b<^#C=i}wBYHS^x
z248uO+G*|hQP}FaUgc=H?1nw|ubw{Aohj>Sys%YS;QNyGvqkdWZp?`AdMi}_cDKV<
z(*t)DW3&}Sul}EJ)i-~djee`a^8FTLZfS1U&(8SzU$$uuTIUkk6JXfc;CtE=9l88c+}|n#Hs0?
zye`C1zB=jj^~2TnvTAp^ug;$G&Gr1|2XP_JFBV)m_{C5`ai{XjX-lLY*rdrWcz=RN
zd%}FiGaS6ePIsyjx15$X*(rUX=fX{)hJ2mkpyoe1JKU~UzAIi{X_!4*@YErN^HHIu
zUtEff#it(VqhAE%Cf==yk437`Lqks8S*gXC1k^82*FW)A*
uJoMbMrE6U4imL*e{(>?YHgIC1JrfUu-Y!1#9~!c(AQhgjelF{r5}E+gPM?$j
diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_action_attachment_dark.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_action_attachment_dark.png
deleted file mode 100644
index 305bc41a46603a4838c6a338e5390694e02d7ace..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 822
zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+m~MEwIEGZ*dNb>6;UfcyHp9)~Tn$V&m|_kDIZU$FWVk>5
zjwe^b`;WEGj0+oc56gVX}RLqm?O?OH<^xNzH{Fh&WwqgSd
zUaKt3+j2AKSkcaDOV?#S*(JKkD{{4p=c>t43Wu~Wrf+H!-_?12)3hX)+7M=!9}{E5
z#5df|4S00Flk;dG&xME20R+
zG?IfOvM0PdQJudjFSod9HKYHoQ=Id9tg?>njaerZcgnThW(DJ?wBVg*csXB8&wkT=
zhh^!>-m_^XCmD?opVtrjv)|gn^IhqUn`sFalK(%RU3g7iqVLw`)yG)#nbYt=kY5&aA4lTxzsGNb&9&dgT?EvUp?Pzw#e<8@{C>%$%0y<4v~yjNJ$oBx>mrSX!F
zkwLsSG7?uCOzmy$^-beG=w{$(^ZeZ3`iLzaT<4#waip0^DWHvHh#J?qfLcV)bQr9H={&6$AKSC49CQo
z4E6~$d~9Xt(Pv4hQDk_`jVZ<6XPziS+_-)^1q>DvCie~upZ|6O`j{{NNv-}x9gk{KF+LEOa1
z01RUV3A~)57~eFO*`J#>DMiTMm?C)a-H|mp9MjyVr8;e}HP+*9`ns^zU7^O!ddvBL
zSB@|Xlx@9M9oJ;S@%l&fy%tlB#N+&|ADEq9d^~J+>El-y1Td+qW@KY9-@Rk0!#@8v
Qz!+xmboFyt=akR{0OTvy#Q*>R
diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_action_back_dark.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_action_back_dark.png
deleted file mode 100644
index 4919a8d7dacc294eded63af5253bb1a4d824f0b0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 463
zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+7z;gJ978H@y}7f|_lSdt>&30bR>`k#FljU_Wmwf{w1Dx}
z0tVx09VdJ~{rf&gJJN$=QuzkKNi$EoPEzp%qm>D_x5XYW-R_e2r~m$H+e4Rf|9pJ-
z^ZfGr(^GdcpXj+SmuPwL$6CQ_lY91mx7hcM(;@B8-uH!jD_Nc%+u!ScL7d_7ceWXs
ze~K73_r`N29Q$~h;fz%sXT!|n{mf_V>O>CwaAbJQ&e$W*Vo)c5m($Svc>c!o9}k!O
zK5xG6*!gWz`!yRra^GR(V(N*v`kmdNuf}taQGm;)N#Tbx4?~L*g8&zUg9Zb`LI#Ew
zCVZSfv$Yy-3d)2sB;>IizsfK}df}IawZ;ll>Wtq#(AMXFysKpF
diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png
deleted file mode 100644
index a9bbcde5a0267fbd3c4c6509ac1c62acf46f150f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 567
zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+7;k#IIEGZ*dNXHt?qLHFSI_A;6@yoJy>&HeX8*_&=~AlY
z`%pHfoh@Pshs;H>pYOJwV`TZC(D7dGud9|S&<QojJWq{W$G32b
z+5V~1gJ(Xw^ejJ`(e%&xUmqVSJPiNw{_E=X^MpPv_%OM-#r}~0Ueza!552v22-k&k
zw)=gRdH<(O`$GtK8R!4~v!1Zbc|A!_KQZ;k^r*>K?Gj2817|C@nmr5G57?Vqso%P4
zo96qq30ql}-e*n?kCATY?BH`Ktv3mA2oX5N&U~1)htK72frZO~6$vuuTo18);X9%D
zr+{&9QxRvp(}8P^maY2A39BF6IW%49Lrz2A!_%AHd(*V&b)d^ZzkL#%zY!3T1~l9vDm!He@N#Jfu^j
zcZ{=T|IvEE2|E;%<@c>-$vgG_=Q5kSK`&;A>NT$GJSg;Hj+UDB-^Sh9Nb<2H?#IoD$9}cKB
rE>@6>R4b4>;QSjo7J%#o8+#@m23aH3DE>zRz930YS3j3^P6#a{g
zR;!|d;+#c=g+U@&8#qlP?>iTDL8fv<-j3NWs1Dzp&i6b`Uf
zX#a4S^$OQ1)f!I5VD@Js`+6EyHWhQndmY%!Xw{~#{@|iQ?BVGm24)xj?M?l$iOJ2&
zW8Fh#s{qD=Ojqze(iZm7@2I
z%I@218TfOAUI_H-2v0oV{2Mtkfb0dj_nCMYChW}1JZTwX29or2^>bP0l+XkKmnG>o
diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_action_done.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_action_done.png
deleted file mode 100644
index 6fda89ec7d8d2ef1caa50a1191c1b2f9a0e65e2d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 649
zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+n6y1z978H@y_vn&?@)k*!|Ik+M|N2r&hGUM-TIHt7{92t
zFt#xG%y-U5#fNXrtdgR_gu;*6Ol=dkEd74(-v0M@Q3OilarG)?VsosHc6X{kFE8|r_utCc
zb^hr(TDA9H+1%eud(S;t@AFLE!QrP&)2yfd=O*mmGSR;w?dN&j*=t???S5Na$gyg=
zeb&VN1s`izI5g%nG(Htp*igg7GHtz`L&ncl%tsXBa~mR_tmYAzTvN)JG(^Jy*f2`2a7taYt1E~`Fiv++F%=bn3Gp8Vp#eT5CeKiL;`Oqf)&
zn8EbZ;*JTk{%}p+uaf_5ao?*sCnY~sSFxVB_gA_4XZxMn35IKKo_VdU82aa~Rq{bZG@b+P#Mt@iqco6CE4p82`js^K+H4XA>%t@~3O;?3l3o
zPaN|Nw+jmUzcVZo+;U?5hi}uL?37nb)!BODyVL^bme|veZ=U#G#9?G1!wVFWTj0zh
z`l*@4pl8C;KM9OhZYRR(E-<9KortRYz@RI*X}Y{?!z>Q1C+@-zR1Qt;*~#`3B_4sC
cpP$qZFdVVp7yd2n{x6WEr>mdKI;Vst0Qu`3kN^Mx
diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_action_done_dark.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_action_done_dark.png
deleted file mode 100644
index 68c41deccb550fc809319aa8efb46f392c6281c7..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 619
zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+n0P&1978H@y_s{+_ppJ8!{n}P_Jl^g15&Add<^BctYsTm
z4>5e_GDLs#>D%YM3-mt2b-{
zQReav(feL9Xr3^aRuKKE#=J!3eoVuaC$qUGEUGbP44Rs+eFZc*?GRW@Ar0{5NQ)mVA*nb!T+$r)Oc&qeP0Zskz@Y3FJFO#+uE1vLFh(0+Ks$ZMkfmrxfS
zP1Te9QVMNzE_s!9pjCjHI8;qcJzn3vHZ_l!SQ3-SwA=Ftc~CDzuKzYpZh%^
z^;pvS#m=#u;d_4ln7V&*@>UiOiG?LUyV*Zrda4p1AWHC^m8a)MB(z5>b!WJ^Un6l^l
sf0mUm#gi8ZJe2&25@A5j&dXL>W2A$!YSA2~)w76%4K0S5*a0S5fcdD8Rv
zceE*+xnB=)Yj?TB;6H(ZLxCZ%&M`j0O9;PKB(w9LEqJYWi4o`^fwP(i7(N^q{1!7k
Q^CifIp00i_>zopr0M9i`&Hw-a
diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_action_play.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_action_play.png
deleted file mode 100644
index 7f7ca2e028450694d6b4b784bdbdc8552080a46d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 702
zcmV;v0zv(WP)C;$pb0l_222&5>$VaH?7dy=ow$S-Tpenpu~00000
z00000007{hY`5D(x?n5dUg{DNewZX$
zoa3iYu%jQ2y-SR*+)tHv7lk*=-D
z;hAS;EQN@@ljF08h`p2ZFObIGZetDa0u+rk+{NBe1Ss=~v)DVD0L4x09aVtt2aPpm
z2(Z1jHXD2QAVB$wy%AtLmNeFwBfyRvYuvODd-p2f`+hKuy?Yn%eLtAQ8VLBgAFBVF
z4*|RPL$%l&0sHsE=&?5fen(^PGX&V~hf#jbhX7*^Xu+S@NZn1R(`N+KXDKyE^EW&J
zby-VYOXJ@dL3MeTT1ey9?11`nK98CuOSnESQnzExc?9gA^SSY_Ttn;6`P}#w?*aAa
z{8Ab}@FHe2=ZCScl?d29=Z9L?N(5Ah4-oJ>Lz(rP)(;v@z^Z)f-@F_+ih$R0tz3IM
zxOV|2@c{xp88s$G!2WCHwWm2BML^Y<7y%8(2R#Wei-~&|U>+0qDxjH|xHkcta;;oO
z9yhHDXfh`5L4e!%z`Fn!F>zD@ZerqS0#*}eF>w?DA>#uN0^G;Mo&|)6iCw}!qXPf{
k000000002MZaxGU0AWNaUcsk$JOBUy07*qoM6N<$g7ES&*Z=?k
diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_action_refresh.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_action_refresh.png
deleted file mode 100644
index 72128fe69086bd90233bd2f16ca25cd52f423326..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 875
zcmV-x1C;!UP)004R>
z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN
zS#tmY3ljhU3ljkVnw%H_00QGlL_t(&-tE~>NRwe4!0}CTo{HE;x%AM%xu62Y4l4=5
zL)5J>sA)kGC5fenLhzE>F|ZsdL3A_fP}i9R5)?rwRM%VObYIzLi4$aA
zihqXFZWXpZqu8**g`zoKtYlnHjrybG@8@_{Ip!(53P$agM%M4?utis$x-&>H*Dp
zk8kE-)