aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2017-10-05 15:58:59 +0900
committerKazuki Yamaguchi <k@rhe.jp>2017-10-05 15:58:59 +0900
commit9db537d339faa3ad44dfdcadb23f4c14bd8aceb4 (patch)
tree6b151cdfd0ca7dc44b9a189045b2b2cbc5aefc21
parent52ad6edcb217762154a80990c34ca94772393848 (diff)
downloadSmileEssence-9db537d339faa3ad44dfdcadb23f4c14bd8aceb4.tar.gz
kotlin work part. 1
-rw-r--r--app/app.iml38
-rw-r--r--app/build.gradle10
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/Application.java113
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/Application.kt112
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/IntentRouter.java143
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/IntentRouter.kt142
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/World.java252
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/World.kt230
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.java170
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.kt153
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.java83
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.kt81
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.java347
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt311
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.java257
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt241
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.java102
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.kt95
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.java51
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.kt (renamed from app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.java)35
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/command/Command.kt (renamed from app/src/main/java/net/lacolaco/smileessence/command/Command.java)19
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.kt (renamed from app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.java)33
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.kt46
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.java68
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.kt (renamed from app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.java)48
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/compat/Twitter4J.java11
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/Account.java149
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/Account.kt134
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.java81
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.kt54
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/ImageCache.java65
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/ImageCache.kt64
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/OrmaHolder.java19
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/OrmaHolder.kt16
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/PostState.java184
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/PostState.kt167
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.java71
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.kt44
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/EntitySupport.java121
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/EntitySupport.kt106
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/Event.java62
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/Event.kt20
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/IdObject.java5
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/IdObject.kt5
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/RBinding.kt (renamed from app/src/main/java/net/lacolaco/smileessence/entity/RBinding.java)6
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.java24
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.kt10
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/Tweet.java281
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/Tweet.kt197
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/User.java183
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/User.kt136
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/logging/Logger.kt (renamed from app/src/main/java/net/lacolaco/smileessence/logging/Logger.java)43
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.java50
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.kt44
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/preference/SharedPreferenceHelper.java125
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/preference/SharedPreferenceHelper.kt127
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.kt (renamed from app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.java)40
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.kt (renamed from app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.java)64
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.java235
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt182
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.java90
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.kt65
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.java68
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.kt40
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.java80
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.kt51
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/TimelineTask.kt (renamed from app/src/main/java/net/lacolaco/smileessence/twitter/task/TimelineTask.java)34
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.java94
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.kt72
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.java74
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.kt56
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.java153
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.kt125
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.java143
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.kt92
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.java111
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.kt113
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.java119
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.kt122
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BitmapThumbnailTask.kt (renamed from app/src/main/java/net/lacolaco/smileessence/util/BitmapThumbnailTask.java)44
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.java80
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.kt68
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/Consumer.java5
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/Function.java5
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.kt (renamed from app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.java)54
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/ListUtils.java24
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/Predicate.java5
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/StringUtils.kt (renamed from app/src/main/java/net/lacolaco/smileessence/util/StringUtils.java)36
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/SystemServiceHelper.kt (renamed from app/src/main/java/net/lacolaco/smileessence/util/SystemServiceHelper.java)34
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/UIHandler.kt (renamed from app/src/main/java/net/lacolaco/smileessence/util/UIHandler.java)12
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/UIObservable.java38
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/UIObservable.kt38
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/UIObserver.java9
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/UIObserverBundle.java31
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/UIObserverBundle.kt26
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.java61
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.kt50
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/DialogHelper.kt (renamed from app/src/main/java/net/lacolaco/smileessence/view/DialogHelper.java)42
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/ExpandedListView.java29
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/ExpandedListView.kt23
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/Partials.java229
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/Partials.kt220
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.java147
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt140
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.java56
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.kt41
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/ToggleableImageButton.java37
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/ToggleableImageButton.kt25
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.java50
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.kt45
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.java116
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.kt102
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.java53
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.kt43
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.java41
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.kt35
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/PageListAdapter.java140
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/PageListAdapter.kt110
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.java39
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.kt29
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/ConfirmDialogFragment.java119
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/ConfirmDialogFragment.kt119
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/DisposeDialog.kt (renamed from app/src/main/java/net/lacolaco/smileessence/view/dialog/DisposeDialog.java)18
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.java80
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.kt81
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.java250
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.kt246
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.java131
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.kt127
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.java28
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.kt25
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.java348
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.kt339
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.java89
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.kt81
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.java423
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt390
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.kt (renamed from app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.java)47
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.java117
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.kt107
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.kt41
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.java104
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.kt97
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.java112
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.kt102
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.java97
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.kt90
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.java32
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt25
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.java334
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.kt304
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.java321
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.kt299
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.java192
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.kt179
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerEditTextPreference.java36
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerEditTextPreference.kt26
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.java37
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.kt27
-rw-r--r--build.gradle2
160 files changed, 7486 insertions, 8555 deletions
diff --git a/app/app.iml b/app/app.iml
index ad948429..731bc1c8 100644
--- a/app/app.iml
+++ b/app/app.iml
@@ -21,12 +21,30 @@
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
+ <facet type="kotlin-language" name="Kotlin">
+ <configuration version="3" platform="JVM 1.8" useProjectSettings="false">
+ <compilerSettings />
+ <compilerArguments>
+ <option name="jvmTarget" value="1.8" />
+ <option name="languageVersion" value="1.1" />
+ <option name="apiVersion" value="1.0" />
+ <option name="pluginOptions">
+ <array />
+ </option>
+ <option name="pluginClasspaths">
+ <array />
+ </option>
+ <option name="version" value="true" />
+ </compilerArguments>
+ </configuration>
+ </facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/kapt/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
@@ -34,6 +52,8 @@
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/kapt/debugUnitTest" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/kapt/debugAndroidTest" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
@@ -62,13 +82,6 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
- <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
- <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
- <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
@@ -76,6 +89,13 @@
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
@@ -94,6 +114,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/sourceFolderJavaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
+ <excludeFolder url="file://$MODULE_DIR$/build/kotlin" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
@@ -106,6 +127,7 @@
<orderEntry type="library" exported="" name="support-core-ui-25.3.1" level="project" />
<orderEntry type="library" exported="" name="crashlytics-core-2.3.17" level="project" />
<orderEntry type="library" exported="" name="antlr4-runtime-4.6" level="project" />
+ <orderEntry type="library" exported="" name="kotlin-stdlib-jre7-1.1.51" level="project" />
<orderEntry type="library" exported="" name="support-v13-25.3.1" level="project" />
<orderEntry type="library" exported="" name="rxandroid-2.0.1" level="project" />
<orderEntry type="library" exported="" name="twitter4j-stream-4.0.6" level="project" />
@@ -115,8 +137,10 @@
<orderEntry type="library" exported="" name="support-fragment-25.3.1" level="project" />
<orderEntry type="library" exported="" name="reactive-streams-1.0.0" level="project" />
<orderEntry type="library" exported="" name="fabric-1.3.17" level="project" />
+ <orderEntry type="library" exported="" name="annotations-13.0" level="project" />
<orderEntry type="library" exported="" name="beta-1.2.5" level="project" />
<orderEntry type="library" exported="" name="answers-1.3.13" level="project" />
+ <orderEntry type="library" exported="" name="kotlin-stdlib-1.1.51" level="project" />
<orderEntry type="library" exported="" name="support-v4-25.3.1" level="project" />
<orderEntry type="library" exported="" name="support-media-compat-25.3.1" level="project" />
<orderEntry type="library" exported="" name="volley-1.0.0" level="project" />
diff --git a/app/build.gradle b/app/build.gradle
index c8100f59..530700ca 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,4 +1,6 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'io.fabric'
@@ -53,6 +55,8 @@ android {
}
dependencies {
+ compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
+
compile 'com.android.support:support-v4:25.+'
compile 'com.android.support:support-v13:25.+'
// volley
@@ -71,7 +75,7 @@ dependencies {
// twitter-text
compile 'com.twitter:twitter-text:1.14.7'
- annotationProcessor "com.github.gfx.android.orma:orma-processor:4.2.5"
+ kapt "com.github.gfx.android.orma:orma-processor:4.2.5"
compile "com.github.gfx.android.orma:orma:4.2.5"
// Fabric
@@ -80,8 +84,10 @@ dependencies {
}
// LeakCanary
-
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
release2Compile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
+}
+repositories {
+ mavenCentral()
} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/Application.java b/app/src/main/java/net/lacolaco/smileessence/Application.java
deleted file mode 100644
index adefcae1..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/Application.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence;
-
-import android.support.annotation.StringRes;
-import android.widget.Toast;
-import com.crashlytics.android.Crashlytics;
-import com.crashlytics.android.core.CrashlyticsCore;
-import com.squareup.leakcanary.LeakCanary;
-import io.fabric.sdk.android.Fabric;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.data.OrmaHolder;
-import net.lacolaco.smileessence.logging.Logger;
-
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * プロセスと同期しているオブジェクト
- * 現在のテーマのリソース ID と現在のアカウント(およびアカウント変更イベントリスナー)を保持します
- * MainActivity の onCreate で resetState を呼び、保持しているデータを破棄すること
- */
-public class Application extends android.app.Application {
- private static Application instance;
- private static WeakReference<World> lastWorld;
- private static Map<Long, WeakReference<World>> worlds = new HashMap<>(); // XXX
-
- @Deprecated
- public static Application getInstance() {
- Application obj = instance;
- if (obj == null) {
- throw new IllegalStateException("[BUG] Application is not initialized?");
- } else {
- return obj;
- }
- }
-
- // --------------------- get instance ---------------------
-
- public static void toast(@StringRes int id) {
- Toast.makeText(instance, id, Toast.LENGTH_LONG).show();
- }
-
- public static void toast(String text) {
- Toast.makeText(instance, text, Toast.LENGTH_LONG).show();
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- if (LeakCanary.isInAnalyzerProcess(this)) {
- return;
- }
- LeakCanary.install(this);
-
- Fabric.with(this, new Crashlytics.Builder().core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()).build());
- OrmaHolder.initialize(this);
-
- // Load eagarly
- Account.load();
- instance = this; // プロセスの寿命の間 1 度しか呼ばれないので安全
- Logger.debug("onCreate");
- }
-
- public static World getCurrentWorld() {
- World w0 = lastWorld != null ? lastWorld.get() : null;
- if (w0 != null)
- return w0;
- for (WeakReference<World> ww : worlds.values()) {
- World w = ww.get();
- if (w != null)
- return w;
- }
- return null;
- }
-
- public static World getWorld(long id) {
- WeakReference<World> ww = worlds.get(id);
- if (ww != null) {
- World w = ww.get();
- if (w != null) {
- lastWorld = ww;
- return w;
- }
- }
- World w = new World(Account.get(id));
- worlds.put(id, lastWorld = new WeakReference<>(w));
- return w;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/Application.kt b/app/src/main/java/net/lacolaco/smileessence/Application.kt
new file mode 100644
index 00000000..7950d62a
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/Application.kt
@@ -0,0 +1,112 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence
+
+import android.support.annotation.StringRes
+import android.widget.Toast
+import com.crashlytics.android.Crashlytics
+import com.crashlytics.android.core.CrashlyticsCore
+import com.squareup.leakcanary.LeakCanary
+import io.fabric.sdk.android.Fabric
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.data.OrmaHolder
+import net.lacolaco.smileessence.logging.Logger
+
+import java.lang.ref.WeakReference
+import java.util.HashMap
+
+/**
+ * プロセスと同期しているオブジェクト
+ * 現在のテーマのリソース ID と現在のアカウント(およびアカウント変更イベントリスナー)を保持します
+ * MainActivity の onCreate で resetState を呼び、保持しているデータを破棄すること
+ */
+class Application : android.app.Application() {
+
+ override fun onCreate() {
+ super.onCreate()
+ if (LeakCanary.isInAnalyzerProcess(this)) {
+ return
+ }
+ LeakCanary.install(this)
+
+ Fabric.with(this, Crashlytics.Builder().core(CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()).build())
+ OrmaHolder.initialize(this)
+
+ // Load eagarly
+ Account.load()
+ instancex = this // プロセスの寿命の間 1 度しか呼ばれないので安全
+ Logger.debug("onCreate")
+ }
+
+ companion object {
+ private var instancex: Application? = null
+ private var lastWorld: WeakReference<World>? = null
+ private val worlds = HashMap<Long, WeakReference<World>>() // XXX
+
+ @Deprecated("")
+ fun getInstance(): Application {
+ val obj = instancex
+ return obj ?: throw IllegalStateException("[BUG] Application is not initialized?")
+ }
+
+ // --------------------- get instance ---------------------
+
+ fun toast(@StringRes id: Int) {
+ Toast.makeText(instancex, id, Toast.LENGTH_LONG).show()
+ }
+
+ fun toast(text: String) {
+ Toast.makeText(instancex, text, Toast.LENGTH_LONG).show()
+ }
+
+ val currentWorld: World?
+ get() {
+ val w0 = if (lastWorld != null) lastWorld!!.get() else null
+ if (w0 != null)
+ return w0
+ for (ww in worlds.values) {
+ val w = ww.get()
+ if (w != null)
+ return w
+ }
+ return null
+ }
+
+ fun getWorld(id: Long): World {
+ val ww0 = worlds[id]
+ if (ww0 != null) {
+ val w0 = ww0.get()
+ if (w0 != null) {
+ lastWorld = ww0
+ return w0
+ }
+ }
+ val w = World(Account.get(id))
+ val ww = WeakReference(w)
+ worlds.put(id, ww)
+ return w
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/IntentRouter.java b/app/src/main/java/net/lacolaco/smileessence/IntentRouter.java
deleted file mode 100644
index 84e41ff6..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/IntentRouter.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.widget.Toast;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.command.CommandOpenUserDetail;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.util.UIHandler;
-import net.lacolaco.smileessence.view.DialogHelper;
-import net.lacolaco.smileessence.view.dialog.StatusDetailDialogFragment;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class IntentRouter {
-
- // ------------------------------ FIELDS ------------------------------
-
- private static final String TWITTER_HOST = "twitter.com";
- private static final Pattern TWITTER_STATUS_PATTERN = Pattern.compile("\\A(?:/#!)?/(?:\\w{1,15})/status(?:es)?/(\\d+)\\z", Pattern.CASE_INSENSITIVE);
- private static final Pattern TWITTER_USER_PATTERN = Pattern.compile("\\A(?:/#!)?/(\\w{1,15})/?\\z", Pattern.CASE_INSENSITIVE);
- private static final Pattern TWITTER_POST_PATTERN = Pattern.compile("\\A/(intent/tweet|share)\\z", Pattern.CASE_INSENSITIVE);
-
- // -------------------------- STATIC METHODS --------------------------
-
- public static void onNewIntent(MainActivity activity, Intent intent) {
- Logger.debug("onNewIntent");
- Uri uri = intent.getData();
- if (uri != null) {
- onUriIntent(activity, uri);
- } else if (intent.getAction() != null) {
- switch (intent.getAction()) {
- case Intent.ACTION_SEND: {
- if ("text/plain".equals(intent.getType())) {
- Bundle extra = intent.getExtras();
- if (extra != null) {
- String text = getText(extra);
- openPostPage(activity, text);
- }
- } else if (intent.getType().startsWith("image/")) {
- Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
- openPostPageWithImage(activity, imageUri);
- }
- break;
- }
- }
- }
- }
-
- private static void onUriIntent(MainActivity activity, Uri uri) {
- Logger.debug(uri.toString());
-
- if (uri.getHost().equals(TWITTER_HOST)) {
- Matcher postMatcher = TWITTER_POST_PATTERN.matcher(uri.getPath()); // /share and /intent/tweet: don't accept status parameter
- if (postMatcher.find()) {
- openPostPage(activity, extractText(uri));
- return;
- }
- Matcher statusMatcher = TWITTER_STATUS_PATTERN.matcher(uri.getPath());
- if (statusMatcher.find()) {
- showStatusDialog(activity, Long.parseLong(statusMatcher.group(1)));
- return;
- }
- Matcher userMatcher = TWITTER_USER_PATTERN.matcher(uri.getPath());
- if (userMatcher.find()) {
- showUserDialog(activity, userMatcher.group(1));
- }
- }
- }
-
- private static String getText(Bundle extra) {
- StringBuilder builder = new StringBuilder();
- if (!TextUtils.isEmpty(extra.getCharSequence(Intent.EXTRA_SUBJECT))) {
- builder.append(extra.getCharSequence(Intent.EXTRA_SUBJECT)).append(" ");
- }
- builder.append(extra.getCharSequence(Intent.EXTRA_TEXT));
- return builder.toString();
- }
-
- private static String extractText(Uri uri) {
- String result = "";
- String text = uri.getQueryParameter("text");
- String url = uri.getQueryParameter("url");
- String via = uri.getQueryParameter("via");
- String hashtags = uri.getQueryParameter("hashtags");
-
- if (!TextUtils.isEmpty(text)) result += text;
- if (!TextUtils.isEmpty(url)) result += " " + url;
- if (!TextUtils.isEmpty(hashtags)) result += " " + hashtags.trim().replaceAll(",", " #");
- if (!TextUtils.isEmpty(via)) result += " via @" + via;
-
- return result;
- }
-
- private static void showStatusDialog(Activity activity, long id) {
- Tweet.fetchTask(id, Application.getCurrentWorld().getAccount())
- .onDoneUI(tweet -> DialogHelper.showDialog(activity, StatusDetailDialogFragment.newInstance(tweet)))
- .onFail(x -> Application.toast(R.string.error_intent_status_cannot_load))
- .execute();
- }
-
- private static void showUserDialog(MainActivity activity, String screenName) {
- CommandOpenUserDetail openUserDetail = new CommandOpenUserDetail(activity, screenName);
- openUserDetail.execute();
- }
-
- private static void openPostPage(final MainActivity activity, final String str) {
- new UIHandler().post(() -> activity.getWorld().getPostState().beginTransaction().setText(str).commitWithOpen(activity));
- }
-
- private static void openPostPageWithImage(final MainActivity activity, final Uri imageUri) {
- new UIHandler().post(() -> activity.openPostPageWithImage(imageUri));
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/IntentRouter.kt b/app/src/main/java/net/lacolaco/smileessence/IntentRouter.kt
new file mode 100644
index 00000000..e5f9d0ce
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/IntentRouter.kt
@@ -0,0 +1,142 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence
+
+import android.app.Activity
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.text.TextUtils
+import android.widget.Toast
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.command.CommandOpenUserDetail
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.util.UIHandler
+import net.lacolaco.smileessence.view.DialogHelper
+import net.lacolaco.smileessence.view.dialog.StatusDetailDialogFragment
+
+import java.util.regex.Matcher
+import java.util.regex.Pattern
+
+object IntentRouter {
+
+ // ------------------------------ FIELDS ------------------------------
+
+ private val TWITTER_HOST = "twitter.com"
+ private val TWITTER_STATUS_PATTERN = Pattern.compile("\\A(?:/#!)?/(?:\\w{1,15})/status(?:es)?/(\\d+)\\z", Pattern.CASE_INSENSITIVE)
+ private val TWITTER_USER_PATTERN = Pattern.compile("\\A(?:/#!)?/(\\w{1,15})/?\\z", Pattern.CASE_INSENSITIVE)
+ private val TWITTER_POST_PATTERN = Pattern.compile("\\A/(intent/tweet|share)\\z", Pattern.CASE_INSENSITIVE)
+
+ // -------------------------- STATIC METHODS --------------------------
+
+ fun onNewIntent(activity: MainActivity, intent: Intent) {
+ Logger.debug("onNewIntent")
+ val uri = intent.data
+ if (uri != null) {
+ onUriIntent(activity, uri)
+ } else if (intent.action != null) {
+ when (intent.action) {
+ Intent.ACTION_SEND -> {
+ if ("text/plain" == intent.type) {
+ val extra = intent.extras
+ if (extra != null) {
+ val text = getText(extra)
+ openPostPage(activity, text)
+ }
+ } else if (intent.type.startsWith("image/")) {
+ val imageUri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
+ openPostPageWithImage(activity, imageUri)
+ }
+ }
+ }
+ }
+ }
+
+ private fun onUriIntent(activity: MainActivity, uri: Uri) {
+ Logger.debug(uri.toString())
+
+ if (uri.host == TWITTER_HOST) {
+ val postMatcher = TWITTER_POST_PATTERN.matcher(uri.path) // /share and /intent/tweet: don't accept status parameter
+ if (postMatcher.find()) {
+ openPostPage(activity, extractText(uri))
+ return
+ }
+ val statusMatcher = TWITTER_STATUS_PATTERN.matcher(uri.path)
+ if (statusMatcher.find()) {
+ showStatusDialog(activity, java.lang.Long.parseLong(statusMatcher.group(1)))
+ return
+ }
+ val userMatcher = TWITTER_USER_PATTERN.matcher(uri.path)
+ if (userMatcher.find()) {
+ showUserDialog(activity, userMatcher.group(1))
+ }
+ }
+ }
+
+ private fun getText(extra: Bundle): String {
+ val builder = StringBuilder()
+ if (!TextUtils.isEmpty(extra.getCharSequence(Intent.EXTRA_SUBJECT))) {
+ builder.append(extra.getCharSequence(Intent.EXTRA_SUBJECT)).append(" ")
+ }
+ builder.append(extra.getCharSequence(Intent.EXTRA_TEXT))
+ return builder.toString()
+ }
+
+ private fun extractText(uri: Uri): String {
+ var result = ""
+ val text = uri.getQueryParameter("text")
+ val url = uri.getQueryParameter("url")
+ val via = uri.getQueryParameter("via")
+ val hashtags = uri.getQueryParameter("hashtags")
+
+ if (!TextUtils.isEmpty(text)) result += text
+ if (!TextUtils.isEmpty(url)) result += " " + url
+ if (!TextUtils.isEmpty(hashtags)) result += " " + hashtags.trim { it <= ' ' }.replace(",".toRegex(), " #")
+ if (!TextUtils.isEmpty(via)) result += " via @" + via
+
+ return result
+ }
+
+ private fun showStatusDialog(activity: Activity, id: Long) {
+ Tweet.fetchTask(id, Application.currentWorld!!.account)
+ .onDoneUI { tweet -> DialogHelper.showDialog(activity, StatusDetailDialogFragment.newInstance(tweet)) }
+ .onFail { x -> Application.toast(R.string.error_intent_status_cannot_load) }
+ .execute()
+ }
+
+ private fun showUserDialog(activity: MainActivity, screenName: String) {
+ val openUserDetail = CommandOpenUserDetail(activity, screenName)
+ openUserDetail.execute()
+ }
+
+ private fun openPostPage(activity: MainActivity, str: String) {
+ UIHandler().post { activity.world.postState.beginTransaction().setText(str).commitWithOpen(activity) }
+ }
+
+ private fun openPostPageWithImage(activity: MainActivity, imageUri: Uri) {
+ UIHandler().post { activity.openPostPageWithImage(imageUri) }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/World.java b/app/src/main/java/net/lacolaco/smileessence/World.java
deleted file mode 100644
index ae9c68cd..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/World.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package net.lacolaco.smileessence;
-
-import android.content.Context;
-import android.support.annotation.StringRes;
-import de.keyboardsurfer.android.widget.crouton.Configuration;
-import de.keyboardsurfer.android.widget.crouton.Crouton;
-import de.keyboardsurfer.android.widget.crouton.Style;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.data.PostState;
-import net.lacolaco.smileessence.entity.DirectMessage;
-import net.lacolaco.smileessence.entity.Event;
-import net.lacolaco.smileessence.entity.SavedSearch;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.preference.UserPreferenceHelper;
-import net.lacolaco.smileessence.twitter.UserStreamListener;
-import net.lacolaco.smileessence.twitter.task.Accounts;
-import net.lacolaco.smileessence.twitter.task.Searches;
-import net.lacolaco.smileessence.twitter.task.Users;
-import net.lacolaco.smileessence.util.*;
-import twitter4j.TwitterStream;
-
-import java.lang.ref.WeakReference;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * World contains data that are specific to an account.
- */
-public class World {
- private static final int NOTIFICATION_DURATION = 1000;
- private Account account;
- private int resId; // XXX: Fetch from Account
- // XXX: Move to MainActivity
- private PostState postState = new PostState();
- // Timelines
- private final List<Tweet> tweets = new ArrayList<>();
- private final WeakHashMap<Object, Consumer<Tweet>> tweetNotifiers = new WeakHashMap<>();
- // Direct messages
- private final Map<Long, DirectMessage> directMessages = new ConcurrentHashMap<>();
- private final WeakHashMap<Object, Consumer<DirectMessage>> directMessageNotifiers = new WeakHashMap<>();
- // Events
- private final List<Event> events = new ArrayList<>();
- private final WeakHashMap<Object, Runnable> eventNotifiers = new WeakHashMap<>();
- // Streaming APIs
- private TwitterStream stream;
- private UserStreamListener userStreamListener;
- // Lists
- private final Set<String> listSubscriptions = Collections.newSetFromMap(new ConcurrentHashMap<>());
- // Mute
- private final Set<Long> muteUserIds = Collections.newSetFromMap(new ConcurrentHashMap<>());
- // Saved searches
- private final Map<Long, SavedSearch> savedSearches = new HashMap<>();
- // Notification
- private WeakReference<MainActivity> mainActivity;
- private boolean isMainActivityActive;
-
- public World(Account a) {
- account = a;
- }
-
- public Account getAccount() {
- return account;
- }
-
- @Deprecated
- public void setAccount(Account a) {
- account = a;
- }
-
- public PostState getPostState() {
- return postState;
- }
-
- // Timelines
-
- public synchronized void addTimeline(Object key, Consumer<Tweet> notify) {
- for (Tweet tweet : tweets)
- notify.accept(tweet);
- tweetNotifiers.put(key, notify);
- }
-
- public synchronized void addTweet(Tweet tweet) {
- tweets.add(tweet);
- tweetNotifiers.forEach((o, c) -> c.accept(tweet));
- }
-
- public synchronized void addTweetAll(Collection<Tweet> ts) {
- tweets.addAll(ts);
- for (Tweet tweet : ts) {
- tweetNotifiers.forEach((o, c) -> c.accept(tweet));
- }
- }
-
- // Direct messages
-
- public synchronized void addDirectMessageTimeline(Object key, Consumer<DirectMessage> notify) {
- directMessageNotifiers.put(key, notify);
- }
-
- public void addDirectMessage(DirectMessage entity) {
- if (directMessages.put(entity.getId(), entity) == null)
- directMessageNotifiers.forEach((o, c) -> c.accept(entity));
- }
-
- // Events
-
- public synchronized void addEventNotifier(Object key, Runnable notify) {
- eventNotifiers.put(key, notify);
- }
-
- public List<Event> getEvents() {
- return events;
- }
-
- public void addEvent(Event e) {
- events.add(e);
- eventNotifiers.forEach((o, a) -> a.run());
- }
-
- // Streaming APIs
-
- public void setupStreaming() {
- if (stream == null) {
- stream = account.getTwitterStream();
- userStreamListener = new UserStreamListener(this);
- stream.addListener(userStreamListener);
- stream.addConnectionLifeCycleListener(userStreamListener);
- stream.user();
- }
- }
-
- public boolean isStreaming() {
- return stream != null && userStreamListener.isConnected();
- }
-
- // Lists
-
- public BackgroundTask<List<String>, Void> refreshListSubscriptions() {
- return new Users.GetManyTask(account)
- .onDone(lists -> {
- listSubscriptions.clear();
- listSubscriptions.addAll(lists);
- })
- // .onFail(x -> { }) // TODO: error message?
- .execute();
- }
-
- public Set<String> getListSubscriptions() {
- return listSubscriptions;
- }
-
- public boolean addListSubscription(String fullName) {
- return listSubscriptions.add(fullName);
- }
-
- public boolean removeListSubscription(String fullName) {
- return listSubscriptions.remove(fullName);
- }
-
- // Mute
-
- public List<BackgroundTask> refreshUserMuteList() {
- List<BackgroundTask> tasks = new ArrayList<>();
- tasks.add(new Accounts.BlockIDsTask(account).onDone(muteUserIds::addAll).execute());
- tasks.add(new Accounts.MutesIDsTask(account).onDone(muteUserIds::addAll).execute());
- return tasks;
- }
-
- public boolean isMutedUserListContains(long id) {
- return muteUserIds.contains(id);
- }
-
- // Saved search queries
-
- public Collection<SavedSearch> getSavedSearches() {
- return savedSearches.values();
- }
-
- public BackgroundTask<List<SavedSearch>, Void> refreshSavedSearches() {
- return new Searches.GetAllSavedSearchesTask(account).onDone(ssl -> {
- savedSearches.clear();
- for (SavedSearch ss : ssl)
- savedSearches.put(ss.getId(), ss);
- }).execute();
- }
-
- // Notifications
-
- public void setMainActivity(MainActivity activity) {
- mainActivity = new WeakReference<>(activity);
- }
-
- public void setMainActivityActive(boolean yes) {
- isMainActivityActive = yes;
- }
-
- public void notify(String text) {
- doNotify(NotificationType.INFO, text);
- }
-
- public void notify(@StringRes int resId, Object... formatArgs) {
- doNotify(NotificationType.INFO, resId, formatArgs);
- }
-
- public void notifyError(String text) {
- doNotify(NotificationType.ALERT, text);
- }
-
- public void notifyError(@StringRes int resId, Object... formatArgs) {
- doNotify(NotificationType.ALERT, resId, formatArgs);
- }
-
- private void doNotify(NotificationType type, @StringRes int resId, Object... formatArgs) {
- Context context = mainActivity.get();
- if (context != null) {
- String text = context.getString(resId, formatArgs);
- doNotify(type, text);
- } else {
- Logger.debug("MainActivity is dead");
- }
- }
-
- private void doNotify(NotificationType type, String text) {
- MainActivity activity = mainActivity.get();
- if (activity == null || activity.isFinishing()) {
- Logger.debug(String.format("notify(log): %s", text));
- } else {
- new UIHandler().post(() -> {
- if (isMainActivityActive) {
- Logger.debug(String.format("notify(crouton): %s", text));
- Configuration.Builder conf = new Configuration.Builder();
- conf.setDuration(NOTIFICATION_DURATION);
- Style.Builder bstyle = new Style.Builder();
- bstyle.setConfiguration(conf.build());
- bstyle.setBackgroundColorValue(type == NotificationType.ALERT ?
- Style.holoRedLight : Style.holoBlueLight);
- Crouton.makeText(activity, text, bstyle.build()).show();
- } else {
- Logger.debug(String.format("notify(toast): %s", text));
- Application.toast(text);
- }
- });
- }
- }
-
- enum NotificationType {
- INFO,
- ALERT
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/World.kt b/app/src/main/java/net/lacolaco/smileessence/World.kt
new file mode 100644
index 00000000..b18522e5
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/World.kt
@@ -0,0 +1,230 @@
+package net.lacolaco.smileessence
+
+import android.support.annotation.StringRes
+import de.keyboardsurfer.android.widget.crouton.Configuration
+import de.keyboardsurfer.android.widget.crouton.Crouton
+import de.keyboardsurfer.android.widget.crouton.Style
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.compat.Twitter4J
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.data.PostState
+import net.lacolaco.smileessence.entity.DirectMessage
+import net.lacolaco.smileessence.entity.Event
+import net.lacolaco.smileessence.entity.SavedSearch
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.twitter.UserStreamListener
+import net.lacolaco.smileessence.twitter.task.Accounts
+import net.lacolaco.smileessence.twitter.task.Searches
+import net.lacolaco.smileessence.twitter.task.Users
+import net.lacolaco.smileessence.util.*
+import twitter4j.TwitterStream
+
+import java.lang.ref.WeakReference
+import java.util.*
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * World contains data that are specific to an account.
+ */
+class World(var account: Account) {
+ private val resId: Int = 0 // XXX: Fetch from Account
+ // XXX: Move to MainActivity
+ val postState = PostState()
+ // Timelines
+ private val tweets = ArrayList<Tweet>()
+ private val tweetNotifiers = WeakHashMap<Any, (Tweet) -> Unit>()
+ // Direct messages
+ private val directMessages = ConcurrentHashMap<Long, DirectMessage>()
+ private val directMessageNotifiers = WeakHashMap<Any, (DirectMessage) -> Unit>()
+ // Events
+ val events = ArrayList<Event>()
+ private val eventNotifiers = WeakHashMap<Any, () -> Unit>()
+ // Streaming APIs
+ private var stream: TwitterStream? = null
+ private var userStreamListener: UserStreamListener? = null
+ // Lists
+ val listSubscriptions = Collections.newSetFromMap(ConcurrentHashMap<String, Boolean>())
+ // Mute
+ private val muteUserIds = Collections.newSetFromMap(ConcurrentHashMap<Long, Boolean>())
+ // Saved searches
+ val savedSearches = HashMap<Long, SavedSearch>()
+ // Notification
+ private var mainActivity: WeakReference<MainActivity>? = null
+ private var isMainActivityActive: Boolean = false
+
+ // Timelines
+
+ @Synchronized
+ fun addTimeline(key: Any, notify: (Tweet) -> Unit) {
+ for (tweet in tweets)
+ notify(tweet)
+ tweetNotifiers.put(key, notify)
+ }
+
+ @Synchronized
+ fun addTweet(tweet: Tweet) {
+ tweets.add(tweet)
+ tweetNotifiers.forEach { o, c -> c(tweet) }
+ }
+
+ @Synchronized
+ fun addTweetAll(ts: Collection<Tweet>) {
+ tweets.addAll(ts)
+ for (tweet in ts) {
+ tweetNotifiers.forEach { o, c -> c(tweet) }
+ }
+ }
+
+ // Direct messages
+
+ @Synchronized
+ fun addDirectMessageTimeline(key: Any, notify: (DirectMessage) -> Unit) {
+ directMessageNotifiers.put(key, notify)
+ }
+
+ fun addDirectMessage(entity: DirectMessage) {
+ if (directMessages.put(entity.id, entity) == null)
+ directMessageNotifiers.forEach { o, c -> c(entity) }
+ }
+
+ // Events
+
+ @Synchronized
+ fun addEventNotifier(key: Any, notify: () -> Unit) {
+ eventNotifiers.put(key, notify)
+ }
+
+ fun addEvent(e: Event) {
+ events.add(e)
+ eventNotifiers.forEach { o, a -> a() }
+ }
+
+ // Streaming APIs
+
+ fun setupStreaming() {
+ if (stream == null) {
+ stream = account.twitterStream
+ userStreamListener = UserStreamListener(this)
+ Twitter4J.twitterStreamAddListener(stream!!, userStreamListener!!)
+ stream!!.addConnectionLifeCycleListener(userStreamListener)
+ stream!!.user()
+ }
+ }
+
+ val isStreaming: Boolean
+ get() = stream != null && userStreamListener!!.isConnected
+
+ // Lists
+
+ fun refreshListSubscriptions(): BackgroundTask<List<String>, Void> {
+ return Users.GetManyTask(account)
+ .onDone { lists ->
+ listSubscriptions.clear()
+ listSubscriptions.addAll(lists)
+ }
+ // .onFail(x -> { }) // TODO: error message?
+ .execute()
+ }
+
+ fun addListSubscription(fullName: String): Boolean {
+ return listSubscriptions.add(fullName)
+ }
+
+ fun removeListSubscription(fullName: String): Boolean {
+ return listSubscriptions.remove(fullName)
+ }
+
+ // Mute
+
+ fun refreshUserMuteList(): List<BackgroundTask<*, *>> {
+ val tasks = ArrayList<BackgroundTask<*, *>>()
+ tasks.add(Accounts.BlockIDsTask(account).onDone { muteUserIds.addAll(it) }.execute())
+ tasks.add(Accounts.MutesIDsTask(account).onDone { muteUserIds.addAll(it) }.execute())
+ return tasks
+ }
+
+ fun isMutedUserListContains(id: Long): Boolean {
+ return muteUserIds.contains(id)
+ }
+
+ // Saved search queries
+
+ fun refreshSavedSearches(): BackgroundTask<List<SavedSearch>, Void> {
+ return Searches.GetAllSavedSearchesTask(account).onDone { ssl ->
+ savedSearches.clear()
+ for (ss in ssl)
+ savedSearches.put(ss.id, ss)
+ }.execute()
+ }
+
+ // Notifications
+
+ fun setMainActivity(activity: MainActivity) {
+ mainActivity = WeakReference(activity)
+ }
+
+ fun setMainActivityActive(yes: Boolean) {
+ isMainActivityActive = yes
+ }
+
+ fun notify(text: String) {
+ doNotify(NotificationType.INFO, text)
+ }
+
+ fun notify(@StringRes resId: Int, vararg formatArgs: Any) {
+ doNotify(NotificationType.INFO, resId, *formatArgs)
+ }
+
+ fun notifyError(text: String) {
+ doNotify(NotificationType.ALERT, text)
+ }
+
+ fun notifyError(@StringRes resId: Int, vararg formatArgs: Any) {
+ doNotify(NotificationType.ALERT, resId, *formatArgs)
+ }
+
+ private fun doNotify(type: NotificationType, @StringRes resId: Int, vararg formatArgs: Any) {
+ val context = mainActivity!!.get()
+ if (context != null) {
+ val text = context.getString(resId, *formatArgs)
+ doNotify(type, text)
+ } else {
+ Logger.debug("MainActivity is dead")
+ }
+ }
+
+ private fun doNotify(type: NotificationType, text: String) {
+ val activity = mainActivity!!.get()
+ if (activity == null || activity.isFinishing) {
+ Logger.debug(String.format("notify(log): %s", text))
+ } else {
+ UIHandler().post {
+ if (isMainActivityActive) {
+ Logger.debug(String.format("notify(crouton): %s", text))
+ val conf = Configuration.Builder()
+ conf.setDuration(NOTIFICATION_DURATION)
+ val bstyle = Style.Builder()
+ bstyle.setConfiguration(conf.build())
+ bstyle.setBackgroundColorValue(if (type == NotificationType.ALERT)
+ Style.holoRedLight
+ else
+ Style.holoBlueLight)
+ Crouton.makeText(activity, text, bstyle.build()).show()
+ } else {
+ Logger.debug(String.format("notify(toast): %s", text))
+ Application.toast(text)
+ }
+ }
+ }
+ }
+
+ internal enum class NotificationType {
+ INFO,
+ ALERT
+ }
+
+ companion object {
+ private val NOTIFICATION_DURATION = 1000
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.java
deleted file mode 100644
index 3876d506..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.activity;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.NavUtils;
-import android.text.TextUtils;
-import android.util.SparseBooleanArray;
-import android.view.*;
-import android.widget.AbsListView;
-import android.widget.ListView;
-import android.widget.TextView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.data.ExtractionWord;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.view.DialogHelper;
-import net.lacolaco.smileessence.view.adapter.CustomListAdapter;
-import net.lacolaco.smileessence.view.dialog.EditTextDialogFragment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class EditExtractionActivity extends Activity implements AbsListView.MultiChoiceModeListener {
- private List<ExtractionWord> list;
- private CustomListAdapter<ExtractionWord> adapter;
-
- private ListView getListView() {
- return (ListView) findViewById(R.id.listview_edit_list);
- }
-
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- menu.clear();
- MenuInflater inflater = mode.getMenuInflater();
- inflater.inflate(R.menu.edit_list, menu);
- return true;
- }
-
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- return false;
- }
-
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_edit_list_delete: {
- deleteSelectedItems();
- }
- }
- mode.finish();
- return true;
- }
-
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- }
-
- @Override
- public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- Logger.debug("onCreate");
- super.onCreate(savedInstanceState);
- setContentView(R.layout.layout_edit_list);
-
- ListView listView = getListView();
- list = new ArrayList<>();
- adapter = new CustomListAdapter<ExtractionWord>() {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = EditExtractionActivity.this.getLayoutInflater().inflate(R.layout.list_item_simple_text, null);
- }
- TextView textView = (TextView) convertView.findViewById(R.id.list_item_textview);
- textView.setText(getItem(position).getPatternString());
- return convertView;
- }
-
- @Override
- protected List<ExtractionWord> getList() {
- return list;
- }
- };
- list.addAll(ExtractionWord.cached());
- adapter.update();
- listView.setAdapter(adapter);
- listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
- listView.setMultiChoiceModeListener(this);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuItem add = menu.add(Menu.NONE, R.id.menu_edit_list_add, Menu.NONE, "");
- add.setIcon(android.R.drawable.ic_menu_add);
- add.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_edit_list_add: {
- addNewExtractionWord();
- break;
- }
- case android.R.id.home: {
- NavUtils.navigateUpFromSameTask(this);
- return true;
- }
- }
- return true;
- }
-
- // -------------------------- OTHER METHODS --------------------------
-
- public void deleteSelectedItems() {
- SparseBooleanArray checkedItems = getListView().getCheckedItemPositions();
- for (int i = adapter.getCount() - 1; i > -1; i--) {
- if (checkedItems.get(i)) {
- ExtractionWord ew = adapter.getItem(i);
- list.remove(ew);
- ew.remove();
- }
- }
- adapter.update();
- }
-
- private void addNewExtractionWord() {
- EditTextDialogFragment dialogFragment = new EditTextDialogFragment() {
- @Override
- public void onTextInput(String text) {
- if (TextUtils.isEmpty(text.trim())) {
- return;
- }
- ExtractionWord extractionWord = ExtractionWord.add(text);
- list.add(extractionWord);
- adapter.update();
- }
- };
- dialogFragment.setParams(getString(R.string.dialog_title_add), "");
- dialogFragment.show(getFragmentManager(), "EDIT_TEXT");
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.kt
new file mode 100644
index 00000000..c621b6f7
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/EditExtractionActivity.kt
@@ -0,0 +1,153 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.activity
+
+import android.app.Activity
+import android.os.Bundle
+import android.support.v4.app.NavUtils
+import android.text.TextUtils
+import android.util.SparseBooleanArray
+import android.view.*
+import android.widget.AbsListView
+import android.widget.ListView
+import android.widget.TextView
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.data.ExtractionWord
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.view.DialogHelper
+import net.lacolaco.smileessence.view.adapter.CustomListAdapter
+import net.lacolaco.smileessence.view.dialog.EditTextDialogFragment
+
+import java.util.ArrayList
+
+class EditExtractionActivity : Activity(), AbsListView.MultiChoiceModeListener {
+ private lateinit var list: MutableList<ExtractionWord>
+ private lateinit var adapter: CustomListAdapter<ExtractionWord>
+
+ private val listView: ListView
+ get() = findViewById(R.id.listview_edit_list) as ListView
+
+ override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
+ menu.clear()
+ val inflater = mode.menuInflater
+ inflater.inflate(R.menu.edit_list, menu)
+ return true
+ }
+
+ override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
+ return false
+ }
+
+ override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.menu_edit_list_delete -> {
+ deleteSelectedItems()
+ }
+ }
+ mode.finish()
+ return true
+ }
+
+ override fun onDestroyActionMode(mode: ActionMode) {}
+
+ override fun onItemCheckedStateChanged(mode: ActionMode, position: Int, id: Long, checked: Boolean) {}
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ Logger.debug("onCreate")
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.layout_edit_list)
+
+ list = ArrayList()
+ adapter = object : CustomListAdapter<ExtractionWord>() {
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ var convertView = convertView
+ if (convertView == null) {
+ convertView = this@EditExtractionActivity.layoutInflater.inflate(R.layout.list_item_simple_text, null)
+ }
+ val textView = convertView!!.findViewById(R.id.list_item_textview) as TextView
+ textView.text = getItem(position).patternString
+ return convertView
+ }
+
+ override val list: List<ExtractionWord>
+ get() = this@EditExtractionActivity.list
+ }
+ list.addAll(ExtractionWord.cached())
+ adapter.update()
+ listView.adapter = adapter
+ listView.choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL
+ listView.setMultiChoiceModeListener(this)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ val add = menu.add(Menu.NONE, R.id.menu_edit_list_add, Menu.NONE, "")
+ add.setIcon(android.R.drawable.ic_menu_add)
+ add.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.menu_edit_list_add -> {
+ addNewExtractionWord()
+ }
+ android.R.id.home -> {
+ NavUtils.navigateUpFromSameTask(this)
+ return true
+ }
+ }
+ return true
+ }
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ fun deleteSelectedItems() {
+ val checkedItems = listView.checkedItemPositions
+ for (i in adapter.count - 1 downTo -1 + 1) {
+ if (checkedItems.get(i)) {
+ val ew = adapter.getItem(i)
+ list.remove(ew)
+ ew.remove()
+ }
+ }
+ adapter.update()
+ }
+
+ private fun addNewExtractionWord() {
+ val dialogFragment = object : EditTextDialogFragment() {
+ override fun onTextInput(text: String) {
+ if (TextUtils.isEmpty(text.trim { it <= ' ' })) {
+ return
+ }
+ val extractionWord = ExtractionWord.add(text)
+ list.add(extractionWord)
+ adapter.update()
+ }
+ }
+ dialogFragment.setParams(getString(R.string.dialog_title_add), "")
+ dialogFragment.show(fragmentManager, "EDIT_TEXT")
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.java
deleted file mode 100644
index 23957c57..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.activity;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.NavUtils;
-import android.view.MenuItem;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class LicenseActivity extends Activity {
-
- // --------------------- GETTER / SETTER METHODS ---------------------
-
- private List<String> getFileNames() {
- List<String> apacheFiles = new ArrayList<>();
- apacheFiles.add(getString(R.string.library_name_twitter4j));
- apacheFiles.add(getString(R.string.library_name_crouton));
- apacheFiles.add(getString(R.string.library_name_pull_to_refresh));
- apacheFiles.add(getString(R.string.library_name_volley));
- apacheFiles.add(getString(R.string.library_name_twitter_text));
- return apacheFiles;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.layout_license);
-
- setFiles();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home: {
- NavUtils.navigateUpFromSameTask(this);
- return true;
- }
- }
- return true;
- }
-
- private void setFiles() {
- LinearLayout files = (LinearLayout) findViewById(R.id.linear_license_files);
- List<String> apacheFiles = getFileNames();
- for (String apacheFile : apacheFiles) {
- TextView name = new TextView(this);
- name.setText(String.format("- %s", apacheFile));
- files.addView(name);
- }
- }
-} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.kt
new file mode 100644
index 00000000..58bcc08c
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/LicenseActivity.kt
@@ -0,0 +1,81 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.activity
+
+import android.app.Activity
+import android.os.Bundle
+import android.support.v4.app.NavUtils
+import android.view.MenuItem
+import android.widget.LinearLayout
+import android.widget.TextView
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+
+import java.util.ArrayList
+
+class LicenseActivity : Activity() {
+
+ // --------------------- GETTER / SETTER METHODS ---------------------
+
+ private val fileNames: List<String>
+ get() {
+ val apacheFiles = ArrayList<String>()
+ apacheFiles.add(getString(R.string.library_name_twitter4j))
+ apacheFiles.add(getString(R.string.library_name_crouton))
+ apacheFiles.add(getString(R.string.library_name_pull_to_refresh))
+ apacheFiles.add(getString(R.string.library_name_volley))
+ apacheFiles.add(getString(R.string.library_name_twitter_text))
+ return apacheFiles
+ }
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ public override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.layout_license)
+
+ setFiles()
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ android.R.id.home -> {
+ NavUtils.navigateUpFromSameTask(this)
+ return true
+ }
+ }
+ return true
+ }
+
+ private fun setFiles() {
+ val files = findViewById(R.id.linear_license_files) as LinearLayout
+ val apacheFiles = fileNames
+ for (apacheFile in apacheFiles) {
+ val name = TextView(this)
+ name.text = String.format("- %s", apacheFile)
+ files.addView(name)
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.java
deleted file mode 100644
index 4997f3f1..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.activity;
-
-import android.app.ActionBar;
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.MediaStore;
-import android.support.v4.view.ViewPager;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.WindowManager;
-import android.widget.ImageView;
-import de.keyboardsurfer.android.widget.crouton.Crouton;
-import net.lacolaco.smileessence.*;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.data.ExtractionWord;
-import net.lacolaco.smileessence.entity.RBinding;
-import net.lacolaco.smileessence.entity.User;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.twitter.task.Users;
-import net.lacolaco.smileessence.util.BitmapOptimizer;
-import net.lacolaco.smileessence.util.BitmapURLTask;
-import net.lacolaco.smileessence.util.IntentUtils;
-import net.lacolaco.smileessence.util.UIObserverBundle;
-import net.lacolaco.smileessence.view.adapter.PageListAdapter;
-import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment;
-import net.lacolaco.smileessence.view.page.*;
-
-import java.lang.reflect.Field;
-
-public class MainActivity extends Activity implements ViewPager.OnPageChangeListener {
- public static final int REQUEST_GET_PICTURE_FROM_GALLERY = 11;
- private final UIObserverBundle currentUserBundle = new UIObserverBundle();
- private World world;
- private ViewPager viewPager;
- private ImageView currentAccountIconImageView;
- private PageListAdapter pagerAdapter;
-
- public World getWorld() {
- return world;
- }
-
- private void setSelectedPageIndex(int position) {
- setSelectedPageIndex(position, true);
- }
-
- private void setSelectedPageIndex(int position, boolean smooth) {
- viewPager.setCurrentItem(position, smooth);
- }
-
- public void openHomePage() {
- setSelectedPageIndex(pagerAdapter.getIndex(HomeFragment.class));
- }
-
- public void openPostPage() {
- setSelectedPageIndex(pagerAdapter.getIndex(PostFragment.class));
- }
-
- public void openPostPageWithImage(Uri uri) {
- try {
- Cursor c = getContentResolver().query(uri, null, null, null, null);
- assert c != null;
- c.moveToFirst();
- String path = c.getString(c.getColumnIndex(MediaStore.MediaColumns.DATA));
- String rotatedPath = path; // BitmapOptimizer.rotateImageByExif(this, path);
- world.getPostState().beginTransaction()
- .setMediaFilePath(rotatedPath)
- .commitWithOpen(this);
- world.notify(R.string.notice_select_image_succeeded);
- c.close();
- } catch (Exception e) {
- e.printStackTrace();
- world.notifyError(R.string.notice_select_image_failed);
- }
- }
-
- public void openSearchPage(String query) {
- SearchFragment fragment = (SearchFragment) pagerAdapter.getCachedFragment(pagerAdapter.getIndex(SearchFragment.class));
- if (fragment != null) {
- fragment.startSearch(query);
- setSelectedPageIndex(pagerAdapter.getIndex(SearchFragment.class));
- }
- }
-
- public void openUserListPage(String listFullName) {
- UserListFragment fragment = (UserListFragment) pagerAdapter.getCachedFragment(pagerAdapter.getIndex(UserListFragment.class));
- if (fragment != null) {
- fragment.startUserList(listFullName);
- setSelectedPageIndex(pagerAdapter.getIndex(UserListFragment.class));
- }
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- public void onBackPressed() {
- this.finish();
- }
-
- @Override
- public void finish() {
- if (viewPager == null) {
- super.finish();
- return;
- }
- int homeIndex = pagerAdapter.getIndex(HomeFragment.class);
- if (viewPager.getCurrentItem() != homeIndex) {
- viewPager.setCurrentItem(homeIndex, true);
- } else {
- ConfirmDialogFragment.show(this, getString(R.string.dialog_confirm_finish_app), super::finish);
- }
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_GET_PICTURE_FROM_GALLERY:
- getImageUri(requestCode, resultCode, data);
- break;
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- Logger.debug("onCreate");
- super.onCreate(savedInstanceState);
-
- Uri uri = getIntent().getData();
- if (uri == null) {
- throw new IllegalStateException("[BUG] data not set");
- }
- String userIdValue = uri.getQueryParameter("user_id");
- if (userIdValue == null)
- throw new IllegalStateException("[BUG] user_id not set");
- long userId = Long.parseLong(userIdValue);
- world = Application.getWorld(userId);
- world.setMainActivity(this);
-
- // XXX
- Account account = world.getAccount();
-
- setTheme(account.themeIndex == 0 ? R.style.theme_dark : R.style.theme_light);
- setContentView(R.layout.layout_main);
-
- viewPager = (ViewPager) findViewById(R.id.viewPager);
- pagerAdapter = new PageListAdapter(this);
- viewPager.addOnPageChangeListener(this);
- getActionBar().setDisplayHomeAsUpEnabled(true);
- currentAccountIconImageView = (ImageView) findViewById(android.R.id.home);
- currentAccountIconImageView.setScaleType(ImageView.ScaleType.FIT_XY);
-
- // TODO: tab order?
- Bundle args = new Bundle();
- args.putLong(PageFragment.KEY_USER_ID, account.getUserId());
- pagerAdapter.addPage(PostFragment.class, getString(R.string.page_name_post), args, false);
- pagerAdapter.addPage(HomeFragment.class, getString(R.string.page_name_home), args, false);
- pagerAdapter.addPage(MentionsFragment.class, getString(R.string.page_name_mentions), args, false);
- pagerAdapter.addPage(HistoryFragment.class, getString(R.string.page_name_history), args, false);
- pagerAdapter.addPage(MessagesFragment.class, getString(R.string.page_name_messages), args, false);
- pagerAdapter.addPage(SearchFragment.class, getString(R.string.page_name_search), args, false);
- pagerAdapter.addPage(UserListFragment.class, getString(R.string.page_name_list), args, false);
- pagerAdapter.notifyDataSetChanged();
- viewPager.setOffscreenPageLimit(pagerAdapter.getCount());
- viewPager.setAdapter(pagerAdapter);
- setSelectedPageIndex(pagerAdapter.getIndex(HomeFragment.class), false);
-
- ExtractionWord.load();
-
- // update cache
- world.refreshListSubscriptions();
- world.refreshUserMuteList();
- world.refreshSavedSearches();
- new Users.GetTask(account, account.getUserId()).execute();
-
- User user = account.getUser();
-
- // Set application title
- setTitle();
-
- // update actionbar
- Runnable update = () -> {
- setTitle();
- updateActionBarTitle();
- String newUrl = user.getProfileImageUrlOriginal();
- if (newUrl != null) {
- new BitmapURLTask(newUrl, currentAccountIconImageView).execute();
- }
- };
- update.run(); //first run
-
- currentUserBundle.detachAll();
- currentUserBundle.attach(user, changes -> {
- if (changes.contains(RBinding.BASIC)) update.run();
- });
-
- // refresh all pages
- for (int i = 0; i < pagerAdapter.getCount(); ++i) {
- PageFragment pf = pagerAdapter.getCachedFragment(i);
- if (pf != null && pf.isAdded()) {
- Logger.debug(String.format("PageFragment %s is already attached; refreshing", pf.getClass().getName()));
- pf.refresh();
- }
- }
-
- // start user stream
- world.setupStreaming();
- }
-
- private void setTitle() {
- String label = getString(R.string.app_name) + " - @" + world.getAccount().getUser().getScreenName();
- ActivityManager.TaskDescription desc = new ActivityManager.TaskDescription(label);
- setTaskDescription(desc);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- currentUserBundle.detachAll();
- Crouton.cancelAllCroutons();
- // Workaround for LeakCanary
- fixCroutonLeak();
- Logger.debug("onDestroy");
- }
-
- private void fixCroutonLeak() {
- try {
- Class klass = Class.forName("de.keyboardsurfer.android.widget.crouton.DefaultAnimationsBuilder");
- Field slideInDownAnimation = klass.getDeclaredField("slideInDownAnimation");
- slideInDownAnimation.setAccessible(true);
- slideInDownAnimation.set(null, null);
- Field slideOutUpAnimation = klass.getDeclaredField("slideOutUpAnimation");
- slideOutUpAnimation.setAccessible(true);
- slideOutUpAnimation.set(null, null);
- } catch (Exception e) {
- Logger.error("crouton fix error: " + e);
- }
- }
-
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home: {
- Intent intent = new Intent(this, ManageAccountsActivity.class);
- intent.putExtra(ManageAccountsActivity.INTENT_KEY_NOINIT, true);
- startActivity(intent);
- return true;
- }
- case R.id.actionbar_setting:
- startActivity(new Intent(this, SettingActivity.class));
- return true;
- case R.id.actionbar_edit_extraction:
- startActivity(new Intent(this, EditExtractionActivity.class));
- return true;
- case R.id.actionbar_aclog:
- IntentUtils.openUri(this, world.getAccount().getUser().getAclogTimelineURL());
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- protected void onPause() {
- Logger.debug("onPause");
- super.onPause();
- world.setMainActivityActive(false);
- }
-
- @Override
- protected void onResume() {
- Logger.debug("onResume");
- super.onResume();
- world.setMainActivityActive(true);
- }
-
- // --------------------- Interface OnPageChangeListener ---------------------
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- }
-
- @Override
- public void onPageSelected(int position) {
- Logger.debug("Page selected: " + position);
- updateActionBarTitle();
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
- }
-
- // -------------------------- OTHER METHODS --------------------------
-
- private void getImageUri(int requestCode, int resultCode, Intent data) {
- if (resultCode != RESULT_OK) {
- Logger.error(requestCode);
- world.notifyError(R.string.notice_select_image_failed);
- finish();
- return;
- }
- openPostPageWithImage(data.getData());
- }
-
- private void updateActionBarTitle() {
- ActionBar actionBar = getActionBar();
- Account currentAccount = world.getAccount();
- if (actionBar != null) {
- String screenName = currentAccount.getUser().getScreenName();
- String pageTitle = pagerAdapter.getName(viewPager.getCurrentItem());
- setTitle(String.format("%s / %s", screenName, pageTitle));
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt
new file mode 100644
index 00000000..8b8da33f
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt
@@ -0,0 +1,311 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.activity
+
+import android.app.Activity
+import android.app.ActivityManager
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.provider.MediaStore
+import android.support.v4.view.ViewPager
+import android.view.Menu
+import android.view.MenuItem
+import android.widget.ImageView
+import de.keyboardsurfer.android.widget.crouton.Crouton
+import net.lacolaco.smileessence.*
+import net.lacolaco.smileessence.data.ExtractionWord
+import net.lacolaco.smileessence.entity.RBinding
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.twitter.task.Users
+import net.lacolaco.smileessence.util.BitmapURLTask
+import net.lacolaco.smileessence.util.IntentUtils
+import net.lacolaco.smileessence.util.UIObserverBundle
+import net.lacolaco.smileessence.view.adapter.PageListAdapter
+import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment
+import net.lacolaco.smileessence.view.page.*
+
+class MainActivity : Activity(), ViewPager.OnPageChangeListener {
+ private val currentUserBundle = UIObserverBundle()
+ val world: World by lazy {
+ val uri = intent.data ?: throw IllegalStateException("[BUG] data not set")
+ val userIdValue = uri.getQueryParameter("user_id") ?: throw IllegalStateException("[BUG] user_id not set")
+ val userId = java.lang.Long.parseLong(userIdValue)
+ Application.getWorld(userId)
+ }
+ private lateinit var viewPager: ViewPager
+ private lateinit var pagerAdapter: PageListAdapter
+ private lateinit var currentAccountIconImageView: ImageView
+
+ private fun setSelectedPageIndex(position: Int, smooth: Boolean = true) {
+ viewPager.setCurrentItem(position, smooth)
+ }
+
+ fun openHomePage() {
+ setSelectedPageIndex(pagerAdapter.getIndex(HomeFragment::class.java))
+ }
+
+ fun openPostPage() {
+ setSelectedPageIndex(pagerAdapter.getIndex(PostFragment::class.java))
+ }
+
+ fun openPostPageWithImage(uri: Uri) {
+ try {
+ val c = contentResolver.query(uri, null, null, null, null)
+ assert(c != null)
+ c!!.moveToFirst()
+ val path = c.getString(c.getColumnIndex(MediaStore.MediaColumns.DATA))
+ world.postState.beginTransaction()
+ .setMediaFilePath(path)
+ .commitWithOpen(this)
+ world.notify(R.string.notice_select_image_succeeded)
+ c.close()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ world.notifyError(R.string.notice_select_image_failed)
+ }
+
+ }
+
+ fun openSearchPage(query: String) {
+ val fragment = pagerAdapter.getCachedFragment(pagerAdapter.getIndex(SearchFragment::class.java)) as SearchFragment?
+ if (fragment != null) {
+ fragment.startSearch(query)
+ setSelectedPageIndex(pagerAdapter.getIndex(SearchFragment::class.java))
+ }
+ }
+
+ fun openUserListPage(listFullName: String) {
+ val fragment = pagerAdapter.getCachedFragment(pagerAdapter.getIndex(UserListFragment::class.java)) as UserListFragment?
+ if (fragment != null) {
+ fragment.startUserList(listFullName)
+ setSelectedPageIndex(pagerAdapter.getIndex(UserListFragment::class.java))
+ }
+ }
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun onBackPressed() {
+ this.finish()
+ }
+
+ override fun finish() {
+ val homeIndex = pagerAdapter.getIndex(HomeFragment::class.java)
+ if (viewPager.currentItem != homeIndex) {
+ viewPager.setCurrentItem(homeIndex, true)
+ } else {
+ ConfirmDialogFragment.show(this, getString(R.string.dialog_confirm_finish_app)) { super.finish() }
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ when (requestCode) {
+ REQUEST_GET_PICTURE_FROM_GALLERY -> getImageUri(requestCode, resultCode, data)
+ }
+ }
+
+ public override fun onCreate(savedInstanceState: Bundle?) {
+ Logger.debug("onCreate")
+ super.onCreate(savedInstanceState)
+
+ world.setMainActivity(this)
+
+ // XXX
+ val account = world.account
+
+ setTheme(if (account.themeIndex == 0) R.style.theme_dark else R.style.theme_light)
+ setContentView(R.layout.layout_main)
+
+ viewPager = findViewById(R.id.viewPager) as ViewPager
+ pagerAdapter = PageListAdapter(this)
+ viewPager.addOnPageChangeListener(this)
+ actionBar.setDisplayHomeAsUpEnabled(true)
+ currentAccountIconImageView = findViewById(android.R.id.home) as ImageView
+ currentAccountIconImageView.scaleType = ImageView.ScaleType.FIT_XY
+
+ // TODO: tab order?
+ val args = Bundle()
+ args.putLong(PageFragment.KEY_USER_ID, account.userId)
+ pagerAdapter.addPage(PostFragment::class.java, getString(R.string.page_name_post), args, false)
+ pagerAdapter.addPage(HomeFragment::class.java, getString(R.string.page_name_home), args, false)
+ pagerAdapter.addPage(MentionsFragment::class.java, getString(R.string.page_name_mentions), args, false)
+ pagerAdapter.addPage(HistoryFragment::class.java, getString(R.string.page_name_history), args, false)
+ pagerAdapter.addPage(MessagesFragment::class.java, getString(R.string.page_name_messages), args, false)
+ pagerAdapter.addPage(SearchFragment::class.java, getString(R.string.page_name_search), args, false)
+ pagerAdapter.addPage(UserListFragment::class.java, getString(R.string.page_name_list), args, false)
+ pagerAdapter.notifyDataSetChanged()
+ viewPager.offscreenPageLimit = pagerAdapter.count
+ viewPager.adapter = pagerAdapter
+ setSelectedPageIndex(pagerAdapter.getIndex(HomeFragment::class.java), false)
+
+ ExtractionWord.load()
+
+ // update cache
+ world.refreshListSubscriptions()
+ world.refreshUserMuteList()
+ world.refreshSavedSearches()
+ Users.GetTask(account, account.userId).execute()
+
+ val user = account.user
+
+ // Set application title
+ setTitle()
+
+ // update actionbar
+ val update = {
+ setTitle()
+ updateActionBarTitle()
+ val newUrl = user.profileImageUrl
+ if (newUrl != null) {
+ BitmapURLTask(newUrl, currentAccountIconImageView).execute()
+ }
+ }
+ update() //first run
+
+ currentUserBundle.detachAll()
+ currentUserBundle.attach(user) { changes -> if (changes.contains(RBinding.BASIC)) update() }
+
+ // refresh all pages
+ for (i in 0..pagerAdapter.count - 1) {
+ val pf = pagerAdapter.getCachedFragment(i)
+ if (pf != null && pf.isAdded) {
+ Logger.debug(String.format("PageFragment %s is already attached; refreshing", pf.javaClass.name))
+ pf.refresh()
+ }
+ }
+
+ // start user stream
+ world.setupStreaming()
+ }
+
+ private fun setTitle() {
+ val label = getString(R.string.app_name) + " - @" + world.account.user.screenName
+ val desc = ActivityManager.TaskDescription(label)
+ setTaskDescription(desc)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ currentUserBundle.detachAll()
+ Crouton.cancelAllCroutons()
+ // Workaround for LeakCanary
+ fixCroutonLeak()
+ Logger.debug("onDestroy")
+ }
+
+ private fun fixCroutonLeak() {
+ try {
+ val klass = Class.forName("de.keyboardsurfer.android.widget.crouton.DefaultAnimationsBuilder")
+ val slideInDownAnimation = klass.getDeclaredField("slideInDownAnimation")
+ slideInDownAnimation.isAccessible = true
+ slideInDownAnimation.set(null, null)
+ val slideOutUpAnimation = klass.getDeclaredField("slideOutUpAnimation")
+ slideOutUpAnimation.isAccessible = true
+ slideOutUpAnimation.set(null, null)
+ } catch (e: Exception) {
+ Logger.error("crouton fix error: " + e)
+ }
+
+ }
+
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ menuInflater.inflate(R.menu.main, menu)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ android.R.id.home -> {
+ val intent = Intent(this, ManageAccountsActivity::class.java)
+ intent.putExtra(ManageAccountsActivity.INTENT_KEY_NOINIT, true)
+ startActivity(intent)
+ return true
+ }
+ R.id.actionbar_setting -> {
+ startActivity(Intent(this, SettingActivity::class.java))
+ return true
+ }
+ R.id.actionbar_edit_extraction -> {
+ startActivity(Intent(this, EditExtractionActivity::class.java))
+ return true
+ }
+ R.id.actionbar_aclog -> {
+ IntentUtils.openUri(this, world.account.user.aclogTimelineURL)
+ return true
+ }
+ else -> return super.onOptionsItemSelected(item)
+ }
+ }
+
+ override fun onPause() {
+ Logger.debug("onPause")
+ super.onPause()
+ world.setMainActivityActive(false)
+ }
+
+ override fun onResume() {
+ Logger.debug("onResume")
+ super.onResume()
+ world.setMainActivityActive(true)
+ }
+
+ // --------------------- Interface OnPageChangeListener ---------------------
+
+ override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
+
+ override fun onPageSelected(position: Int) {
+ Logger.debug("Page selected: " + position)
+ updateActionBarTitle()
+ }
+
+ override fun onPageScrollStateChanged(state: Int) {}
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ private fun getImageUri(requestCode: Int, resultCode: Int, data: Intent?) {
+ if (resultCode != Activity.RESULT_OK) {
+ Logger.error(requestCode)
+ world.notifyError(R.string.notice_select_image_failed)
+ finish()
+ return
+ }
+ openPostPageWithImage(data!!.data)
+ }
+
+ private fun updateActionBarTitle() {
+ val actionBar = actionBar
+ val currentAccount = world.account
+ if (actionBar != null) {
+ val screenName = currentAccount.user.screenName
+ val pageTitle = pagerAdapter.getName(viewPager.currentItem)
+ title = String.format("%s / %s", screenName, pageTitle)
+ }
+ }
+
+ companion object {
+ val REQUEST_GET_PICTURE_FROM_GALLERY = 11
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.java
deleted file mode 100644
index af891fec..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.activity;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.*;
-import com.android.volley.toolbox.NetworkImageView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.World;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.data.ImageCache;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.twitter.OAuthSession;
-import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ManageAccountsActivity extends Activity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {
- public static final String INTENT_KEY_NOINIT = "noInit";
- private static final int REQUEST_OAUTH = 10;
- private static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 11;
- private EditAccountsAdapter adapter;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Check if it is initiated from launcher
- if (!getIntent().getBooleanExtra(INTENT_KEY_NOINIT, false)) {
- int wextPermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
- if (wextPermission != PackageManager.PERMISSION_GRANTED) {
- ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION);
- }
-
- // Skip this activity if app is already started
- World currentWorld = Application.getCurrentWorld();
- if (currentWorld != null) {
- goToWorld(currentWorld);
- return;
- }
- }
-
- setContentView(R.layout.layout_edit_list);
- adapter = new EditAccountsAdapter();
- ListView listView = (ListView) findViewById(R.id.listview_edit_list);
- listView.setAdapter(adapter);
- listView.setOnItemClickListener(this);
- listView.setOnItemLongClickListener(this);
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
- switch (requestCode) {
- case REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION: {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- // OK
- World currentWorld = Application.getCurrentWorld();
- if (currentWorld != null) {
- goToWorld(currentWorld);
- }
- } else {
- Application.toast(R.string.notice_error_storage_permission);
- // TODO: Kill Process?
- finish();
- }
- break;
- }
- }
- }
-
- private void goToWorld(World world) {
- // Continue the existing MainActivity
- Intent intent = new Intent(this, MainActivity.class);
- intent.setData(Uri.parse("smileessence://mainactivity/?user_id=" + world.getAccount().getUserId()));
- finish();
- startActivity(intent);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuItem add = menu.add(Menu.NONE, R.id.menu_edit_list_add, Menu.NONE, "");
- add.setIcon(android.R.drawable.ic_menu_add);
- add.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- return true;
- }
-
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
- Account account = adapter.getItem(i);
- goToWorld(Application.getWorld(account.getUserId()));
- }
-
- @Override
- public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
- if (adapter.getCount() > 1) {
- // remove account from application
- Account account = adapter.getItem(i);
- ConfirmDialogFragment.show(this, getString(R.string.dialog_confirm_clear_account, account.getUser().getScreenName()), () -> {
- adapter.removeAt(i);
- Account.unregister(account.getUserId());
- }, false);
- return true;
- } else {
- Application.toast(R.string.notice_cant_remove_last_account);
- return false;
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_edit_list_add: {
- startActivityForResult(new Intent(this, OAuthActivity.class), REQUEST_OAUTH);
- break;
- }
- case android.R.id.home: {
- safeFinish();
- }
- }
- return true;
- }
-
- @Override
- public void onBackPressed() {
- safeFinish();
- }
-
- private void safeFinish() {
- World currentWorld = Application.getCurrentWorld();
-
- if (currentWorld != null) {
- goToWorld(currentWorld);
- } else {
- setResult(RESULT_CANCELED);
- finish();
- }
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_OAUTH: {
- receiveOAuth(requestCode, resultCode, data);
- break;
- }
- default: {
- Logger.error("[BUG] unexpected activity result: reqCode=" + requestCode + ", resCode=" + resultCode);
- break;
- }
- }
- }
-
- private void receiveOAuth(int requestCode, int resultCode, Intent data) {
- if (resultCode == RESULT_OK) {
- Account account = Account.register(data.getStringExtra(OAuthSession.KEY_TOKEN),
- data.getStringExtra(OAuthSession.KEY_TOKEN_SECRET),
- data.getLongExtra(OAuthSession.KEY_USER_ID, -1L),
- data.getStringExtra(OAuthSession.KEY_SCREEN_NAME));
- adapter.add(account);
- } else {
- Logger.error(requestCode);
- Application.toast(R.string.notice_error_authenticate);
- }
- }
-
- private class EditAccountsAdapter extends BaseAdapter {
- private final List<Account> accounts;
-
- public EditAccountsAdapter() {
- accounts = new ArrayList<>(Account.all());
- }
-
- @Override
- public int getCount() {
- return accounts.size();
- }
-
- @Override
- public Account getItem(int position) {
- return accounts.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return accounts.get(position).getUserId();
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = getLayoutInflater().inflate(R.layout.list_item_account, null);
- }
- Account account = getItem(position);
- NetworkImageView iconView = (NetworkImageView) convertView.findViewById(R.id.account_icon);
- iconView.setImageUrl(account.getUser().getProfileImageUrlOriginal(), ImageCache.getImageLoader());
-
- TextView textView = (TextView) convertView.findViewById(R.id.account_text_view);
- String text = "@" + account.getUser().getScreenName();
- textView.setText(text);
-
- return convertView;
- }
-
- public int add(Account account) {
- if (!accounts.contains(account)) {
- accounts.add(account);
- notifyDataSetChanged();
- return accounts.size() - 1;
- } else {
- return accounts.indexOf(account);
- }
- }
-
- public Account removeAt(int position) {
- Account account = accounts.remove(position);
- if (account != null) {
- notifyDataSetChanged();
- }
- return account;
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt
new file mode 100644
index 00000000..2ef184fc
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt
@@ -0,0 +1,241 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.activity
+
+import android.app.Activity
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Bundle
+import android.support.v4.app.ActivityCompat
+import android.support.v4.content.ContextCompat
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
+import android.widget.*
+import com.android.volley.toolbox.NetworkImageView
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.data.ImageCache
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.twitter.OAuthSession
+import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment
+
+import java.util.ArrayList
+
+class ManageAccountsActivity : Activity(), AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {
+ private var adapter: EditAccountsAdapter? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // Check if it is initiated from launcher
+ if (!intent.getBooleanExtra(INTENT_KEY_NOINIT, false)) {
+ val wextPermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ if (wextPermission != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION)
+ }
+
+ // Skip this activity if app is already started
+ val currentWorld = Application.currentWorld
+ if (currentWorld != null) {
+ goToWorld(currentWorld)
+ return
+ }
+ }
+
+ setContentView(R.layout.layout_edit_list)
+ adapter = EditAccountsAdapter()
+ val listView = findViewById(R.id.listview_edit_list) as ListView
+ listView.adapter = adapter
+ listView.onItemClickListener = this
+ listView.onItemLongClickListener = this
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
+ when (requestCode) {
+ REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION -> {
+ if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ // OK
+ val currentWorld = Application.currentWorld
+ if (currentWorld != null) {
+ goToWorld(currentWorld)
+ }
+ } else {
+ Application.toast(R.string.notice_error_storage_permission)
+ // TODO: Kill Process?
+ finish()
+ }
+ }
+ }
+ }
+
+ private fun goToWorld(world: World) {
+ // Continue the existing MainActivity
+ val intent = Intent(this, MainActivity::class.java)
+ intent.data = Uri.parse("smileessence://mainactivity/?user_id=" + world.account.userId)
+ finish()
+ startActivity(intent)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ val add = menu.add(Menu.NONE, R.id.menu_edit_list_add, Menu.NONE, "")
+ add.setIcon(android.R.drawable.ic_menu_add)
+ add.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
+ return true
+ }
+
+ override fun onItemClick(adapterView: AdapterView<*>, view: View, i: Int, l: Long) {
+ val account = adapter!!.getItem(i)
+ goToWorld(Application.getWorld(account.userId))
+ }
+
+ override fun onItemLongClick(adapterView: AdapterView<*>, view: View, i: Int, l: Long): Boolean {
+ if (adapter!!.count > 1) {
+ // remove account from application
+ val account = adapter!!.getItem(i)
+ ConfirmDialogFragment.show(this, getString(R.string.dialog_confirm_clear_account, account.user.screenName), {
+ adapter!!.removeAt(i)
+ Account.unregister(account.userId)
+ }, false)
+ return true
+ } else {
+ Application.toast(R.string.notice_cant_remove_last_account)
+ return false
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.menu_edit_list_add -> {
+ startActivityForResult(Intent(this, OAuthActivity::class.java), REQUEST_OAUTH)
+ }
+ android.R.id.home -> {
+ safeFinish()
+ }
+ }
+ return true
+ }
+
+ override fun onBackPressed() {
+ safeFinish()
+ }
+
+ private fun safeFinish() {
+ val currentWorld = Application.currentWorld
+
+ if (currentWorld != null) {
+ goToWorld(currentWorld)
+ } else {
+ setResult(Activity.RESULT_CANCELED)
+ finish()
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
+ when (requestCode) {
+ REQUEST_OAUTH -> {
+ receiveOAuth(requestCode, resultCode, data)
+ }
+ else -> {
+ Logger.error("[BUG] unexpected activity result: reqCode=$requestCode, resCode=$resultCode")
+ }
+ }
+ }
+
+ private fun receiveOAuth(requestCode: Int, resultCode: Int, data: Intent) {
+ if (resultCode == Activity.RESULT_OK) {
+ val account = Account.register(data.getStringExtra(OAuthSession.KEY_TOKEN),
+ data.getStringExtra(OAuthSession.KEY_TOKEN_SECRET),
+ data.getLongExtra(OAuthSession.KEY_USER_ID, -1L),
+ data.getStringExtra(OAuthSession.KEY_SCREEN_NAME))
+ adapter!!.add(account)
+ } else {
+ Logger.error(requestCode)
+ Application.toast(R.string.notice_error_authenticate)
+ }
+ }
+
+ private inner class EditAccountsAdapter : BaseAdapter() {
+ private val accounts: MutableList<Account>
+
+ init {
+ accounts = ArrayList(Account.all())
+ }
+
+ override fun getCount(): Int {
+ return accounts.size
+ }
+
+ override fun getItem(position: Int): Account {
+ return accounts[position]
+ }
+
+ override fun getItemId(position: Int): Long {
+ return accounts[position].userId
+ }
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ var convertView = convertView
+ if (convertView == null) {
+ convertView = layoutInflater.inflate(R.layout.list_item_account, null)
+ }
+ val account = getItem(position)
+ val iconView = convertView!!.findViewById(R.id.account_icon) as NetworkImageView
+ iconView.setImageUrl(account.user.profileImageUrl, ImageCache.getImageLoader())
+
+ val textView = convertView.findViewById(R.id.account_text_view) as TextView
+ val text = "@" + account.user.screenName
+ textView.text = text
+
+ return convertView
+ }
+
+ fun add(account: Account): Int {
+ if (!accounts.contains(account)) {
+ accounts.add(account)
+ notifyDataSetChanged()
+ return accounts.size - 1
+ } else {
+ return accounts.indexOf(account)
+ }
+ }
+
+ fun removeAt(position: Int): Account? {
+ val account = accounts.removeAt(position)
+ notifyDataSetChanged()
+ return account
+ }
+ }
+
+ companion object {
+ val INTENT_KEY_NOINIT = "noInit"
+ private val REQUEST_OAUTH = 10
+ private val REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 11
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.java
deleted file mode 100644
index e3d15bc2..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.activity;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.twitter.OAuthSession;
-import twitter4j.auth.AccessToken;
-
-public class OAuthActivity extends Activity implements View.OnClickListener, TextWatcher {
- private EditText pinEditText;
- private Button authButton;
- private OAuthSession oauthSession;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.layout_oauth);
-
- TextView linkTextView = (TextView) findViewById(R.id.textView_oauth_link);
- pinEditText = (EditText) findViewById(R.id.editText_oauth_pin);
- pinEditText.addTextChangedListener(this);
- authButton = (Button) findViewById(R.id.button_oauth_auth);
- authButton.setOnClickListener(this);
- authButton.setEnabled(false);
-
- oauthSession = new OAuthSession();
- String url = oauthSession.getAuthorizationURL();
- if (!TextUtils.isEmpty(url)) {
- linkTextView.setText(url);
- } else {
- Application.toast(R.string.notice_error_authenticate_request);
- finish();
- }
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.button_oauth_auth: {
- AccessToken accessToken = oauthSession.getAccessToken(pinEditText.getText().toString());
- if (accessToken != null) {
- Intent intent = new Intent();
- intent.putExtra(OAuthSession.KEY_TOKEN, accessToken.getToken());
- intent.putExtra(OAuthSession.KEY_TOKEN_SECRET, accessToken.getTokenSecret());
- intent.putExtra(OAuthSession.KEY_USER_ID, accessToken.getUserId());
- intent.putExtra(OAuthSession.KEY_SCREEN_NAME, accessToken.getScreenName());
- setResult(RESULT_OK, intent);
- finish();
- } else {
- setResult(RESULT_CANCELED);
- finish();
- }
- }
- }
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- authButton.setEnabled(s.length() > 0);
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- }
-} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.kt
new file mode 100644
index 00000000..c2388bbf
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/OAuthActivity.kt
@@ -0,0 +1,95 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.activity
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextUtils
+import android.text.TextWatcher
+import android.view.View
+import android.widget.Button
+import android.widget.EditText
+import android.widget.TextView
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.twitter.OAuthSession
+import twitter4j.auth.AccessToken
+
+class OAuthActivity : Activity(), View.OnClickListener, TextWatcher {
+ private lateinit var pinEditText: EditText
+ private lateinit var authButton: Button
+ private lateinit var oauthSession: OAuthSession
+
+ public override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.layout_oauth)
+
+ val linkTextView = findViewById(R.id.textView_oauth_link) as TextView
+ pinEditText = findViewById(R.id.editText_oauth_pin) as EditText
+ pinEditText.addTextChangedListener(this)
+ authButton = findViewById(R.id.button_oauth_auth) as Button
+ authButton.setOnClickListener(this)
+ authButton.isEnabled = false
+
+ oauthSession = OAuthSession()
+ val url = oauthSession.authorizationURL
+ if (!TextUtils.isEmpty(url)) {
+ linkTextView.text = url
+ } else {
+ Application.toast(R.string.notice_error_authenticate_request)
+ finish()
+ }
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_oauth_auth -> {
+ val accessToken = oauthSession.getAccessToken(pinEditText.text.toString())
+ if (accessToken != null) {
+ val intent = Intent()
+ intent.putExtra(OAuthSession.KEY_TOKEN, accessToken.token)
+ intent.putExtra(OAuthSession.KEY_TOKEN_SECRET, accessToken.tokenSecret)
+ intent.putExtra(OAuthSession.KEY_USER_ID, accessToken.userId)
+ intent.putExtra(OAuthSession.KEY_SCREEN_NAME, accessToken.screenName)
+ setResult(Activity.RESULT_OK, intent)
+ finish()
+ } else {
+ setResult(Activity.RESULT_CANCELED)
+ finish()
+ }
+ }
+ }
+ }
+
+ override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
+
+ override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+ authButton.isEnabled = s.length > 0
+ }
+
+ override fun afterTextChanged(s: Editable) {}
+} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.java b/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.java
deleted file mode 100644
index 87f44e16..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.activity;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.NavUtils;
-import android.view.MenuItem;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-
-public class SettingActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.layout_setting);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home: {
- NavUtils.navigateUpFromSameTask(this);
- return true;
- }
- }
- return true;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.java b/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.kt
index 5f04114e..07518480 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.java
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/SettingActivity.kt
@@ -22,25 +22,28 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.view.page;
+package net.lacolaco.smileessence.activity
-import android.os.Bundle;
-import com.handmark.pulltorefresh.library.PullToRefreshBase;
-import net.lacolaco.smileessence.World;
-import net.lacolaco.smileessence.view.adapter.EventListAdapter;
+import android.app.Activity
+import android.os.Bundle
+import android.support.v4.app.NavUtils
+import android.view.MenuItem
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
-public class HistoryFragment extends CustomListFragment<EventListAdapter> {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- World world = getWorld();
- final EventListAdapter adapter = new EventListAdapter(world, getActivity());
- setAdapter(adapter);
- world.addEventNotifier(this, () -> adapter.update()); // XXX
+class SettingActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.layout_setting)
}
- @Override
- public void refresh() {
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ android.R.id.home -> {
+ NavUtils.navigateUpFromSameTask(this)
+ return true
+ }
+ }
+ return true
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/command/Command.java b/app/src/main/java/net/lacolaco/smileessence/command/Command.kt
index 0225b886..98183dc7 100644
--- a/app/src/main/java/net/lacolaco/smileessence/command/Command.java
+++ b/app/src/main/java/net/lacolaco/smileessence/command/Command.kt
@@ -22,23 +22,14 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.command;
+package net.lacolaco.smileessence.command
-import net.lacolaco.smileessence.activity.MainActivity;
+import net.lacolaco.smileessence.activity.MainActivity
-public abstract class Command {
- private final MainActivity activity;
+abstract class Command(protected val activity: MainActivity) {
- public Command(MainActivity activity) {
- this.activity = activity;
- }
+ abstract fun execute(): Boolean
- protected MainActivity getActivity() {
- return activity;
- }
-
- public abstract boolean execute();
-
- public abstract String getText();
+ abstract val text: String
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.java b/app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.kt
index c62e2601..5d8077d5 100644
--- a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.java
+++ b/app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.kt
@@ -22,36 +22,27 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.command;
+package net.lacolaco.smileessence.command
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.util.IntentUtils;
+import net.lacolaco.smileessence.activity.MainActivity
-public class CommandOpenURL extends Command {
+class CommandAddHashtag
+// --------------------------- CONSTRUCTORS ---------------------------
- // ------------------------------ FIELDS ------------------------------
+(activity: MainActivity,
+ // ------------------------------ FIELDS ------------------------------
- private final String url;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public CommandOpenURL(MainActivity activity, String url) {
- super(activity);
- this.url = url;
- }
+ private val hashtag: String) : Command(activity) {
// --------------------- GETTER / SETTER METHODS ---------------------
- @Override
- public String getText() {
- return url;
- }
+ override val text: String
+ get() = "#" + hashtag
// -------------------------- OTHER METHODS --------------------------
- @Override
- public boolean execute() {
- IntentUtils.openUri(getActivity(), url);
- return true;
+ override fun execute(): Boolean {
+ activity.world.postState.beginTransaction().appendText(" #" + hashtag).commit()
+ return true
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.kt b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.kt
new file mode 100644
index 00000000..b9150e12
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenURL.kt
@@ -0,0 +1,46 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.command
+
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.util.IntentUtils
+
+class CommandOpenURL
+// --------------------------- CONSTRUCTORS ---------------------------
+
+(activity: MainActivity,
+ // ------------------------------ FIELDS ------------------------------
+
+ // --------------------- GETTER / SETTER METHODS ---------------------
+
+ override val text: String) : Command(activity) {
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ override fun execute(): Boolean {
+ IntentUtils.openUri(activity, text)
+ return true
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.java b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.java
deleted file mode 100644
index 600e0bc0..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.command;
-
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.twitter.task.Users;
-import net.lacolaco.smileessence.view.DialogHelper;
-import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment;
-
-public class CommandOpenUserDetail extends Command {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final String screenName;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public CommandOpenUserDetail(MainActivity activity, String screenName) {
- super(activity);
- this.screenName = screenName;
- }
-
- // --------------------- GETTER / SETTER METHODS ---------------------
-
- @Override
- public String getText() {
- return String.format("@%s", screenName);
- }
-
- // -------------------------- OTHER METHODS --------------------------
-
- @Override
- public boolean execute() {
- new Users.GetTask(getActivity().getWorld().getAccount(), screenName)
- .onDoneUI(user -> {
- UserDetailDialogFragment fragment = new UserDetailDialogFragment();
- fragment.setUserID(user.getId());
- DialogHelper.showDialog(getActivity(), fragment);
- })
- .onFail(x -> getActivity().getWorld().notifyError(R.string.notice_error_show_user))
- .execute();
-
- return false;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.java b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.kt
index e3eb95ea..89d5d2ef 100644
--- a/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.java
+++ b/app/src/main/java/net/lacolaco/smileessence/command/CommandOpenUserDetail.kt
@@ -22,37 +22,37 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.preference;
+package net.lacolaco.smileessence.command
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.twitter.task.Users
+import net.lacolaco.smileessence.view.DialogHelper
+import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment
-public class UserPreferenceHelper extends SharedPreferenceHelper {
- // --------------------------- CONSTRUCTORS ---------------------------
+class CommandOpenUserDetail
+// --------------------------- CONSTRUCTORS ---------------------------
- private static final UserPreferenceHelper instance = new UserPreferenceHelper();
+(activity: MainActivity,
+ // ------------------------------ FIELDS ------------------------------
- private UserPreferenceHelper() {
- }
-
- public static UserPreferenceHelper getInstance() {
- return instance;
- }
+ private val screenName: String) : Command(activity) {
// --------------------- GETTER / SETTER METHODS ---------------------
- @Override
- protected SharedPreferences getPreferences() {
- return PreferenceManager.getDefaultSharedPreferences(Application.getInstance());
- }
- // --------------------- HELPER METHODS ---------------------
- public int getThemeIndex() {
- return get(R.string.key_setting_theme, 0);
- }
+ override val text: String
+ get() = String.format("@%s", screenName)
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ override fun execute(): Boolean {
+ Users.GetTask(activity.world.account, screenName)
+ .onDoneUI { user ->
+ DialogHelper.showDialog(activity, UserDetailDialogFragment.newInstance(user))
+ }
+ .onFail { x -> activity.world.notifyError(R.string.notice_error_show_user) }
+ .execute()
- public int getTextSize() {
- return get(R.string.key_setting_text_size, 10);
+ return false
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/compat/Twitter4J.java b/app/src/main/java/net/lacolaco/smileessence/compat/Twitter4J.java
new file mode 100644
index 00000000..1d9ab25e
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/compat/Twitter4J.java
@@ -0,0 +1,11 @@
+package net.lacolaco.smileessence.compat;
+
+import twitter4j.StatusListener;
+import twitter4j.TwitterStream;
+
+public class Twitter4J {
+ // Make it work with Kotlin. Problem exists in v4.0.6
+ public static void twitterStreamAddListener(TwitterStream stream, StatusListener listener) {
+ stream.addListener(listener);
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/Account.java b/app/src/main/java/net/lacolaco/smileessence/data/Account.java
deleted file mode 100644
index 280f9a09..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/data/Account.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.data;
-
-import com.github.gfx.android.orma.annotation.Column;
-import com.github.gfx.android.orma.annotation.PrimaryKey;
-import com.github.gfx.android.orma.annotation.Table;
-import net.lacolaco.smileessence.entity.User;
-import twitter4j.Twitter;
-import twitter4j.TwitterFactory;
-import twitter4j.TwitterStream;
-import twitter4j.TwitterStreamFactory;
-import twitter4j.auth.AccessToken;
-import twitter4j.conf.ConfigurationBuilder;
-
-import java.util.*;
-
-@Table
-public class Account {
- private static Map<Long, Account> cache;
- @PrimaryKey
- public long userId;
- @Column
- public String screenName;
- @Column
- public String oauthToken;
- @Column
- public String oauthTokenSecret;
- @Column(defaultExpr = "0")
- public int themeIndex;
-
- private User user;
-
- public Account() {
- }
-
- public static synchronized Account get(long i) {
- if (cache == null) {
- throw new IllegalStateException("[BUG] Load first");
- }
- Account a = cache.get(i);
- if (a == null)
- throw new IllegalStateException("[BUG] Account with userId == " + i + " not found");
- return a;
- }
-
- public static synchronized List<Account> all() {
- return new ArrayList<>(cache.values());
- }
-
- public static synchronized void load() {
- cache = new LinkedHashMap<>();
- for (Account item : relation().selector())
- cache.put(item.userId, item);
- }
-
- private static Account_Relation relation() {
- OrmaDatabase orma = OrmaHolder.getORMA();
- return orma.relationOfAccount();
- }
-
- public static synchronized Account register(String token, String tokenSecret, long userId, String screenName) {
- Account account = null;
- for (Account a : all()) {
- if (a.getUserId() == userId) {
- account = a;
- break;
- }
- }
- if (account == null)
- account = new Account();
- account.userId = userId;
- account.screenName = screenName;
- account.oauthToken = token;
- account.oauthTokenSecret = tokenSecret;
- account.themeIndex = 0;
-
- relation().upserter().execute(account);
-
- cache.put(account.userId, account);
-
- return account;
- }
-
- public static synchronized Account unregister(long id) {
- Account account = cache.remove(id);
- if (account != null) {
- relation().deleter().userIdEq(id).execute();
- }
- return account;
- }
-
- public long getUserId() {
- return userId;
- }
-
- public Twitter getTwitter() {
- ConfigurationBuilder cb = new ConfigurationBuilder();
- cb.setTweetModeExtended(true);
- Twitter twitter = new TwitterFactory(cb.build()).getInstance();
- twitter.setOAuthAccessToken(new AccessToken(oauthToken, oauthTokenSecret));
- return twitter;
- }
-
- public TwitterStream getTwitterStream() {
- TwitterStream stream = new TwitterStreamFactory().getInstance();
- stream.setOAuthAccessToken(new AccessToken(oauthToken, oauthTokenSecret));
- return stream;
- }
-
- public User getUser() {
- if (user == null) {
- user = User.fetch(userId);
- if (user == null) {
- user = User._makeSkeleton(userId, screenName);
- }
- user.addObserver(this, (objs) -> {
- if (!screenName.equals(user.getScreenName())) {
- screenName = user.getScreenName();
- relation().upserter().execute(this);
- }
- });
- }
-
- return user;
- }
-} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/Account.kt b/app/src/main/java/net/lacolaco/smileessence/data/Account.kt
new file mode 100644
index 00000000..6dc8262c
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/data/Account.kt
@@ -0,0 +1,134 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.data
+
+import com.github.gfx.android.orma.annotation.Column
+import com.github.gfx.android.orma.annotation.PrimaryKey
+import com.github.gfx.android.orma.annotation.Table
+import net.lacolaco.smileessence.data.Account.Companion.cache
+import net.lacolaco.smileessence.entity.User
+import twitter4j.Twitter
+import twitter4j.TwitterFactory
+import twitter4j.TwitterStream
+import twitter4j.TwitterStreamFactory
+import twitter4j.auth.AccessToken
+import twitter4j.conf.ConfigurationBuilder
+
+import java.util.*
+
+@Table
+class Account {
+ @PrimaryKey
+ var userId: Long = 0
+ @Column
+ var screenName: String? = null
+ @Column
+ var oauthToken: String? = null
+ @Column
+ var oauthTokenSecret: String? = null
+ @Column(defaultExpr = "0")
+ var themeIndex: Int = 0
+
+ val user: User by lazy {
+ val _user = User.fetch(userId) ?: User._makeSkeleton(userId, screenName!!)
+ _user.addObserver(this) { objs ->
+ if (screenName!! != _user.screenName) {
+ screenName = _user.screenName
+ relation().upserter().execute(this)
+ }
+ }
+ _user
+ }
+
+ val twitter: Twitter
+ get() {
+ val cb = ConfigurationBuilder()
+ cb.setTweetModeExtended(true)
+ val twitter = TwitterFactory(cb.build()).instance
+ twitter.oAuthAccessToken = AccessToken(oauthToken, oauthTokenSecret)
+ return twitter
+ }
+
+ val twitterStream: TwitterStream
+ get() {
+ val stream = TwitterStreamFactory().instance
+ stream.oAuthAccessToken = AccessToken(oauthToken, oauthTokenSecret)
+ return stream
+ }
+
+
+ companion object {
+ private var cache: MutableMap<Long, Account>? = null
+
+ @Synchronized
+ operator fun get(i: Long): Account {
+ if (cache == null) {
+ throw IllegalStateException("[BUG] Load first")
+ }
+ return cache!![i] ?: throw IllegalStateException("[BUG] Account with userId == $i not found")
+ }
+
+ @Synchronized
+ fun all(): List<Account> {
+ return ArrayList(cache!!.values)
+ }
+
+ @Synchronized
+ fun load() {
+ cache = LinkedHashMap()
+ for (item in relation().selector())
+ cache!!.put(item.userId, item)
+ }
+
+ private fun relation(): Account_Relation {
+ return OrmaHolder.orma.relationOfAccount()
+ }
+
+ @Synchronized
+ fun register(token: String, tokenSecret: String, userId: Long, screenName: String): Account {
+ val account = all().find { a -> a.userId == userId } ?: Account()
+ account.userId = userId
+ account.screenName = screenName
+ account.oauthToken = token
+ account.oauthTokenSecret = tokenSecret
+ account.themeIndex = 0
+
+ relation().upserter().execute(account)
+
+ cache!!.put(account.userId, account)
+
+ return account
+ }
+
+ @Synchronized
+ fun unregister(id: Long): Account? {
+ val account = cache!!.remove(id)
+ if (account != null) {
+ relation().deleter().userIdEq(id).execute()
+ }
+ return account
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.java b/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.java
deleted file mode 100644
index 334ab5e7..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.data;
-
-import com.github.gfx.android.orma.annotation.PrimaryKey;
-import com.github.gfx.android.orma.annotation.Table;
-
-import java.util.*;
-import java.util.regex.Pattern;
-
-@Table
-public class ExtractionWord {
- private static Set<ExtractionWord> cache;
- @PrimaryKey
- String patternString;
- private Pattern pattern;
-
- public ExtractionWord() {
- }
-
- private ExtractionWord(String patternString) {
- this.patternString = patternString;
- }
-
- public static synchronized Collection<ExtractionWord> cached() {
- return cache;
- }
-
- public static synchronized void load() {
- OrmaDatabase orma = OrmaHolder.getORMA();
- cache = new HashSet<>(orma.selectFromExtractionWord().toList());
- }
-
- private static ExtractionWord_Relation relation() {
- return OrmaHolder.getORMA().relationOfExtractionWord();
- }
-
- public static synchronized ExtractionWord add(String patternString) {
- ExtractionWord extractionWord = new ExtractionWord(patternString);
- relation().upserter().execute(extractionWord);
- cache.add(extractionWord);
- return extractionWord;
- }
-
- public Pattern getPattern() {
- if (pattern == null)
- pattern = Pattern.compile(patternString);
- return pattern;
- }
-
- public String getPatternString() {
- return patternString;
- }
-
- public void remove() {
- relation().deleter().patternStringEq(patternString).execute();
- cache.remove(this);
- }
-} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.kt b/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.kt
new file mode 100644
index 00000000..6fd1be36
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/data/ExtractionWord.kt
@@ -0,0 +1,54 @@
+package net.lacolaco.smileessence.data
+
+import com.github.gfx.android.orma.annotation.PrimaryKey
+import com.github.gfx.android.orma.annotation.Table
+
+import java.util.*
+import java.util.regex.Pattern
+
+@Table
+class ExtractionWord {
+ @PrimaryKey
+ lateinit var patternString: String
+
+ val pattern: Pattern by lazy {
+ Pattern.compile(patternString)
+ }
+
+ constructor()
+
+ private constructor(patternString: String) {
+ this.patternString = patternString
+ }
+
+ fun remove() {
+ relation().deleter().patternStringEq(patternString).execute()
+ cache!!.remove(this)
+ }
+
+ companion object {
+ private var cache: MutableSet<ExtractionWord>? = null
+
+ @Synchronized
+ fun cached(): Collection<ExtractionWord> {
+ return cache ?: throw IllegalStateException("extraction pattern not loaded")
+ }
+
+ @Synchronized
+ fun load() {
+ cache = HashSet(OrmaHolder.orma.selectFromExtractionWord().toList())
+ }
+
+ private fun relation(): ExtractionWord_Relation {
+ return OrmaHolder.orma.relationOfExtractionWord()
+ }
+
+ @Synchronized
+ fun add(patternString: String): ExtractionWord {
+ val extractionWord = ExtractionWord(patternString)
+ relation().upserter().execute(extractionWord)
+ cache!!.add(extractionWord)
+ return extractionWord
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.java b/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.java
deleted file mode 100644
index daa2a443..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.data;
-
-import android.graphics.Bitmap;
-import android.util.LruCache;
-import com.android.volley.Cache;
-import com.android.volley.RequestQueue;
-import com.android.volley.toolbox.*;
-import net.lacolaco.smileessence.Application;
-
-public class ImageCache {
- private static ImageCache instance = new ImageCache();
- private ImageLoader imageLoader;
-
- private ImageCache() {
- int cacheSizeInBytes = 64 * 1024 * 1024; // 64MB
- Cache diskCache = new DiskBasedCache(Application.getInstance().getCacheDir(), cacheSizeInBytes);
- RequestQueue requestQueue = new RequestQueue(diskCache, new BasicNetwork(new HurlStack()));
- imageLoader = new ImageLoader(requestQueue, new ImageLruCache());
- requestQueue.start();
- }
-
- public static ImageLoader getImageLoader() { return instance.imageLoader; }
-
- private static class ImageLruCache implements ImageLoader.ImageCache {
- private LruCache<String, Bitmap> cache;
-
- private ImageLruCache() {
- cache = new LruCache<>(4 * 1024 * 1024); // 4MB
- }
-
- @Override
- public Bitmap getBitmap(String url) {
- return cache.get(url);
- }
-
- @Override
- public void putBitmap(String url, Bitmap bitmap) {
- cache.put(url, bitmap);
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.kt b/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.kt
new file mode 100644
index 00000000..d7b4eeac
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/data/ImageCache.kt
@@ -0,0 +1,64 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.data
+
+import android.graphics.Bitmap
+import android.util.LruCache
+import com.android.volley.Cache
+import com.android.volley.RequestQueue
+import com.android.volley.toolbox.*
+import net.lacolaco.smileessence.Application
+
+class ImageCache private constructor() {
+ private val imageLoader: ImageLoader
+
+ init {
+ val cacheSizeInBytes = 64 * 1024 * 1024 // 64MB
+ val diskCache = DiskBasedCache(Application.getInstance().cacheDir, cacheSizeInBytes)
+ val requestQueue = RequestQueue(diskCache, BasicNetwork(HurlStack()))
+ imageLoader = ImageLoader(requestQueue, ImageLruCache())
+ requestQueue.start()
+ }
+
+ private class ImageLruCache : ImageLoader.ImageCache {
+ private val cache: LruCache<String, Bitmap> = LruCache(4 * 1024 * 1024) // 4MB
+
+ override fun getBitmap(url: String): Bitmap? {
+ return cache.get(url)
+ }
+
+ override fun putBitmap(url: String, bitmap: Bitmap) {
+ cache.put(url, bitmap)
+ }
+ }
+
+ companion object {
+ private val instance = ImageCache()
+
+ fun getImageLoader(): ImageLoader {
+ return instance.imageLoader
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/OrmaHolder.java b/app/src/main/java/net/lacolaco/smileessence/data/OrmaHolder.java
deleted file mode 100644
index 5fd41c0c..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/data/OrmaHolder.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package net.lacolaco.smileessence.data;
-
-import android.content.Context;
-import com.github.gfx.android.orma.AccessThreadConstraint;
-
-public class OrmaHolder {
- private static OrmaDatabase ORMA;
-
- public static void initialize(Context context) {
- ORMA = OrmaDatabase
- .builder(context)
- .writeOnMainThread(AccessThreadConstraint.WARNING)
- .build();
- }
-
- public static OrmaDatabase getORMA() {
- return ORMA;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/OrmaHolder.kt b/app/src/main/java/net/lacolaco/smileessence/data/OrmaHolder.kt
new file mode 100644
index 00000000..f05f4def
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/data/OrmaHolder.kt
@@ -0,0 +1,16 @@
+package net.lacolaco.smileessence.data
+
+import android.content.Context
+import com.github.gfx.android.orma.AccessThreadConstraint
+
+object OrmaHolder {
+ lateinit var orma: OrmaDatabase
+ private set
+
+ fun initialize(context: Context) {
+ orma = OrmaDatabase
+ .builder(context)
+ .writeOnMainThread(AccessThreadConstraint.WARNING)
+ .build()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/PostState.java b/app/src/main/java/net/lacolaco/smileessence/data/PostState.java
deleted file mode 100644
index 4bbd83a4..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/data/PostState.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.data;
-
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.view.DialogHelper;
-import twitter4j.StatusUpdate;
-
-public class PostState {
- private String text = "";
- private Tweet inReplyTo;
- private String mediaFilePath = "";
- private boolean directMessage = false;
- private OnPostStateChangeListener listener;
- private int selectionStart, selectionEnd;
-
- public Tweet getInReplyTo() {
- return inReplyTo;
- }
-
- public String getMediaFilePath() {
- return mediaFilePath;
- }
-
- public int getSelectionEnd() {
- if (selectionEnd < 0) {
- return text.length();
- }
- return selectionEnd;
- }
-
- public int getSelectionStart() {
- if (selectionStart < 0) {
- return text.length();
- }
- return selectionStart;
- }
-
- public String getText() {
- return text;
- }
-
- public PostState setListener(OnPostStateChangeListener listener) {
- this.listener = listener;
- return this;
- }
-
- public PostStateTransaction beginTransaction() {
- return new PostStateTransaction(this);
- }
-
- public void removeListener() {
- this.listener = null;
- }
-
- /**
- * Convert to StatusUpdate for tweet.
- *
- * @return StatusUpdate
- */
- public StatusUpdate toStatusUpdate() {
- StatusUpdate su = new StatusUpdate(getText());
- if (getInReplyTo() != null) {
- su.setInReplyToStatusId(getInReplyTo().getId());
- }
- return su;
- }
-
- private PostState copy(PostState another) {
- this.text = another.text;
- this.inReplyTo = another.getInReplyTo();
- this.mediaFilePath = another.mediaFilePath;
- this.directMessage = another.directMessage;
- this.selectionStart = another.selectionStart;
- this.selectionEnd = another.selectionEnd;
- this.listener = another.listener;
- return this;
- }
-
- private void postStateChange() {
- if (listener != null) {
- listener.onPostStateChange(this);
- }
- }
-
- // -------------------------- INNER CLASSES --------------------------
-
- public interface OnPostStateChangeListener {
-
- void onPostStateChange(PostState postState);
- }
-
- public static class PostStateTransaction {
- private PostState origState, state;
-
- private PostStateTransaction(PostState state) {
- this.origState = state;
- this.state = new PostState().copy(state);
- }
-
- public PostStateTransaction setText(String text) {
- state.text = text;
- return this;
- }
-
- public PostStateTransaction appendText(String text) {
- state.text = state.text + text;
- return this;
- }
-
- public PostStateTransaction insertText(int index, String text) {
- StringBuilder builder = new StringBuilder(state.text);
- builder.insert(index, text);
- state.text = builder.toString();
- return this;
- }
-
- public PostStateTransaction setInReplyTo(Tweet inReplyTo) {
- state.inReplyTo = inReplyTo;
- return this;
- }
-
- public PostStateTransaction setMediaFilePath(String mediaFilePath) {
- state.mediaFilePath = mediaFilePath;
- return this;
- }
-
- public PostStateTransaction setCursor(int cursor) {
- state.selectionStart = state.selectionEnd = cursor;
- return this;
- }
-
- public PostStateTransaction setSelection(int start, int end) {
- state.selectionStart = start;
- state.selectionEnd = end;
- return this;
- }
-
- public PostStateTransaction clear() {
- state.text = "";
- state.selectionStart = state.selectionEnd = 0;
- state.inReplyTo = null;
- return this;
- }
-
- public void commit() {
- origState.copy(state).postStateChange();
- }
-
- public void commitWithOpen(MainActivity activity) {
- DialogHelper.closeAll(activity);
- origState.copy(state).postStateChange();
- activity.openPostPage();
- }
-
- public PostStateTransaction moveCursor(int length) {
- int cursor = state.selectionEnd + length;
- return setCursor(cursor);
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/PostState.kt b/app/src/main/java/net/lacolaco/smileessence/data/PostState.kt
new file mode 100644
index 00000000..4bc07443
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/data/PostState.kt
@@ -0,0 +1,167 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.data
+
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.view.DialogHelper
+import twitter4j.StatusUpdate
+
+class PostState {
+ var text = ""
+ private set
+ var inReplyTo: Tweet? = null
+ private set
+ var mediaFilePath = ""
+ private set
+ private var listener: OnPostStateChangeListener? = null
+ var selectionStart: Int = 0
+ get() {
+ return if (field < 0) {
+ text.length
+ } else field
+ }
+ var selectionEnd: Int = 0
+ get() {
+ return if (field < 0) {
+ text.length
+ } else field
+ }
+
+ fun setListener(listener: OnPostStateChangeListener): PostState {
+ this.listener = listener
+ return this
+ }
+
+ fun beginTransaction(): PostStateTransaction {
+ return PostStateTransaction(this)
+ }
+
+ fun removeListener() {
+ this.listener = null
+ }
+
+ /**
+ * Convert to StatusUpdate for tweet.
+ *
+ * @return StatusUpdate
+ */
+ fun toStatusUpdate(): StatusUpdate {
+ val su = StatusUpdate(text)
+ if (inReplyTo != null) {
+ su.inReplyToStatusId = inReplyTo!!.id
+ }
+ return su
+ }
+
+ private fun copy(another: PostState): PostState {
+ this.text = another.text
+ this.inReplyTo = another.inReplyTo
+ this.mediaFilePath = another.mediaFilePath
+ this.selectionStart = another.selectionStart
+ this.selectionEnd = another.selectionEnd
+ this.listener = another.listener
+ return this
+ }
+
+ private fun postStateChange() {
+ if (listener != null) {
+ listener!!.onPostStateChange(this)
+ }
+ }
+
+ // -------------------------- INNER CLASSES --------------------------
+
+ interface OnPostStateChangeListener {
+
+ fun onPostStateChange(postState: PostState)
+ }
+
+ class PostStateTransaction constructor(private val origState: PostState) {
+ private val state: PostState = PostState().copy(origState)
+
+ fun setText(text: String): PostStateTransaction {
+ state.text = text
+ return this
+ }
+
+ fun appendText(text: String): PostStateTransaction {
+ state.text = state.text + text
+ return this
+ }
+
+ fun insertText(index: Int, text: String): PostStateTransaction {
+ val builder = StringBuilder(state.text)
+ builder.insert(index, text)
+ state.text = builder.toString()
+ return this
+ }
+
+ fun setInReplyTo(inReplyTo: Tweet?): PostStateTransaction {
+ state.inReplyTo = inReplyTo
+ return this
+ }
+
+ fun setMediaFilePath(mediaFilePath: String): PostStateTransaction {
+ state.mediaFilePath = mediaFilePath
+ return this
+ }
+
+ fun setCursor(cursor: Int): PostStateTransaction {
+ state.selectionEnd = cursor
+ state.selectionStart = state.selectionEnd
+ return this
+ }
+
+ fun setSelection(start: Int, end: Int): PostStateTransaction {
+ state.selectionStart = start
+ state.selectionEnd = end
+ return this
+ }
+
+ fun clear(): PostStateTransaction {
+ state.text = ""
+ state.selectionEnd = 0
+ state.selectionStart = state.selectionEnd
+ state.inReplyTo = null
+ return this
+ }
+
+ fun commit() {
+ origState.copy(state).postStateChange()
+ }
+
+ fun commitWithOpen(activity: MainActivity) {
+ DialogHelper.closeAll(activity)
+ origState.copy(state).postStateChange()
+ activity.openPostPage()
+ }
+
+ fun moveCursor(length: Int): PostStateTransaction {
+ val cursor = state.selectionEnd + length
+ return setCursor(cursor)
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.java b/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.java
deleted file mode 100644
index f2862151..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package net.lacolaco.smileessence.entity;
-
-import net.lacolaco.smileessence.util.ListUtils;
-
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class DirectMessage extends EntitySupport implements IdObject {
- private static Map<Long, DirectMessage> storage = new HashMap<>();
- private long id;
- private User sender;
- private User recipient;
- private String text;
- private Date createdAt;
-
- private DirectMessage(twitter4j.DirectMessage st) {
- update(st);
- }
-
- public synchronized static DirectMessage fetch(long statusId) {
- return storage.get(statusId);
- }
-
- public synchronized static DirectMessage fromTwitter(twitter4j.DirectMessage st) {
- DirectMessage t = fetch(st.getId());
- if (t == null) {
- t = new DirectMessage(st);
- storage.put(st.getId(), t);
- } else {
- t.update(st);
- }
- return t;
- }
-
- public synchronized static List<DirectMessage> fromTwitter(List<twitter4j.DirectMessage> sts) {
- return ListUtils.map(sts, DirectMessage::fromTwitter);
- }
-
- private void update(twitter4j.DirectMessage message) {
- id = message.getId();
- sender = User.fromTwitter(message.getSender());
- recipient = User.fromTwitter(message.getRecipient());
- text = extractText(message, false);
- createdAt = message.getCreatedAt();
-
- updateEntities(message);
- }
-
- @Override
- public long getId() {
- return id;
- }
-
- public User getSender() {
- return sender;
- }
-
- public User getRecipient() {
- return recipient;
- }
-
- public String getText() {
- return text;
- }
-
- public Date getCreatedAt() {
- return createdAt;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.kt b/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.kt
new file mode 100644
index 00000000..e89868f8
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/DirectMessage.kt
@@ -0,0 +1,44 @@
+package net.lacolaco.smileessence.entity
+
+import java.util.Date
+import java.util.HashMap
+
+class DirectMessage private constructor(message: twitter4j.DirectMessage) : EntitySupport(), IdObject {
+ override val id: Long = message.id
+ val sender: User = User.fromTwitter(message.sender)
+ val recipient: User = User.fromTwitter(message.recipient)
+ val text: String = extractText(message, false)
+ val createdAt: Date = message.createdAt
+
+ init {
+ updateEntities(message)
+ }
+
+ companion object {
+ private val storage = HashMap<Long, DirectMessage>()
+
+ @Synchronized
+ fun fetch(statusId: Long): DirectMessage? {
+ return storage[statusId]
+ }
+
+ @Synchronized
+ fun fromTwitter(st: twitter4j.DirectMessage): DirectMessage {
+ var t: DirectMessage? = fetch(st.id)
+ if (t == null) {
+ t = DirectMessage(st)
+ storage.put(st.id, t)
+ } else {
+ // Update local cache
+ User.fromTwitter(st.sender)
+ User.fromTwitter(st.recipient)
+ }
+ return t
+ }
+
+ @Synchronized
+ fun fromTwitter(sts: Iterable<twitter4j.DirectMessage>): List<DirectMessage> {
+ return sts.map { fromTwitter(it) }
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/EntitySupport.java b/app/src/main/java/net/lacolaco/smileessence/entity/EntitySupport.java
deleted file mode 100644
index 9629bea2..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/entity/EntitySupport.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package net.lacolaco.smileessence.entity;
-
-import net.lacolaco.smileessence.util.UIObservable;
-import twitter4j.*;
-
-import java.util.*;
-
-public abstract class EntitySupport extends UIObservable {
- private List<String> mentions;
- private List<String> hashtags;
- private List<String> mediaUrls;
- private List<String> urlsExpanded;
- private List<String> symbols;
-
- protected void updateEntities(twitter4j.EntitySupport status) {
- mentions = extractMentions(status.getUserMentionEntities());
- hashtags = extractHashtags(status.getHashtagEntities());
- mediaUrls = extractMediaUrls(status.getMediaEntities());
- urlsExpanded = extractExpandedUrls(status.getURLEntities());
- symbols = extractSymbols(status.getSymbolEntities());
- }
-
- public List<String> getMentions() {
- return mentions;
- }
-
- public List<String> getHashtags() {
- return hashtags;
- }
-
- public List<String> getMediaUrls() {
- return mediaUrls;
- }
-
- public List<String> getUrlsExpanded() {
- return urlsExpanded;
- }
-
- public List<String> getSymbols() {
- return symbols;
- }
-
- private List<String> extractMentions(UserMentionEntity[] entities) {
- List<String> names = new ArrayList<>();
- if (entities != null) {
- for (UserMentionEntity entity : entities) {
- names.add(entity.getScreenName());
- }
- }
- return names;
- }
-
- private List<String> extractSymbols(SymbolEntity[] entities) {
- List<String> names = new ArrayList<>();
- if (entities != null) {
- for (SymbolEntity entity : entities) {
- names.add(entity.getText());
- }
- }
- return names;
- }
-
- private List<String> extractExpandedUrls(URLEntity[] entities) {
- List<String> names = new ArrayList<>();
- if (entities != null) {
- for (URLEntity entity : entities) {
- names.add(entity.getExpandedURL());
- }
- }
- return names;
- }
-
- private List<String> extractMediaUrls(MediaEntity[] entities) {
- List<String> names = new ArrayList<>();
- if (entities != null) {
- for (MediaEntity entity : entities) {
- if ("photo".equals(entity.getType())) {
- names.add(entity.getMediaURLHttps());
- } else {
- names.add(entity.getExpandedURL());
- }
- }
- }
- return names;
- }
-
- private List<String> extractHashtags(HashtagEntity[] entities) {
- List<String> names = new ArrayList<>();
- if (entities != null) {
- for (HashtagEntity entity : entities) {
- names.add(entity.getText());
- }
- }
- return names;
- }
-
- protected String extractText(twitter4j.Status status, boolean expand) {
- return extractText(status, status.getText(), expand);
- }
-
- protected String extractText(twitter4j.DirectMessage status, boolean expand) {
- return extractText(status, status.getText(), expand);
- }
-
- private String extractText(twitter4j.EntitySupport status, String text, boolean expand) {
- SortedSet<twitter4j.URLEntity> set = new TreeSet<>((a, b) -> a.getStart() - b.getStart());
- if (status.getURLEntities() != null) {
- Collections.addAll(set, status.getURLEntities());
- }
- if (status.getMediaEntities() != null) {
- Collections.addAll(set, status.getMediaEntities());
- }
-
- for (URLEntity entity : set) {
- String newString = expand ? entity.getExpandedURL() : entity.getDisplayURL();
- text = text.replaceFirst(entity.getText(), newString);
- }
-
- return text;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/EntitySupport.kt b/app/src/main/java/net/lacolaco/smileessence/entity/EntitySupport.kt
new file mode 100644
index 00000000..c1b3e4a3
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/EntitySupport.kt
@@ -0,0 +1,106 @@
+package net.lacolaco.smileessence.entity
+
+import net.lacolaco.smileessence.util.UIObservable
+import twitter4j.*
+
+import java.util.*
+
+abstract class EntitySupport : UIObservable() {
+ open lateinit var mentions: List<String>
+ protected set
+ open lateinit var hashtags: List<String>
+ protected set
+ open lateinit var mediaUrls: List<String>
+ protected set
+ open lateinit var urlsExpanded: List<String>
+ protected set
+ open lateinit var symbols: List<String>
+ protected set
+
+ protected fun updateEntities(status: twitter4j.EntitySupport) {
+ mentions = extractMentions(status.userMentionEntities)
+ hashtags = extractHashtags(status.hashtagEntities)
+ mediaUrls = extractMediaUrls(status.mediaEntities)
+ urlsExpanded = extractExpandedUrls(status.urlEntities)
+ symbols = extractSymbols(status.symbolEntities)
+ }
+
+ private fun extractMentions(entities: Array<UserMentionEntity>?): List<String> {
+ val names = ArrayList<String>()
+ if (entities != null) {
+ for (entity in entities) {
+ names.add(entity.screenName)
+ }
+ }
+ return names
+ }
+
+ private fun extractSymbols(entities: Array<SymbolEntity>?): List<String> {
+ val names = ArrayList<String>()
+ if (entities != null) {
+ for (entity in entities) {
+ names.add(entity.text)
+ }
+ }
+ return names
+ }
+
+ private fun extractExpandedUrls(entities: Array<URLEntity>?): List<String> {
+ val names = ArrayList<String>()
+ if (entities != null) {
+ for (entity in entities) {
+ names.add(entity.expandedURL)
+ }
+ }
+ return names
+ }
+
+ private fun extractMediaUrls(entities: Array<MediaEntity>?): List<String> {
+ val names = ArrayList<String>()
+ if (entities != null) {
+ for (entity in entities) {
+ if ("photo" == entity.type) {
+ names.add(entity.mediaURLHttps)
+ } else {
+ names.add(entity.expandedURL)
+ }
+ }
+ }
+ return names
+ }
+
+ private fun extractHashtags(entities: Array<HashtagEntity>?): List<String> {
+ val names = ArrayList<String>()
+ if (entities != null) {
+ for (entity in entities) {
+ names.add(entity.text)
+ }
+ }
+ return names
+ }
+
+ protected fun extractText(status: twitter4j.Status, expand: Boolean): String {
+ return extractText(status, status.text, expand)
+ }
+
+ protected fun extractText(status: twitter4j.DirectMessage, expand: Boolean): String {
+ return extractText(status, status.text, expand)
+ }
+
+ private fun extractText(status: twitter4j.EntitySupport, text: String, expand: Boolean): String {
+ val set = TreeSet<twitter4j.URLEntity> { a, b -> a.start - b.start }
+ if (status.urlEntities != null) {
+ Collections.addAll(set, *status.urlEntities)
+ }
+ if (status.mediaEntities != null) {
+ Collections.addAll(set, *status.mediaEntities)
+ }
+
+ var t = text
+ for (entity in set) {
+ val newString = if (expand) entity.expandedURL else entity.displayURL
+ t = t.replaceFirst(entity.text.toRegex(), newString)
+ }
+ return t
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/Event.java b/app/src/main/java/net/lacolaco/smileessence/entity/Event.java
deleted file mode 100644
index e2002cb9..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/entity/Event.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package net.lacolaco.smileessence.entity;
-
-import java.util.Date;
-
-public class Event {
- private final Date createdAt;
- private final EnumEvent event;
- private final User source;
- private final Tweet targetObject;
-
- public Event(EnumEvent e, User s) {
- this(e, s, null);
- }
-
- public Event(EnumEvent e, User s, Tweet t) {
- event = e;
- createdAt = new Date();
- source = s;
- targetObject = t;
- }
-
- public Date getCreatedAt() {
- return createdAt;
- }
-
- public EnumEvent getEvent() {
- return event;
- }
-
- public User getSource() {
- return source;
- }
-
- public Tweet getTargetObject() {
- return targetObject;
- }
-
- public String getFormattedString() {
- return String.format(event.getFormat(), source.getScreenName());
- }
-
- public enum EnumEvent {
- FAVORITED("Favorited by %s"),
- UNFAVORITED("Unfavorited by %s"),
- RETWEETED("Retweeted by %s"),
- MENTIONED("Replied by %s"),
- FOLLOWED("Followed by %s"),
- BLOCKED("Blocked by %s"),
- UNBLOCKED("Unblocked by %s"),
- RECEIVE_MESSAGE("Received a direct message from %s");
-
- private final String format;
-
- EnumEvent(String f) {
- format = f;
- }
-
- public String getFormat() {
- return format;
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/Event.kt b/app/src/main/java/net/lacolaco/smileessence/entity/Event.kt
new file mode 100644
index 00000000..d7d7a9cd
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/Event.kt
@@ -0,0 +1,20 @@
+package net.lacolaco.smileessence.entity
+
+import java.util.Date
+
+class Event constructor(val event: EnumEvent, val source: User, val targetObject: Tweet? = null) {
+ val createdAt: Date = Date()
+ val formattedString: String
+ get() = String.format(event.format, source.screenName)
+
+ enum class EnumEvent(val format: String) {
+ FAVORITED("Favorited by %s"),
+ UNFAVORITED("Unfavorited by %s"),
+ RETWEETED("Retweeted by %s"),
+ MENTIONED("Replied by %s"),
+ FOLLOWED("Followed by %s"),
+ BLOCKED("Blocked by %s"),
+ UNBLOCKED("Unblocked by %s"),
+ RECEIVE_MESSAGE("Received a direct message from %s")
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/IdObject.java b/app/src/main/java/net/lacolaco/smileessence/entity/IdObject.java
deleted file mode 100644
index 444a627b..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/entity/IdObject.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.lacolaco.smileessence.entity;
-
-public interface IdObject {
- long getId();
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/IdObject.kt b/app/src/main/java/net/lacolaco/smileessence/entity/IdObject.kt
new file mode 100644
index 00000000..eb08d55f
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/IdObject.kt
@@ -0,0 +1,5 @@
+package net.lacolaco.smileessence.entity
+
+interface IdObject {
+ val id: Long
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/RBinding.java b/app/src/main/java/net/lacolaco/smileessence/entity/RBinding.kt
index 5ade81b2..1a25cdd5 100644
--- a/app/src/main/java/net/lacolaco/smileessence/entity/RBinding.java
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/RBinding.kt
@@ -1,6 +1,6 @@
-package net.lacolaco.smileessence.entity;
+package net.lacolaco.smileessence.entity
-public enum RBinding {
+enum class RBinding {
// Tweet
REACTION_COUNT,
FAVORITERS,
@@ -8,5 +8,5 @@ public enum RBinding {
// User
BASIC,
- DETAIL,;
+ DETAIL
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.java b/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.java
deleted file mode 100644
index 8fcd0acd..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package net.lacolaco.smileessence.entity;
-
-public class SavedSearch implements IdObject {
- private long id;
- private String query;
-
- private SavedSearch(long id, String query) {
- this.id = id;
- this.query = query;
- }
-
- public synchronized static SavedSearch fromTwitter(twitter4j.SavedSearch obj) {
- return new SavedSearch(obj.getId(), obj.getQuery());
- }
-
- @Override
- public long getId() {
- return id;
- }
-
- public String getQuery() {
- return query;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.kt b/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.kt
new file mode 100644
index 00000000..318a2184
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/SavedSearch.kt
@@ -0,0 +1,10 @@
+package net.lacolaco.smileessence.entity
+
+class SavedSearch private constructor(override val id: Long, val query: String) : IdObject {
+ companion object {
+ @Synchronized
+ fun fromTwitter(obj: twitter4j.SavedSearch): SavedSearch {
+ return SavedSearch(obj.id, obj.query)
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.java b/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.java
deleted file mode 100644
index c79c58ef..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.java
+++ /dev/null
@@ -1,281 +0,0 @@
-package net.lacolaco.smileessence.entity;
-
-import android.net.Uri;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.twitter.task.Tweets;
-import net.lacolaco.smileessence.util.BackgroundTask;
-import net.lacolaco.smileessence.util.ListUtils;
-import twitter4j.Status;
-
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class Tweet extends EntitySupport implements IdObject {
- private static Map<Long, Tweet> storage = new HashMap<>();
- private final long id;
- private User user;
- private String text;
- private Date createdAt;
- private String source;
- private boolean isRetweet;
- private Tweet retweetedTweet;
- private long inReplyToStatusId;
- private int favoriteCount;
- private int retweetCount;
- private Set<Long> favoriters;
- private Map<Long, Long> retweets;
-
- private Tweet(long id) {
- this.id = id;
- }
-
- public synchronized static Tweet fetch(long statusId) {
- return storage.get(statusId);
- }
-
- public synchronized static BackgroundTask<Tweet, Void> fetchTask(long statusId, Account account) {
- Tweet tweet = fetch(statusId);
- if (tweet != null) {
- return new BackgroundTask<Tweet, Void>() {
- @Override
- protected Tweet doInBackground() throws Exception {
- return tweet;
- }
- };
- } else {
- return new Tweets.GetTask(account, statusId);
- }
- }
-
- public synchronized static Tweet fromTwitter(final twitter4j.Status st, long myUserId) {
- Tweet t = fetch(st.getId());
- if (t == null) {
- t = new Tweet(st.getId());
- storage.put(st.getId(), t);
- }
-
- t.update(st, myUserId);
- return t;
- }
-
- public synchronized static List<Tweet> fromTwitter(List<Status> sts, long myUserId) {
- return ListUtils.map(sts, st -> fromTwitter(st, myUserId));
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- super.finalize();
- } finally {
- Tweet original = getRetweetedTweet();
- if (original != null) {
- original.removeRetweet(getId());
- }
- }
- }
-
- private void update(twitter4j.Status status, long myUserId) {
- if (id != status.getId())
- throw new IllegalStateException("Invalid update");
- user = User.fromTwitter(status.getUser());
- createdAt = status.getCreatedAt();
- source = status.getSource();
- isRetweet = status.isRetweet();
-
- if (!isRetweet) {
- text = extractText(status, false);
- inReplyToStatusId = status.getInReplyToStatusId();
- updateEntities(status);
- if (favoriters == null) favoriters = Collections.newSetFromMap(new ConcurrentHashMap<>());
- if (retweets == null) retweets = new ConcurrentHashMap<>();
-
- if (favoriteCount != status.getFavoriteCount() || retweetCount != status.getRetweetCount()) {
- favoriteCount = status.getFavoriteCount();
- retweetCount = status.getRetweetCount();
-
- notifyChange(RBinding.REACTION_COUNT);
- }
-
- if (status.isFavorited()) {
- addFavoriter(myUserId);
- } else {
- removeFavoriter(myUserId);
- }
- if (status.getCurrentUserRetweetId() > 0) {
- addRetweet(myUserId, status.getCurrentUserRetweetId());
- }
- } else {
- retweetedTweet = Tweet.fromTwitter(status.getRetweetedStatus(), myUserId);
- retweetedTweet.addRetweet(this);
- if (status.isFavorited()) {
- retweetedTweet.addFavoriter(myUserId);
- }
- if (status.getCurrentUserRetweetId() > 0) {
- retweetedTweet.addRetweet(myUserId, status.getCurrentUserRetweetId());
- }
- }
- }
-
- public String getTwitterUrl() {
- return String.format("https://twitter.com/%s/status/%s", getUser().getScreenName(), id);
- }
-
- @Override
- public long getId() {
- return id;
- }
-
- public User getUser() {
- return user;
- }
-
- public String getText() {
- return getOriginalTweet().text;
- }
-
- public Date getCreatedAt() {
- return createdAt;
- }
-
- public String getSource() {
- return source;
- }
-
- public boolean isRetweet() {
- return isRetweet;
- }
-
- public Tweet getRetweetedTweet() {
- return retweetedTweet;
- }
-
- public Tweet getOriginalTweet() {
- if (isRetweet()) {
- return getRetweetedTweet();
- } else {
- return this;
- }
- }
-
- public int getFavoriteCount() {
- return getOriginalTweet().favoriteCount;
- }
-
- public int getRetweetCount() {
- return getOriginalTweet().retweetCount;
- }
-
- public long getInReplyToStatusId() {
- return getOriginalTweet().inReplyToStatusId;
- }
-
- public boolean isFavoritedBy(long id) {
- return getOriginalTweet().favoriters.contains(id);
- }
-
- public Set<Long> getFavoriters() {
- return getOriginalTweet().favoriters;
- }
-
- public boolean addFavoriter(long id) {
- boolean changed = getOriginalTweet().favoriters.add(id);
- if (changed) notifyChange(RBinding.FAVORITERS);
- return changed;
- }
-
- public boolean removeFavoriter(long id) {
- boolean changed = getOriginalTweet().favoriters.remove(id);
- if (changed) notifyChange(RBinding.FAVORITERS);
- return changed;
- }
-
- public boolean isRetweetedBy(long id) {
- return getOriginalTweet().retweets.get(id) != null;
- }
-
- public long getRetweetIdBy(long id) {
- return getOriginalTweet().retweets.get(id);
- }
-
- public Map<Long, Long> getRetweets() {
- return getOriginalTweet().retweets;
- }
-
- public boolean addRetweet(Tweet retweet) {
- return addRetweet(retweet.getUser().getId(), retweet.getId());
- }
-
- public boolean addRetweet(long uid, long sid) {
- Long result = getOriginalTweet().retweets.put(uid, sid);
- boolean changed = result == null || result != sid;
- if (changed) notifyChange(RBinding.RETWEETERS);
- return changed;
- }
-
- private boolean removeRetweet(long sid) {
- boolean changed = getOriginalTweet().retweets.values().remove(sid);
- if (changed) notifyChange(RBinding.RETWEETERS);
- return changed;
- }
-
- // helper methods::
- public List<Long> getEmbeddedStatusIDs() {
- ArrayList<Long> list = new ArrayList<>();
- for (String url : getUrlsExpanded()) {
- Uri uri = Uri.parse(url);
- if ("twitter.com".equals(uri.getHost())) {
- String[] arr = uri.toString().split("/");
- if (arr.length > 2 && "status".equals(arr[arr.length - 2])) {
- list.add(Long.parseLong(arr[arr.length - 1].split("\\?")[0]));
- }
- }
- }
- return list;
- }
-
- // override EntitySupport
- @Override
- public List<String> getMentions() {
- if (isRetweet) {
- return getOriginalTweet().getMentions();
- } else {
- return super.getMentions();
- }
- }
-
- @Override
- public List<String> getHashtags() {
- if (isRetweet) {
- return getOriginalTweet().getHashtags();
- } else {
- return super.getHashtags();
- }
- }
-
- @Override
- public List<String> getMediaUrls() {
- if (isRetweet) {
- return getOriginalTweet().getMediaUrls();
- } else {
- return super.getMediaUrls();
- }
- }
-
- @Override
- public List<String> getUrlsExpanded() {
- if (isRetweet) {
- return getOriginalTweet().getUrlsExpanded();
- } else {
- return super.getUrlsExpanded();
- }
- }
-
- @Override
- public List<String> getSymbols() {
- if (isRetweet) {
- return getOriginalTweet().getSymbols();
- } else {
- return super.getSymbols();
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.kt b/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.kt
new file mode 100644
index 00000000..437e69c7
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/Tweet.kt
@@ -0,0 +1,197 @@
+package net.lacolaco.smileessence.entity
+
+import android.net.Uri
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.twitter.task.Tweets
+import net.lacolaco.smileessence.util.BackgroundTask
+import twitter4j.Status
+
+import java.util.*
+import java.util.concurrent.ConcurrentHashMap
+
+class Tweet private constructor(st: twitter4j.Status, myUserId: Long) : EntitySupport(), IdObject {
+ override val id: Long = st.id
+ val user: User = User.fromTwitter(st.user)
+ val text: String = extractText(st, false)
+ get() {
+ return if (isRetweet) originalTweet.text else field
+ }
+ val createdAt: Date = st.createdAt
+ val source: String = st.source
+ val isRetweet: Boolean = st.isRetweet
+ val retweetedTweet: Tweet? = if (st.isRetweet) Tweet.fromTwitter(st.retweetedStatus, myUserId) else null
+ val originalTweet: Tweet
+ get() = retweetedTweet ?: this
+ val inReplyToStatusId: Long = st.inReplyToStatusId
+ get() = if (isRetweet) originalTweet.inReplyToStatusId else field
+ var favoriteCount: Int = st.favoriteCount
+ get() = if (isRetweet) originalTweet.originalTweet.favoriteCount else field
+ private set
+ var retweetCount: Int = st.retweetCount
+ get() = if (isRetweet) originalTweet.originalTweet.retweetCount else field
+ private set
+ private val favoriters: MutableSet<Long> = Collections.newSetFromMap(ConcurrentHashMap())
+ private val retweets: MutableMap<Long, Long> = ConcurrentHashMap()
+
+ protected fun finalize() {
+ retweetedTweet?.retweets?.remove(id)
+ }
+
+ init {
+ updateEntities(st)
+ update(st, myUserId)
+ }
+
+ private fun update(status: twitter4j.Status, myUserId: Long) {
+ User.fromTwitter(status.user)
+ if (retweetedTweet != null) {
+ Tweet.fromTwitter(status.retweetedStatus, myUserId)
+ if (status.isFavorited) {
+ retweetedTweet.favoriters.add(myUserId)
+ }
+ if (status.currentUserRetweetId > 0) {
+ retweetedTweet.retweets.put(myUserId, status.currentUserRetweetId)
+ }
+ } else {
+ if (favoriteCount != status.favoriteCount || retweetCount != status.retweetCount) {
+ favoriteCount = status.favoriteCount
+ retweetCount = status.retweetCount
+ notifyChange(RBinding.REACTION_COUNT)
+ }
+
+ if (status.isFavorited)
+ favoriters.add(myUserId)
+ else
+ favoriters.remove(myUserId)
+ if (status.currentUserRetweetId > 0)
+ retweets.put(myUserId, status.currentUserRetweetId)
+ }
+ }
+
+ val twitterUrl: String
+ get() = String.format("https://twitter.com/%s/status/%s", user.screenName, id)
+
+ fun isFavoritedBy(id: Long): Boolean {
+ return originalTweet.favoriters.contains(id)
+ }
+
+ fun addFavoriter(id: Long): Boolean {
+ val changed = originalTweet.favoriters.add(id)
+ if (changed) notifyChange(RBinding.FAVORITERS)
+ return changed
+ }
+
+ fun removeFavoriter(id: Long): Boolean {
+ val changed = originalTweet.favoriters.remove(id)
+ if (changed) notifyChange(RBinding.FAVORITERS)
+ return changed
+ }
+
+ fun isRetweetedBy(id: Long): Boolean {
+ return originalTweet.retweets[id] != null
+ }
+
+ fun getRetweetIdBy(id: Long): Long {
+ return originalTweet.retweets[id]!!
+ }
+
+ // helper methods::
+ val embeddedStatusIDs: List<Long>
+ get() {
+ val list = ArrayList<Long>()
+ for (url in urlsExpanded) {
+ val uri = Uri.parse(url)
+ if ("twitter.com" == uri.host) {
+ val arr = uri.toString().split("/".toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()
+ if (arr.size > 2 && "status" == arr[arr.size - 2]) {
+ list.add(java.lang.Long.parseLong(arr[arr.size - 1].split("\\?".toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()[0]))
+ }
+ }
+ }
+ return list
+ }
+
+ // override EntitySupport
+ override var mentions: List<String>
+ get() = if (isRetweet) originalTweet.mentions else super.mentions
+ set(value) {
+ super.mentions = value
+ }
+
+ override var hashtags: List<String>
+ get() = if (isRetweet) originalTweet.hashtags else super.hashtags
+ set(value) {
+ super.hashtags = value
+ }
+
+ override var mediaUrls: List<String>
+ get() = if (isRetweet) {
+ originalTweet.mediaUrls
+ } else {
+ super.mediaUrls
+ }
+ set(value) {
+ super.mediaUrls = value
+ }
+
+ override var urlsExpanded: List<String>
+ get() = if (isRetweet) {
+ originalTweet.urlsExpanded
+ } else {
+ super.urlsExpanded
+ }
+ set(value) {
+ super.urlsExpanded = value
+ }
+
+ override var symbols: List<String>
+ get() = if (isRetweet) {
+ originalTweet.symbols
+ } else {
+ super.symbols
+ }
+ set(value) {
+ super.symbols = value
+ }
+
+ companion object {
+ private val storage = HashMap<Long, Tweet>()
+
+ @Synchronized
+ fun fetch(statusId: Long): Tweet? {
+ return storage[statusId]
+ }
+
+ @Synchronized
+ fun fetchTask(statusId: Long, account: Account): BackgroundTask<Tweet, Void> {
+ val tweet = fetch(statusId)
+ return if (tweet != null) {
+ object : BackgroundTask<Tweet, Void>() {
+ @Throws(Exception::class)
+ override fun doInBackground(): Tweet {
+ return tweet
+ }
+ }
+ } else {
+ Tweets.GetTask(account, statusId)
+ }
+ }
+
+ @Synchronized
+ fun fromTwitter(st: twitter4j.Status, myUserId: Long): Tweet {
+ var t = fetch(st.id)
+ if (t == null) {
+ t = Tweet(st, myUserId)
+ storage.put(st.id, t)
+ } else {
+ t.update(st, myUserId)
+ }
+ return t
+ }
+
+ @Synchronized
+ fun fromTwitter(sts: List<Status>, myUserId: Long): List<Tweet> {
+ return sts.map { st -> fromTwitter(st, myUserId) }
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/User.java b/app/src/main/java/net/lacolaco/smileessence/entity/User.java
deleted file mode 100644
index abc2c047..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/entity/User.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package net.lacolaco.smileessence.entity;
-
-import net.lacolaco.smileessence.util.UIObservable;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class User extends UIObservable implements IdObject {
- private static Map<Long, User> storage = new HashMap<>();
- private long id;
- private boolean isProtected;
- private String screenName;
- private String name;
- private String profileImageUrl;
- private String profileBannerUrl;
- private String description;
- private String location;
- private String url;
- private int favoritesCount;
- private int statusesCount;
- private int friendsCount;
- private int followersCount;
- private boolean isVerified;
-
- private User() {
- }
-
- public synchronized static User fetch(long userId) {
- return storage.get(userId);
- }
-
- public synchronized static User fromTwitter(final twitter4j.User st) {
- User u = fetch(st.getId());
- if (u == null) {
- u = new User();
- storage.put(st.getId(), u);
- }
-
- u.update(st);
- return u;
- }
-
- // only for initialization; DO NOT have reference for this object
- public synchronized static User _makeSkeleton(long id, String screenName) {
- User u = fetch(id);
- if (u != null) {
- return u;
- } else {
- u = new User();
- u.id = id;
- u.screenName = screenName;
- storage.put(id, u);
- return u;
- }
- }
-
- private void update(twitter4j.User user) {
- id = user.getId();
-
- if (isProtected() != user.isProtected() ||
- getScreenName() == null || !getScreenName().equals(user.getScreenName()) ||
- getName() == null || !getName().equals(user.getName()) ||
- profileImageUrl == null || !profileImageUrl.equals(user.getProfileImageURLHttps())) {
- isProtected = user.isProtected();
- if (user.getScreenName() != null)
- screenName = user.getScreenName();
- if (user.getName() != null)
- name = user.getName();
- if (user.getProfileImageURLHttps() != null)
- profileImageUrl = user.getProfileImageURLHttps();
-
- notifyChange(RBinding.BASIC);
- }
-
- if (getProfileBannerUrl() == null || !getProfileBannerUrl().equals(user.getProfileBannerURL()) ||
- getDescription() == null || !getDescription().equals(user.getDescription()) ||
- getLocation() == null || !getLocation().equals(user.getLocation()) ||
- getUrl() == null || !getUrl().equals(user.getURL()) ||
- getFavoritesCount() != user.getFavouritesCount() ||
- getStatusesCount() != user.getStatusesCount() ||
- getFriendsCount() != user.getFriendsCount() ||
- getFollowersCount() != user.getFollowersCount()) {
- isVerified = user.isVerified();
- if (user.getProfileBannerURL() != null)
- profileBannerUrl = user.getProfileBannerURL();
- if (user.getDescription() != null)
- description = user.getDescription();
- if (user.getLocation() != null)
- location = user.getLocation();
- if (user.getURL() != null)
- url = user.getURL();
- if (user.getFavouritesCount() != -1)
- favoritesCount = user.getFavouritesCount();
- if (user.getStatusesCount() != -1)
- statusesCount = user.getStatusesCount();
- if (user.getFriendsCount() != -1)
- friendsCount = user.getFriendsCount();
- if (user.getFollowersCount() != -1)
- followersCount = user.getFollowersCount();
-
- notifyChange(RBinding.DETAIL);
- }
- }
-
- @Override
- public long getId() {
- return id;
- }
-
- public boolean isProtected() {
- return isProtected;
- }
-
- public String getScreenName() {
- return screenName;
- }
-
- public String getName() {
- return name;
- }
-
- public String getProfileImageUrlOriginal() {
- String original = profileImageUrl;
- if (original != null) {
- String url = original.substring(0, original.lastIndexOf("_"));
- int extIndex = original.lastIndexOf(".");
- if (extIndex > original.lastIndexOf("/")) {
- url += original.substring(extIndex);
- }
- return url;
- }
- return null;
- }
-
- public String getProfileBannerUrl() {
- return profileBannerUrl;
- }
-
- public String getDescription() {
- return description;
- }
-
- public String getLocation() {
- return location;
- }
-
- public String getUrl() {
- return url;
- }
-
- public int getFavoritesCount() {
- return favoritesCount;
- }
-
- public int getStatusesCount() {
- return statusesCount;
- }
-
- public int getFriendsCount() {
- return friendsCount;
- }
-
- public int getFollowersCount() {
- return followersCount;
- }
-
- public boolean isVerified() {
- return isVerified;
- }
-
- // helper methods
- public String getUserHomeURL() {
- return String.format("https://twitter.com/%s", getScreenName());
- }
-
- public String getAclogTimelineURL() {
- return String.format("https://aclog.rhe.jp/%s/timeline", getScreenName());
- }
-
- public String getFormattedName() {
- return screenName + " / " + name;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/User.kt b/app/src/main/java/net/lacolaco/smileessence/entity/User.kt
new file mode 100644
index 00000000..6a92b54e
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/User.kt
@@ -0,0 +1,136 @@
+package net.lacolaco.smileessence.entity
+
+import net.lacolaco.smileessence.util.UIObservable
+
+import java.util.HashMap
+
+class User private constructor(override val id: Long, screenName: String) : UIObservable(), IdObject {
+ var screenName = screenName
+ private set
+ var name: String? = null
+ private set
+ var profileImageUrl: String? = null
+ get() {
+ val original = field
+ if (original != null) {
+ var url = original.substring(0, original.lastIndexOf("_"))
+ val extIndex = original.lastIndexOf(".")
+ if (extIndex > original.lastIndexOf("/")) {
+ url += original.substring(extIndex)
+ }
+ return url
+ }
+ return null
+ }
+ private set
+ var profileBannerUrl: String? = null
+ private set
+ var description: String? = null
+ private set
+ var location: String? = null
+ private set
+ var url: String? = null
+ private set
+ var favoritesCount: Int = 0
+ private set
+ var statusesCount: Int = 0
+ private set
+ var friendsCount: Int = 0
+ private set
+ var followersCount: Int = 0
+ private set
+ var isProtected: Boolean = false
+ private set
+ var isVerified: Boolean = false
+ private set
+
+ private fun update(user: twitter4j.User) {
+ if (isProtected != user.isProtected ||
+ screenName != user.screenName ||
+ name == null || name != user.name ||
+ this.profileImageUrl == null || this.profileImageUrl != user.profileImageURLHttps) {
+ isProtected = user.isProtected
+ if (user.screenName != null)
+ screenName = user.screenName
+ if (user.name != null)
+ name = user.name
+ if (user.profileImageURLHttps != null)
+ this.profileImageUrl = user.profileImageURLHttps
+
+ notifyChange(RBinding.BASIC)
+ }
+
+ if (profileBannerUrl == null || profileBannerUrl != user.profileBannerURL ||
+ description == null || description != user.description ||
+ location == null || location != user.location ||
+ url == null || url != user.url ||
+ favoritesCount != user.favouritesCount ||
+ statusesCount != user.statusesCount ||
+ friendsCount != user.friendsCount ||
+ followersCount != user.followersCount) {
+ isVerified = user.isVerified
+ if (user.profileBannerURL != null)
+ profileBannerUrl = user.profileBannerURL
+ if (user.description != null)
+ description = user.description
+ if (user.location != null)
+ location = user.location
+ if (user.url != null)
+ url = user.url
+ if (user.favouritesCount != -1)
+ favoritesCount = user.favouritesCount
+ if (user.statusesCount != -1)
+ statusesCount = user.statusesCount
+ if (user.friendsCount != -1)
+ friendsCount = user.friendsCount
+ if (user.followersCount != -1)
+ followersCount = user.followersCount
+
+ notifyChange(RBinding.DETAIL)
+ }
+ }
+
+ // helper methods
+ val userHomeURL: String
+ get() = String.format("https://twitter.com/%s", screenName)
+
+ val aclogTimelineURL: String
+ get() = String.format("https://aclog.rhe.jp/%s/timeline", screenName)
+
+ val formattedName: String
+ get() = screenName + " / " + name
+
+ companion object {
+ private val storage = HashMap<Long, User>()
+
+ @Synchronized
+ fun fetch(userId: Long): User? {
+ return storage[userId]
+ }
+
+ @Synchronized
+ fun fromTwitter(st: twitter4j.User): User {
+ var u: User? = fetch(st.id)
+ if (u == null) {
+ u = User(st.id, st.screenName)
+ storage.put(st.id, u)
+ }
+
+ u.update(st)
+ return u
+ }
+
+ // only for initialization; DO NOT have reference for this object
+ @Synchronized
+ fun _makeSkeleton(id: Long, screenName: String): User {
+ var u: User? = fetch(id)
+ if (u != null) {
+ return u
+ } else {
+ u = User(id, screenName)
+ storage.put(id, u)
+ return u
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/logging/Logger.java b/app/src/main/java/net/lacolaco/smileessence/logging/Logger.kt
index 675a14f1..7e898c1b 100644
--- a/app/src/main/java/net/lacolaco/smileessence/logging/Logger.java
+++ b/app/src/main/java/net/lacolaco/smileessence/logging/Logger.kt
@@ -22,45 +22,46 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.logging;
+package net.lacolaco.smileessence.logging
-import android.util.Log;
+import android.util.Log
-public class Logger {
+object Logger {
// ------------------------------ FIELDS ------------------------------
- private static final String TAG = "SmileEssence";
+ private val TAG = "SmileEssence"
// -------------------------- STATIC METHODS --------------------------
- public static void debug(Object message) {
- Log.d(getTag(), String.valueOf(message));
+ fun debug(message: Any) {
+ Log.d(tag, message.toString())
}
- public static void info(Object message) {
- Log.i(getTag(), String.valueOf(message));
+ fun info(message: Any) {
+ Log.i(tag, message.toString())
}
- public static void error(Object message) {
- Log.e(getTag(), String.valueOf(message));
+ fun error(message: Any) {
+ Log.e(tag, message.toString())
}
- public static void warn(Object message) {
- Log.w(getTag(), String.valueOf(message));
+ fun warn(message: Any) {
+ Log.w(tag, message.toString())
}
- public static void verbose(Object message) {
- Log.v(getTag(), String.valueOf(message));
+ fun verbose(message: Any) {
+ Log.v(tag, message.toString())
}
- private static String getTag() {
- StackTraceElement[] st = Thread.currentThread().getStackTrace();
- for (int i = 0; i < st.length; ++i) {
- if ("getTag".equals(st[i].getMethodName())) {
- return st[i + 2].getClassName() + ":" + st[i + 2].getMethodName();
+ private val tag: String
+ get() {
+ val st = Thread.currentThread().stackTrace
+ for (i in st.indices) {
+ if ("getTag" == st[i].methodName) {
+ return st[i + 2].className + ":" + st[i + 2].methodName
+ }
}
+ return TAG
}
- return TAG;
- }
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.java b/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.java
deleted file mode 100644
index 9d500cd4..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.preference;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import net.lacolaco.smileessence.Application;
-
-public class InternalPreferenceHelper extends SharedPreferenceHelper {
-
- // ------------------------------ FIELDS ------------------------------
-
- private static final String FILE_NAME = "AppPreference";
- private static final InternalPreferenceHelper instance = new InternalPreferenceHelper();
-
- private InternalPreferenceHelper() {
- }
-
- public static InternalPreferenceHelper getInstance() {
- return instance;
- }
-
- // --------------------------- OVERRIDE ---------------------------
- @Override
- protected SharedPreferences getPreferences() {
- return Application.getInstance().getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.kt b/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.kt
new file mode 100644
index 00000000..1353eb2a
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/preference/InternalPreferenceHelper.kt
@@ -0,0 +1,44 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.preference
+
+import android.content.Context
+import android.content.SharedPreferences
+import net.lacolaco.smileessence.Application
+
+class InternalPreferenceHelper private constructor() : SharedPreferenceHelper() {
+
+ // --------------------------- OVERRIDE ---------------------------
+ override val preferences: SharedPreferences
+ get() = Application.getInstance().getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
+
+ companion object {
+
+ // ------------------------------ FIELDS ------------------------------
+
+ private val FILE_NAME = "AppPreference"
+ val instance = InternalPreferenceHelper()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/preference/SharedPreferenceHelper.java b/app/src/main/java/net/lacolaco/smileessence/preference/SharedPreferenceHelper.java
deleted file mode 100644
index 979dc732..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/preference/SharedPreferenceHelper.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.preference;
-
-import android.content.SharedPreferences;
-import net.lacolaco.smileessence.Application;
-
-import java.util.Set;
-
-public abstract class SharedPreferenceHelper {
- // --------------------- GETTER / SETTER METHODS ---------------------
-
- protected abstract SharedPreferences getPreferences();
-
- // -------------------------- OTHER METHODS --------------------------
-
- public String get(int key, String defaultValue) {
- return getPreferences().getString(getString(key), defaultValue);
- }
-
- // int, long, float value may be stored in String format (old versions)
- public int get(int key, int defaultValue) {
- try {
- return getPreferences().getInt(getString(key), defaultValue);
- } catch (ClassCastException ex) {
- int ret = Integer.parseInt(get(key, String.valueOf(defaultValue)));
- set(key, ret);
- return ret;
- }
- }
-
- public long get(int key, long defaultValue) {
- try {
- return getPreferences().getLong(getString(key), defaultValue);
- } catch (ClassCastException ex) {
- long ret = Long.parseLong(get(key, String.valueOf(defaultValue)));
- set(key, ret);
- return ret;
- }
- }
-
- public float get(int key, float defaultValue) {
- try {
- return getPreferences().getFloat(getString(key), defaultValue);
- } catch (ClassCastException ex) {
- float ret = Float.parseFloat(get(key, String.valueOf(defaultValue)));
- set(key, ret);
- return ret;
- }
- }
-
- public boolean get(int key, boolean defaultValue) {
- return getPreferences().getBoolean(getString(key), defaultValue);
- }
-
- public Set<String> get(int key, Set<String> defaultValue) {
- return getPreferences().getStringSet(getString(key), defaultValue);
- }
-
- public boolean set(int key, String value) {
- return getPreferences().edit()
- .putString(getString(key), value)
- .commit();
- }
-
- public boolean set(int key, int value) {
- return getPreferences().edit()
- .putInt(getString(key), value)
- .commit();
- }
-
- public boolean set(int key, long value) {
- return getPreferences().edit()
- .putLong(getString(key), value)
- .commit();
- }
-
- public boolean set(int key, float value) {
- return getPreferences().edit()
- .putFloat(getString(key), value)
- .commit();
- }
-
- public boolean set(int key, boolean value) {
- return getPreferences().edit()
- .putBoolean(getString(key), value)
- .commit();
- }
-
- public boolean set(int key, Set<String> value) {
- return getPreferences().edit()
- .putStringSet(getString(key), value)
- .commit();
- }
-
- private String getString(int resID) {
- try {
- return Application.getInstance().getString(resID);
- } catch (Exception e) {
- return null;
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/preference/SharedPreferenceHelper.kt b/app/src/main/java/net/lacolaco/smileessence/preference/SharedPreferenceHelper.kt
new file mode 100644
index 00000000..6702f1c3
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/preference/SharedPreferenceHelper.kt
@@ -0,0 +1,127 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.preference
+
+import android.content.SharedPreferences
+import net.lacolaco.smileessence.Application
+
+abstract class SharedPreferenceHelper {
+ // --------------------- GETTER / SETTER METHODS ---------------------
+
+ protected abstract val preferences: SharedPreferences
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ operator fun get(key: Int, defaultValue: String): String {
+ return preferences.getString(getString(key), defaultValue)
+ }
+
+ // int, long, float value may be stored in String format (old versions)
+ operator fun get(key: Int, defaultValue: Int): Int {
+ try {
+ return preferences.getInt(getString(key), defaultValue)
+ } catch (ex: ClassCastException) {
+ val ret = Integer.parseInt(get(key, defaultValue.toString()))
+ set(key, ret)
+ return ret
+ }
+
+ }
+
+ operator fun get(key: Int, defaultValue: Long): Long {
+ try {
+ return preferences.getLong(getString(key), defaultValue)
+ } catch (ex: ClassCastException) {
+ val ret = java.lang.Long.parseLong(get(key, defaultValue.toString()))
+ set(key, ret)
+ return ret
+ }
+
+ }
+
+ operator fun get(key: Int, defaultValue: Float): Float {
+ try {
+ return preferences.getFloat(getString(key), defaultValue)
+ } catch (ex: ClassCastException) {
+ val ret = java.lang.Float.parseFloat(get(key, defaultValue.toString()))
+ set(key, ret)
+ return ret
+ }
+
+ }
+
+ operator fun get(key: Int, defaultValue: Boolean): Boolean {
+ return preferences.getBoolean(getString(key), defaultValue)
+ }
+
+ operator fun get(key: Int, defaultValue: Set<String>): Set<String> {
+ return preferences.getStringSet(getString(key), defaultValue)
+ }
+
+ operator fun set(key: Int, value: String): Boolean {
+ return preferences.edit()
+ .putString(getString(key), value)
+ .commit()
+ }
+
+ operator fun set(key: Int, value: Int): Boolean {
+ return preferences.edit()
+ .putInt(getString(key), value)
+ .commit()
+ }
+
+ operator fun set(key: Int, value: Long): Boolean {
+ return preferences.edit()
+ .putLong(getString(key), value)
+ .commit()
+ }
+
+ operator fun set(key: Int, value: Float): Boolean {
+ return preferences.edit()
+ .putFloat(getString(key), value)
+ .commit()
+ }
+
+ operator fun set(key: Int, value: Boolean): Boolean {
+ return preferences.edit()
+ .putBoolean(getString(key), value)
+ .commit()
+ }
+
+ operator fun set(key: Int, value: Set<String>): Boolean {
+ return preferences.edit()
+ .putStringSet(getString(key), value)
+ .commit()
+ }
+
+ private fun getString(resID: Int): String? {
+ try {
+ return Application.getInstance().getString(resID)
+ } catch (e: Exception) {
+ return null
+ }
+
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.java b/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.kt
index b2de5c21..41f7f019 100644
--- a/app/src/main/java/net/lacolaco/smileessence/command/CommandAddHashtag.java
+++ b/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.kt
@@ -22,35 +22,29 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.command;
+package net.lacolaco.smileessence.preference
-import net.lacolaco.smileessence.activity.MainActivity;
+import android.content.SharedPreferences
+import android.preference.PreferenceManager
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
-public class CommandAddHashtag extends Command {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final String hashtag;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public CommandAddHashtag(MainActivity activity, String hashtag) {
- super(activity);
- this.hashtag = hashtag;
- }
+class UserPreferenceHelper private constructor() : SharedPreferenceHelper() {
// --------------------- GETTER / SETTER METHODS ---------------------
+ override val preferences: SharedPreferences
+ get() = PreferenceManager.getDefaultSharedPreferences(Application.getInstance())
- @Override
- public String getText() {
- return "#" + hashtag;
- }
+ // --------------------- HELPER METHODS ---------------------
+ val themeIndex: Int
+ get() = get(R.string.key_setting_theme, 0)
+
+ val textSize: Int
+ get() = get(R.string.key_setting_text_size, 10)
- // -------------------------- OTHER METHODS --------------------------
+ companion object {
+ // --------------------------- CONSTRUCTORS ---------------------------
- @Override
- public boolean execute() {
- getActivity().getWorld().getPostState().beginTransaction().appendText(" #" + hashtag).commit();
- return true;
+ val instance = UserPreferenceHelper()
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.java b/app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.kt
index 160e710a..63a0c484 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.java
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/OAuthSession.kt
@@ -22,45 +22,51 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.twitter;
+package net.lacolaco.smileessence.twitter
-import net.lacolaco.smileessence.twitter.task.Accounts;
-import twitter4j.Twitter;
-import twitter4j.TwitterFactory;
-import twitter4j.auth.AccessToken;
-import twitter4j.auth.RequestToken;
+import net.lacolaco.smileessence.twitter.task.Accounts
+import twitter4j.Twitter
+import twitter4j.TwitterFactory
+import twitter4j.auth.AccessToken
+import twitter4j.auth.RequestToken
-public class OAuthSession {
- public static final String KEY_TOKEN = "token";
- public static final String KEY_TOKEN_SECRET = "tokenSecret";
- public static final String KEY_SCREEN_NAME = "screenName";
- public static final String KEY_USER_ID = "userID";
- private RequestToken requestToken;
+class OAuthSession {
+ private var requestToken: RequestToken? = null
// --------------------- GETTER / SETTER METHODS ---------------------
- public String getAuthorizationURL() {
- Twitter twitter = new TwitterFactory().getInstance();
- Accounts.RequestTokenTask task = new Accounts.RequestTokenTask(twitter);
- task.execute();
- try {
- requestToken = task.getImmediately();
- return requestToken.getAuthorizationURL();
- } catch (Exception e) {
- return null;
+ val authorizationURL: String?
+ get() {
+ val twitter = TwitterFactory().instance
+ val task = Accounts.RequestTokenTask(twitter)
+ task.execute()
+ try {
+ requestToken = task.immediately
+ return requestToken!!.authorizationURL
+ } catch (e: Exception) {
+ return null
+ }
+
}
- }
// -------------------------- OTHER METHODS --------------------------
- public AccessToken getAccessToken(String pinCode) {
- Twitter twitter = new TwitterFactory().getInstance();
- Accounts.AccessTokenTask task = new Accounts.AccessTokenTask(twitter, requestToken, pinCode);
- task.execute();
+ fun getAccessToken(pinCode: String): AccessToken? {
+ val twitter = TwitterFactory().instance
+ val task = Accounts.AccessTokenTask(twitter, requestToken!!, pinCode)
+ task.execute()
try {
- return task.getImmediately();
- } catch (Exception e) {
- return null;
+ return task.immediately
+ } catch (e: Exception) {
+ return null
}
+
+ }
+
+ companion object {
+ val KEY_TOKEN = "token"
+ val KEY_TOKEN_SECRET = "tokenSecret"
+ val KEY_SCREEN_NAME = "screenName"
+ val KEY_USER_ID = "userID"
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.java b/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.java
deleted file mode 100644
index acfb44be..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.twitter;
-
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.World;
-import net.lacolaco.smileessence.entity.DirectMessage;
-import net.lacolaco.smileessence.entity.Event;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.entity.User;
-import net.lacolaco.smileessence.logging.Logger;
-import twitter4j.ConnectionLifeCycleListener;
-import twitter4j.Status;
-import twitter4j.StatusDeletionNotice;
-
-public class UserStreamListener implements twitter4j.UserStreamListener, ConnectionLifeCycleListener {
- private final World world;
- private boolean connected = false;
-
- public UserStreamListener(World world) {
- this.world = world;
- }
-
- public boolean isConnected() {
- return connected;
- }
-
- @Override
- public void onConnect() {
- connected = true;
- world.notify(R.string.notice_stream_connect);
- }
-
- @Override
- public void onDisconnect() {
- connected = false;
- world.notify(R.string.notice_stream_disconnect);
- }
-
- @Override
- public void onCleanUp() {
- }
-
- // --------------------- Interface StatusListener ---------------------
-
- @Override
- public void onStatus(Status status) {
- User user = world.getAccount().getUser();
- Tweet tweet = Tweet.fromTwitter(status, user.getId());
- world.addTweet(tweet);
- if (tweet.isRetweet()) {
- if (tweet.getOriginalTweet().getUser().getId() == user.getId()) {
- addToHistory(new Event(Event.EnumEvent.RETWEETED, tweet.getUser(), tweet));
- }
- } else if (tweet.getMentions().contains(user.getScreenName())) {
- Event mentioned = new Event(Event.EnumEvent.MENTIONED, tweet.getUser(), tweet);
- world.notify(mentioned.getFormattedString());
- }
- }
-
- @Override
- public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
- // FIXME
- // StatusFilter.getInstance().remove(StatusViewModel.class, statusDeletionNotice.getStatusId());
- // Tweet.remove(statusDeletionNotice.getStatusId());
- }
-
- @Override
- public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
- }
-
- @Override
- public void onScrubGeo(long userId, long upToStatusId) {
- }
-
- @Override
- public void onStallWarning(twitter4j.StallWarning warning) {
- }
-
- // --------------------- Interface StreamListener ---------------------
-
- @Override
- public void onException(Exception ex) {
- Logger.error(ex.toString());
- }
-
- // --------------------- Interface UserStreamListener ---------------------
-
- @Override
- public void onDeletionNotice(long directMessageId, long userId) {
- // FIXME
- // StatusFilter.getInstance().remove(MessageViewModel.class, directMessageId);
- // DirectMessage.remove(directMessageId);
- }
-
- @Override
- public void onFriendList(long[] friendIds) {
- }
-
- @Override
- public void onFavorite(twitter4j.User source, twitter4j.User target, Status favoritedStatus) {
- Tweet tweet = Tweet.fromTwitter(favoritedStatus, world.getAccount().getUserId());
- tweet.addFavoriter(source.getId());
- if (User.fromTwitter(target) == world.getAccount().getUser()) {
- addToHistory(new Event(Event.EnumEvent.FAVORITED, User.fromTwitter(source), tweet));
- }
- }
-
- @Override
- public void onUnfavorite(twitter4j.User source, twitter4j.User target, twitter4j.Status unfavoritedStatus) {
- Tweet tweet = Tweet.fromTwitter(unfavoritedStatus, world.getAccount().getUserId());
- tweet.removeFavoriter(source.getId());
- if (User.fromTwitter(target) == world.getAccount().getUser()) {
- addToHistory(new Event(Event.EnumEvent.UNFAVORITED, User.fromTwitter(source), tweet));
- }
- }
-
- @Override
- public void onFollow(twitter4j.User source, twitter4j.User followedUser) {
- if (User.fromTwitter(followedUser) == world.getAccount().getUser()) {
- addToHistory(new Event(Event.EnumEvent.FOLLOWED, User.fromTwitter(source)));
- }
- }
-
- @Override
- public void onUnfollow(twitter4j.User source, twitter4j.User unfollowedUser) {
- }
-
- @Override
- public void onDirectMessage(twitter4j.DirectMessage directMessage) {
- DirectMessage message = DirectMessage.fromTwitter(directMessage);
- world.addDirectMessage(message);
- if (message.getRecipient() == world.getAccount().getUser()) {
- addToHistory(new Event(Event.EnumEvent.RECEIVE_MESSAGE, message.getSender()));
- }
- }
-
- @Override
- public void onUserListMemberAddition(twitter4j.User addedMember, twitter4j.User listOwner, twitter4j.UserList list) {
- }
-
- @Override
- public void onUserListMemberDeletion(twitter4j.User deletedMember, twitter4j.User listOwner, twitter4j.UserList list) {
- }
-
- @Override
- public void onUserListSubscription(twitter4j.User subscriber, twitter4j.User listOwner, twitter4j.UserList list) {
- world.addListSubscription(list.getFullName());
- }
-
- @Override
- public void onUserListUnsubscription(twitter4j.User subscriber, twitter4j.User listOwner, twitter4j.UserList list) {
- world.removeListSubscription(list.getFullName());
- }
-
- @Override
- public void onUserListCreation(twitter4j.User listOwner, twitter4j.UserList list) {
- world.addListSubscription(list.getFullName());
- }
-
- @Override
- public void onUserListUpdate(twitter4j.User listOwner, twitter4j.UserList list) {
- }
-
- @Override
- public void onUserListDeletion(twitter4j.User listOwner, twitter4j.UserList list) {
- world.removeListSubscription(list.getFullName());
- }
-
- @Override
- public void onUserProfileUpdate(twitter4j.User updatedUser) {
- User.fromTwitter(updatedUser);
- }
-
- @Override
- public void onUserSuspension(long suspendedUser) {
- }
-
- @Override
- public void onUserDeletion(long deletedUser) {
- }
-
- @Override
- public void onBlock(twitter4j.User source, twitter4j.User blockedUser) {
- if (User.fromTwitter(blockedUser) == world.getAccount().getUser()) {
- addToHistory(new Event(Event.EnumEvent.BLOCKED, User.fromTwitter(source)));
- }
- }
-
- @Override
- public void onUnblock(twitter4j.User source, twitter4j.User unblockedUser) {
- if (User.fromTwitter(unblockedUser) == world.getAccount().getUser()) {
- addToHistory(new Event(Event.EnumEvent.UNBLOCKED, User.fromTwitter(source)));
- }
- }
-
- @Override
- public void onRetweetedRetweet(twitter4j.User source, twitter4j.User target, twitter4j.Status retweetedStatus) {
- }
-
- @Override
- public void onFavoritedRetweet(twitter4j.User source, twitter4j.User target, twitter4j.Status favoritedRetweeet) {
- }
-
- @Override
- public void onQuotedTweet(twitter4j.User source, twitter4j.User target, twitter4j.Status quotingTweet) {
- }
-
- private void addToHistory(Event mentioned) {
- world.addEvent(mentioned);
- world.notify(mentioned.getFormattedString());
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt
new file mode 100644
index 00000000..80a0c808
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt
@@ -0,0 +1,182 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.twitter
+
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.entity.DirectMessage
+import net.lacolaco.smileessence.entity.Event
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.entity.User
+import net.lacolaco.smileessence.logging.Logger
+import twitter4j.ConnectionLifeCycleListener
+import twitter4j.Status
+import twitter4j.StatusDeletionNotice
+
+class UserStreamListener(private val world: World) : twitter4j.UserStreamListener, ConnectionLifeCycleListener {
+ var isConnected = false
+ private set
+
+ override fun onConnect() {
+ isConnected = true
+ world.notify(R.string.notice_stream_connect)
+ }
+
+ override fun onDisconnect() {
+ isConnected = false
+ world.notify(R.string.notice_stream_disconnect)
+ }
+
+ override fun onCleanUp() {}
+
+ // --------------------- Interface StatusListener ---------------------
+
+ override fun onStatus(status: Status) {
+ val user = world.account.user
+ val tweet = Tweet.fromTwitter(status, user.id)
+ world.addTweet(tweet)
+ if (tweet.isRetweet) {
+ if (tweet.originalTweet.user.id == user.id) {
+ addToHistory(Event(Event.EnumEvent.RETWEETED, tweet.user, tweet))
+ }
+ } else if (tweet.mentions.contains(user.screenName)) {
+ val mentioned = Event(Event.EnumEvent.MENTIONED, tweet.user, tweet)
+ world.notify(mentioned.formattedString)
+ }
+ }
+
+ override fun onDeletionNotice(statusDeletionNotice: StatusDeletionNotice) {
+ // FIXME
+ // StatusFilter.getInstance().remove(StatusViewModel.class, statusDeletionNotice.getStatusId());
+ // Tweet.remove(statusDeletionNotice.getStatusId());
+ }
+
+ override fun onTrackLimitationNotice(numberOfLimitedStatuses: Int) {}
+
+ override fun onScrubGeo(userId: Long, upToStatusId: Long) {}
+
+ override fun onStallWarning(warning: twitter4j.StallWarning) {}
+
+ // --------------------- Interface StreamListener ---------------------
+
+ override fun onException(ex: Exception) {
+ Logger.error(ex.toString())
+ }
+
+ // --------------------- Interface UserStreamListener ---------------------
+
+ override fun onDeletionNotice(directMessageId: Long, userId: Long) {
+ // FIXME
+ // StatusFilter.getInstance().remove(MessageViewModel.class, directMessageId);
+ // DirectMessage.remove(directMessageId);
+ }
+
+ override fun onFriendList(friendIds: LongArray) {}
+
+ override fun onFavorite(source: twitter4j.User, target: twitter4j.User, favoritedStatus: Status) {
+ val tweet = Tweet.fromTwitter(favoritedStatus, world.account.userId)
+ tweet.addFavoriter(source.id)
+ if (User.fromTwitter(target) === world.account.user) {
+ addToHistory(Event(Event.EnumEvent.FAVORITED, User.fromTwitter(source), tweet))
+ }
+ }
+
+ override fun onUnfavorite(source: twitter4j.User, target: twitter4j.User, unfavoritedStatus: twitter4j.Status) {
+ val tweet = Tweet.fromTwitter(unfavoritedStatus, world.account.userId)
+ tweet.removeFavoriter(source.id)
+ if (User.fromTwitter(target) === world.account.user) {
+ addToHistory(Event(Event.EnumEvent.UNFAVORITED, User.fromTwitter(source), tweet))
+ }
+ }
+
+ override fun onFollow(source: twitter4j.User, followedUser: twitter4j.User) {
+ if (User.fromTwitter(followedUser) === world.account.user) {
+ addToHistory(Event(Event.EnumEvent.FOLLOWED, User.fromTwitter(source)))
+ }
+ }
+
+ override fun onUnfollow(source: twitter4j.User, unfollowedUser: twitter4j.User) {}
+
+ override fun onDirectMessage(directMessage: twitter4j.DirectMessage) {
+ val message = DirectMessage.fromTwitter(directMessage)
+ world.addDirectMessage(message)
+ if (message.recipient === world.account.user) {
+ addToHistory(Event(Event.EnumEvent.RECEIVE_MESSAGE, message.sender))
+ }
+ }
+
+ override fun onUserListMemberAddition(addedMember: twitter4j.User, listOwner: twitter4j.User, list: twitter4j.UserList) {}
+
+ override fun onUserListMemberDeletion(deletedMember: twitter4j.User, listOwner: twitter4j.User, list: twitter4j.UserList) {}
+
+ override fun onUserListSubscription(subscriber: twitter4j.User, listOwner: twitter4j.User, list: twitter4j.UserList) {
+ world.addListSubscription(list.fullName)
+ }
+
+ override fun onUserListUnsubscription(subscriber: twitter4j.User, listOwner: twitter4j.User, list: twitter4j.UserList) {
+ world.removeListSubscription(list.fullName)
+ }
+
+ override fun onUserListCreation(listOwner: twitter4j.User, list: twitter4j.UserList) {
+ world.addListSubscription(list.fullName)
+ }
+
+ override fun onUserListUpdate(listOwner: twitter4j.User, list: twitter4j.UserList) {}
+
+ override fun onUserListDeletion(listOwner: twitter4j.User, list: twitter4j.UserList) {
+ world.removeListSubscription(list.fullName)
+ }
+
+ override fun onUserProfileUpdate(updatedUser: twitter4j.User) {
+ User.fromTwitter(updatedUser)
+ }
+
+ override fun onUserSuspension(suspendedUser: Long) {}
+
+ override fun onUserDeletion(deletedUser: Long) {}
+
+ override fun onBlock(source: twitter4j.User, blockedUser: twitter4j.User) {
+ if (User.fromTwitter(blockedUser) === world.account.user) {
+ addToHistory(Event(Event.EnumEvent.BLOCKED, User.fromTwitter(source)))
+ }
+ }
+
+ override fun onUnblock(source: twitter4j.User, unblockedUser: twitter4j.User) {
+ if (User.fromTwitter(unblockedUser) === world.account.user) {
+ addToHistory(Event(Event.EnumEvent.UNBLOCKED, User.fromTwitter(source)))
+ }
+ }
+
+ override fun onRetweetedRetweet(source: twitter4j.User, target: twitter4j.User, retweetedStatus: twitter4j.Status) {}
+
+ override fun onFavoritedRetweet(source: twitter4j.User, target: twitter4j.User, favoritedRetweeet: twitter4j.Status) {}
+
+ override fun onQuotedTweet(source: twitter4j.User, target: twitter4j.User, quotingTweet: twitter4j.Status) {}
+
+ private fun addToHistory(mentioned: Event) {
+ world.addEvent(mentioned)
+ world.notify(mentioned.formattedString)
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.java
deleted file mode 100644
index 7842e349..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package net.lacolaco.smileessence.twitter.task;
-
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.util.BackgroundTask;
-import twitter4j.IDs;
-import twitter4j.Twitter;
-import twitter4j.TwitterException;
-import twitter4j.auth.AccessToken;
-import twitter4j.auth.RequestToken;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Accounts {
- public static class AccessTokenTask extends BackgroundTask<AccessToken, Void> {
- private final Twitter twitter;
- private final RequestToken requestToken;
- private final String pinCode;
-
- public AccessTokenTask(Twitter twitter, RequestToken requestToken, String pinCode) {
- this.twitter = twitter;
- this.requestToken = requestToken;
- this.pinCode = pinCode;
- }
-
- @Override
- protected AccessToken doInBackground() throws TwitterException {
- return twitter.getOAuthAccessToken(requestToken, pinCode);
- }
- }
-
- public static class RequestTokenTask extends BackgroundTask<RequestToken, Void> {
- private final Twitter twitter;
-
- public RequestTokenTask(Twitter twitter) {
- this.twitter = twitter;
- }
-
- @Override
- protected RequestToken doInBackground() throws TwitterException {
- return twitter.getOAuthRequestToken("oob");
- }
- }
-
- public static class BlockIDsTask extends BackgroundTask<List<Long>, Void> {
- private final Account account;
-
- public BlockIDsTask(Account account) {
- this.account = account;
- }
-
- @Override
- protected List<Long> doInBackground() throws TwitterException {
- List<Long> idList = new ArrayList<>();
- long cursor = -1;
-
- while (cursor != 0) {
- IDs blocksIDs = account.getTwitter().getBlocksIDs(cursor);
- cursor = blocksIDs.getNextCursor();
- for (long id : blocksIDs.getIDs()) {
- idList.add(id);
- }
- }
-
- return idList;
- }
- }
-
- public static class MutesIDsTask extends BackgroundTask<List<Long>, Void> {
- private final Account account;
-
- public MutesIDsTask(Account account) {
- this.account = account;
- }
-
- @Override
- protected List<Long> doInBackground() throws TwitterException {
- List<Long> idList = new ArrayList<>();
- long cursor = -1;
- while (cursor != 0) {
- IDs mutesIDs = account.getTwitter().getMutesIDs(cursor);
- cursor = mutesIDs.getNextCursor();
- for (long id : mutesIDs.getIDs()) {
- idList.add(id);
- }
- }
- return idList;
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.kt
new file mode 100644
index 00000000..22a90374
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.kt
@@ -0,0 +1,65 @@
+package net.lacolaco.smileessence.twitter.task
+
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.util.BackgroundTask
+import twitter4j.IDs
+import twitter4j.Twitter
+import twitter4j.TwitterException
+import twitter4j.auth.AccessToken
+import twitter4j.auth.RequestToken
+
+import java.util.ArrayList
+
+class Accounts {
+ class AccessTokenTask(private val twitter: Twitter, private val requestToken: RequestToken, private val pinCode: String) : BackgroundTask<AccessToken, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): AccessToken {
+ return twitter.getOAuthAccessToken(requestToken, pinCode)
+ }
+ }
+
+ class RequestTokenTask(private val twitter: Twitter) : BackgroundTask<RequestToken, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): RequestToken {
+ return twitter.getOAuthRequestToken("oob")
+ }
+ }
+
+ class BlockIDsTask(private val account: Account) : BackgroundTask<List<Long>, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<Long> {
+ val idList = ArrayList<Long>()
+ var cursor: Long = -1
+
+ while (cursor != 0L) {
+ val blocksIDs = account.twitter.getBlocksIDs(cursor)
+ cursor = blocksIDs.nextCursor
+ for (id in blocksIDs.iDs) {
+ idList.add(id)
+ }
+ }
+
+ return idList
+ }
+ }
+
+ class MutesIDsTask(private val account: Account) : BackgroundTask<List<Long>, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<Long> {
+ val idList = ArrayList<Long>()
+ var cursor: Long = -1
+ while (cursor != 0L) {
+ val mutesIDs = account.twitter.getMutesIDs(cursor)
+ cursor = mutesIDs.nextCursor
+ for (id in mutesIDs.iDs) {
+ idList.add(id)
+ }
+ }
+ return idList
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.java
deleted file mode 100644
index ff13a07c..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package net.lacolaco.smileessence.twitter.task;
-
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.entity.DirectMessage;
-import net.lacolaco.smileessence.util.BackgroundTask;
-import twitter4j.TwitterException;
-
-import java.util.List;
-
-public class Messages {
- public static class CreateTask extends BackgroundTask<DirectMessage, Void> {
- private final Account account;
- private final long userID;
- private final String text;
-
- public CreateTask(Account account, long userID, String text) {
- this.account = account;
- this.userID = userID;
- this.text = text;
- }
-
- @Override
- protected DirectMessage doInBackground() throws TwitterException {
- return DirectMessage.fromTwitter(account.getTwitter().directMessages().sendDirectMessage(userID, text));
- }
- }
-
- public static class DestroyTask extends BackgroundTask<DirectMessage, Void> {
- private final Account account;
- private final long messageID;
-
- public DestroyTask(Account account, long messageID) {
- this.account = account;
- this.messageID = messageID;
- }
-
- @Override
- protected DirectMessage doInBackground() throws TwitterException {
- return DirectMessage.fromTwitter(account.getTwitter().directMessages().destroyDirectMessage(messageID));
- }
- }
-
- public static class GetAllReceived extends TimelineTask<DirectMessage> {
- private final Account account;
-
- public GetAllReceived(Account account) {
- this.account = account;
- }
-
- @Override
- protected List<DirectMessage> doInBackground() throws TwitterException {
- return DirectMessage.fromTwitter(account.getTwitter().directMessages().getDirectMessages(getPaging()));
- }
- }
-
- public static class GetAllSent extends TimelineTask<DirectMessage> {
- private final Account account;
-
- public GetAllSent(Account account) {
- this.account = account;
- }
-
- @Override
- protected List<DirectMessage> doInBackground() throws TwitterException {
- return DirectMessage.fromTwitter(account.getTwitter().directMessages().getSentDirectMessages(getPaging()));
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.kt
new file mode 100644
index 00000000..b5553c32
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.kt
@@ -0,0 +1,40 @@
+package net.lacolaco.smileessence.twitter.task
+
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.entity.DirectMessage
+import net.lacolaco.smileessence.util.BackgroundTask
+import twitter4j.TwitterException
+
+class Messages {
+ class CreateTask(private val account: Account, private val userID: Long, private val text: String) : BackgroundTask<DirectMessage, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): DirectMessage {
+ return DirectMessage.fromTwitter(account.twitter.directMessages().sendDirectMessage(userID, text))
+ }
+ }
+
+ class DestroyTask(private val account: Account, private val messageID: Long) : BackgroundTask<DirectMessage, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): DirectMessage {
+ return DirectMessage.fromTwitter(account.twitter.directMessages().destroyDirectMessage(messageID))
+ }
+ }
+
+ class GetAllReceived(private val account: Account) : TimelineTask<DirectMessage>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<DirectMessage> {
+ return DirectMessage.fromTwitter(account.twitter.directMessages().getDirectMessages(paging))
+ }
+ }
+
+ class GetAllSent(private val account: Account) : TimelineTask<DirectMessage>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<DirectMessage> {
+ return DirectMessage.fromTwitter(account.twitter.directMessages().getSentDirectMessages(paging))
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.java
deleted file mode 100644
index 91f6fbcc..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package net.lacolaco.smileessence.twitter.task;
-
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.entity.SavedSearch;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.util.BackgroundTask;
-import net.lacolaco.smileessence.util.ListUtils;
-import twitter4j.Query;
-import twitter4j.TwitterException;
-
-import java.util.List;
-
-public class Searches {
- public static class CreateSavedSearchTask extends BackgroundTask<SavedSearch, Void> {
- private final Account account;
- private final String query;
-
- public CreateSavedSearchTask(Account account, String query) {
- this.account = account;
- this.query = query;
- }
-
- @Override
- protected SavedSearch doInBackground() throws Exception {
- return SavedSearch.fromTwitter(account.getTwitter().savedSearches().createSavedSearch(query));
- }
- }
-
- public static class DestroySavedSearchTask extends BackgroundTask<Void, Void> {
- private final Account account;
- private final long id;
-
- public DestroySavedSearchTask(Account account, long id) {
- this.account = account;
- this.id = id;
- }
-
- @Override
- protected Void doInBackground() throws Exception {
- account.getTwitter().savedSearches().destroySavedSearch(id);
- return null;
- }
- }
-
- public static class GetAllSavedSearchesTask extends BackgroundTask<List<SavedSearch>, Void> {
- private final Account account;
-
- public GetAllSavedSearchesTask(Account account) {
- this.account = account;
- }
-
- @Override
- protected List<SavedSearch> doInBackground() throws Exception {
- return ListUtils.map(account.getTwitter().savedSearches().getSavedSearches(), SavedSearch::fromTwitter);
- }
- }
-
- // TODO: List<Tweet> is not good here
- public static class SearchTask extends BackgroundTask<List<Tweet>, Void> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final Account account;
- private final Query query;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public SearchTask(Account account, Query query) {
- this.account = account;
- this.query = query;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected List<Tweet> doInBackground() throws TwitterException {
- return Tweet.fromTwitter(account.getTwitter().search(query).getTweets(), account.getUserId());
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.kt
new file mode 100644
index 00000000..9ea1792b
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.kt
@@ -0,0 +1,51 @@
+package net.lacolaco.smileessence.twitter.task
+
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.entity.SavedSearch
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.util.BackgroundTask
+import twitter4j.Query
+import twitter4j.TwitterException
+
+class Searches {
+ class CreateSavedSearchTask(private val account: Account, private val query: String) : BackgroundTask<SavedSearch, Void>() {
+
+ @Throws(Exception::class)
+ override fun doInBackground(): SavedSearch {
+ return SavedSearch.fromTwitter(account.twitter.savedSearches().createSavedSearch(query))
+ }
+ }
+
+ class DestroySavedSearchTask(private val account: Account, private val id: Long) : BackgroundTask<Unit, Void>() {
+
+ @Throws(Exception::class)
+ override fun doInBackground() {
+ account.twitter.savedSearches().destroySavedSearch(id)
+ }
+ }
+
+ class GetAllSavedSearchesTask(private val account: Account) : BackgroundTask<List<SavedSearch>, Void>() {
+
+ @Throws(Exception::class)
+ override fun doInBackground(): List<SavedSearch> {
+ return account.twitter.savedSearches().savedSearches.map { SavedSearch.fromTwitter(it)}
+ }
+ }
+
+ // TODO: List<Tweet> is not good here
+ class SearchTask
+ // --------------------------- CONSTRUCTORS ---------------------------
+
+ (
+ // ------------------------------ FIELDS ------------------------------
+
+ private val account: Account, private val query: Query) : BackgroundTask<List<Tweet>, Void>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<Tweet> {
+ return Tweet.fromTwitter(account.twitter.search(query).tweets, account.userId)
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/TimelineTask.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/TimelineTask.kt
index 1025d3e9..d6b2c054 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/TimelineTask.java
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/TimelineTask.kt
@@ -22,36 +22,30 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.twitter.task;
+package net.lacolaco.smileessence.twitter.task
-import net.lacolaco.smileessence.util.BackgroundTask;
-import twitter4j.Paging;
+import net.lacolaco.smileessence.util.BackgroundTask
+import twitter4j.Paging
-import java.util.List;
+abstract class TimelineTask<T> : BackgroundTask<List<T>, Void>() {
+ protected val paging = Paging()
-public abstract class TimelineTask<T> extends BackgroundTask<List<T>, Void> {
- private Paging paging = new Paging();
-
- public TimelineTask<T> setCount(int count) {
- paging.setCount(count);
- return this;
+ fun setCount(count: Int): TimelineTask<T> {
+ paging.count = count
+ return this
}
- public TimelineTask<T> setMaxId(long maxId) {
+ fun setMaxId(maxId: Long): TimelineTask<T> {
if (maxId > 0) {
- paging.setMaxId(maxId);
+ paging.maxId = maxId
}
- return this;
+ return this
}
- public TimelineTask<T> setSinceId(long sinceId) {
+ fun setSinceId(sinceId: Long): TimelineTask<T> {
if (sinceId > 0) {
- paging.setSinceId(sinceId);
+ paging.sinceId = sinceId
}
- return this;
- }
-
- protected Paging getPaging() {
- return paging;
+ return this
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.java
deleted file mode 100644
index ae1aa0ea..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package net.lacolaco.smileessence.twitter.task;
-
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.entity.Tweet;
-import twitter4j.TwitterException;
-
-import java.util.List;
-
-public class Timelines {
- public static class HomeTimelineTask extends TimelineTask<Tweet> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final Account account;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public HomeTimelineTask(Account account) {
- this.account = account;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected List<Tweet> doInBackground() throws TwitterException {
- return Tweet.fromTwitter(account.getTwitter().timelines().getHomeTimeline(getPaging()), account.getUserId());
- }
- }
-
- public static class MentionsTimelineTask extends TimelineTask<Tweet> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final Account account;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public MentionsTimelineTask(Account account) {
- this.account = account;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected List<Tweet> doInBackground() throws TwitterException {
- return Tweet.fromTwitter(account.getTwitter().timelines().getMentionsTimeline(getPaging()), account.getUserId());
- }
- }
-
- public static class UserTimelineTask extends TimelineTask<Tweet> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final long userID;
- private final Account account;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public UserTimelineTask(Account account, long userID) {
- this.account = account;
- this.userID = userID;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected List<Tweet> doInBackground() throws TwitterException {
- return Tweet.fromTwitter(account.getTwitter().timelines().getUserTimeline(userID, getPaging()), account.getUserId());
- }
- }
-
- public static class UserListStatusesTask extends TimelineTask<Tweet> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final Account account;
- private final String listFullName;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public UserListStatusesTask(Account account, String listFullName) {
- this.account = account;
- this.listFullName = listFullName;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected List<Tweet> doInBackground() throws TwitterException {
- String[] strings = listFullName.split("/");
- return Tweet.fromTwitter(account.getTwitter().list().getUserListStatuses(strings[0], strings[1], getPaging()), account.getUserId());
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.kt
new file mode 100644
index 00000000..6893319c
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.kt
@@ -0,0 +1,72 @@
+package net.lacolaco.smileessence.twitter.task
+
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.entity.Tweet
+import twitter4j.TwitterException
+
+class Timelines {
+ class HomeTimelineTask
+ // --------------------------- CONSTRUCTORS ---------------------------
+
+ (
+ // ------------------------------ FIELDS ------------------------------
+
+ private val account: Account) : TimelineTask<Tweet>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<Tweet> {
+ return Tweet.fromTwitter(account.twitter.timelines().getHomeTimeline(paging), account.userId)
+ }
+ }
+
+ class MentionsTimelineTask
+ // --------------------------- CONSTRUCTORS ---------------------------
+
+ (
+ // ------------------------------ FIELDS ------------------------------
+
+ private val account: Account) : TimelineTask<Tweet>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<Tweet> {
+ return Tweet.fromTwitter(account.twitter.timelines().getMentionsTimeline(paging), account.userId)
+ }
+ }
+
+ class UserTimelineTask
+ // --------------------------- CONSTRUCTORS ---------------------------
+
+ (private val account: Account,
+ // ------------------------------ FIELDS ------------------------------
+
+ private val userID: Long) : TimelineTask<Tweet>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<Tweet> {
+ return Tweet.fromTwitter(account.twitter.timelines().getUserTimeline(userID, paging), account.userId)
+ }
+ }
+
+ class UserListStatusesTask
+ // --------------------------- CONSTRUCTORS ---------------------------
+
+ (
+ // ------------------------------ FIELDS ------------------------------
+
+ private val account: Account, private val listFullName: String) : TimelineTask<Tweet>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<Tweet> {
+ val strings = listFullName.split("/".toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()
+ return Tweet.fromTwitter(account.twitter.list().getUserListStatuses(strings[0], strings[1], paging), account.userId)
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.java
deleted file mode 100644
index f201492e..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package net.lacolaco.smileessence.twitter.task;
-
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.util.BackgroundTask;
-import twitter4j.TwitterException;
-
-public class TweetReactions {
- public static class RetweetTask extends BackgroundTask<Tweet, Void> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final Account account;
- private final long statusID;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public RetweetTask(Account account, long statusID) {
- this.account = account;
- this.statusID = statusID;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected Tweet doInBackground() throws TwitterException {
- return Tweet.fromTwitter(account.getTwitter().tweets().retweetStatus(statusID), account.getUserId());
- }
- }
-
- public static class FavoriteTask extends BackgroundTask<Tweet, Void> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final Account account;
- private final long statusID;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public FavoriteTask(Account account, long statusID) {
- this.account = account;
- this.statusID = statusID;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected Tweet doInBackground() throws TwitterException {
- return Tweet.fromTwitter(account.getTwitter().favorites().createFavorite(statusID), account.getUserId());
- }
- }
-
- public static class UnfavoriteTask extends BackgroundTask<Tweet, Void> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final Account account;
- private final long statusID;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public UnfavoriteTask(Account account, long statusID) {
- this.account = account;
- this.statusID = statusID;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected Tweet doInBackground() throws TwitterException {
- return Tweet.fromTwitter(account.getTwitter().favorites().destroyFavorite(statusID), account.getUserId());
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.kt
new file mode 100644
index 00000000..bffcd832
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.kt
@@ -0,0 +1,56 @@
+package net.lacolaco.smileessence.twitter.task
+
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.util.BackgroundTask
+import twitter4j.TwitterException
+
+class TweetReactions {
+ class RetweetTask
+ // --------------------------- CONSTRUCTORS ---------------------------
+
+ (
+ // ------------------------------ FIELDS ------------------------------
+
+ private val account: Account, private val statusID: Long) : BackgroundTask<Tweet, Void>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): Tweet {
+ return Tweet.fromTwitter(account.twitter.tweets().retweetStatus(statusID), account.userId)
+ }
+ }
+
+ class FavoriteTask
+ // --------------------------- CONSTRUCTORS ---------------------------
+
+ (
+ // ------------------------------ FIELDS ------------------------------
+
+ private val account: Account, private val statusID: Long) : BackgroundTask<Tweet, Void>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): Tweet {
+ return Tweet.fromTwitter(account.twitter.favorites().createFavorite(statusID), account.userId)
+ }
+ }
+
+ class UnfavoriteTask
+ // --------------------------- CONSTRUCTORS ---------------------------
+
+ (
+ // ------------------------------ FIELDS ------------------------------
+
+ private val account: Account, private val statusID: Long) : BackgroundTask<Tweet, Void>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): Tweet {
+ return Tweet.fromTwitter(account.twitter.favorites().destroyFavorite(statusID), account.userId)
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.java
deleted file mode 100644
index dcad94dc..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package net.lacolaco.smileessence.twitter.task;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Environment;
-import android.text.TextUtils;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.util.BackgroundTask;
-import twitter4j.StatusUpdate;
-import twitter4j.TwitterException;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-public class Tweets {
- public static class GetTask extends BackgroundTask<Tweet, Void> {
- private final Account account;
- private final long id;
-
- public GetTask(Account account, long id) {
- this.account = account;
- this.id = id;
- }
-
- @Override
- protected Tweet doInBackground() throws TwitterException {
- return Tweet.fromTwitter(account.getTwitter().tweets().showStatus(id), account.getUserId());
- }
- }
-
- public static class CreateTask extends BackgroundTask<Tweet, Void> {
- private static final int MEDIA_SIZE_LIMIT = 5 * 1024 * 1024;
- private final Account account;
- private final StatusUpdate update;
- private final String mediaPath;
- private String tempFilePath;
- private boolean resizeFlag;
-
- public CreateTask(Account account, StatusUpdate update, String mediaPath, boolean resize) {
- this.account = account;
- this.update = update;
- this.mediaPath = mediaPath;
- resizeFlag = resize;
- }
-
- private File getMediaFile() {
- File file = new File(mediaPath);
- if (file.length() >= MEDIA_SIZE_LIMIT && resizeFlag) {
- BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inJustDecodeBounds = true; //decoder is not return bitmap but set option
- BitmapFactory.decodeFile(mediaPath, opt);
- tempFilePath = Environment.getExternalStorageDirectory() + "/temp.jpg";
- File compressedFile = new File(tempFilePath);
- FileOutputStream fos = null;
- try {
- fos = new FileOutputStream(compressedFile);
- float ratio = (float) file.length() / (float) MEDIA_SIZE_LIMIT;
- BitmapFactory.Options resizeOpt = new BitmapFactory.Options();
- resizeOpt.inPurgeable = true;
- resizeOpt.inSampleSize = (int) Math.ceil(ratio);
- Bitmap bitmap = BitmapFactory.decodeFile(mediaPath, resizeOpt);
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
- bitmap.recycle();
- return compressedFile;
- } catch (Exception e) {
- e.printStackTrace();
- Logger.error(e);
- } finally {
- try {
- if (fos != null) fos.close();
- } catch (IOException e) {
- e.printStackTrace();
- Logger.error(e);
- }
- }
- }
- return file;
- }
-
- @Override
- protected Tweet doInBackground() throws TwitterException {
- try {
- if (!TextUtils.isEmpty(mediaPath)) {
- File mediaFile = getMediaFile();
- if (mediaFile.exists()) {
- update.setMedia(mediaFile);
- }
- }
- return Tweet.fromTwitter(account.getTwitter().tweets().updateStatus(update), account.getUserId());
- } finally {
- if (tempFilePath != null) {
- new File(tempFilePath).delete();
- }
- }
- }
- }
-
- public static class DestroyTask extends BackgroundTask<Tweet, Void> {
- private final Account account;
- private final long statusID;
-
- public DestroyTask(Account account, long statusID) {
- this.account = account;
- this.statusID = statusID;
- }
-
- @Override
- protected Tweet doInBackground() throws TwitterException {
- Tweet t = Tweet.fromTwitter(account.getTwitter().tweets().destroyStatus(statusID), account.getUserId());
- // FIXME: Tweet.remove(t.getId());
- return t;
- }
- }
-
- public static class GetTalkTask extends BackgroundTask<List<Tweet>, Tweet> {
- private final Account account;
- private final long statusId;
-
- public GetTalkTask(Account account, long statusId) {
- this.account = account;
- this.statusId = statusId;
- }
-
- @Override
- protected List<Tweet> doInBackground() {
- ArrayList<Tweet> list = new ArrayList<>();
- long id = statusId;
- while (id != -1) {
- Tweet tweet = Tweet.fetch(id);
- if (tweet == null) {
- try {
- tweet = Tweet.fromTwitter(account.getTwitter().showStatus(id), account.getUserId());
- } catch (TwitterException ignored) {
- }
- }
-
- if (tweet == null) {
- break;
- } else {
- list.add(tweet);
- progress(tweet);
- id = tweet.getInReplyToStatusId();
- }
- }
- return list;
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.kt
new file mode 100644
index 00000000..1af42d20
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.kt
@@ -0,0 +1,125 @@
+package net.lacolaco.smileessence.twitter.task
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.os.Environment
+import android.text.TextUtils
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.util.BackgroundTask
+import twitter4j.StatusUpdate
+import twitter4j.TwitterException
+
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.util.ArrayList
+
+class Tweets {
+ class GetTask(private val account: Account, private val id: Long) : BackgroundTask<Tweet, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): Tweet {
+ return Tweet.fromTwitter(account.twitter.tweets().showStatus(id), account.userId)
+ }
+ }
+
+ class CreateTask(private val account: Account, private val update: StatusUpdate, private val mediaPath: String, private val resizeFlag: Boolean) : BackgroundTask<Tweet, Void>() {
+ private var tempFilePath: String? = null
+
+ private //decoder is not return bitmap but set option
+ val mediaFile: File
+ get() {
+ val file = File(mediaPath)
+ if (file.length() >= MEDIA_SIZE_LIMIT && resizeFlag) {
+ val opt = BitmapFactory.Options()
+ opt.inJustDecodeBounds = true
+ BitmapFactory.decodeFile(mediaPath, opt)
+ tempFilePath = Environment.getExternalStorageDirectory().toString() + "/temp.jpg"
+ val compressedFile = File(tempFilePath)
+ var fos: FileOutputStream? = null
+ try {
+ fos = FileOutputStream(compressedFile)
+ val ratio = file.length().toFloat() / MEDIA_SIZE_LIMIT.toFloat()
+ val resizeOpt = BitmapFactory.Options()
+ resizeOpt.inPurgeable = true
+ resizeOpt.inSampleSize = Math.ceil(ratio.toDouble()).toInt()
+ val bitmap = BitmapFactory.decodeFile(mediaPath, resizeOpt)
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
+ bitmap.recycle()
+ return compressedFile
+ } catch (e: Exception) {
+ e.printStackTrace()
+ Logger.error(e)
+ } finally {
+ try {
+ if (fos != null) fos.close()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ Logger.error(e)
+ }
+
+ }
+ }
+ return file
+ }
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): Tweet {
+ try {
+ if (!TextUtils.isEmpty(mediaPath)) {
+ val mediaFile = mediaFile
+ if (mediaFile.exists()) {
+ update.setMedia(mediaFile)
+ }
+ }
+ return Tweet.fromTwitter(account.twitter.tweets().updateStatus(update), account.userId)
+ } finally {
+ if (tempFilePath != null) {
+ File(tempFilePath).delete()
+ }
+ }
+ }
+
+ companion object {
+ private val MEDIA_SIZE_LIMIT = 5 * 1024 * 1024
+ }
+ }
+
+ class DestroyTask(private val account: Account, private val statusID: Long) : BackgroundTask<Tweet, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): Tweet {
+// FIXME: Tweet.remove(t.getId());
+ return Tweet.fromTwitter(account.twitter.tweets().destroyStatus(statusID), account.userId)
+ }
+ }
+
+ class GetTalkTask(private val account: Account, private val statusId: Long) : BackgroundTask<List<Tweet>, Tweet>() {
+
+ override fun doInBackground(): List<Tweet> {
+ val list = ArrayList<Tweet>()
+ var id = statusId
+ while (id != -1L) {
+ var tweet = Tweet.fetch(id)
+ if (tweet == null) {
+ try {
+ tweet = Tweet.fromTwitter(account.twitter.showStatus(id), account.userId)
+ } catch (ignored: TwitterException) {
+ }
+
+ }
+
+ if (tweet == null) {
+ break
+ } else {
+ list.add(tweet)
+ progress(tweet)
+ id = tweet.inReplyToStatusId
+ }
+ }
+ return list
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.java b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.java
deleted file mode 100644
index 60b62841..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package net.lacolaco.smileessence.twitter.task;
-
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.entity.User;
-import net.lacolaco.smileessence.util.BackgroundTask;
-import net.lacolaco.smileessence.util.ListUtils;
-import twitter4j.Relationship;
-import twitter4j.TwitterException;
-import twitter4j.UserList;
-
-import java.util.List;
-
-public class Users {
- public static class GetTask extends BackgroundTask<User, Void> {
- private final Account account;
- private final long userID;
- private final String screenName;
-
- public GetTask(Account account, long userID) {
- this.account = account;
- this.userID = userID;
- this.screenName = null;
- }
-
- public GetTask(Account account, String screenName) {
- this.account = account;
- this.screenName = screenName;
- this.userID = -1;
- }
-
- @Override
- protected User doInBackground() throws TwitterException {
- if (screenName != null) {
- return User.fromTwitter(account.getTwitter().users().showUser(screenName));
- } else {
- return User.fromTwitter(account.getTwitter().users().showUser(userID));
- }
- }
- }
-
- public static class GetManyTask extends BackgroundTask<List<String>, Void> {
- private final Account account;
-
- public GetManyTask(Account account) {
- this.account = account;
- }
-
- @Override
- protected List<String> doInBackground() throws TwitterException {
- return ListUtils.map(account.getTwitter().list().getUserLists(account.getUserId()), UserList::getFullName);
- }
- }
-
- public static class FollowTask extends BackgroundTask<User, Void> {
- private final Account account;
- private final long userID;
-
- public FollowTask(Account account, long userID) {
- this.account = account;
- this.userID = userID;
- }
-
- @Override
- protected User doInBackground() throws TwitterException {
- return User.fromTwitter(account.getTwitter().friendsFollowers().createFriendship(userID));
- }
- }
-
- public static class UnfollowTask extends BackgroundTask<User, Void> {
- private final Account account;
- private final long userID;
-
- public UnfollowTask(Account account, long userID) {
- this.account = account;
- this.userID = userID;
- }
-
- @Override
- protected User doInBackground() throws TwitterException {
- return User.fromTwitter(account.getTwitter().friendsFollowers().destroyFriendship(userID));
- }
- }
-
- public static class BlockTask extends BackgroundTask<User, Void> {
- private final Account account;
- private final long userID;
-
- public BlockTask(Account account, long userID) {
- this.account = account;
- this.userID = userID;
- }
-
- @Override
- protected User doInBackground() throws TwitterException {
- return User.fromTwitter(account.getTwitter().users().createBlock(userID));
- }
- }
-
- public static class ReportForSpamTask extends BackgroundTask<User, Void> {
- private final Account account;
- private final long userID;
-
- public ReportForSpamTask(Account account, long userID) {
- this.account = account;
- this.userID = userID;
- }
-
- @Override
- protected User doInBackground() throws TwitterException {
- return User.fromTwitter(account.getTwitter().spamReporting().reportSpam(userID));
- }
- }
-
- public static class UnblockTask extends BackgroundTask<User, Void> {
- private final Account account;
- private final long userID;
-
- public UnblockTask(Account account, long userID) {
- this.account = account;
- this.userID = userID;
- }
-
- @Override
- protected User doInBackground() throws TwitterException {
- return User.fromTwitter(account.getTwitter().users().destroyBlock(userID));
- }
- }
-
- public static class ShowFriendshipTask extends BackgroundTask<Relationship, Void> {
- private final Account account;
- private final long userID;
-
- public ShowFriendshipTask(Account account, long userID) {
- this.account = account;
- this.userID = userID;
- }
-
- @Override
- protected Relationship doInBackground() throws TwitterException {
- return account.getTwitter().friendsFollowers().showFriendship(account.getTwitter().getId(), userID);
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.kt
new file mode 100644
index 00000000..c435b560
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.kt
@@ -0,0 +1,92 @@
+package net.lacolaco.smileessence.twitter.task
+
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.entity.User
+import net.lacolaco.smileessence.util.BackgroundTask
+import twitter4j.Relationship
+import twitter4j.TwitterException
+
+class Users {
+ class GetTask : BackgroundTask<User, Void> {
+ private val account: Account
+ private val userID: Long
+ private val screenName: String?
+
+ constructor(account: Account, userID: Long) {
+ this.account = account
+ this.userID = userID
+ this.screenName = null
+ }
+
+ constructor(account: Account, screenName: String) {
+ this.account = account
+ this.screenName = screenName
+ this.userID = -1
+ }
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): User {
+ return if (screenName != null) {
+ User.fromTwitter(account.twitter.users().showUser(screenName))
+ } else {
+ User.fromTwitter(account.twitter.users().showUser(userID))
+ }
+ }
+ }
+
+ class GetManyTask(private val account: Account) : BackgroundTask<List<String>, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): List<String> {
+ return account.twitter.list().getUserLists(account.userId).map { it.fullName }
+ }
+ }
+
+ class FollowTask(private val account: Account, private val userID: Long) : BackgroundTask<User, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): User {
+ return User.fromTwitter(account.twitter.friendsFollowers().createFriendship(userID))
+ }
+ }
+
+ class UnfollowTask(private val account: Account, private val userID: Long) : BackgroundTask<User, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): User {
+ return User.fromTwitter(account.twitter.friendsFollowers().destroyFriendship(userID))
+ }
+ }
+
+ class BlockTask(private val account: Account, private val userID: Long) : BackgroundTask<User, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): User {
+ return User.fromTwitter(account.twitter.users().createBlock(userID))
+ }
+ }
+
+ class ReportForSpamTask(private val account: Account, private val userID: Long) : BackgroundTask<User, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): User {
+ return User.fromTwitter(account.twitter.spamReporting().reportSpam(userID))
+ }
+ }
+
+ class UnblockTask(private val account: Account, private val userID: Long) : BackgroundTask<User, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): User {
+ return User.fromTwitter(account.twitter.users().destroyBlock(userID))
+ }
+ }
+
+ class ShowFriendshipTask(private val account: Account, private val userID: Long) : BackgroundTask<Relationship, Void>() {
+
+ @Throws(TwitterException::class)
+ override fun doInBackground(): Relationship {
+ return account.twitter.friendsFollowers().showFriendship(account.twitter.id, userID)
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.java b/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.java
deleted file mode 100644
index b6d985e2..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package net.lacolaco.smileessence.util;
-
-import android.os.AsyncTask;
-import net.lacolaco.smileessence.logging.Logger;
-
-public abstract class BackgroundTask<Result, Progress> {
- private final InnerAsyncTask task;
- private Consumer<Result> then;
- private Consumer<Progress> progress;
- private Consumer<Exception> fail;
- private Runnable finish;
- private Exception exception;
-
- public BackgroundTask() {
- this.task = new InnerAsyncTask();
- }
-
- public BackgroundTask<Result, Progress> onDone(Consumer<Result> cb) {
- this.then = cb;
- return this;
- }
-
- public BackgroundTask<Result, Progress> onProgress(Consumer<Progress> cb) {
- this.progress = cb;
- return this;
- }
-
- public BackgroundTask<Result, Progress> onFail(Consumer<Exception> cb) {
- this.fail = cb;
- return this;
- }
-
- public BackgroundTask<Result, Progress> onFinish(Runnable cb) {
- this.finish = cb;
- return this;
- }
-
- public BackgroundTask<Result, Progress> onDoneUI(Consumer<Result> cb) {
- return onDone(r -> new UIHandler().post(() -> cb.accept(r)));
- }
-
- public BackgroundTask<Result, Progress> onProgressUI(Consumer<Progress> cb) {
- return onProgress(p -> new UIHandler().post(() -> cb.accept(p)));
- }
-
- public BackgroundTask<Result, Progress> onFailUI(Consumer<Exception> cb) {
- return onFail(e -> new UIHandler().post(() -> cb.accept(e)));
- }
-
- public BackgroundTask<Result, Progress> onFinishUI(Runnable cb) {
- return onFinish(() -> new UIHandler().post(cb));
- }
-
- public boolean cancel() {
- return task.cancel(true);
- }
-
- public final BackgroundTask<Result, Progress> execute() {
- task.execute();
- return this;
- }
-
- public final Result getImmediately() throws Exception {
- Result result = task.get();
- if (exception == null) {
- return result;
- } else {
- throw exception;
- }
- }
-
- protected void fail(Exception ex) {
- exception = ex;
- ex.printStackTrace();
- Logger.error(ex);
-
- if (!task.isCancelled() && fail != null) {
- fail.accept(ex);
- }
- }
-
- protected void progress(Progress value) {
- if (!task.isCancelled() && exception == null && progress != null) {
- progress.accept(value);
- }
- }
-
- protected abstract Result doInBackground() throws Exception;
-
- private class InnerAsyncTask extends AsyncTask<Void, Progress, Result> {
- @Override
- protected final void onPostExecute(Result result) {
- if (!isCancelled() && exception == null && then != null) {
- then.accept(result);
- }
- if (finish != null) {
- finish.run();
- }
- }
-
- @Override
- protected Result doInBackground(Void... params) {
- try {
- return BackgroundTask.this.doInBackground();
- } catch (Exception ex) {
- fail(ex);
- return null;
- }
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.kt b/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.kt
new file mode 100644
index 00000000..7b9e188a
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/util/BackgroundTask.kt
@@ -0,0 +1,113 @@
+package net.lacolaco.smileessence.util
+
+import android.os.AsyncTask
+import net.lacolaco.smileessence.logging.Logger
+
+abstract class BackgroundTask<Result, Progress> {
+ private val task: InnerAsyncTask
+ private var cbThen: ((Result) -> Unit)? = null
+ private var cbProgress: ((Progress) -> Unit)? = null
+ private var cbFail: ((Exception) -> Unit)? = null
+ private var cbFinish: (() -> Unit)? = null
+ private var exception: Exception? = null
+
+ init {
+ this.task = InnerAsyncTask()
+ }
+
+ fun onDone(cb: (Result) -> Unit): BackgroundTask<Result, Progress> {
+ this.cbThen = cb
+ return this
+ }
+
+ fun onProgress(cb: (Progress) -> Unit): BackgroundTask<Result, Progress> {
+ this.cbProgress = cb
+ return this
+ }
+
+ fun onFail(cb: (Exception) -> Unit): BackgroundTask<Result, Progress> {
+ this.cbFail = cb
+ return this
+ }
+
+ fun onFinish(cb: () -> Unit): BackgroundTask<Result, Progress> {
+ this.cbFinish = cb
+ return this
+ }
+
+ fun onDoneUI(cb: (Result) -> Unit): BackgroundTask<Result, Progress> {
+ return onDone({ r -> UIHandler().post { cb(r) } })
+ }
+
+ fun onProgressUI(cb: (Progress) -> Unit): BackgroundTask<Result, Progress> {
+ return onProgress({ p -> UIHandler().post { cb(p) } })
+ }
+
+ fun onFailUI(cb: (Exception) -> Unit): BackgroundTask<Result, Progress> {
+ return onFail({ e -> UIHandler().post { cb(e) } })
+ }
+
+ fun onFinishUI(cb: () -> Unit): BackgroundTask<Result, Progress> {
+ return onFinish({ UIHandler().post(cb) })
+ }
+
+ fun cancel(): Boolean {
+ return task.cancel(true)
+ }
+
+ fun execute(): BackgroundTask<Result, Progress> {
+ task.execute()
+ return this
+ }
+
+ val immediately: Result
+ @Throws(Exception::class)
+ get() {
+ val result = task.get()
+ return if (exception == null) {
+ result
+ } else {
+ throw exception!!
+ }
+ }
+
+ protected fun fail(ex: Exception) {
+ exception = ex
+ ex.printStackTrace()
+ Logger.error(ex)
+
+ if (!task.isCancelled && cbFail != null) {
+ cbFail!!(ex)
+ }
+ }
+
+ protected fun progress(value: Progress) {
+ if (!task.isCancelled && exception == null && cbProgress != null) {
+ cbProgress!!(value)
+ }
+ }
+
+ @Throws(Exception::class)
+ protected abstract fun doInBackground(): Result
+
+ private inner class InnerAsyncTask : AsyncTask<Void, Progress, Result>() {
+ override fun onPostExecute(result: Result) {
+ if (!isCancelled && exception == null && cbThen != null) {
+ cbThen!!(result)
+ }
+ if (cbFinish != null) {
+ cbFinish!!()
+ }
+ }
+
+ override fun doInBackground(vararg params: Void): Result? {
+ try {
+ return this@BackgroundTask.doInBackground()
+ } catch (ex: Exception) {
+ fail(ex)
+ return null
+ }
+
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.java b/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.java
deleted file mode 100644
index dbb6fccd..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.util;
-
-import android.app.Activity;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
-import android.media.ExifInterface;
-import android.os.Environment;
-import net.lacolaco.smileessence.logging.Logger;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BitmapOptimizer {
-
- // -------------------------- STATIC METHODS --------------------------
-
- public static String rotateImageByExif(Activity activity, String filePath) {
- filePath = filePath.replace("file://", "");
- int degree = getRotateDegreeFromExif(filePath);
- if (degree > 0) {
- OutputStream out = null;
- Bitmap bitmap = null;
- Bitmap rotatedImage = null;
- try {
- Matrix mat = new Matrix();
- mat.postRotate(degree);
- BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(filePath, opt);
- int width = 480;
- int scale = 1;
- if (opt.outWidth > width) {
- scale = opt.outWidth / width + 2;
- }
- opt.inJustDecodeBounds = false;
- opt.inSampleSize = scale;
- bitmap = BitmapFactory.decodeFile(filePath, opt);
- rotatedImage = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mat, true);
- File file = new File(filePath);
- String outPath = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/" + file.getName();
- Logger.debug(outPath);
- out = new FileOutputStream(outPath);
- rotatedImage.compress(Bitmap.CompressFormat.JPEG, 100, out);
- return outPath;
- } catch (Exception e) {
- e.printStackTrace();
- Logger.error(e);
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {
- e.printStackTrace();
- Logger.error(e);
- }
- }
- if (bitmap != null) {
- bitmap.recycle();
- }
- if (rotatedImage != null) {
- rotatedImage.recycle();
- }
- }
- }
- return filePath;
- }
-
- private static int getRotateDegreeFromExif(String filePath) {
- int degree = 0;
- try {
- ExifInterface exifInterface = new ExifInterface(filePath);
- int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
- if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
- degree = 90;
- } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
- degree = 180;
- } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
- degree = 270;
- }
- if (degree != 0) {
- exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION, "0");
- exifInterface.saveAttributes();
- }
- } catch (IOException e) {
- degree = -1;
- e.printStackTrace();
- Logger.error(e);
- }
- Logger.debug("Exif degree = " + degree);
- return degree;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.kt b/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.kt
new file mode 100644
index 00000000..b49c9f08
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.kt
@@ -0,0 +1,122 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.util
+
+import android.app.Activity
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Matrix
+import android.media.ExifInterface
+import android.os.Environment
+import net.lacolaco.smileessence.logging.Logger
+
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.OutputStream
+
+object BitmapOptimizer {
+
+ // -------------------------- STATIC METHODS --------------------------
+
+ fun rotateImageByExif(activity: Activity, filePath: String): String {
+ var filePath = filePath
+ filePath = filePath.replace("file://", "")
+ val degree = getRotateDegreeFromExif(filePath)
+ if (degree > 0) {
+ var out: OutputStream? = null
+ var bitmap: Bitmap? = null
+ var rotatedImage: Bitmap? = null
+ try {
+ val mat = Matrix()
+ mat.postRotate(degree.toFloat())
+ val opt = BitmapFactory.Options()
+ opt.inJustDecodeBounds = true
+ BitmapFactory.decodeFile(filePath, opt)
+ val width = 480
+ var scale = 1
+ if (opt.outWidth > width) {
+ scale = opt.outWidth / width + 2
+ }
+ opt.inJustDecodeBounds = false
+ opt.inSampleSize = scale
+ bitmap = BitmapFactory.decodeFile(filePath, opt)
+ rotatedImage = Bitmap.createBitmap(bitmap, 0, 0, bitmap!!.width, bitmap.height, mat, true)
+ val file = File(filePath)
+ val outPath = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES).toString() + "/" + file.name
+ Logger.debug(outPath)
+ out = FileOutputStream(outPath)
+ rotatedImage!!.compress(Bitmap.CompressFormat.JPEG, 100, out)
+ return outPath
+ } catch (e: Exception) {
+ e.printStackTrace()
+ Logger.error(e)
+ } finally {
+ if (out != null) {
+ try {
+ out.close()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ Logger.error(e)
+ }
+
+ }
+ if (bitmap != null) {
+ bitmap.recycle()
+ }
+ if (rotatedImage != null) {
+ rotatedImage.recycle()
+ }
+ }
+ }
+ return filePath
+ }
+
+ private fun getRotateDegreeFromExif(filePath: String): Int {
+ var degree = 0
+ try {
+ val exifInterface = ExifInterface(filePath)
+ val orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
+ if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
+ degree = 90
+ } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
+ degree = 180
+ } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
+ degree = 270
+ }
+ if (degree != 0) {
+ exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION, "0")
+ exifInterface.saveAttributes()
+ }
+ } catch (e: IOException) {
+ degree = -1
+ e.printStackTrace()
+ Logger.error(e)
+ }
+
+ Logger.debug("Exif degree = " + degree)
+ return degree
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BitmapThumbnailTask.java b/app/src/main/java/net/lacolaco/smileessence/util/BitmapThumbnailTask.kt
index 0aa292cb..6e353716 100644
--- a/app/src/main/java/net/lacolaco/smileessence/util/BitmapThumbnailTask.java
+++ b/app/src/main/java/net/lacolaco/smileessence/util/BitmapThumbnailTask.kt
@@ -22,42 +22,34 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.util;
+package net.lacolaco.smileessence.util
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.ThumbnailUtils;
-import android.os.AsyncTask;
-import android.widget.ImageView;
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.media.ThumbnailUtils
+import android.os.AsyncTask
+import android.widget.ImageView
-public class BitmapThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
+class BitmapThumbnailTask
+// --------------------------- CONSTRUCTORS ---------------------------
- // ------------------------------ FIELDS ------------------------------
+(
+ // ------------------------------ FIELDS ------------------------------
- private final String filePath;
- private final ImageView imageView;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public BitmapThumbnailTask(String filePath, ImageView imageView) {
- this.filePath = filePath;
- this.imageView = imageView;
- }
+ private val filePath: String, private val imageView: ImageView?) : AsyncTask<Void, Void, Bitmap?>() {
// ------------------------ OVERRIDE METHODS ------------------------
- @Override
- protected void onPostExecute(Bitmap bitmap) {
+ override fun onPostExecute(bitmap: Bitmap?) {
if (bitmap != null && imageView != null) {
- imageView.setImageBitmap(bitmap);
+ imageView.setImageBitmap(bitmap)
}
}
- @Override
- protected Bitmap doInBackground(Void... params) {
- BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inPurgeable = true; // GC可能にする
- opt.inSampleSize = 2;
+ override fun doInBackground(vararg params: Void): Bitmap? {
+ val opt = BitmapFactory.Options()
+ opt.inPurgeable = true // GC可能にする
+ opt.inSampleSize = 2
// ContentResolver resolver = activity.getContentResolver();
// Cursor cursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.ImageColumns.DATA + " = ?", new String[]{filePath}, null);
// if(cursor.moveToFirst())
@@ -67,6 +59,6 @@ public class BitmapThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
// return MediaStore.Images.Thumbnails.getThumbnail(resolver, id, MediaStore.Images.Thumbnails.MICRO_KIND, opt);
// }
// return null;
- return ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filePath), 100, 100, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
+ return ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filePath), 100, 100, ThumbnailUtils.OPTIONS_RECYCLE_INPUT)
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.java b/app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.java
deleted file mode 100644
index 151498c3..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.util;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.AsyncTask;
-import android.widget.ImageView;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-public class BitmapURLTask extends AsyncTask<Void, Void, Bitmap> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final String url;
- private final ImageView imageView;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public BitmapURLTask(String url, ImageView imageView) {
- this.url = url;
- this.imageView = imageView;
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- if (imageView != null) {
- imageView.setImageBitmap(bitmap);
- }
- }
-
- @Override
- protected Bitmap doInBackground(Void... params) {
- InputStream inputStream = null;
- try {
- inputStream = new URL(url).openStream();
- BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inPurgeable = true; // GC可能にする
- return BitmapFactory.decodeStream(inputStream, null, opt);
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- } finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.kt b/app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.kt
new file mode 100644
index 00000000..f71e4afb
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.kt
@@ -0,0 +1,68 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.util
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.os.AsyncTask
+import android.widget.ImageView
+
+import java.io.IOException
+import java.io.InputStream
+import java.net.URL
+
+class BitmapURLTask
+// --------------------------- CONSTRUCTORS ---------------------------
+
+(
+ // ------------------------------ FIELDS ------------------------------
+
+ private val url: String, private val imageView: ImageView?) : AsyncTask<Void, Void, Bitmap>() {
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun onPostExecute(bitmap: Bitmap) {
+ imageView?.setImageBitmap(bitmap)
+ }
+
+ override fun doInBackground(vararg params: Void): Bitmap? {
+ var inputStream: InputStream? = null
+ try {
+ inputStream = URL(url).openStream()
+ val opt = BitmapFactory.Options()
+ opt.inPurgeable = true // GC可能にする
+ return BitmapFactory.decodeStream(inputStream, null, opt)
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return null
+ } finally {
+ try {
+ inputStream?.close()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/Consumer.java b/app/src/main/java/net/lacolaco/smileessence/util/Consumer.java
deleted file mode 100644
index a8712293..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/Consumer.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.lacolaco.smileessence.util;
-
-public interface Consumer<T> {
- void accept(T t);
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/Function.java b/app/src/main/java/net/lacolaco/smileessence/util/Function.java
deleted file mode 100644
index 5e374e8e..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/Function.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.lacolaco.smileessence.util;
-
-public interface Function<T, R> {
- R apply(T t);
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.java b/app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.kt
index 9ec4aa46..48b6f9e4 100644
--- a/app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.java
+++ b/app/src/main/java/net/lacolaco/smileessence/util/IntentUtils.kt
@@ -22,19 +22,17 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.util;
+package net.lacolaco.smileessence.util
-import android.app.Activity;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
+import android.app.Activity
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
+import android.net.Uri
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
-import java.util.List;
-
-public class IntentUtils {
+object IntentUtils {
// -------------------------- STATIC METHODS --------------------------
@@ -45,14 +43,14 @@ public class IntentUtils {
* @param intent
* @return
*/
- public static boolean startActivityIfFound(Activity activity, Intent intent) {
+ fun startActivityIfFound(activity: Activity, intent: Intent): Boolean {
if (canStartActivity(activity, intent)) {
- activity.startActivity(intent);
- return true;
+ activity.startActivity(intent)
+ return true
} else {
- Application.toast(R.string.notice_error_start_activity);
+ Application.toast(R.string.notice_error_start_activity)
}
- return false;
+ return false
}
/**
@@ -62,10 +60,10 @@ public class IntentUtils {
* @param intent
* @return
*/
- public static boolean canStartActivity(Activity activity, Intent intent) {
- PackageManager packageManager = activity.getPackageManager();
- List<ResolveInfo> infos = packageManager.queryIntentActivities(intent, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
- return !infos.isEmpty();
+ fun canStartActivity(activity: Activity, intent: Intent): Boolean {
+ val packageManager = activity.packageManager
+ val infos = packageManager.queryIntentActivities(intent, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
+ return !infos.isEmpty()
}
/**
@@ -76,18 +74,18 @@ public class IntentUtils {
* @param requestCode
* @return
*/
- public static boolean startActivityForResultIfFound(Activity activity, Intent intent, int requestCode) {
+ fun startActivityForResultIfFound(activity: Activity, intent: Intent, requestCode: Int): Boolean {
if (canStartActivity(activity, intent)) {
- activity.startActivityForResult(intent, requestCode);
- return true;
+ activity.startActivityForResult(intent, requestCode)
+ return true
} else {
- Application.toast(R.string.notice_error_start_activity);
+ Application.toast(R.string.notice_error_start_activity)
}
- return false;
+ return false
}
- public static boolean openUri(Activity activity, String uriString) {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uriString));
- return startActivityIfFound(activity, intent);
+ fun openUri(activity: Activity, uriString: String): Boolean {
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(uriString))
+ return startActivityIfFound(activity, intent)
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/ListUtils.java b/app/src/main/java/net/lacolaco/smileessence/util/ListUtils.java
deleted file mode 100644
index 36ade3e6..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/ListUtils.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package net.lacolaco.smileessence.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ListUtils {
- public static <T, R> List<R> map(List<T> orig, Function<T, R> func) {
- List<R> result = new ArrayList<>(orig.size());
- for (T item : orig) {
- result.add(func.apply(item));
- }
- return result;
- }
-
- public static <T> List<T> filter(Iterable<T> orig, Predicate<T> pred) {
- List<T> result = new ArrayList<>();
- for (T item : orig) {
- if (pred.test(item)) {
- result.add(item);
- }
- }
- return result;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/Predicate.java b/app/src/main/java/net/lacolaco/smileessence/util/Predicate.java
deleted file mode 100644
index 400310a9..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/Predicate.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.lacolaco.smileessence.util;
-
-public interface Predicate<T> {
- boolean test(T t);
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/StringUtils.java b/app/src/main/java/net/lacolaco/smileessence/util/StringUtils.kt
index 07dedb46..cdfe59f5 100644
--- a/app/src/main/java/net/lacolaco/smileessence/util/StringUtils.java
+++ b/app/src/main/java/net/lacolaco/smileessence/util/StringUtils.kt
@@ -22,40 +22,40 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.util;
+package net.lacolaco.smileessence.util
-import android.annotation.SuppressLint;
+import android.annotation.SuppressLint
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Date
-public class StringUtils {
+object StringUtils {
// -------------------------- STATIC METHODS --------------------------
@SuppressLint("SimpleDateFormat")
- public static String dateToString(Date date) {
- Calendar current = Calendar.getInstance();
- Calendar cal = Calendar.getInstance();
- cal.setTime(date);
+ fun dateToString(date: Date): String {
+ val current = Calendar.getInstance()
+ val cal = Calendar.getInstance()
+ cal.time = date
- if (isSameYear(current, cal)) {
+ return if (isSameYear(current, cal)) {
if (isSameDay(current, cal)) {
- return new SimpleDateFormat("HH:mm:ss").format(date);
+ SimpleDateFormat("HH:mm:ss").format(date)
} else {
- return new SimpleDateFormat("MM/dd HH:mm:ss").format(date);
+ SimpleDateFormat("MM/dd HH:mm:ss").format(date)
}
} else {
- return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(date);
+ SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(date)
}
}
- private static boolean isSameDay(Calendar current, Calendar cal) {
- return cal.get(Calendar.DAY_OF_YEAR) == current.get(Calendar.DAY_OF_YEAR);
+ private fun isSameDay(current: Calendar, cal: Calendar): Boolean {
+ return cal.get(Calendar.DAY_OF_YEAR) == current.get(Calendar.DAY_OF_YEAR)
}
- private static boolean isSameYear(Calendar current, Calendar cal) {
- return cal.get(Calendar.YEAR) == current.get(Calendar.YEAR);
+ private fun isSameYear(current: Calendar, cal: Calendar): Boolean {
+ return cal.get(Calendar.YEAR) == current.get(Calendar.YEAR)
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/SystemServiceHelper.java b/app/src/main/java/net/lacolaco/smileessence/util/SystemServiceHelper.kt
index 919ef351..efed67ca 100644
--- a/app/src/main/java/net/lacolaco/smileessence/util/SystemServiceHelper.java
+++ b/app/src/main/java/net/lacolaco/smileessence/util/SystemServiceHelper.kt
@@ -22,32 +22,32 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.util;
+package net.lacolaco.smileessence.util
-import android.app.Activity;
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.view.View;
-import android.view.inputmethod.InputMethodManager;
+import android.app.Activity
+import android.content.ClipData
+import android.content.ClipboardManager
+import android.content.Context
+import android.view.View
+import android.view.inputmethod.InputMethodManager
-public class SystemServiceHelper {
- public static void hideIM(Context context, View view) {
+object SystemServiceHelper {
+ fun hideIM(context: Context, view: View?) {
if (view != null) {
- InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN);
+ val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ imm.hideSoftInputFromWindow(view.windowToken, InputMethodManager.RESULT_UNCHANGED_SHOWN)
}
}
- public static void showIM(Context context, View view) {
+ fun showIM(context: Context, view: View?) {
if (view != null) {
- InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(view, InputMethodManager.RESULT_UNCHANGED_SHOWN);
+ val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ imm.showSoftInput(view, InputMethodManager.RESULT_UNCHANGED_SHOWN)
}
}
- public static void copyToClipboard(Context context, String label, String text) {
- ClipboardManager manager = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
- manager.setPrimaryClip(ClipData.newPlainText(label, text));
+ fun copyToClipboard(context: Context, label: String, text: String) {
+ val manager = context.getSystemService(Activity.CLIPBOARD_SERVICE) as ClipboardManager
+ manager.primaryClip = ClipData.newPlainText(label, text)
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/UIHandler.java b/app/src/main/java/net/lacolaco/smileessence/util/UIHandler.kt
index f228f23f..5c9898a2 100644
--- a/app/src/main/java/net/lacolaco/smileessence/util/UIHandler.java
+++ b/app/src/main/java/net/lacolaco/smileessence/util/UIHandler.kt
@@ -22,13 +22,9 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.util;
+package net.lacolaco.smileessence.util
-import android.os.Handler;
-import android.os.Looper;
+import android.os.Handler
+import android.os.Looper
-public class UIHandler extends Handler {
- public UIHandler() {
- super(Looper.getMainLooper());
- }
-}
+class UIHandler : Handler(Looper.getMainLooper())
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/UIObservable.java b/app/src/main/java/net/lacolaco/smileessence/util/UIObservable.java
deleted file mode 100644
index 1cf4efeb..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/UIObservable.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package net.lacolaco.smileessence.util;
-
-import net.lacolaco.smileessence.entity.RBinding;
-
-import java.util.*;
-
-public abstract class UIObservable {
- private Map<Object, UIObserver> observers = new WeakHashMap<>();
-
- public void addObserver(Object weakKey, UIObserver observer) {
- synchronized (this) {
- observers.put(weakKey, observer);
- }
- }
-
- public UIObserver removeObserver(Object weakKey) {
- synchronized (this) {
- return observers.remove(weakKey);
- }
- }
-
- protected void notifyChange(RBinding flag) {
- notifyChange(EnumSet.of(flag));
- }
-
- protected void notifyChange(EnumSet<RBinding> flags) {
- List<UIObserver> obs = new ArrayList<>();
- synchronized (this) {
- obs.addAll(observers.values());
- }
-
- new UIHandler().post(() -> {
- for (UIObserver observer : obs) {
- observer.update(flags);
- }
- });
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/UIObservable.kt b/app/src/main/java/net/lacolaco/smileessence/util/UIObservable.kt
new file mode 100644
index 00000000..a8f89585
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/util/UIObservable.kt
@@ -0,0 +1,38 @@
+package net.lacolaco.smileessence.util
+
+import net.lacolaco.smileessence.entity.RBinding
+
+import java.util.*
+
+abstract class UIObservable {
+ private val observers = WeakHashMap<Any, (EnumSet<RBinding>) -> Unit>()
+
+ fun addObserver(weakKey: Any, observer: (EnumSet<RBinding>) -> Unit) {
+ synchronized(this) {
+ observers.put(weakKey, observer)
+ }
+ }
+
+ fun removeObserver(weakKey: Any) {
+ synchronized(this) {
+ observers.remove(weakKey)
+ }
+ }
+
+ protected fun notifyChange(flag: RBinding) {
+ notifyChange(EnumSet.of(flag))
+ }
+
+ protected fun notifyChange(flags: EnumSet<RBinding>) {
+ val obs = ArrayList<(EnumSet<RBinding>) -> Unit>()
+ synchronized(this) {
+ obs.addAll(observers.values)
+ }
+
+ UIHandler().post {
+ for (observer in obs) {
+ observer(flags)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/UIObserver.java b/app/src/main/java/net/lacolaco/smileessence/util/UIObserver.java
deleted file mode 100644
index 6a621c61..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/UIObserver.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package net.lacolaco.smileessence.util;
-
-import net.lacolaco.smileessence.entity.RBinding;
-
-import java.util.EnumSet;
-
-public interface UIObserver {
- void update(EnumSet<RBinding> flags);
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/UIObserverBundle.java b/app/src/main/java/net/lacolaco/smileessence/util/UIObserverBundle.java
deleted file mode 100644
index a1d8957a..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/UIObserverBundle.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package net.lacolaco.smileessence.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-// UIObserver と UIObservable のセットを管理するオブジェクトだよ〜〜
-public class UIObserverBundle {
- private Map<UIObservable, UIObserver> map = new HashMap<>();
-
- public void detachAll() {
- for (Map.Entry<UIObservable, UIObserver> entry : map.entrySet()) {
- entry.getKey().removeObserver(this);
- }
- map.clear();
- }
-
- public UIObserver attach(UIObservable observable, UIObserver observer) {
- observable.addObserver(this, observer);
- map.put(observable, observer);
- return observer;
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- super.finalize();
- } finally {
- detachAll();
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/UIObserverBundle.kt b/app/src/main/java/net/lacolaco/smileessence/util/UIObserverBundle.kt
new file mode 100644
index 00000000..f6c8403b
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/util/UIObserverBundle.kt
@@ -0,0 +1,26 @@
+package net.lacolaco.smileessence.util
+
+import net.lacolaco.smileessence.entity.RBinding
+import java.util.*
+
+// UIObserver と UIObservable のセットを管理するオブジェクトだよ〜〜
+class UIObserverBundle {
+ private val map = HashMap<UIObservable, (EnumSet<RBinding>) -> Unit>()
+
+ fun detachAll() {
+ for ((key) in map) {
+ key.removeObserver(this)
+ }
+ map.clear()
+ }
+
+ fun attach(observable: UIObservable, observer: (EnumSet<RBinding>) -> Unit): (EnumSet<RBinding>) -> Unit {
+ observable.addObserver(this, observer)
+ map.put(observable, observer)
+ return observer
+ }
+
+ protected fun finalize() {
+ detachAll()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.java b/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.java
deleted file mode 100644
index 33fc05ac..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package net.lacolaco.smileessence.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.widget.RelativeLayout;
-import net.lacolaco.smileessence.R;
-
-
-public class ColoredRelativeLayout extends RelativeLayout {
- public static final int HIGHLIGHT_NONE = 0;
- private final Paint paint = new Paint();
- private int highlightColors[] = new int[4];
- private boolean showAccent = false;
-
- public ColoredRelativeLayout(Context context) {
- this(context, null);
- }
-
- public ColoredRelativeLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ColoredRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public ColoredRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
-
- setWillNotDraw(false);
-
- TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ColoredRelativeLayout);
- highlightColors[0] = ta.getColor(R.styleable.ColoredRelativeLayout_highlight_none, R.color.black);
- highlightColors[1] = ta.getColor(R.styleable.ColoredRelativeLayout_highlight_type1, R.color.orange);
- highlightColors[2] = ta.getColor(R.styleable.ColoredRelativeLayout_highlight_type2, R.color.green);
- highlightColors[3] = ta.getColor(R.styleable.ColoredRelativeLayout_highlight_type3, R.color.metro_blue);
- setHighlight(HIGHLIGHT_NONE);
- paint.setColor(ta.getColor(R.styleable.ColoredRelativeLayout_accent_color, R.color.red));
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(3);
- ta.recycle();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (showAccent)
- canvas.drawLine(1, 0, 1, getMeasuredHeight(), paint);
- }
-
- public void setAccentVisibility(boolean yes) {
- showAccent = yes;
- }
-
- public void setHighlight(int type) {
- setBackgroundColor(highlightColors[type]);
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.kt b/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.kt
new file mode 100644
index 00000000..0bf69378
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/ColoredRelativeLayout.kt
@@ -0,0 +1,50 @@
+package net.lacolaco.smileessence.view
+
+import android.content.Context
+import android.content.res.TypedArray
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.widget.RelativeLayout
+import net.lacolaco.smileessence.R
+
+
+class ColoredRelativeLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0) : RelativeLayout(context, attrs, defStyleAttr, defStyleRes) {
+ private val paint = Paint()
+ private val highlightColors = IntArray(4)
+ private var showAccent = false
+
+ init {
+
+ setWillNotDraw(false)
+
+ val ta = context.obtainStyledAttributes(attrs, R.styleable.ColoredRelativeLayout)
+ highlightColors[0] = ta.getColor(R.styleable.ColoredRelativeLayout_highlight_none, R.color.black)
+ highlightColors[1] = ta.getColor(R.styleable.ColoredRelativeLayout_highlight_type1, R.color.orange)
+ highlightColors[2] = ta.getColor(R.styleable.ColoredRelativeLayout_highlight_type2, R.color.green)
+ highlightColors[3] = ta.getColor(R.styleable.ColoredRelativeLayout_highlight_type3, R.color.metro_blue)
+ setHighlight(HIGHLIGHT_NONE)
+ paint.color = ta.getColor(R.styleable.ColoredRelativeLayout_accent_color, R.color.red)
+ paint.style = Paint.Style.STROKE
+ paint.strokeWidth = 3f
+ ta.recycle()
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ if (showAccent)
+ canvas.drawLine(1f, 0f, 1f, measuredHeight.toFloat(), paint)
+ }
+
+ fun setAccentVisibility(yes: Boolean) {
+ showAccent = yes
+ }
+
+ fun setHighlight(type: Int) {
+ setBackgroundColor(highlightColors[type])
+ }
+
+ companion object {
+ val HIGHLIGHT_NONE = 0
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/DialogHelper.java b/app/src/main/java/net/lacolaco/smileessence/view/DialogHelper.kt
index 3a0003d6..c9b4a428 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/DialogHelper.java
+++ b/app/src/main/java/net/lacolaco/smileessence/view/DialogHelper.kt
@@ -22,38 +22,38 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.view;
+package net.lacolaco.smileessence.view
-import android.app.Activity;
-import net.lacolaco.smileessence.view.dialog.StackableDialogFragment;
+import android.app.Activity
+import net.lacolaco.smileessence.view.dialog.StackableDialogFragment
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import java.util.UUID;
+import java.util.ArrayList
+import java.util.LinkedHashSet
+import java.util.UUID
/**
* DialogFragment のタグの一覧を保持し「全てのダイアログを閉じる」機能を提供するヘルパークラス
*/
-public class DialogHelper {
- private static Set<String> dialogStack = new LinkedHashSet<>();
+object DialogHelper {
+ private val dialogStack = LinkedHashSet<String>()
- public synchronized static void closeAll(Activity activity) {
- for (String tag : new ArrayList<>(dialogStack)) {
- StackableDialogFragment dialogFragment = (StackableDialogFragment) activity.getFragmentManager().findFragmentByTag(tag);
- if (dialogFragment != null) {
- dialogFragment.dismiss();
- }
+ @Synchronized
+ fun closeAll(activity: Activity) {
+ for (tag in ArrayList(dialogStack)) {
+ val dialogFragment = activity.fragmentManager.findFragmentByTag(tag) as StackableDialogFragment?
+ dialogFragment?.dismiss()
}
}
- public synchronized static int showDialog(Activity activity, StackableDialogFragment dialogFragment) {
- String tag = "stackingDialog:" + dialogFragment.getClass().getSimpleName() + ":" + UUID.randomUUID();
- dialogStack.add(tag);
- return dialogFragment.show(activity.getFragmentManager().beginTransaction(), tag);
+ @Synchronized
+ fun showDialog(activity: Activity, dialogFragment: StackableDialogFragment): Int {
+ val tag = "stackingDialog:" + dialogFragment.javaClass.simpleName + ":" + UUID.randomUUID()
+ dialogStack.add(tag)
+ return dialogFragment.show(activity.fragmentManager.beginTransaction(), tag)
}
- public synchronized static void unregisterDialog(String tag) {
- dialogStack.remove(tag);
+ @Synchronized
+ fun unregisterDialog(tag: String) {
+ dialogStack.remove(tag)
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ExpandedListView.java b/app/src/main/java/net/lacolaco/smileessence/view/ExpandedListView.java
deleted file mode 100644
index e0a4a651..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/ExpandedListView.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package net.lacolaco.smileessence.view;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-import android.widget.ListView;
-
-public class ExpandedListView extends ListView {
- public ExpandedListView(Context context) {
- super(context);
- }
-
- public ExpandedListView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public ExpandedListView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- @Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
- super.onMeasure(widthMeasureSpec, expandSpec);
-
- ViewGroup.LayoutParams params = getLayoutParams();
- params.height = getMeasuredHeight();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ExpandedListView.kt b/app/src/main/java/net/lacolaco/smileessence/view/ExpandedListView.kt
new file mode 100644
index 00000000..288354ba
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/ExpandedListView.kt
@@ -0,0 +1,23 @@
+package net.lacolaco.smileessence.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ListView
+
+class ExpandedListView : ListView {
+ constructor(context: Context) : super(context)
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
+
+ public override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ val expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE shr 2, View.MeasureSpec.AT_MOST)
+ super.onMeasure(widthMeasureSpec, expandSpec)
+
+ val params = layoutParams
+ params.height = measuredHeight
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/Partials.java b/app/src/main/java/net/lacolaco/smileessence/view/Partials.java
deleted file mode 100644
index fc0e35cb..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/Partials.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package net.lacolaco.smileessence.view;
-
-import android.app.Activity;
-import android.text.Html;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-import com.android.volley.toolbox.NetworkImageView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.data.ImageCache;
-import net.lacolaco.smileessence.entity.DirectMessage;
-import net.lacolaco.smileessence.entity.RBinding;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.preference.UserPreferenceHelper;
-import net.lacolaco.smileessence.util.StringUtils;
-import net.lacolaco.smileessence.util.UIObserverBundle;
-import net.lacolaco.smileessence.view.adapter.CustomListAdapter;
-import net.lacolaco.smileessence.view.dialog.MessageDetailDialogFragment;
-import net.lacolaco.smileessence.view.dialog.StatusDetailDialogFragment;
-import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment;
-import net.lacolaco.smileessence.view.listener.ListItemClickListener;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-
-public class Partials {
- public static View getTweetView(Tweet tweet, Activity activity, View convertView, boolean expandEmbeddedTweets) {
- if (convertView == null) {
- convertView = activity.getLayoutInflater().inflate(R.layout.list_item_status, null);
- }
- UIObserverBundle bundle = (UIObserverBundle) convertView.getTag();
- if (bundle != null) {
- bundle.detachAll();
- } else {
- bundle = new UIObserverBundle();
- convertView.setTag(bundle);
- }
-
- convertView.setOnClickListener(new ListItemClickListener(activity, () -> DialogHelper.showDialog(activity, StatusDetailDialogFragment.newInstance(tweet))));
-
- updateViewUser(tweet, activity, convertView);
- updateViewBody(tweet, activity, convertView);
- updateViewFavorited(tweet, convertView);
- updateViewEmbeddeds(tweet, activity, convertView, expandEmbeddedTweets);
-
- final WeakReference<View> weakView = new WeakReference<>(convertView);
- final WeakReference<Activity> weakActivity = new WeakReference<>(activity);
- bundle.attach(tweet.getOriginalTweet(), changes -> {
- View strongView = weakView.get();
- if (strongView != null && changes.contains(RBinding.FAVORITERS))
- updateViewFavorited(tweet, strongView);
- });
- bundle.attach(tweet.getUser(), changes -> {
- View strongView = weakView.get();
- Activity strongActivity = weakActivity.get();
- if (strongView != null && strongActivity != null && changes.contains(RBinding.BASIC))
- updateViewUser(tweet, strongActivity, strongView);
- });
-
- return convertView;
- }
-
-
- private static void updateViewEmbeddeds(Tweet tweet, Activity activity, View convertView, boolean expandEmbeddedTweets) {
- final ListView embeddedStatus = (ListView) convertView.findViewById(R.id.listview_status_embedded_status);
- if (expandEmbeddedTweets) {
- final List<Tweet> list = new ArrayList<>();
- CustomListAdapter<Tweet> embeddedTweetsAdapter = new CustomListAdapter<Tweet>() {
- @Override
- protected List<Tweet> getList() {
- return list;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- return Partials.getTweetView(getItem(position), activity, convertView, false);
- }
- };
-
- Account account = Application.getCurrentWorld().getAccount();
- for (long id : tweet.getEmbeddedStatusIDs()) {
- Tweet.fetchTask(id, account).onDone(t -> list.add(t)).execute();
- }
- embeddedStatus.setAdapter(embeddedTweetsAdapter);
- embeddedStatus.setVisibility(View.VISIBLE);
- } else {
- embeddedStatus.setAdapter(null); // view may be reused, set null explicitly
- embeddedStatus.setVisibility(View.GONE);
- }
- }
-
- private static void updateViewUser(Tweet tweet, Activity activity, View convertView) {
- int textSize = UserPreferenceHelper.getInstance().getTextSize();
-
- NetworkImageView icon = (NetworkImageView) convertView.findViewById(R.id.imageview_status_icon);
- String iconUrl = tweet.getOriginalTweet().getUser().getProfileImageUrlOriginal();
- icon.setImageUrl(iconUrl, ImageCache.getImageLoader());
- icon.setOnClickListener(v -> onIconClick(tweet, activity));
-
- TextView header = (TextView) convertView.findViewById(R.id.textview_status_header);
- header.setTextSize(textSize);
- header.setText(tweet.getOriginalTweet().getUser().getFormattedName());
-
- ((ColoredRelativeLayout) convertView).setAccentVisibility(tweet.getUser() == Application.getCurrentWorld().getAccount().getUser());
- }
-
- private static void updateViewBody(Tweet tweet, Activity activity, View convertView) {
- int textSize = UserPreferenceHelper.getInstance().getTextSize();
-
- TextView content = (TextView) convertView.findViewById(R.id.textview_status_text);
- content.setTextSize(textSize);
- String rawText = tweet.getOriginalTweet().getText();
- content.setText(rawText);
- TextView footer = (TextView) convertView.findViewById(R.id.textview_status_footer);
- footer.setTextSize(textSize - 2);
- footer.setText(getFooterText(tweet));
-
- ColoredRelativeLayout typedView = (ColoredRelativeLayout) convertView;
- if (tweet.isRetweet()) {
- typedView.setHighlight(2);
- } else if (tweet.getOriginalTweet().getMentions().contains(Application.getCurrentWorld().getAccount().getUser().getScreenName())) {
- typedView.setHighlight(1);
- } else {
- typedView.setHighlight(0);
- }
- }
-
- private static void updateViewFavorited(Tweet tweet, View convertView) {
- ImageView favorited = (ImageView) convertView.findViewById(R.id.imageview_status_favorited);
- favorited.setVisibility(tweet.isFavoritedBy(Application.getCurrentWorld().getAccount().getUserId()) ? View.VISIBLE : View.GONE);
- }
-
- private static void onIconClick(Tweet tweet, Activity activity) {
- UserDetailDialogFragment dialogFragment = new UserDetailDialogFragment();
- dialogFragment.setUserID(tweet.getOriginalTweet().getUser().getId());
- DialogHelper.showDialog(activity, dialogFragment);
- }
-
- private static String getFooterText(Tweet tweet) {
- StringBuilder builder = new StringBuilder();
- if (tweet.isRetweet()) {
- builder
- .append("(RT: ")
- .append(tweet.getUser().getScreenName())
- .append(") ");
- }
- builder.append(StringUtils.dateToString(tweet.getOriginalTweet().getCreatedAt()));
- builder.append(" via ");
- builder.append(Html.fromHtml(tweet.getOriginalTweet().getSource()));
- return builder.toString();
- }
-
- public static View getDirectMessageView(DirectMessage directMessage, Activity activity, View convertView) {
- if (convertView == null) {
- convertView = activity.getLayoutInflater().inflate(R.layout.list_item_status, null);
- }
- UIObserverBundle bundle = (UIObserverBundle) convertView.getTag();
- if (bundle != null) {
- bundle.detachAll();
- } else {
- bundle = new UIObserverBundle();
- convertView.setTag(bundle);
- }
-
- convertView.setOnClickListener(new ListItemClickListener(activity, () -> DialogHelper.showDialog(activity, MessageDetailDialogFragment.newInstance(directMessage))));
-
- ImageView favorited = (ImageView) convertView.findViewById(R.id.imageview_status_favorited);
- favorited.setVisibility(View.GONE);
-
- updateViewSender(directMessage, activity, convertView);
- updateViewBody(directMessage, activity, convertView);
-
- final WeakReference<View> weakView = new WeakReference<>(convertView);
- final WeakReference<MainActivity> weakActivity = new WeakReference<>((MainActivity) activity);
- bundle.attach(directMessage.getSender(), changes -> {
- View strongView = weakView.get();
- MainActivity strongActivity = weakActivity.get();
- if (strongView != null && strongActivity != null && changes.contains(RBinding.BASIC))
- updateViewSender(directMessage, strongActivity, strongView);
- });
-
- return convertView;
- }
-
- private static String getFooterText(DirectMessage directMessage, Account account) {
- StringBuilder builder = new StringBuilder();
- builder.append(StringUtils.dateToString(directMessage.getCreatedAt()));
- if (directMessage.getSender().getId() == account.getUserId()) {
- builder.append(" to @").append(directMessage.getRecipient().getScreenName());
- }
- return builder.toString();
- }
-
- private static void updateViewSender(DirectMessage directMessage, Activity activity, View convertView) {
- int textSize = UserPreferenceHelper.getInstance().getTextSize();
-
- NetworkImageView icon = (NetworkImageView) convertView.findViewById(R.id.imageview_status_icon);
- String iconUrl = directMessage.getSender().getProfileImageUrlOriginal();
- icon.setImageUrl(iconUrl, ImageCache.getImageLoader());
- icon.setOnClickListener(v -> {
- UserDetailDialogFragment dialogFragment = new UserDetailDialogFragment();
- dialogFragment.setUserID(directMessage.getSender().getId());
- DialogHelper.showDialog(activity, dialogFragment);
- });
-
- TextView header = (TextView) convertView.findViewById(R.id.textview_status_header);
- header.setTextSize(textSize);
- header.setText(directMessage.getSender().getFormattedName());
-
- ((ColoredRelativeLayout) convertView).setAccentVisibility(directMessage.getSender() == Application.getCurrentWorld().getAccount().getUser());
- }
-
- private static void updateViewBody(DirectMessage directMessage, Activity activity, View convertView) {
- int textSize = UserPreferenceHelper.getInstance().getTextSize();
-
- TextView content = (TextView) convertView.findViewById(R.id.textview_status_text);
- content.setTextSize(textSize);
- content.setText(directMessage.getText());
- TextView footer = (TextView) convertView.findViewById(R.id.textview_status_footer);
- footer.setTextSize(textSize - 2);
- footer.setText(getFooterText(directMessage, Application.getCurrentWorld().getAccount()));
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/Partials.kt b/app/src/main/java/net/lacolaco/smileessence/view/Partials.kt
new file mode 100644
index 00000000..27d8c3cd
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/Partials.kt
@@ -0,0 +1,220 @@
+package net.lacolaco.smileessence.view
+
+import android.app.Activity
+import android.text.Html
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.ListView
+import android.widget.TextView
+import com.android.volley.toolbox.NetworkImageView
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.data.ImageCache
+import net.lacolaco.smileessence.entity.DirectMessage
+import net.lacolaco.smileessence.entity.RBinding
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.preference.UserPreferenceHelper
+import net.lacolaco.smileessence.util.StringUtils
+import net.lacolaco.smileessence.util.UIObserverBundle
+import net.lacolaco.smileessence.view.adapter.CustomListAdapter
+import net.lacolaco.smileessence.view.dialog.MessageDetailDialogFragment
+import net.lacolaco.smileessence.view.dialog.StatusDetailDialogFragment
+import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment
+import net.lacolaco.smileessence.view.listener.ListItemClickListener
+
+import java.lang.ref.WeakReference
+import java.util.ArrayList
+
+object Partials {
+ fun getTweetView(tweet: Tweet, activity: Activity, convertView: View?, expandEmbeddedTweets: Boolean): View {
+ var convertView: View = convertView ?: activity.layoutInflater.inflate(R.layout.list_item_status, null)
+ var bundle: UIObserverBundle? = convertView.tag as UIObserverBundle?
+ if (bundle != null) {
+ bundle.detachAll()
+ } else {
+ bundle = UIObserverBundle()
+ convertView.tag = bundle
+ }
+
+ convertView.setOnClickListener(ListItemClickListener(activity) { DialogHelper.showDialog(activity, StatusDetailDialogFragment.newInstance(tweet)) })
+
+ updateViewUser(tweet, activity, convertView)
+ updateViewBody(tweet, activity, convertView)
+ updateViewFavorited(tweet, convertView)
+ updateViewEmbeddeds(tweet, activity, convertView, expandEmbeddedTweets)
+
+ val weakView = WeakReference(convertView)
+ val weakActivity = WeakReference(activity)
+ bundle.attach(tweet.originalTweet) { changes ->
+ val strongView = weakView.get()
+ if (strongView != null && changes.contains(RBinding.FAVORITERS))
+ updateViewFavorited(tweet, strongView)
+ }
+ bundle.attach(tweet.user) { changes ->
+ val strongView = weakView.get()
+ val strongActivity = weakActivity.get()
+ if (strongView != null && strongActivity != null && changes.contains(RBinding.BASIC))
+ updateViewUser(tweet, strongActivity, strongView)
+ }
+
+ return convertView
+ }
+
+
+ private fun updateViewEmbeddeds(tweet: Tweet, activity: Activity, convertView: View, expandEmbeddedTweets: Boolean) {
+ val embeddedStatus = convertView.findViewById(R.id.listview_status_embedded_status) as ListView
+ if (expandEmbeddedTweets) {
+ val list = ArrayList<Tweet>()
+ val embeddedTweetsAdapter = object : CustomListAdapter<Tweet>() {
+ override val list: List<Tweet>
+ get() = list
+
+ override fun getView(position: Int, convertView: View, parent: ViewGroup): View {
+ return Partials.getTweetView(getItem(position), activity, convertView, false)
+ }
+ }
+
+ val account = Application.currentWorld!!.account
+ for (id in tweet.embeddedStatusIDs) {
+ Tweet.fetchTask(id, account).onDone { t -> list.add(t) }.execute()
+ }
+ embeddedStatus.adapter = embeddedTweetsAdapter
+ embeddedStatus.visibility = View.VISIBLE
+ } else {
+ embeddedStatus.adapter = null // view may be reused, set null explicitly
+ embeddedStatus.visibility = View.GONE
+ }
+ }
+
+ private fun updateViewUser(tweet: Tweet, activity: Activity, convertView: View) {
+ val textSize = UserPreferenceHelper.instance.textSize
+
+ val icon = convertView.findViewById(R.id.imageview_status_icon) as NetworkImageView
+ val iconUrl = tweet.originalTweet.user.profileImageUrl
+ icon.setImageUrl(iconUrl, ImageCache.getImageLoader())
+ icon.setOnClickListener { v -> onIconClick(tweet, activity) }
+
+ val header = convertView.findViewById(R.id.textview_status_header) as TextView
+ header.textSize = textSize.toFloat()
+ header.text = tweet.originalTweet.user.formattedName
+
+ (convertView as ColoredRelativeLayout).setAccentVisibility(tweet.user === Application.currentWorld!!.account.user)
+ }
+
+ private fun updateViewBody(tweet: Tweet, activity: Activity, convertView: View) {
+ val textSize = UserPreferenceHelper.instance.textSize
+
+ val content = convertView.findViewById(R.id.textview_status_text) as TextView
+ content.textSize = textSize.toFloat()
+ val rawText = tweet.originalTweet.text
+ content.text = rawText
+ val footer = convertView.findViewById(R.id.textview_status_footer) as TextView
+ footer.textSize = (textSize - 2).toFloat()
+ footer.text = getFooterText(tweet)
+
+ val typedView = convertView as ColoredRelativeLayout
+ if (tweet.isRetweet) {
+ typedView.setHighlight(2)
+ } else if (tweet.originalTweet.mentions.contains(Application.currentWorld!!.account.user.screenName)) {
+ typedView.setHighlight(1)
+ } else {
+ typedView.setHighlight(0)
+ }
+ }
+
+ private fun updateViewFavorited(tweet: Tweet, convertView: View) {
+ val favorited = convertView.findViewById(R.id.imageview_status_favorited) as ImageView
+ favorited.visibility = if (tweet.isFavoritedBy(Application.currentWorld!!.account.userId)) View.VISIBLE else View.GONE
+ }
+
+ private fun onIconClick(tweet: Tweet, activity: Activity) {
+ DialogHelper.showDialog(activity, UserDetailDialogFragment.newInstance(tweet.originalTweet.user))
+ }
+
+ private fun getFooterText(tweet: Tweet): String {
+ val builder = StringBuilder()
+ if (tweet.isRetweet) {
+ builder
+ .append("(RT: ")
+ .append(tweet.user.screenName)
+ .append(") ")
+ }
+ builder.append(StringUtils.dateToString(tweet.originalTweet.createdAt))
+ builder.append(" via ")
+ builder.append(Html.fromHtml(tweet.originalTweet.source))
+ return builder.toString()
+ }
+
+ fun getDirectMessageView(directMessage: DirectMessage, activity: Activity, convertView: View?): View {
+ var convertView = convertView
+ if (convertView == null) {
+ convertView = activity.layoutInflater.inflate(R.layout.list_item_status, null)
+ }
+ var bundle: UIObserverBundle? = convertView!!.tag as UIObserverBundle?
+ if (bundle != null) {
+ bundle.detachAll()
+ } else {
+ bundle = UIObserverBundle()
+ convertView.tag = bundle
+ }
+
+ convertView.setOnClickListener(ListItemClickListener(activity) { DialogHelper.showDialog(activity, MessageDetailDialogFragment.newInstance(directMessage)) })
+
+ val favorited = convertView.findViewById(R.id.imageview_status_favorited) as ImageView
+ favorited.visibility = View.GONE
+
+ updateViewSender(directMessage, activity, convertView)
+ updateViewBody(directMessage, activity, convertView)
+
+ val weakView = WeakReference(convertView)
+ val weakActivity = WeakReference(activity as MainActivity)
+ bundle.attach(directMessage.sender) { changes ->
+ val strongView = weakView.get()
+ val strongActivity = weakActivity.get()
+ if (strongView != null && strongActivity != null && changes.contains(RBinding.BASIC))
+ updateViewSender(directMessage, strongActivity, strongView)
+ }
+
+ return convertView
+ }
+
+ private fun getFooterText(directMessage: DirectMessage, account: Account): String {
+ val builder = StringBuilder()
+ builder.append(StringUtils.dateToString(directMessage.createdAt))
+ if (directMessage.sender.id == account.userId) {
+ builder.append(" to @").append(directMessage.recipient.screenName)
+ }
+ return builder.toString()
+ }
+
+ private fun updateViewSender(directMessage: DirectMessage, activity: Activity, convertView: View) {
+ val textSize = UserPreferenceHelper.instance.textSize
+
+ val icon = convertView.findViewById(R.id.imageview_status_icon) as NetworkImageView
+ val iconUrl = directMessage.sender.profileImageUrl
+ icon.setImageUrl(iconUrl, ImageCache.getImageLoader())
+ icon.setOnClickListener { v ->
+ DialogHelper.showDialog(activity, UserDetailDialogFragment.newInstance(directMessage.sender))
+ }
+
+ val header = convertView.findViewById(R.id.textview_status_header) as TextView
+ header.textSize = textSize.toFloat()
+ header.text = directMessage.sender.formattedName
+
+ (convertView as ColoredRelativeLayout).setAccentVisibility(directMessage.sender === Application.currentWorld!!.account.user)
+ }
+
+ private fun updateViewBody(directMessage: DirectMessage, activity: Activity, convertView: View) {
+ val textSize = UserPreferenceHelper.instance.textSize
+
+ val content = convertView.findViewById(R.id.textview_status_text) as TextView
+ content.textSize = textSize.toFloat()
+ content.text = directMessage.text
+ val footer = convertView.findViewById(R.id.textview_status_footer) as TextView
+ footer.textSize = (textSize - 2).toFloat()
+ footer.text = getFooterText(directMessage, Application.currentWorld!!.account)
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.java
deleted file mode 100644
index 7ed9636b..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view;
-
-import android.app.AlertDialog;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.EditTextPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.BuildConfig;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.LicenseActivity;
-
-import static android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-
-public class SettingFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener,
- Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- String newValueStr = String.valueOf(newValue);
- if (preference.getKey().contentEquals(getString(R.string.key_setting_text_size))) {
- if (TextUtils.isDigitsOnly(newValueStr)) {
- return true;
- } else {
- Application.toast(R.string.error_setting_text_size_not_number);
- }
- return false;
- } else if (preference.getKey().contentEquals(getString(R.string.key_setting_theme))) {
- Application.toast(R.string.notice_theme_changed);
- }
- return true;
- }
-
- // --------------------- Interface OnPreferenceClickListener ---------------------
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- String key = preference.getKey();
- if (key.contentEquals(getString(R.string.key_setting_application_information))) {
- openAppInfoDialog();
- } else if (key.contentEquals(getString(R.string.key_setting_licenses))) {
- openLicenseActivity();
- }
- return true;
- }
-
- // --------------------- Interface OnSharedPreferenceChangeListener ---------------------
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- setSummaryCurrentValue();
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.setting);
- EditTextPreference textSizePreference = (EditTextPreference) findPreference(R.string.key_setting_text_size);
- textSizePreference.setSummary(textSizePreference.getText());
- textSizePreference.setOnPreferenceChangeListener(this);
- ListPreference themePreference = (ListPreference) findPreference(R.string.key_setting_theme);
- themePreference.setSummary(themePreference.getEntry());
- themePreference.setOnPreferenceChangeListener(this);
- Preference appInfoPreference = findPreference(R.string.key_setting_application_information);
- appInfoPreference.setOnPreferenceClickListener(this);
- appInfoPreference.setSummary(BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")");
- Preference license = findPreference(R.string.key_setting_licenses);
- license.setOnPreferenceClickListener(this);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
- sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
- sharedPreferences.registerOnSharedPreferenceChangeListener(this);
- }
-
- // -------------------------- OTHER METHODS --------------------------
-
- public Preference findPreference(int preferenceResID) {
- return findPreference(getString(preferenceResID));
- }
-
- private void openLicenseActivity() {
- Intent intent = new Intent(getActivity(), LicenseActivity.class);
- getActivity().startActivity(intent);
- }
-
- private void openAppInfoDialog() {
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View contentView = inflater.inflate(R.layout.dialog_app_info, null);
- TextView versionTextView = (TextView) contentView.findViewById(R.id.versionTextView);
- versionTextView.setText(BuildConfig.VERSION_NAME + " (rev: " + BuildConfig.VERSION_CODE + "; upstream: " + getString(R.string.app_version_full) + ")");
-
- new AlertDialog.Builder(getActivity())
- .setTitle(R.string.dialog_title_about)
- .setView(contentView)
- .setPositiveButton(R.string.alert_dialog_ok, (dialog, which) -> dialog.dismiss())
- .create().show();
- }
-
- private void setSummaryCurrentValue() {
- EditTextPreference textSizePreference = (EditTextPreference) findPreference(R.string.key_setting_text_size);
- textSizePreference.setSummary(textSizePreference.getText());
- ListPreference themePreference = (ListPreference) findPreference(R.string.key_setting_theme);
- themePreference.setSummary(themePreference.getEntry());
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt
new file mode 100644
index 00000000..05490f97
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt
@@ -0,0 +1,140 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view
+
+import android.app.AlertDialog
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.preference.EditTextPreference
+import android.preference.ListPreference
+import android.preference.Preference
+import android.preference.PreferenceFragment
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.TextView
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.BuildConfig
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.LicenseActivity
+
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener
+
+class SettingFragment : PreferenceFragment(), OnSharedPreferenceChangeListener, Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
+ override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
+ val newValueStr = newValue.toString()
+ if (preference.key.contentEquals(getString(R.string.key_setting_text_size))) {
+ if (TextUtils.isDigitsOnly(newValueStr)) {
+ return true
+ } else {
+ Application.toast(R.string.error_setting_text_size_not_number)
+ }
+ return false
+ } else if (preference.key.contentEquals(getString(R.string.key_setting_theme))) {
+ Application.toast(R.string.notice_theme_changed)
+ }
+ return true
+ }
+
+ // --------------------- Interface OnPreferenceClickListener ---------------------
+
+ override fun onPreferenceClick(preference: Preference): Boolean {
+ val key = preference.key
+ if (key.contentEquals(getString(R.string.key_setting_application_information))) {
+ openAppInfoDialog()
+ } else if (key.contentEquals(getString(R.string.key_setting_licenses))) {
+ openLicenseActivity()
+ }
+ return true
+ }
+
+ // --------------------- Interface OnSharedPreferenceChangeListener ---------------------
+
+ override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
+ setSummaryCurrentValue()
+ }
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ addPreferencesFromResource(R.xml.setting)
+ val textSizePreference = findPreference(R.string.key_setting_text_size) as EditTextPreference
+ textSizePreference.summary = textSizePreference.text
+ textSizePreference.onPreferenceChangeListener = this
+ val themePreference = findPreference(R.string.key_setting_theme) as ListPreference
+ themePreference.summary = themePreference.entry
+ themePreference.onPreferenceChangeListener = this
+ val appInfoPreference = findPreference(R.string.key_setting_application_information)
+ appInfoPreference.onPreferenceClickListener = this
+ appInfoPreference.summary = BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")"
+ val license = findPreference(R.string.key_setting_licenses)
+ license.onPreferenceClickListener = this
+ }
+
+ override fun onPause() {
+ super.onPause()
+ val sharedPreferences = preferenceScreen.sharedPreferences
+ sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ val sharedPreferences = preferenceScreen.sharedPreferences
+ sharedPreferences.registerOnSharedPreferenceChangeListener(this)
+ }
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ fun findPreference(preferenceResID: Int): Preference {
+ return findPreference(getString(preferenceResID))
+ }
+
+ private fun openLicenseActivity() {
+ val intent = Intent(activity, LicenseActivity::class.java)
+ activity.startActivity(intent)
+ }
+
+ private fun openAppInfoDialog() {
+ val inflater = activity.layoutInflater
+ val contentView = inflater.inflate(R.layout.dialog_app_info, null)
+ val versionTextView = contentView.findViewById(R.id.versionTextView) as TextView
+ versionTextView.text = BuildConfig.VERSION_NAME + " (rev: " + BuildConfig.VERSION_CODE + "; upstream: " + getString(R.string.app_version_full) + ")"
+
+ AlertDialog.Builder(activity)
+ .setTitle(R.string.dialog_title_about)
+ .setView(contentView)
+ .setPositiveButton(R.string.alert_dialog_ok) { dialog, which -> dialog.dismiss() }
+ .create().show()
+ }
+
+ private fun setSummaryCurrentValue() {
+ val textSizePreference = findPreference(R.string.key_setting_text_size) as EditTextPreference
+ textSizePreference.summary = textSizePreference.text
+ val themePreference = findPreference(R.string.key_setting_theme) as ListPreference
+ themePreference.summary = themePreference.entry
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.java b/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.java
deleted file mode 100644
index d5358db5..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package net.lacolaco.smileessence.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.widget.Button;
-import net.lacolaco.smileessence.R;
-
-public class ThreeStateButton extends Button {
- public static final int STATE_OFF = 0;
- public static final int STATE_ON = 1;
- public static final int STATE_LOCKED = 2;
-
- private int state = STATE_OFF;
- private String texts[] = new String[3];
- private Drawable backgrounds[] = new Drawable[3];
-
- public ThreeStateButton(Context context) {
- this(context, null);
- }
-
- public ThreeStateButton(Context context, AttributeSet attrs) {
- this(context, attrs, android.R.attr.buttonStyle);
- }
-
- public ThreeStateButton(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public ThreeStateButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
-
- TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ThreeStateButton);
- texts[STATE_OFF] = ta.getString(R.styleable.ThreeStateButton_off_text);
- texts[STATE_ON] = ta.getString(R.styleable.ThreeStateButton_on_text);
- texts[STATE_LOCKED] = ta.getString(R.styleable.ThreeStateButton_locked_text);
- backgrounds[STATE_OFF] = ta.getDrawable(R.styleable.ThreeStateButton_off_background);
- backgrounds[STATE_ON] = ta.getDrawable(R.styleable.ThreeStateButton_on_background);
- backgrounds[STATE_LOCKED] = ta.getDrawable(R.styleable.ThreeStateButton_locked_background);
- ta.recycle();
-
- setState(STATE_OFF);
- }
-
- public int getState() {
- return state;
- }
-
- public void setState(int s) {
- state = s;
- setText(texts[state]);
- setBackground(backgrounds[state]);
- setEnabled(state != STATE_LOCKED);
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.kt b/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.kt
new file mode 100644
index 00000000..547aa84d
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/ThreeStateButton.kt
@@ -0,0 +1,41 @@
+package net.lacolaco.smileessence.view
+
+import android.content.Context
+import android.content.res.TypedArray
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.widget.Button
+import net.lacolaco.smileessence.R
+
+class ThreeStateButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.buttonStyle, defStyleRes: Int = 0) : Button(context, attrs, defStyleAttr, defStyleRes) {
+
+ var state = STATE_OFF
+ set(s) {
+ field = s
+ text = texts[this.state]
+ background = backgrounds[this.state]
+ isEnabled = this.state != STATE_LOCKED
+ }
+ private val texts = arrayOfNulls<String>(3)
+ private val backgrounds = arrayOfNulls<Drawable>(3)
+
+ init {
+
+ val ta = context.obtainStyledAttributes(attrs, R.styleable.ThreeStateButton)
+ texts[STATE_OFF] = ta.getString(R.styleable.ThreeStateButton_off_text)
+ texts[STATE_ON] = ta.getString(R.styleable.ThreeStateButton_on_text)
+ texts[STATE_LOCKED] = ta.getString(R.styleable.ThreeStateButton_locked_text)
+ backgrounds[STATE_OFF] = ta.getDrawable(R.styleable.ThreeStateButton_off_background)
+ backgrounds[STATE_ON] = ta.getDrawable(R.styleable.ThreeStateButton_on_background)
+ backgrounds[STATE_LOCKED] = ta.getDrawable(R.styleable.ThreeStateButton_locked_background)
+ ta.recycle()
+
+ state = STATE_OFF
+ }
+
+ companion object {
+ val STATE_OFF = 0
+ val STATE_ON = 1
+ val STATE_LOCKED = 2
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ToggleableImageButton.java b/app/src/main/java/net/lacolaco/smileessence/view/ToggleableImageButton.java
deleted file mode 100644
index b7b2d174..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/ToggleableImageButton.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package net.lacolaco.smileessence.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.widget.ImageButton;
-import net.lacolaco.smileessence.R;
-
-public class ToggleableImageButton extends ImageButton {
- private Drawable onSrc, offSrc;
-
- public ToggleableImageButton(Context context) {
- this(context, null);
- }
-
- public ToggleableImageButton(Context context, AttributeSet attrs) {
- this(context, attrs, android.R.attr.imageButtonStyle);
- }
-
- public ToggleableImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public ToggleableImageButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
-
- TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ToggleableImageButton);
- offSrc = ta.getDrawable(R.styleable.ToggleableImageButton_offSrc);
- onSrc = ta.getDrawable(R.styleable.ToggleableImageButton_onSrc);
- ta.recycle();
- }
-
- public void setState(boolean isOn) {
- setImageDrawable(isOn ? onSrc : offSrc);
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/ToggleableImageButton.kt b/app/src/main/java/net/lacolaco/smileessence/view/ToggleableImageButton.kt
new file mode 100644
index 00000000..47a1821a
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/ToggleableImageButton.kt
@@ -0,0 +1,25 @@
+package net.lacolaco.smileessence.view
+
+import android.content.Context
+import android.content.res.TypedArray
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.widget.ImageButton
+import net.lacolaco.smileessence.R
+
+class ToggleableImageButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.imageButtonStyle, defStyleRes: Int = 0) : ImageButton(context, attrs, defStyleAttr, defStyleRes) {
+ private val onSrc: Drawable
+ private val offSrc: Drawable
+
+ init {
+
+ val ta = context.obtainStyledAttributes(attrs, R.styleable.ToggleableImageButton)
+ offSrc = ta.getDrawable(R.styleable.ToggleableImageButton_offSrc)
+ onSrc = ta.getDrawable(R.styleable.ToggleableImageButton_onSrc)
+ ta.recycle()
+ }
+
+ fun setState(isOn: Boolean) {
+ setImageDrawable(if (isOn) onSrc else offSrc)
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.java
deleted file mode 100644
index 6d7420fb..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package net.lacolaco.smileessence.view.adapter;
-
-import android.widget.BaseAdapter;
-import net.lacolaco.smileessence.util.UIHandler;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public abstract class CustomListAdapter<T> extends BaseAdapter {
- private boolean isNotifiable = true;
- private List<T> frozenList = new ArrayList<>();
-
- public final void setNotifiable(boolean notifiable) {
- isNotifiable = notifiable;
- }
-
- @Override
- public final int getCount() {
- return frozenList.size();
- }
-
- @Override
- public final T getItem(int position) {
- return frozenList.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public final void notifyDataSetChanged() {
- frozenList = Collections.unmodifiableList(getList());
- super.notifyDataSetChanged();
- }
-
- protected abstract List<T> getList();
-
- public void update() {
- if (isNotifiable) {
- updateForce();
- }
- }
-
- public void updateForce() {
- new UIHandler().post(this::notifyDataSetChanged);
- }
-} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.kt
new file mode 100644
index 00000000..3b022012
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/CustomListAdapter.kt
@@ -0,0 +1,45 @@
+package net.lacolaco.smileessence.view.adapter
+
+import android.widget.BaseAdapter
+import net.lacolaco.smileessence.util.UIHandler
+
+import java.util.ArrayList
+import java.util.Collections
+
+abstract class CustomListAdapter<T> : BaseAdapter() {
+ private var isNotifiable = true
+ private var frozenList: List<T> = ArrayList()
+
+ fun setNotifiable(notifiable: Boolean) {
+ isNotifiable = notifiable
+ }
+
+ override fun getCount(): Int {
+ return frozenList.size
+ }
+
+ override fun getItem(position: Int): T {
+ return frozenList[position]
+ }
+
+ override fun getItemId(position: Int): Long {
+ return position.toLong()
+ }
+
+ override fun notifyDataSetChanged() {
+ frozenList = Collections.unmodifiableList(list)
+ super.notifyDataSetChanged()
+ }
+
+ protected abstract val list: List<T>
+
+ fun update() {
+ if (isNotifiable) {
+ updateForce()
+ }
+ }
+
+ fun updateForce() {
+ UIHandler().post { this.notifyDataSetChanged() }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.java
deleted file mode 100644
index 3f98cfaa..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.adapter;
-
-import android.app.Activity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-import com.android.volley.toolbox.NetworkImageView;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.World;
-import net.lacolaco.smileessence.data.ImageCache;
-import net.lacolaco.smileessence.entity.Event;
-import net.lacolaco.smileessence.entity.RBinding;
-import net.lacolaco.smileessence.preference.UserPreferenceHelper;
-import net.lacolaco.smileessence.util.StringUtils;
-import net.lacolaco.smileessence.util.UIObserverBundle;
-import net.lacolaco.smileessence.view.DialogHelper;
-import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment;
-import net.lacolaco.smileessence.view.listener.ListItemClickListener;
-
-import java.lang.ref.WeakReference;
-import java.util.List;
-
-public class EventListAdapter extends CustomListAdapter<Event> {
- private final World world;
- private final Activity activity;
-
- public EventListAdapter(World world, Activity activity) {
- super();
- this.world = world;
- this.activity = activity;
- }
-
- @Override
- protected List<Event> getList() {
- return world.getEvents();
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Event event = getItem(position);
- if (convertView == null) {
- convertView = activity.getLayoutInflater().inflate(R.layout.list_item_status, null);
- }
- UIObserverBundle bundle = (UIObserverBundle) convertView.getTag();
- if (bundle != null) {
- bundle.detachAll();
- } else {
- bundle = new UIObserverBundle();
- convertView.setTag(bundle);
- }
-
- int textSize = UserPreferenceHelper.getInstance().getTextSize();
-
- TextView header = (TextView) convertView.findViewById(R.id.textview_status_header);
- header.setTextSize(textSize);
-
- updateViewUser(event, convertView);
-
- TextView content = (TextView) convertView.findViewById(R.id.textview_status_text);
- content.setTextSize(textSize);
- content.setText(event.getTargetObject() != null ? event.getTargetObject().getText() : "");
- TextView footer = (TextView) convertView.findViewById(R.id.textview_status_footer);
- footer.setTextSize(textSize - 2);
- footer.setText(StringUtils.dateToString(event.getCreatedAt()));
- ImageView favorited = (ImageView) convertView.findViewById(R.id.imageview_status_favorited);
- favorited.setVisibility(View.GONE);
- convertView.setOnClickListener(new ListItemClickListener(activity, () -> {
- UserDetailDialogFragment fragment = new UserDetailDialogFragment();
- fragment.setUserID(event.getSource().getId());
- DialogHelper.showDialog(activity, fragment);
- }));
-
- final WeakReference<View> weakView = new WeakReference<>(convertView);
- bundle.attach(event.getSource(), changes -> {
- View strongView = weakView.get();
- if (strongView != null && changes.contains(RBinding.BASIC))
- updateViewUser(event, strongView);
- });
-
- return convertView;
- }
-
- private void updateViewUser(Event event, View convertedView) {
- NetworkImageView icon = (NetworkImageView) convertedView.findViewById(R.id.imageview_status_icon);
- String iconUrl = event.getSource().getProfileImageUrlOriginal();
- icon.setImageUrl(iconUrl, ImageCache.getImageLoader());
-
- TextView header = (TextView) convertedView.findViewById(R.id.textview_status_header);
- header.setText(event.getFormattedString());
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.kt
new file mode 100644
index 00000000..1c19d4ec
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.kt
@@ -0,0 +1,102 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.adapter
+
+import android.app.Activity
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import com.android.volley.toolbox.NetworkImageView
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.data.ImageCache
+import net.lacolaco.smileessence.entity.Event
+import net.lacolaco.smileessence.entity.RBinding
+import net.lacolaco.smileessence.preference.UserPreferenceHelper
+import net.lacolaco.smileessence.util.StringUtils
+import net.lacolaco.smileessence.util.UIObserverBundle
+import net.lacolaco.smileessence.view.DialogHelper
+import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment
+import net.lacolaco.smileessence.view.listener.ListItemClickListener
+
+import java.lang.ref.WeakReference
+
+class EventListAdapter(private val world: World, private val activity: Activity) : CustomListAdapter<Event>() {
+ override val list: List<Event>
+ get() = world.events
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ var convertView = convertView
+ val event = getItem(position)
+ if (convertView == null) {
+ convertView = activity.layoutInflater.inflate(R.layout.list_item_status, null)
+ }
+ var bundle: UIObserverBundle? = convertView!!.tag as UIObserverBundle?
+ if (bundle != null) {
+ bundle.detachAll()
+ } else {
+ bundle = UIObserverBundle()
+ convertView.tag = bundle
+ }
+
+ val textSize = UserPreferenceHelper.instance.textSize
+
+ val header = convertView.findViewById(R.id.textview_status_header) as TextView
+ header.textSize = textSize.toFloat()
+
+ updateViewUser(event, convertView)
+
+ val content = convertView.findViewById(R.id.textview_status_text) as TextView
+ content.textSize = textSize.toFloat()
+ content.text = event.targetObject?.text ?: ""
+ val footer = convertView.findViewById(R.id.textview_status_footer) as TextView
+ footer.textSize = (textSize - 2).toFloat()
+ footer.text = StringUtils.dateToString(event.createdAt)
+ val favorited = convertView.findViewById(R.id.imageview_status_favorited) as ImageView
+ favorited.visibility = View.GONE
+ convertView.setOnClickListener(ListItemClickListener(activity) {
+ DialogHelper.showDialog(activity, UserDetailDialogFragment.newInstance(event.source))
+ })
+
+ val weakView = WeakReference(convertView)
+ bundle.attach(event.source) { changes ->
+ val strongView = weakView.get()
+ if (strongView != null && changes.contains(RBinding.BASIC))
+ updateViewUser(event, strongView)
+ }
+
+ return convertView
+ }
+
+ private fun updateViewUser(event: Event, convertedView: View) {
+ val icon = convertedView.findViewById(R.id.imageview_status_icon) as NetworkImageView
+ val iconUrl = event.source.profileImageUrl
+ icon.setImageUrl(iconUrl, ImageCache.getImageLoader())
+
+ val header = convertedView.findViewById(R.id.textview_status_header) as TextView
+ header.text = event.formattedString
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.java
deleted file mode 100644
index 9f8e5039..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.adapter;
-
-import android.app.Activity;
-import android.view.View;
-import android.view.ViewGroup;
-import net.lacolaco.smileessence.entity.DirectMessage;
-import net.lacolaco.smileessence.view.Partials;
-
-public class MessageListAdapter extends OrderedCustomListAdapter<DirectMessage> {
- private final Activity activity;
-
- public MessageListAdapter(Activity activity) {
- super();
- this.activity = activity;
- }
-
- public long getLastID() {
- return getCount() > 0 ? getItem(getCount() - 1).getId() : -1;
- }
-
- public long getTopID() {
- return getCount() > 0 ? getItem(0).getId() : -1;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- return Partials.getDirectMessageView(getItem(position), activity, convertView);
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.kt
new file mode 100644
index 00000000..d72ab564
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.kt
@@ -0,0 +1,43 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.adapter
+
+import android.app.Activity
+import android.view.View
+import android.view.ViewGroup
+import net.lacolaco.smileessence.entity.DirectMessage
+import net.lacolaco.smileessence.view.Partials
+
+class MessageListAdapter(private val activity: Activity) : OrderedCustomListAdapter<DirectMessage>() {
+ val lastID: Long
+ get() = if (count > 0) getItem(count - 1).id else -1
+
+ val topID: Long
+ get() = if (count > 0) getItem(0).id else -1
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ return Partials.getDirectMessageView(getItem(position), activity, convertView)
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.java
deleted file mode 100644
index 3de58658..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package net.lacolaco.smileessence.view.adapter;
-
-import net.lacolaco.smileessence.entity.IdObject;
-
-import java.util.*;
-
-public abstract class OrderedCustomListAdapter<T extends IdObject> extends CustomListAdapter<T> {
- private final Map<Long, T> treeMap;
-
- public OrderedCustomListAdapter() {
- this(Long::compare);
- }
-
- public OrderedCustomListAdapter(Comparator<Long> comparator) {
- super();
- this.treeMap = new TreeMap<>(Collections.reverseOrder(comparator));
- }
-
- @Override
- protected synchronized List<T> getList() {
- return new ArrayList<>(treeMap.values());
- }
-
- public synchronized void add(T item) {
- treeMap.put(item.getId(), item);
- }
-
- public synchronized void addAll(Collection<T> items) {
- for (T item : items) {
- treeMap.put(item.getId(), item);
- }
- }
-
- public synchronized void clear() {
- treeMap.clear();
- }
-
- public synchronized T remove(T item) {
- return treeMap.remove(item.getId());
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.kt
new file mode 100644
index 00000000..53b1c824
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/OrderedCustomListAdapter.kt
@@ -0,0 +1,35 @@
+package net.lacolaco.smileessence.view.adapter
+
+import net.lacolaco.smileessence.entity.IdObject
+
+import java.util.*
+
+abstract class OrderedCustomListAdapter<T : IdObject>
+constructor(comparator: Comparator<Long> = Comparator { x, y -> java.lang.Long.compare(x, y) }) : CustomListAdapter<T>() {
+ private val treeMap: MutableMap<Long, T> = TreeMap(Collections.reverseOrder(comparator))
+
+ override val list: List<T>
+ @Synchronized get() = ArrayList(treeMap.values)
+
+ @Synchronized
+ fun add(item: T) {
+ treeMap.put(item.id, item)
+ }
+
+ @Synchronized
+ fun addAll(items: Collection<T>) {
+ for (item in items) {
+ treeMap.put(item.id, item)
+ }
+ }
+
+ @Synchronized
+ fun clear() {
+ treeMap.clear()
+ }
+
+ @Synchronized
+ fun remove(item: T): T {
+ return treeMap.remove(item.id)!!
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/PageListAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/PageListAdapter.java
deleted file mode 100644
index 76e72093..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/PageListAdapter.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.adapter;
-
-import android.os.Bundle;
-import android.support.v13.app.FragmentPagerAdapter;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.view.page.PageFragment;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class PageListAdapter extends FragmentPagerAdapter {
-
- // ------------------------------ FIELDS ------------------------------
-
- private final List<PageInfo> pages = new ArrayList<>();
- private final Map<Integer, WeakReference<PageFragment>> fragmentCache = new HashMap<>();
-
- // --------------------------- FragmentPagerAdapter ---------------------------
-
- public PageListAdapter(MainActivity _activity) {
- super(_activity.getFragmentManager());
- }
-
- @Override
- public synchronized PageFragment getItem(int position) {
- PageFragment pf;
- PageInfo info = pages.get(position);
- try {
- pf = info.getFragmentClass().newInstance();
- } catch (Exception e) {
- Logger.error("should not happen: fragmentClass is private or Android is broken?");
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- pf.setArguments(info.getArgs());
- fragmentCache.put(position, new WeakReference<>(pf));
- return pf;
- }
-
- public synchronized PageFragment getCachedFragment(int pos) {
- WeakReference<PageFragment> wpf = fragmentCache.get(pos);
- if (wpf == null) {
- return null;
- } else {
- return wpf.get();
- }
- }
-
- @Override
- public synchronized int getCount() {
- return pages.size();
- }
-
- // ------------------------ INTERFACE METHODS ------------------------
-
- // -------------------------- OTHER METHODS --------------------------
-
- public void addPage(Class<? extends PageFragment> klass, String name, Bundle args) {
- this.addPage(klass, name, args, true);
- }
-
- public void addPage(Class<? extends PageFragment> klass, String name, Bundle args, boolean notifyChanged) {
- pages.add(new PageInfo(klass, name, args));
- if (notifyChanged) notifyDataSetChanged();
- }
-
- public synchronized boolean removePage(int position) {
- //if (removePageWithoutNotify(position)) {
- // refreshListNavigation();
- // return true;
- //}
- return pages.remove(position) != null; // TODO
- }
-
- public String getName(int pos) {
- return pages.get(pos).getName();
- }
-
- @Deprecated
- public int getIndex(Class<? extends PageFragment> fragmentClass) {
- for (int i = 0; i < pages.size(); ++i) {
- if (pages.get(i).getFragmentClass() == fragmentClass) {
- return i;
- }
- }
- return -1;
- }
-
- private static final class PageInfo {
- private final Class<? extends PageFragment> fragmentClass;
- private final Bundle args;
- private final String name;
-
- PageInfo(Class<? extends PageFragment> _fragmentClass, String _name, Bundle _args) {
- fragmentClass = _fragmentClass;
- name = _name;
- args = _args;
- }
-
- public Class<? extends PageFragment> getFragmentClass() {
- return fragmentClass;
- }
-
- public String getName() {
- return name;
- }
-
- public Bundle getArgs() {
- return args;
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/PageListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/PageListAdapter.kt
new file mode 100644
index 00000000..34d158f0
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/PageListAdapter.kt
@@ -0,0 +1,110 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.adapter
+
+import android.os.Bundle
+import android.support.v13.app.FragmentPagerAdapter
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.view.page.PageFragment
+
+import java.lang.ref.WeakReference
+import java.util.ArrayList
+import java.util.HashMap
+
+class PageListAdapter
+// --------------------------- FragmentPagerAdapter ---------------------------
+
+(_activity: MainActivity) : FragmentPagerAdapter(_activity.fragmentManager) {
+
+ // ------------------------------ FIELDS ------------------------------
+
+ private val pages = ArrayList<PageInfo>()
+ private val fragmentCache = HashMap<Int, WeakReference<PageFragment<*>>>()
+
+ @Synchronized override fun getItem(position: Int): PageFragment<*> {
+ val pf: PageFragment<*>
+ val info = pages[position]
+ try {
+ pf = info.fragmentClass.newInstance()
+ } catch (e: Exception) {
+ Logger.error("should not happen: fragmentClass is private or Android is broken?")
+ e.printStackTrace()
+ throw RuntimeException(e)
+ }
+
+ pf.arguments = info.args
+ fragmentCache.put(position, WeakReference(pf))
+ return pf
+ }
+
+ @Synchronized
+ fun getCachedFragment(pos: Int): PageFragment<*>? {
+ val wpf = fragmentCache[pos]
+ return wpf?.get()
+ }
+
+ @Synchronized override fun getCount(): Int {
+ return pages.size
+ }
+
+ // ------------------------ INTERFACE METHODS ------------------------
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ fun addPage(klass: Class<out PageFragment<*>>, name: String, args: Bundle) {
+ this.addPage(klass, name, args, true)
+ }
+
+ fun addPage(klass: Class<out PageFragment<*>>, name: String, args: Bundle, notifyChanged: Boolean) {
+ pages.add(PageInfo(klass, name, args))
+ if (notifyChanged) notifyDataSetChanged()
+ }
+
+ @Synchronized
+ fun removePage(position: Int): Boolean {
+ //if (removePageWithoutNotify(position)) {
+ // refreshListNavigation();
+ // return true;
+ //}
+ return pages.removeAt(position) != null // TODO
+ }
+
+ fun getName(pos: Int): String {
+ return pages[pos].name
+ }
+
+ @Deprecated("")
+ fun getIndex(fragmentClass: Class<out PageFragment<*>>): Int {
+ for (i in pages.indices) {
+ if (pages[i].fragmentClass == fragmentClass) {
+ return i
+ }
+ }
+ return -1
+ }
+
+ private class PageInfo internal constructor(val fragmentClass: Class<out PageFragment<*>>, val name: String, val args: Bundle)
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.java b/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.java
deleted file mode 100644
index 0dbe8d53..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package net.lacolaco.smileessence.view.adapter;
-
-import android.app.Activity;
-import android.view.View;
-import android.view.ViewGroup;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.view.Partials;
-
-import java.util.*;
-
-public class TimelineAdapter extends OrderedCustomListAdapter<Tweet> {
- private final Activity activity;
-
- public TimelineAdapter(Activity activity) {
- super();
- this.activity = activity;
- }
-
- public long getLastID() {
- if (getCount() > 0) {
- return getItem(getCount() - 1).getId();
- } else {
- return -1;
- }
- }
-
- public long getTopID() {
- if (getCount() > 0) {
- return getItem(0).getId();
- } else {
- return -1;
- }
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- return Partials.getTweetView(getItem(position), activity, convertView, true);
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.kt
new file mode 100644
index 00000000..750b63a0
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/TimelineAdapter.kt
@@ -0,0 +1,29 @@
+package net.lacolaco.smileessence.view.adapter
+
+import android.app.Activity
+import android.view.View
+import android.view.ViewGroup
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.view.Partials
+
+import java.util.*
+
+class TimelineAdapter(private val activity: Activity) : OrderedCustomListAdapter<Tweet>() {
+ val lastID: Long
+ get() = if (count > 0) {
+ getItem(count - 1).id
+ } else {
+ -1
+ }
+
+ val topID: Long
+ get() = if (count > 0) {
+ getItem(0).id
+ } else {
+ -1
+ }
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ return Partials.getTweetView(getItem(position), activity, convertView, true)
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/ConfirmDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/ConfirmDialogFragment.java
deleted file mode 100644
index 74dcc468..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/ConfirmDialogFragment.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.dialog;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.preference.UserPreferenceHelper;
-import net.lacolaco.smileessence.view.DialogHelper;
-
-public abstract class ConfirmDialogFragment extends StackableDialogFragment {
-
- // ------------------------------ FIELDS ------------------------------
-
- private static final String ARG_TEXT = "text";
- private final DialogInterface.OnClickListener listener = (dialog, which) -> {
- onButtonClick(which);
- dialog.dismiss();
- };
- private String text;
-
- // -------------------------- STATIC METHODS --------------------------
-
- public static void show(Activity activity, String text, final Runnable onYes) {
- show(activity, text, onYes, null, true);
- }
-
- public static void show(Activity activity, String text, final Runnable onYes, boolean ignorable) {
- show(activity, text, onYes, null, ignorable);
- }
-
- public static void show(Activity activity, String text, final Runnable onOK, final Runnable onCancel, boolean ignorable) {
- boolean confirm = UserPreferenceHelper.getInstance().get(R.string.key_setting_show_confirm_dialog, true);
- if (!confirm && ignorable) {
- onOK.run();
- return;
- }
- final ConfirmDialogFragment fragment = new ConfirmDialogFragment() {
- @Override
- public void onButtonClick(int which) {
- switch (which) {
- case DialogInterface.BUTTON_POSITIVE: {
- if (onOK != null) {
- dismiss();
- onOK.run();
- }
- break;
- }
- case DialogInterface.BUTTON_NEGATIVE: {
- if (onCancel != null) {
- dismiss();
- onCancel.run();
- }
- break;
- }
- }
- }
- };
- fragment.setText(text);
- DialogHelper.showDialog(activity, fragment);
- }
-
- // --------------------- GETTER / SETTER METHODS ---------------------
-
- public void setText(String text) {
- Bundle args = new Bundle();
- args.putString(ARG_TEXT, text);
- setArguments(args);
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Bundle args = getArguments();
- if (args != null) {
- text = args.getString(ARG_TEXT);
- }
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- return new AlertDialog.Builder(getActivity()).setTitle(text)
- .setCancelable(false)
- .setPositiveButton(R.string.alert_dialog_ok, listener)
- .setNegativeButton(R.string.alert_dialog_cancel, listener)
- .create();
- }
-
- // -------------------------- OTHER METHODS --------------------------
-
- protected abstract void onButtonClick(int which);
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/ConfirmDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/ConfirmDialogFragment.kt
new file mode 100644
index 00000000..094aa18a
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/ConfirmDialogFragment.kt
@@ -0,0 +1,119 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.dialog
+
+import android.app.Activity
+import android.app.AlertDialog
+import android.app.Dialog
+import android.content.DialogInterface
+import android.os.Bundle
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.preference.UserPreferenceHelper
+import net.lacolaco.smileessence.view.DialogHelper
+
+abstract class ConfirmDialogFragment : StackableDialogFragment() {
+ private var text: String? = null
+
+ // --------------------- GETTER / SETTER METHODS ---------------------
+
+ fun setText(text: String) {
+ val args = Bundle()
+ args.putString(ARG_TEXT, text)
+ arguments = args
+ }
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val args = arguments
+ if (args != null) {
+ text = args.getString(ARG_TEXT)
+ }
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ return AlertDialog.Builder(activity).setTitle(text)
+ .setCancelable(false)
+ .setPositiveButton(R.string.alert_dialog_ok, { dialog, which ->
+ onButtonClick(which)
+ dialog.dismiss()
+ })
+ .setNegativeButton(R.string.alert_dialog_cancel, { dialog, which ->
+ onButtonClick(which)
+ dialog.dismiss()
+ })
+ .create()
+ }
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ protected abstract fun onButtonClick(which: Int)
+
+ companion object {
+
+ // ------------------------------ FIELDS ------------------------------
+
+ private val ARG_TEXT = "text"
+
+ // -------------------------- STATIC METHODS --------------------------
+
+ fun show(activity: Activity, text: String, onYes: () -> Unit) {
+ show(activity, text, onYes, null, true)
+ }
+
+ fun show(activity: Activity, text: String, onYes: () -> Unit, ignorable: Boolean) {
+ show(activity, text, onYes, null, ignorable)
+ }
+
+ fun show(activity: Activity, text: String, onOK: (() -> Unit)?, onCancel: (() -> Unit)?, ignorable: Boolean) {
+ val confirm = UserPreferenceHelper.instance.get(R.string.key_setting_show_confirm_dialog, true)
+ if (!confirm && ignorable) {
+ onOK!!()
+ return
+ }
+ val fragment = object : ConfirmDialogFragment() {
+ public override fun onButtonClick(which: Int) {
+ when (which) {
+ DialogInterface.BUTTON_POSITIVE -> {
+ if (onOK != null) {
+ dismiss()
+ onOK()
+ }
+ }
+ DialogInterface.BUTTON_NEGATIVE -> {
+ if (onCancel != null) {
+ dismiss()
+ onCancel()
+ }
+ }
+ }
+ }
+ }
+ fragment.setText(text)
+ DialogHelper.showDialog(activity, fragment)
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/DisposeDialog.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/DisposeDialog.kt
index eb3d3613..3cd486bd 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/DisposeDialog.java
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/DisposeDialog.kt
@@ -22,22 +22,16 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.view.dialog;
+package net.lacolaco.smileessence.view.dialog
-import android.app.Dialog;
-import android.content.Context;
+import android.app.Dialog
+import android.content.Context
/**
* Dialog for dispose soon.
*/
-public final class DisposeDialog extends Dialog {
-
- public DisposeDialog(Context context) {
- super(context);
- }
-
- @Override
- public void show() {
- dismiss();
+class DisposeDialog(context: Context) : Dialog(context) {
+ override fun show() {
+ dismiss()
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.java
deleted file mode 100644
index 8ce25145..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.EditText;
-import net.lacolaco.smileessence.R;
-
-public abstract class EditTextDialogFragment extends DialogFragment {
-
- // ------------------------------ FIELDS ------------------------------
-
- private static final String titleKey = "title";
- private static final String textKey = "text";
- private String title;
- private String text;
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Bundle args = getArguments();
- text = args.getString(textKey);
- title = args.getString(titleKey);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- View view = getActivity().getLayoutInflater().inflate(R.layout.part_edittext, null);
- final EditText editText = (EditText) view.findViewById(R.id.part_edittext);
- editText.setText(text);
- return new AlertDialog.Builder(getActivity())
- .setTitle(title)
- .setView(view)
- .setPositiveButton(R.string.alert_dialog_ok, (dialog, which) -> {
- onTextInput(editText.getText().toString());
- dialog.dismiss();
- })
- .setNegativeButton(R.string.alert_dialog_cancel, (dialog, which) -> dialog.dismiss())
- .create();
- }
-
- // -------------------------- OTHER METHODS --------------------------
-
- public abstract void onTextInput(String text);
-
- public void setParams(String title, String text) {
- Bundle args = new Bundle();
- args.putString(titleKey, title);
- args.putString(textKey, text);
- setArguments(args);
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.kt
new file mode 100644
index 00000000..399b84ad
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/EditTextDialogFragment.kt
@@ -0,0 +1,81 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.dialog
+
+import android.app.AlertDialog
+import android.app.Dialog
+import android.app.DialogFragment
+import android.os.Bundle
+import android.view.View
+import android.widget.EditText
+import net.lacolaco.smileessence.R
+
+abstract class EditTextDialogFragment : DialogFragment() {
+ private lateinit var title: String
+ private lateinit var text: String
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val args = arguments
+ text = args.getString(textKey)
+ title = args.getString(titleKey)
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val view = activity.layoutInflater.inflate(R.layout.part_edittext, null)
+ val editText = view.findViewById(R.id.part_edittext) as EditText
+ editText.setText(text)
+ return AlertDialog.Builder(activity)
+ .setTitle(title)
+ .setView(view)
+ .setPositiveButton(R.string.alert_dialog_ok) { dialog, which ->
+ onTextInput(editText.text.toString())
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.alert_dialog_cancel) { dialog, which -> dialog.dismiss() }
+ .create()
+ }
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ abstract fun onTextInput(text: String)
+
+ fun setParams(title: String, text: String) {
+ val args = Bundle()
+ args.putString(titleKey, title)
+ args.putString(textKey, text)
+ arguments = args
+ }
+
+ companion object {
+
+ // ------------------------------ FIELDS ------------------------------
+
+ private val titleKey = "title"
+ private val textKey = "text"
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.java
deleted file mode 100644
index f8a1e2e5..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2015 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.ListView;
-import android.widget.TextView;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.command.Command;
-import net.lacolaco.smileessence.command.CommandAddHashtag;
-import net.lacolaco.smileessence.command.CommandOpenURL;
-import net.lacolaco.smileessence.command.CommandOpenUserDetail;
-import net.lacolaco.smileessence.entity.DirectMessage;
-import net.lacolaco.smileessence.preference.UserPreferenceHelper;
-import net.lacolaco.smileessence.twitter.task.Messages;
-import net.lacolaco.smileessence.util.SystemServiceHelper;
-import net.lacolaco.smileessence.view.DialogHelper;
-import net.lacolaco.smileessence.view.Partials;
-import net.lacolaco.smileessence.view.adapter.CustomListAdapter;
-import net.lacolaco.smileessence.view.adapter.MessageListAdapter;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class MessageDetailDialogFragment extends StackableDialogFragment implements View.OnClickListener {
- private static final String KEY_MESSAGE_ID = "message_id";
- private DirectMessage message;
-
- public static MessageDetailDialogFragment newInstance(DirectMessage message) {
- MessageDetailDialogFragment obj = new MessageDetailDialogFragment();
- Bundle args = new Bundle();
- args.putLong(KEY_MESSAGE_ID, message.getId());
- obj.setArguments(args);
- return obj;
- }
-
- @Override
- public void onClick(final View v) {
- switch (v.getId()) {
- case R.id.button_status_detail_reply: {
- openSendMessageDialog();
- break;
- }
- case R.id.button_status_detail_delete: {
- deleteMessage();
- break;
- }
- case R.id.button_status_detail_menu: {
- openMenu();
- break;
- }
- default: {
- dismiss();
- }
- }
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- message = DirectMessage.fetch(getArguments().getLong(KEY_MESSAGE_ID));
- if (message == null) {
- getWorld().notifyError(R.string.notice_error_get_messages);
- return new DisposeDialog(getActivity());
- }
-
- View header = getTitleView();
- ListView listView = (ListView) header.findViewById(R.id.listview_status_detail_reply_to);
- final MessageListAdapter adapter = new MessageListAdapter(getActivity());
- listView.setAdapter(adapter);
-
- // TODO: 効率的な探索どうする
- DirectMessage replyTo = null;
- // FIXME
- // for (DirectMessage mes : DirectMessage.cached()) {
- // if (message.getId() > mes.getId() &&
- // message.getRecipient() == mes.getSender() &&
- // message.getSender() == mes.getRecipient() &&
- // (replyTo == null || replyTo.getId() < mes.getId())) {
- // replyTo = mes;
- // }
- // }
- if (replyTo != null) {
- listView.setVisibility(View.VISIBLE);
- adapter.add(replyTo);
- adapter.updateForce();
- } else {
- listView.setVisibility(View.GONE);
- }
-
- return new AlertDialog.Builder(getActivity()).setView(header).create();
- }
-
- // -------------------------- OTHER METHODS --------------------------
-
- private void deleteMessage() {
- ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () -> {
- new Messages.DestroyTask(getWorld().getAccount(), message.getId())
- .onDone(x -> getWorld().notify(R.string.notice_message_delete_succeeded))
- .onFail(x -> getWorld().notifyError(R.string.notice_message_delete_failed))
- .execute();
- dismiss();
- });
- }
-
- private void openSendMessageDialog() {
- DialogHelper.showDialog(getActivity(), SendMessageDialogFragment.newInstance(message.getSender()));
- }
-
- private View getTitleView() {
- MainActivity activity = (MainActivity) getActivity();
-
- View view = activity.getLayoutInflater().inflate(R.layout.dialog_status_detail, null);
-
- View messageHeader = Partials.getDirectMessageView(message, activity, view.findViewById(R.id.layout_status_header));
- messageHeader.setClickable(false);
-
- view.setBackgroundColor(((ColorDrawable) messageHeader.getBackground()).getColor());
- updateViewButtons(view);
- updateViewMenu(view);
-
- // status only parts
- view.findViewById(R.id.detail_dialog_divider_top).setVisibility(View.GONE);
- view.findViewById(R.id.button_status_detail_retweet).setVisibility(View.GONE);
- view.findViewById(R.id.button_status_detail_favorite).setVisibility(View.GONE);
- view.findViewById(R.id.image_status_detail_fav_count).setVisibility(View.GONE);
- view.findViewById(R.id.image_status_detail_rt_count).setVisibility(View.GONE);
-
- return view;
- }
-
- private void updateViewButtons(View view) {
- //--- buttons
- ImageButton reply = (ImageButton) view.findViewById(R.id.button_status_detail_reply);
- reply.setOnClickListener(this);
-
- ImageButton delete = (ImageButton) view.findViewById(R.id.button_status_detail_delete);
- delete.setOnClickListener(this);
- delete.setVisibility(View.VISIBLE);
- }
-
- private void updateViewMenu(View view) {
- // -- menu dialog
- ImageButton menu = (ImageButton) view.findViewById(R.id.button_status_detail_menu);
- menu.setOnClickListener(this);
-
- // -- menu embedded in dialog
- View divider = view.findViewById(R.id.detail_dialog_divider_bottom);
- ListView listView = (ListView) view.findViewById(R.id.listview_status_detail_menu);
- List<Command> commands = getCommands();
- if (commands.size() > 0) {
- divider.setVisibility(View.VISIBLE);
- listView.setVisibility(View.VISIBLE);
- final CustomListAdapter<Command> adapter = new CustomListAdapter<Command>() {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = getActivity().getLayoutInflater().inflate(R.layout.menu_item_simple_text, null);
- }
- TextView textView = (TextView) convertView.findViewById(R.id.list_item_textview);
- textView.setTextSize(UserPreferenceHelper.getInstance().getTextSize());
- textView.setText(getItem(position).getText());
- return convertView;
- }
-
- @Override
- protected List<Command> getList() {
- return commands;
- }
- };
- adapter.update();
- listView.setAdapter(adapter);
- listView.setOnItemClickListener((parent, view1, position, id) -> {
- Command command = (Command) parent.getItemAtPosition(position);
- command.execute();
- });
- } else {
- divider.setVisibility(View.GONE);
- listView.setVisibility(View.GONE);
- }
- }
-
- private List<Command> getCommands() {
- MainActivity activity = (MainActivity) getActivity();
- List<Command> commands = new ArrayList<>();
- // Mentions
- if (message.getSender() != message.getRecipient()) {
- commands.add(new CommandOpenUserDetail(activity, message.getRecipient().getScreenName()));
- }
- for (String screenName : message.getMentions()) {
- commands.add(new CommandOpenUserDetail(activity, screenName));
- }
- for (String hashtag : message.getHashtags()) {
- commands.add(new CommandAddHashtag(activity, hashtag));
- }
- // URL
- for (String url : message.getUrlsExpanded()) {
- commands.add(new CommandOpenURL(activity, url));
- }
- for (String url : message.getMediaUrls()) {
- commands.add(new CommandOpenURL(activity, url));
- }
- return commands;
- }
-
- private void openMenu() {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle("@" + message.getSender().getScreenName() + ": " + message.getText())
- .setItems(R.array.message_commands, (dialog, which) -> {
- switch (which) {
- case 0:
- SystemServiceHelper.copyToClipboard(getActivity(), "message text", message.getText());
- getWorld().notify(R.string.notice_copy_clipboard);
- break;
- default:
- throw new IllegalStateException();
- }
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.kt
new file mode 100644
index 00000000..36f7584f
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.kt
@@ -0,0 +1,246 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2015 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.dialog
+
+import android.app.AlertDialog
+import android.app.Dialog
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageButton
+import android.widget.ListView
+import android.widget.TextView
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.command.Command
+import net.lacolaco.smileessence.command.CommandAddHashtag
+import net.lacolaco.smileessence.command.CommandOpenURL
+import net.lacolaco.smileessence.command.CommandOpenUserDetail
+import net.lacolaco.smileessence.entity.DirectMessage
+import net.lacolaco.smileessence.preference.UserPreferenceHelper
+import net.lacolaco.smileessence.twitter.task.Messages
+import net.lacolaco.smileessence.util.SystemServiceHelper
+import net.lacolaco.smileessence.view.DialogHelper
+import net.lacolaco.smileessence.view.Partials
+import net.lacolaco.smileessence.view.adapter.CustomListAdapter
+import net.lacolaco.smileessence.view.adapter.MessageListAdapter
+
+import java.util.ArrayList
+
+class MessageDetailDialogFragment : StackableDialogFragment(), View.OnClickListener {
+ private lateinit var message: DirectMessage
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_status_detail_reply -> {
+ openSendMessageDialog()
+ }
+ R.id.button_status_detail_delete -> {
+ deleteMessage()
+ }
+ R.id.button_status_detail_menu -> {
+ openMenu()
+ }
+ else -> {
+ dismiss()
+ }
+ }
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val found = DirectMessage.fetch(arguments.getLong(KEY_MESSAGE_ID))
+ if (found == null) {
+ world.notifyError(R.string.notice_error_get_messages)
+ return DisposeDialog(activity)
+ }
+ message = found
+
+ val header = titleView
+ val listView = header.findViewById(R.id.listview_status_detail_reply_to) as ListView
+ val adapter = MessageListAdapter(activity)
+ listView.adapter = adapter
+
+ // TODO: 効率的な探索どうする
+ val replyTo: DirectMessage? = null
+ // FIXME
+ // for (DirectMessage mes : DirectMessage.cached()) {
+ // if (message.getId() > mes.getId() &&
+ // message.getRecipient() == mes.getSender() &&
+ // message.getSender() == mes.getRecipient() &&
+ // (replyTo == null || replyTo.getId() < mes.getId())) {
+ // replyTo = mes;
+ // }
+ // }
+ if (replyTo != null) {
+ listView.visibility = View.VISIBLE
+ adapter.add(replyTo)
+ adapter.updateForce()
+ } else {
+ listView.visibility = View.GONE
+ }
+
+ return AlertDialog.Builder(activity).setView(header).create()
+ }
+
+ // -------------------------- OTHER METHODS --------------------------
+
+ private fun deleteMessage() {
+ ConfirmDialogFragment.show(activity, getString(R.string.dialog_confirm_commands)) {
+ Messages.DestroyTask(world.account, message.id)
+ .onDone { x -> world.notify(R.string.notice_message_delete_succeeded) }
+ .onFail { x -> world.notifyError(R.string.notice_message_delete_failed) }
+ .execute()
+ dismiss()
+ }
+ }
+
+ private fun openSendMessageDialog() {
+ DialogHelper.showDialog(activity, SendMessageDialogFragment.newInstance(message.sender))
+ }
+
+ private // status only parts
+ val titleView: View
+ get() {
+ val activity = activity as MainActivity
+
+ val view = activity.layoutInflater.inflate(R.layout.dialog_status_detail, null)
+
+ val messageHeader = Partials.getDirectMessageView(message, activity, view.findViewById(R.id.layout_status_header))
+ messageHeader.isClickable = false
+
+ view.setBackgroundColor((messageHeader.background as ColorDrawable).color)
+ updateViewButtons(view)
+ updateViewMenu(view)
+ view.findViewById(R.id.detail_dialog_divider_top).visibility = View.GONE
+ view.findViewById(R.id.button_status_detail_retweet).visibility = View.GONE
+ view.findViewById(R.id.button_status_detail_favorite).visibility = View.GONE
+ view.findViewById(R.id.image_status_detail_fav_count).visibility = View.GONE
+ view.findViewById(R.id.image_status_detail_rt_count).visibility = View.GONE
+
+ return view
+ }
+
+ private fun updateViewButtons(view: View) {
+ //--- buttons
+ val reply = view.findViewById(R.id.button_status_detail_reply) as ImageButton
+ reply.setOnClickListener(this)
+
+ val delete = view.findViewById(R.id.button_status_detail_delete) as ImageButton
+ delete.setOnClickListener(this)
+ delete.visibility = View.VISIBLE
+ }
+
+ private fun updateViewMenu(view: View) {
+ // -- menu dialog
+ val menu = view.findViewById(R.id.button_status_detail_menu) as ImageButton
+ menu.setOnClickListener(this)
+
+ // -- menu embedded in dialog
+ val divider = view.findViewById(R.id.detail_dialog_divider_bottom)
+ val listView = view.findViewById(R.id.listview_status_detail_menu) as ListView
+ val commands = commands
+ if (commands.size > 0) {
+ divider.visibility = View.VISIBLE
+ listView.visibility = View.VISIBLE
+ val adapter = object : CustomListAdapter<Command>() {
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ var convertView = convertView
+ if (convertView == null) {
+ convertView = activity.layoutInflater.inflate(R.layout.menu_item_simple_text, null)
+ }
+ val textView = convertView!!.findViewById(R.id.list_item_textview) as TextView
+ textView.textSize = UserPreferenceHelper.instance.textSize.toFloat()
+ textView.text = getItem(position).text
+ return convertView
+ }
+
+ override val list: List<Command>
+ get() = commands
+ }
+ adapter.update()
+ listView.adapter = adapter
+ listView.setOnItemClickListener { parent, view1, position, id ->
+ val command = parent.getItemAtPosition(position) as Command
+ command.execute()
+ }
+ } else {
+ divider.visibility = View.GONE
+ listView.visibility = View.GONE
+ }
+ }
+
+ private // Mentions
+ // URL
+ val commands: List<Command>
+ get() {
+ val activity = activity as MainActivity
+ val commands = ArrayList<Command>()
+ if (message.sender !== message.recipient) {
+ commands.add(CommandOpenUserDetail(activity, message.recipient.screenName))
+ }
+ for (screenName in message.mentions) {
+ commands.add(CommandOpenUserDetail(activity, screenName))
+ }
+ for (hashtag in message.hashtags) {
+ commands.add(CommandAddHashtag(activity, hashtag))
+ }
+ for (url in message.urlsExpanded) {
+ commands.add(CommandOpenURL(activity, url))
+ }
+ for (url in message.mediaUrls) {
+ commands.add(CommandOpenURL(activity, url))
+ }
+ return commands
+ }
+
+ private fun openMenu() {
+ val builder = AlertDialog.Builder(activity)
+ builder.setTitle("@" + message.sender.screenName + ": " + message.text)
+ .setItems(R.array.message_commands) { dialog, which ->
+ when (which) {
+ 0 -> {
+ SystemServiceHelper.copyToClipboard(activity, "message text", message.text)
+ world.notify(R.string.notice_copy_clipboard)
+ }
+ else -> throw IllegalStateException()
+ }
+ }
+ val dialog = builder.create()
+ dialog.show()
+ }
+
+ companion object {
+ private val KEY_MESSAGE_ID = "message_id"
+
+ fun newInstance(message: DirectMessage): MessageDetailDialogFragment {
+ val obj = MessageDetailDialogFragment()
+ val args = Bundle()
+ args.putLong(KEY_MESSAGE_ID, message.id)
+ obj.arguments = args
+ return obj
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.java
deleted file mode 100644
index 20917d8f..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.os.Bundle;
-import android.support.v4.content.ContextCompat;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.TextView;
-import com.twitter.Validator;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.entity.User;
-import net.lacolaco.smileessence.twitter.task.Messages;
-import net.lacolaco.smileessence.util.SystemServiceHelper;
-
-public class SendMessageDialogFragment extends StackableDialogFragment implements TextWatcher, View.OnClickListener {
- private static final String KEY_RECIPIENT_ID = "KEY_RECIPIENT_ID";
- private User recipient;
- private EditText editText;
- private TextView textViewCount;
- private Button buttonSend;
-
- public static SendMessageDialogFragment newInstance(User recipient) {
- SendMessageDialogFragment obj = new SendMessageDialogFragment();
- Bundle args = new Bundle();
- args.putLong(KEY_RECIPIENT_ID, recipient.getId());
- obj.setArguments(args);
- return obj;
- }
- @Override
- public void onClick(View v) {
- int id = v.getId();
- switch (id) {
- case R.id.button_send_message: {
- sendMessage();
- break;
- }
- case R.id.button_send_message_delete: {
- deleteMessage();
- }
- }
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- Validator validator = new Validator();
- int remainingCount = 140 - validator.getTweetLength(s.toString());
- textViewCount.setText(String.valueOf(remainingCount));
- if (remainingCount == 140 || remainingCount < 0) {
- textViewCount.setTextColor(ContextCompat.getColor(getActivity(), R.color.red));
- } else {
- textViewCount.setTextAppearance(getActivity(), android.R.style.TextAppearance_Widget_TextView);
- }
- }
-
- @Override
- public void afterTextChanged(Editable s) {
-
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- recipient = User.fetch(getArguments().getLong(KEY_RECIPIENT_ID));
- View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_send_message, null);
- TextView textViewName = (TextView) view.findViewById(R.id.textview_send_message_name);
- textViewName.setText("To: @" + recipient.getScreenName());
- textViewCount = (TextView) view.findViewById(R.id.textview_send_message_count);
- editText = (EditText) view.findViewById(R.id.edittext_send_message);
- editText.addTextChangedListener(this);
- buttonSend = (Button) view.findViewById(R.id.button_send_message);
- buttonSend.setOnClickListener(this);
- ImageButton buttonDelete = (ImageButton) view.findViewById(R.id.button_send_message_delete);
- buttonDelete.setOnClickListener(this);
- editText.setText("");
- return new AlertDialog.Builder(getActivity())
- .setView(view)
- .create();
- }
-
- private void deleteMessage() {
- editText.setText("");
- }
-
- private void sendMessage() {
- SystemServiceHelper.hideIM(getActivity(), editText);
- String text = editText.getText().toString();
- new Messages.CreateTask(getWorld().getAccount(), recipient.getId(), text)
- .onDoneUI(m -> {
- getWorld().addDirectMessage(m);
- getWorld().notify(R.string.notice_message_send_succeeded);
- dismiss();
- })
- .onFail(e -> getWorld().notifyError(R.string.notice_message_send_failed, e))
- .execute();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.kt
new file mode 100644
index 00000000..fb7e9d2f
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/SendMessageDialogFragment.kt
@@ -0,0 +1,127 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.dialog
+
+import android.app.AlertDialog
+import android.app.Dialog
+import android.os.Bundle
+import android.support.v4.content.ContextCompat
+import android.text.Editable
+import android.text.TextUtils
+import android.text.TextWatcher
+import android.view.View
+import android.widget.Button
+import android.widget.EditText
+import android.widget.ImageButton
+import android.widget.TextView
+import com.twitter.Validator
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.entity.User
+import net.lacolaco.smileessence.twitter.task.Messages
+import net.lacolaco.smileessence.util.SystemServiceHelper
+
+class SendMessageDialogFragment : StackableDialogFragment(), TextWatcher, View.OnClickListener {
+ private var recipient: User? = null
+ private var editText: EditText? = null
+ private var textViewCount: TextView? = null
+ private var buttonSend: Button? = null
+ override fun onClick(v: View) {
+ val id = v.id
+ when (id) {
+ R.id.button_send_message -> {
+ sendMessage()
+ }
+ R.id.button_send_message_delete -> {
+ deleteMessage()
+ }
+ }
+ }
+
+ override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
+
+ }
+
+ override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+ val validator = Validator()
+ val remainingCount = 140 - validator.getTweetLength(s.toString())
+ textViewCount!!.text = remainingCount.toString()
+ if (remainingCount == 140 || remainingCount < 0) {
+ textViewCount!!.setTextColor(ContextCompat.getColor(activity, R.color.red))
+ } else {
+ textViewCount!!.setTextAppearance(activity, android.R.style.TextAppearance_Widget_TextView)
+ }
+ }
+
+ override fun afterTextChanged(s: Editable) {
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ recipient = User.fetch(arguments.getLong(KEY_RECIPIENT_ID))
+ val view = activity.layoutInflater.inflate(R.layout.dialog_send_message, null)
+ val textViewName = view.findViewById(R.id.textview_send_message_name) as TextView
+ textViewName.text = "To: @" + recipient!!.screenName
+ textViewCount = view.findViewById(R.id.textview_send_message_count) as TextView
+ editText = view.findViewById(R.id.edittext_send_message) as EditText
+ editText!!.addTextChangedListener(this)
+ buttonSend = view.findViewById(R.id.button_send_message) as Button
+ buttonSend!!.setOnClickListener(this)
+ val buttonDelete = view.findViewById(R.id.button_send_message_delete) as ImageButton
+ buttonDelete.setOnClickListener(this)
+ editText!!.setText("")
+ return AlertDialog.Builder(activity)
+ .setView(view)
+ .create()
+ }
+
+ private fun deleteMessage() {
+ editText!!.setText("")
+ }
+
+ private fun sendMessage() {
+ SystemServiceHelper.hideIM(activity, editText)
+ val text = editText!!.text.toString()
+ Messages.CreateTask(world.account, recipient!!.id, text)
+ .onDoneUI { m ->
+ world.addDirectMessage(m)
+ world.notify(R.string.notice_message_send_succeeded)
+ dismiss()
+ }
+ .onFail { e -> world.notifyError(R.string.notice_message_send_failed, e) }
+ .execute()
+ }
+
+ companion object {
+ private val KEY_RECIPIENT_ID = "KEY_RECIPIENT_ID"
+
+ fun newInstance(recipient: User): SendMessageDialogFragment {
+ val obj = SendMessageDialogFragment()
+ val args = Bundle()
+ args.putLong(KEY_RECIPIENT_ID, recipient.id)
+ obj.arguments = args
+ return obj
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.java
deleted file mode 100644
index 848c6465..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.lacolaco.smileessence.view.dialog;
-
-import android.app.DialogFragment;
-import net.lacolaco.smileessence.World;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.view.DialogHelper;
-
-/**
- * Only used by MainActivity.
- */
-public class StackableDialogFragment extends DialogFragment {
- @Override
- public void dismiss() {
- super.dismiss();
- DialogHelper.unregisterDialog(getTag());
- }
-
- @Override
- public void dismissAllowingStateLoss() {
- super.dismissAllowingStateLoss();
- DialogHelper.unregisterDialog(getTag());
- }
-
- protected World getWorld() {
- final MainActivity activity = (MainActivity) getActivity();
- return activity.getWorld();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.kt
new file mode 100644
index 00000000..7822cfe3
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StackableDialogFragment.kt
@@ -0,0 +1,25 @@
+package net.lacolaco.smileessence.view.dialog
+
+import android.app.DialogFragment
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.view.DialogHelper
+
+/**
+ * Only used by MainActivity.
+ */
+open class StackableDialogFragment : DialogFragment() {
+ override fun dismiss() {
+ super.dismiss()
+ DialogHelper.unregisterDialog(tag)
+ }
+
+ override fun dismissAllowingStateLoss() {
+ super.dismissAllowingStateLoss()
+ DialogHelper.unregisterDialog(tag)
+ }
+
+ protected val world: World by lazy {
+ (activity as MainActivity).world
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.java
deleted file mode 100644
index 5b2ee58c..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.command.Command;
-import net.lacolaco.smileessence.command.CommandAddHashtag;
-import net.lacolaco.smileessence.command.CommandOpenURL;
-import net.lacolaco.smileessence.command.CommandOpenUserDetail;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.entity.RBinding;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.preference.UserPreferenceHelper;
-import net.lacolaco.smileessence.twitter.task.TweetReactions;
-import net.lacolaco.smileessence.twitter.task.Tweets;
-import net.lacolaco.smileessence.util.IntentUtils;
-import net.lacolaco.smileessence.util.SystemServiceHelper;
-import net.lacolaco.smileessence.util.UIObserverBundle;
-import net.lacolaco.smileessence.view.DialogHelper;
-import net.lacolaco.smileessence.view.Partials;
-import net.lacolaco.smileessence.view.ToggleableImageButton;
-import net.lacolaco.smileessence.view.adapter.CustomListAdapter;
-import net.lacolaco.smileessence.view.adapter.TimelineAdapter;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.List;
-
-public class StatusDetailDialogFragment extends StackableDialogFragment implements View.OnClickListener {
- private static final String KEY_STATUS_ID = "status_id";
- private Tweet tweet;
-
- public static StatusDetailDialogFragment newInstance(Tweet tweet) {
- StatusDetailDialogFragment obj = new StatusDetailDialogFragment();
- Bundle args = new Bundle();
- args.putLong(KEY_STATUS_ID, tweet.getId());
- obj.setArguments(args);
- return obj;
- }
-
- @Override
- public void onClick(final View v) {
- switch (v.getId()) {
- case R.id.button_status_detail_reply: {
- Tweet originalTweet = tweet.getOriginalTweet();
-
- StringBuilder builder = new StringBuilder();
- builder.append("@" + originalTweet.getUser().getScreenName() + " ");
-
- for (String screenName : originalTweet.getMentions()) {
- if (!screenName.equals(getWorld().getAccount().getUser().getScreenName()))
- builder.append("@" + screenName + " ");
- }
- String text = builder.toString();
- int selStart = originalTweet.getUser().getScreenName().length() + 2; // "@" and " "
-
- getWorld().getPostState().beginTransaction()
- .clear()
- .insertText(0, text)
- .setInReplyTo(originalTweet)
- .setSelection(selStart, text.length())
- .commitWithOpen((MainActivity) getActivity());
- break;
- }
- case R.id.button_status_detail_retweet: {
- Account account = getWorld().getAccount();
- confirm(() -> {
- if (tweet.isRetweetedBy(account.getUserId())) {
- new Tweets.DestroyTask(account, tweet.getRetweetIdBy(account.getUserId()))
- .onDone(t -> getWorld().notify(R.string.notice_status_delete_succeeded))
- .onFail(e -> getWorld().notifyError(R.string.notice_status_delete_failed))
- .execute();
- dismiss();
- } else {
- new TweetReactions.RetweetTask(account, tweet.getId())
- .onDone(x -> getWorld().notify(R.string.notice_retweet_succeeded))
- .onFail(x -> getWorld().notifyError(R.string.notice_retweet_failed))
- .execute();
- }
- });
- break;
- }
- case R.id.button_status_detail_favorite: {
- Account account = getWorld().getAccount();
- if (tweet.isFavoritedBy(account.getUserId())) {
- new TweetReactions.UnfavoriteTask(account, tweet.getId())
- .onDone(x -> getWorld().notify(R.string.notice_unfavorite_succeeded))
- .onFail(x -> getWorld().notifyError(R.string.notice_unfavorite_failed))
- .execute();
- } else {
- new TweetReactions.FavoriteTask(account, tweet.getId())
- .onDone(x -> getWorld().notify(R.string.notice_favorite_succeeded))
- .onFail(x -> getWorld().notifyError(R.string.notice_favorite_failed))
- .execute();
- }
- break;
- }
- case R.id.button_status_detail_delete: {
- confirm(() -> {
- new Tweets.DestroyTask(getWorld().getAccount(), tweet.getOriginalTweet().getId())
- .onDone(t -> getWorld().notify(R.string.notice_status_delete_succeeded))
- .onFail(e -> getWorld().notifyError(R.string.notice_status_delete_failed))
- .execute();
- dismiss();
- });
- break;
- }
- case R.id.button_status_detail_menu: {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle("@" + tweet.getUser().getScreenName() + ": " + tweet.getText())
- .setItems(R.array.status_commands, (dialog, which) -> {
- switch (which) {
- case 0:
- String text = String.format("@%s ", tweet.getOriginalTweet().getUser().getScreenName());
- getWorld().getPostState().beginTransaction().insertText(0, text).moveCursor(text.length()).commit();
- getWorld().notify(R.string.notice_add_to_reply);
- break;
- case 1:
- TalkChainDialogFragment dialogFragment = new TalkChainDialogFragment();
- dialogFragment.setStatusID(tweet.getOriginalTweet().getId());
- DialogHelper.showDialog(getActivity(), dialogFragment);
- break;
- case 2:
- IntentUtils.openUri(getActivity(), tweet.getOriginalTweet().getTwitterUrl());
- break;
- case 3:
- SystemServiceHelper.copyToClipboard(getActivity(), "tweet text", tweet.getOriginalTweet().getText());
- getWorld().notify(R.string.notice_copy_clipboard);
- break;
- case 4:
- String statusURL = tweet.getOriginalTweet().getTwitterUrl();
- SystemServiceHelper.copyToClipboard(getActivity(), "tweet url", statusURL);
- getWorld().notify(R.string.notice_copy_clipboard);
- break;
- default:
- throw new IllegalStateException();
- }
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- break;
- }
- default: {
- dismiss();
- }
- }
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- tweet = Tweet.fetch(getArguments().getLong(KEY_STATUS_ID));
- if (tweet == null) { // trying to open deleted tweet?
- getWorld().notifyError(R.string.notice_error_show_status);
- return new DisposeDialog(getActivity());
- }
-
- View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_status_detail, null);
- UIObserverBundle bundle = new UIObserverBundle();
- view.setTag(bundle);
-
- View statusHeader = Partials.getTweetView(tweet, getActivity(), view.findViewById(R.id.layout_status_header), true);
- statusHeader.setClickable(false);
-
- view.setBackgroundColor(((ColorDrawable) statusHeader.getBackground()).getColor());
- updateViewReactions(view);
- updateViewButtons(view);
- setupViewMenu(view);
-
- final WeakReference<View> weakView = new WeakReference<>(view);
- bundle.attach(tweet.getOriginalTweet(), changes -> {
- View strongView = weakView.get();
- if (strongView != null && getActivity() != null) {
- if (changes.contains(RBinding.REACTION_COUNT))
- updateViewReactions(strongView);
- if (changes.contains(RBinding.FAVORITERS) || changes.contains(RBinding.RETWEETERS))
- updateViewButtons(strongView);
- }
- });
-
- ListView listView = (ListView) view.findViewById(R.id.listview_status_detail_reply_to);
- final TimelineAdapter adapter = new TimelineAdapter(getActivity());
- listView.setAdapter(adapter);
-
- View replyDivider = view.findViewById(R.id.detail_dialog_divider_top);
-
- if (tweet.getInReplyToStatusId() != -1) {
- replyDivider.setVisibility(View.VISIBLE);
- listView.setVisibility(View.VISIBLE);
- Tweet.fetchTask(tweet.getInReplyToStatusId(), getWorld().getAccount())
- .onDoneUI(replyTo -> {
- adapter.add(replyTo);
- adapter.update();
- })
- .execute();
- } else {
- replyDivider.setVisibility(View.GONE);
- listView.setVisibility(View.GONE);
- }
-
- return new AlertDialog.Builder(getActivity()).setView(view).create();
- }
-
- private void updateViewReactions(View view) {
- ImageView favCountIcon = (ImageView) view.findViewById(R.id.image_status_detail_fav_count);
- TextView favCountText = (TextView) view.findViewById(R.id.textview_status_detail_fav_count);
- if (tweet.getFavoriteCount() > 0) {
- favCountText.setText(Integer.toString(tweet.getFavoriteCount()));
- favCountIcon.setVisibility(View.VISIBLE);
- favCountText.setVisibility(View.VISIBLE);
- } else {
- favCountIcon.setVisibility(View.GONE);
- favCountText.setVisibility(View.GONE);
- }
-
- ImageView rtCountIcon = (ImageView) view.findViewById(R.id.image_status_detail_rt_count);
- TextView rtCountText = (TextView) view.findViewById(R.id.textview_status_detail_rt_count);
- if (tweet.getRetweetCount() > 0) {
- rtCountText.setText(Integer.toString(tweet.getRetweetCount()));
- rtCountIcon.setVisibility(View.VISIBLE);
- rtCountText.setVisibility(View.VISIBLE);
- } else {
- rtCountIcon.setVisibility(View.GONE);
- rtCountText.setVisibility(View.GONE);
- }
- }
-
- private void updateViewButtons(View view) {
- Account account = getWorld().getAccount();
-
- //--- buttons
- ImageButton reply = (ImageButton) view.findViewById(R.id.button_status_detail_reply);
- reply.setOnClickListener(this);
-
- ToggleableImageButton retweet = (ToggleableImageButton) view.findViewById(R.id.button_status_detail_retweet);
- retweet.setOnClickListener(this);
- retweet.setState(tweet.isRetweetedBy(account.getUserId()));
-
- ToggleableImageButton favorite = (ToggleableImageButton) view.findViewById(R.id.button_status_detail_favorite);
- favorite.setOnClickListener(this);
- favorite.setState(tweet.isFavoritedBy(account.getUserId()));
-
- ImageButton delete = (ImageButton) view.findViewById(R.id.button_status_detail_delete);
- delete.setOnClickListener(this);
- delete.setVisibility(tweet.getOriginalTweet().getUser() == account.getUser() ? View.VISIBLE : View.GONE);
-
- ImageButton menu = (ImageButton) view.findViewById(R.id.button_status_detail_menu);
- menu.setOnClickListener(this);
- }
-
- private void setupViewMenu(View view) {
- View divider = view.findViewById(R.id.detail_dialog_divider_bottom);
- ListView listView = (ListView) view.findViewById(R.id.listview_status_detail_menu);
- List<Command> commands = getCommands();
- if (commands.size() > 0) {
- divider.setVisibility(View.VISIBLE);
- listView.setVisibility(View.VISIBLE);
- final CustomListAdapter<Command> adapter = new CustomListAdapter<Command>() {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = getActivity().getLayoutInflater().inflate(R.layout.menu_item_simple_text, null);
- }
- TextView textView = (TextView) convertView.findViewById(R.id.list_item_textview);
- textView.setTextSize(UserPreferenceHelper.getInstance().getTextSize());
- textView.setText(getItem(position).getText());
- return convertView;
- }
-
- @Override
- protected List<Command> getList() {
- return commands;
- }
- };
- adapter.update();
- listView.setAdapter(adapter);
- listView.setOnItemClickListener((parent, view1, position, id) -> {
- Command command = (Command) parent.getItemAtPosition(position);
- command.execute();
- });
- } else {
- divider.setVisibility(View.GONE);
- listView.setVisibility(View.GONE);
- }
- }
-
- private void confirm(Runnable onYes) {
- ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), onYes);
- }
-
- private List<Command> getCommands() {
- MainActivity activity = (MainActivity) getActivity();
- ArrayList<Command> commands = new ArrayList<>();
- // Retweeter
- if (tweet.getRetweetedTweet() != null && tweet.getUser() != tweet.getRetweetedTweet().getUser())
- commands.add(new CommandOpenUserDetail(activity, tweet.getUser().getScreenName()));
- // Mentions
- for (String screenName : new ArrayList<>(new LinkedHashSet<>(tweet.getMentions()))) { // Array#uniq
- commands.add(new CommandOpenUserDetail(activity, screenName));
- }
- // Hashtags
- for (String hashtag : tweet.getHashtags()) {
- commands.add(new CommandAddHashtag(activity, hashtag));
- }
- // URL
- for (String url : tweet.getUrlsExpanded()) {
- commands.add(new CommandOpenURL(activity, url));
- }
- for (String url : tweet.getMediaUrls()) {
- commands.add(new CommandOpenURL(activity, url));
- }
- return commands;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.kt
new file mode 100644
index 00000000..c18b6b4d
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.kt
@@ -0,0 +1,339 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.dialog
+
+import android.app.AlertDialog
+import android.app.Dialog
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageButton
+import android.widget.ImageView
+import android.widget.ListView
+import android.widget.TextView
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.command.Command
+import net.lacolaco.smileessence.command.CommandAddHashtag
+import net.lacolaco.smileessence.command.CommandOpenURL
+import net.lacolaco.smileessence.command.CommandOpenUserDetail
+import net.lacolaco.smileessence.data.Account
+import net.lacolaco.smileessence.entity.RBinding
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.preference.UserPreferenceHelper
+import net.lacolaco.smileessence.twitter.task.TweetReactions
+import net.lacolaco.smileessence.twitter.task.Tweets
+import net.lacolaco.smileessence.util.IntentUtils
+import net.lacolaco.smileessence.util.SystemServiceHelper
+import net.lacolaco.smileessence.util.UIObserverBundle
+import net.lacolaco.smileessence.view.DialogHelper
+import net.lacolaco.smileessence.view.Partials
+import net.lacolaco.smileessence.view.ToggleableImageButton
+import net.lacolaco.smileessence.view.adapter.CustomListAdapter
+import net.lacolaco.smileessence.view.adapter.TimelineAdapter
+
+import java.lang.ref.WeakReference
+import java.util.ArrayList
+import java.util.LinkedHashSet
+
+class StatusDetailDialogFragment : StackableDialogFragment(), View.OnClickListener {
+ private lateinit var tweet: Tweet
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_status_detail_reply -> {
+ val originalTweet = tweet.originalTweet
+
+ val builder = StringBuilder()
+ builder.append("@" + originalTweet.user.screenName + " ")
+
+ for (screenName in originalTweet.mentions) {
+ if (screenName != world.account.user.screenName)
+ builder.append("@$screenName ")
+ }
+ val text = builder.toString()
+ val selStart = originalTweet.user.screenName.length + 2 // "@" and " "
+
+ world.postState.beginTransaction()
+ .clear()
+ .insertText(0, text)
+ .setInReplyTo(originalTweet)
+ .setSelection(selStart, text.length)
+ .commitWithOpen(activity as MainActivity)
+ }
+ R.id.button_status_detail_retweet -> {
+ val account = world.account
+ confirm({
+ if (tweet.isRetweetedBy(account.userId)) {
+ Tweets.DestroyTask(account, tweet.getRetweetIdBy(account.userId))
+ .onDone { t -> world.notify(R.string.notice_status_delete_succeeded) }
+ .onFail { e -> world.notifyError(R.string.notice_status_delete_failed) }
+ .execute()
+ dismiss()
+ } else {
+ TweetReactions.RetweetTask(account, tweet.id)
+ .onDone { x -> world.notify(R.string.notice_retweet_succeeded) }
+ .onFail { x -> world.notifyError(R.string.notice_retweet_failed) }
+ .execute()
+ }
+ })
+ }
+ R.id.button_status_detail_favorite -> {
+ val account = world.account
+ if (tweet.isFavoritedBy(account.userId)) {
+ TweetReactions.UnfavoriteTask(account, tweet.id)
+ .onDone { x -> world.notify(R.string.notice_unfavorite_succeeded) }
+ .onFail { x -> world.notifyError(R.string.notice_unfavorite_failed) }
+ .execute()
+ } else {
+ TweetReactions.FavoriteTask(account, tweet.id)
+ .onDone { x -> world.notify(R.string.notice_favorite_succeeded) }
+ .onFail { x -> world.notifyError(R.string.notice_favorite_failed) }
+ .execute()
+ }
+ }
+ R.id.button_status_detail_delete -> {
+ confirm({
+ Tweets.DestroyTask(world.account, tweet.originalTweet.id)
+ .onDone { t -> world.notify(R.string.notice_status_delete_succeeded) }
+ .onFail { e -> world.notifyError(R.string.notice_status_delete_failed) }
+ .execute()
+ dismiss()
+ })
+ }
+ R.id.button_status_detail_menu -> {
+ val builder = AlertDialog.Builder(activity)
+ builder.setTitle("@" + tweet.user.screenName + ": " + tweet.text)
+ .setItems(R.array.status_commands) { dialog, which ->
+ when (which) {
+ 0 -> {
+ val text = String.format("@%s ", tweet.originalTweet.user.screenName)
+ world.postState.beginTransaction().insertText(0, text).moveCursor(text.length).commit()
+ world.notify(R.string.notice_add_to_reply)
+ }
+ 1 -> {
+ DialogHelper.showDialog(activity, TalkChainDialogFragment.newInstance(tweet))
+ }
+ 2 -> IntentUtils.openUri(activity, tweet.originalTweet.twitterUrl)
+ 3 -> {
+ SystemServiceHelper.copyToClipboard(activity, "tweet text", tweet.originalTweet.text)
+ world.notify(R.string.notice_copy_clipboard)
+ }
+ 4 -> {
+ val statusURL = tweet.originalTweet.twitterUrl
+ SystemServiceHelper.copyToClipboard(activity, "tweet url", statusURL)
+ world.notify(R.string.notice_copy_clipboard)
+ }
+ else -> throw IllegalStateException()
+ }
+ }
+ val dialog = builder.create()
+ dialog.show()
+ }
+ else -> {
+ dismiss()
+ }
+ }
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val found = Tweet.fetch(arguments.getLong(KEY_STATUS_ID))
+ if (found == null) { // trying to open deleted tweet?
+ world.notifyError(R.string.notice_error_show_status)
+ return DisposeDialog(activity)
+ }
+ tweet = found
+
+ val view = activity.layoutInflater.inflate(R.layout.dialog_status_detail, null)
+ val bundle = UIObserverBundle()
+ view.tag = bundle
+
+ val statusHeader = Partials.getTweetView(tweet, activity, view.findViewById(R.id.layout_status_header), true)
+ statusHeader.isClickable = false
+
+ view.setBackgroundColor((statusHeader.background as ColorDrawable).color)
+ updateViewReactions(view)
+ updateViewButtons(view)
+ setupViewMenu(view)
+
+ val weakView = WeakReference(view)
+ bundle.attach(tweet.originalTweet) { changes ->
+ val strongView = weakView.get()
+ if (strongView != null && activity != null) {
+ if (changes.contains(RBinding.REACTION_COUNT))
+ updateViewReactions(strongView)
+ if (changes.contains(RBinding.FAVORITERS) || changes.contains(RBinding.RETWEETERS))
+ updateViewButtons(strongView)
+ }
+ }
+
+ val listView = view.findViewById(R.id.listview_status_detail_reply_to) as ListView
+ val adapter = TimelineAdapter(activity)
+ listView.adapter = adapter
+
+ val replyDivider = view.findViewById(R.id.detail_dialog_divider_top)
+
+ if (tweet.inReplyToStatusId != -1L) {
+ replyDivider.visibility = View.VISIBLE
+ listView.visibility = View.VISIBLE
+ Tweet.fetchTask(tweet.inReplyToStatusId, world.account)
+ .onDoneUI { replyTo ->
+ adapter.add(replyTo)
+ adapter.update()
+ }
+ .execute()
+ } else {
+ replyDivider.visibility = View.GONE
+ listView.visibility = View.GONE
+ }
+
+ return AlertDialog.Builder(activity).setView(view).create()
+ }
+
+ private fun updateViewReactions(view: View) {
+ val favCountIcon = view.findViewById(R.id.image_status_detail_fav_count) as ImageView
+ val favCountText = view.findViewById(R.id.textview_status_detail_fav_count) as TextView
+ if (tweet.favoriteCount > 0) {
+ favCountText.text = Integer.toString(tweet.favoriteCount)
+ favCountIcon.visibility = View.VISIBLE
+ favCountText.visibility = View.VISIBLE
+ } else {
+ favCountIcon.visibility = View.GONE
+ favCountText.visibility = View.GONE
+ }
+
+ val rtCountIcon = view.findViewById(R.id.image_status_detail_rt_count) as ImageView
+ val rtCountText = view.findViewById(R.id.textview_status_detail_rt_count) as TextView
+ if (tweet.retweetCount > 0) {
+ rtCountText.text = Integer.toString(tweet.retweetCount)
+ rtCountIcon.visibility = View.VISIBLE
+ rtCountText.visibility = View.VISIBLE
+ } else {
+ rtCountIcon.visibility = View.GONE
+ rtCountText.visibility = View.GONE
+ }
+ }
+
+ private fun updateViewButtons(view: View) {
+ val account = world.account
+
+ //--- buttons
+ val reply = view.findViewById(R.id.button_status_detail_reply) as ImageButton
+ reply.setOnClickListener(this)
+
+ val retweet = view.findViewById(R.id.button_status_detail_retweet) as ToggleableImageButton
+ retweet.setOnClickListener(this)
+ retweet.setState(tweet.isRetweetedBy(account.userId))
+
+ val favorite = view.findViewById(R.id.button_status_detail_favorite) as ToggleableImageButton
+ favorite.setOnClickListener(this)
+ favorite.setState(tweet.isFavoritedBy(account.userId))
+
+ val delete = view.findViewById(R.id.button_status_detail_delete) as ImageButton
+ delete.setOnClickListener(this)
+ delete.visibility = if (tweet.originalTweet.user === account.user) View.VISIBLE else View.GONE
+
+ val menu = view.findViewById(R.id.button_status_detail_menu) as ImageButton
+ menu.setOnClickListener(this)
+ }
+
+ private fun setupViewMenu(view: View) {
+ val divider = view.findViewById(R.id.detail_dialog_divider_bottom)
+ val listView = view.findViewById(R.id.listview_status_detail_menu) as ListView
+ val commands = commands
+ if (commands.size > 0) {
+ divider.visibility = View.VISIBLE
+ listView.visibility = View.VISIBLE
+ val adapter = object : CustomListAdapter<Command>() {
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ var convertView = convertView
+ if (convertView == null) {
+ convertView = activity.layoutInflater.inflate(R.layout.menu_item_simple_text, null)
+ }
+ val textView = convertView!!.findViewById(R.id.list_item_textview) as TextView
+ textView.textSize = UserPreferenceHelper.instance.textSize.toFloat()
+ textView.text = getItem(position).text
+ return convertView
+ }
+
+ override val list: List<Command>
+ get() = commands
+ }
+ adapter.update()
+ listView.adapter = adapter
+ listView.setOnItemClickListener { parent, view1, position, id ->
+ val command = parent.getItemAtPosition(position) as Command
+ command.execute()
+ }
+ } else {
+ divider.visibility = View.GONE
+ listView.visibility = View.GONE
+ }
+ }
+
+ private fun confirm(onYes: () -> Unit) {
+ ConfirmDialogFragment.show(activity, getString(R.string.dialog_confirm_commands), onYes)
+ }
+
+ private // Retweeter
+ // Mentions
+ // Array#uniq
+ // Hashtags
+ // URL
+ val commands: List<Command>
+ get() {
+ val activity = activity as MainActivity
+ val commands = ArrayList<Command>()
+ if (tweet.retweetedTweet != null && tweet.user !== tweet.retweetedTweet!!.user)
+ commands.add(CommandOpenUserDetail(activity, tweet.user.screenName))
+ for (screenName in ArrayList(LinkedHashSet(tweet.mentions))) {
+ commands.add(CommandOpenUserDetail(activity, screenName))
+ }
+ for (hashtag in tweet.hashtags) {
+ commands.add(CommandAddHashtag(activity, hashtag))
+ }
+ for (url in tweet.urlsExpanded) {
+ commands.add(CommandOpenURL(activity, url))
+ }
+ for (url in tweet.mediaUrls) {
+ commands.add(CommandOpenURL(activity, url))
+ }
+ return commands
+ }
+
+ companion object {
+ private val KEY_STATUS_ID = "status_id"
+
+ fun newInstance(tweet: Tweet): StatusDetailDialogFragment {
+ val obj = StatusDetailDialogFragment()
+ val args = Bundle()
+ args.putLong(KEY_STATUS_ID, tweet.id)
+ obj.arguments = args
+ return obj
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.java
deleted file mode 100644
index 95bbac5c..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.twitter.task.Tweets;
-import net.lacolaco.smileessence.view.Partials;
-import net.lacolaco.smileessence.view.adapter.CustomListAdapter;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class TalkChainDialogFragment extends StackableDialogFragment {
- private static final String KEY_STATUS_ID = "KEY_STATUS_ID";
-
- private long getStatusID() {
- return getArguments().getLong(KEY_STATUS_ID);
- }
-
- public void setStatusID(long id) {
- Bundle bundle = new Bundle();
- bundle.putLong(KEY_STATUS_ID, id);
- setArguments(bundle);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- Account account = getWorld().getAccount();
-
- View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_talk_list, null);
- ListView listView = (ListView) view.findViewById(R.id.listview_dialog_talk_list);
- final List<Tweet> list = new ArrayList<>();
- final CustomListAdapter<Tweet> adapter = new CustomListAdapter<Tweet>() {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- return Partials.getTweetView(getItem(position), getActivity(), convertView, true);
- }
-
- @Override
- protected List<Tweet> getList() {
- return list;
- }
- };
- listView.setAdapter(adapter);
-
- new Tweets.GetTalkTask(account, getStatusID()).onProgressUI(tweet -> {
- list.add(tweet);
- adapter.updateForce();
- }).execute();
-
- return new AlertDialog.Builder(getActivity())
- .setTitle(R.string.dialog_title_talk_chain)
- .setView(view)
- .setCancelable(true)
- .create();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.kt
new file mode 100644
index 00000000..1b39e50a
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/TalkChainDialogFragment.kt
@@ -0,0 +1,81 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.dialog
+
+import android.app.AlertDialog
+import android.app.Dialog
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ListView
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.twitter.task.Tweets
+import net.lacolaco.smileessence.view.Partials
+import net.lacolaco.smileessence.view.adapter.CustomListAdapter
+
+import java.util.ArrayList
+
+class TalkChainDialogFragment : StackableDialogFragment() {
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val account = world.account
+
+ val view = activity.layoutInflater.inflate(R.layout.dialog_talk_list, null)
+ val listView = view.findViewById(R.id.listview_dialog_talk_list) as ListView
+ val list = ArrayList<Tweet>()
+ val adapter = object : CustomListAdapter<Tweet>() {
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ return Partials.getTweetView(getItem(position), activity, convertView, true)
+ }
+
+ override val list: List<Tweet>
+ get() = list
+ }
+ listView.adapter = adapter
+
+ Tweets.GetTalkTask(account, arguments.getLong(KEY_STATUS_ID)).onProgressUI { tweet ->
+ list.add(tweet)
+ adapter.updateForce()
+ }.execute()
+
+ return AlertDialog.Builder(activity)
+ .setTitle(R.string.dialog_title_talk_chain)
+ .setView(view)
+ .setCancelable(true)
+ .create()
+ }
+
+ companion object {
+ private val KEY_STATUS_ID = "KEY_STATUS_ID"
+
+ fun newInstance(tweet: Tweet): TalkChainDialogFragment {
+ val obj = TalkChainDialogFragment()
+ val bundle = Bundle()
+ bundle.putLong(KEY_STATUS_ID, tweet.originalTweet.id)
+ obj.arguments = bundle
+ return obj
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.java
deleted file mode 100644
index c8d62fa8..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.dialog;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.os.Bundle;
-import android.text.Html;
-import android.text.TextUtils;
-import android.text.method.LinkMovementMethod;
-import android.view.View;
-import android.widget.AbsListView;
-import android.widget.ListView;
-import android.widget.TabHost;
-import android.widget.TextView;
-import com.android.volley.toolbox.NetworkImageView;
-import com.handmark.pulltorefresh.library.PullToRefreshBase;
-import com.handmark.pulltorefresh.library.PullToRefreshListView;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.data.Account;
-import net.lacolaco.smileessence.data.ImageCache;
-import net.lacolaco.smileessence.entity.RBinding;
-import net.lacolaco.smileessence.entity.User;
-import net.lacolaco.smileessence.twitter.task.Timelines;
-import net.lacolaco.smileessence.twitter.task.Users;
-import net.lacolaco.smileessence.util.IntentUtils;
-import net.lacolaco.smileessence.util.UIHandler;
-import net.lacolaco.smileessence.util.UIObserverBundle;
-import net.lacolaco.smileessence.view.DialogHelper;
-import net.lacolaco.smileessence.view.ThreeStateButton;
-import net.lacolaco.smileessence.view.adapter.TimelineAdapter;
-
-public class UserDetailDialogFragment extends StackableDialogFragment implements View.OnClickListener,
- PullToRefreshBase.OnRefreshListener2<ListView> {
-
- // ------------------------------ FIELDS ------------------------------
-
- private static final String KEY_USER_ID = "userID";
- private TimelineAdapter adapter;
- private TextView textViewScreenName;
- private TextView textViewName;
- private TextView textViewURL;
- private TextView textViewLocate;
- private TextView textViewFollowed;
- private TextView textViewProtected;
- private TextView textViewDescription;
- private TextView textViewTweetCount;
- private TextView textViewFriendCount;
- private TextView textViewFollowerCount;
- private TextView textViewFavoriteCount;
- private NetworkImageView imageViewIcon;
- private NetworkImageView imageViewHeader;
- private ThreeStateButton buttonFollow;
- private PullToRefreshListView listViewTimeline;
- private TabHost tabHost;
- private UIObserverBundle observerBundle;
- private User user;
-
- // --------------------- GETTER / SETTER METHODS ---------------------
-
- public long getUserID() {
- return getArguments().getLong(KEY_USER_ID);
- }
-
- public void setUserID(long userID) {
- Bundle args = new Bundle();
- args.putLong(KEY_USER_ID, userID);
- setArguments(args);
- }
-
- // ------------------------ INTERFACE METHODS ------------------------
-
-
- // --------------------- Interface OnClickListener ---------------------
-
- @Override
- public void onClick(final View v) {
- switch (v.getId()) {
- case R.id.imageview_user_detail_menu: {
- openUserMenu();
- break;
- }
- case R.id.imageview_user_detail_icon: {
- IntentUtils.openUri(getActivity(), user.getProfileImageUrlOriginal());
- break;
- }
- case R.id.textview_user_detail_screenname:
- case R.id.textview_user_detail_tweet_count: {
- IntentUtils.openUri(getActivity(), user.getUserHomeURL());
- break;
- }
- case R.id.textview_user_detail_friend_count: {
- IntentUtils.openUri(getActivity(), String.format("%s/following", user.getUserHomeURL()));
- break;
- }
- case R.id.textview_user_detail_follower_count: {
- IntentUtils.openUri(getActivity(), String.format("%s/followers", user.getUserHomeURL()));
- break;
- }
- case R.id.textview_user_detail_favorite_count: {
- IntentUtils.openUri(getActivity(), String.format("%s/favorites", user.getUserHomeURL()));
- break;
- }
- case R.id.button_user_detail_follow: {
- ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), this::toggleFollowing);
- break;
- }
- }
- }
-
- // --------------------- Interface OnRefreshListener2 ---------------------
-
- @Override
- public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) {
- Account currentAccount = getWorld().getAccount();
- new Timelines.UserTimelineTask(currentAccount, getUserID())
- .setCount(200)
- .setSinceId(adapter.getTopID())
- .onFail(x -> getWorld().notifyError(R.string.notice_error_get_user_timeline))
- .onDoneUI(tweets -> {
- adapter.addAll(tweets);
- updateListView(refreshView.getRefreshableView(), adapter, true);
- refreshView.onRefreshComplete();
- })
- .execute();
- }
-
- @Override
- public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) {
- Account currentAccount = getWorld().getAccount();
- new Timelines.UserTimelineTask(currentAccount, getUserID())
- .setCount(200)
- .setMaxId(adapter.getLastID() - 1)
- .onFail(x -> getWorld().notifyError(R.string.notice_error_get_user_timeline))
- .onDoneUI(tweets -> {
- adapter.addAll(tweets);
- updateListView(refreshView.getRefreshableView(), adapter, false);
- refreshView.onRefreshComplete();
- })
- .execute();
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- user = User.fetch(getUserID());
- observerBundle = new UIObserverBundle();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- observerBundle.detachAll();
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- MainActivity activity = (MainActivity) getActivity();
- if (user == null) {
- getWorld().notify(R.string.notice_error_show_user);
- return new DisposeDialog(activity);
- }
-
- View v = activity.getLayoutInflater().inflate(R.layout.dialog_user_detail, null);
- View menu = v.findViewById(R.id.imageview_user_detail_menu);
- menu.setOnClickListener(this);
- textViewScreenName = (TextView) v.findViewById(R.id.textview_user_detail_screenname);
- textViewScreenName.setOnClickListener(this);
- textViewName = (TextView) v.findViewById(R.id.textview_user_detail_name);
- textViewURL = (TextView) v.findViewById(R.id.textview_user_detail_url);
- textViewLocate = (TextView) v.findViewById(R.id.textview_user_detail_locate);
- textViewFollowed = (TextView) v.findViewById(R.id.textview_user_detail_followed);
- textViewProtected = (TextView) v.findViewById(R.id.texttview_user_detail_protected);
- textViewDescription = (TextView) v.findViewById(R.id.textview_user_detail_description);
- textViewDescription.setMovementMethod(LinkMovementMethod.getInstance());
- textViewTweetCount = (TextView) v.findViewById(R.id.textview_user_detail_tweet_count);
- textViewTweetCount.setOnClickListener(this);
- textViewFriendCount = (TextView) v.findViewById(R.id.textview_user_detail_friend_count);
- textViewFriendCount.setOnClickListener(this);
- textViewFollowerCount = (TextView) v.findViewById(R.id.textview_user_detail_follower_count);
- textViewFollowerCount.setOnClickListener(this);
- textViewFavoriteCount = (TextView) v.findViewById(R.id.textview_user_detail_favorite_count);
- textViewFavoriteCount.setOnClickListener(this);
- imageViewIcon = (NetworkImageView) v.findViewById(R.id.imageview_user_detail_icon);
- imageViewIcon.setOnClickListener(this);
- imageViewHeader = (NetworkImageView) v.findViewById(R.id.imageview_user_detail_header);
- buttonFollow = (ThreeStateButton) v.findViewById(R.id.button_user_detail_follow);
- buttonFollow.setOnClickListener(this);
- listViewTimeline = (PullToRefreshListView) v.findViewById(R.id.listview_user_detail_timeline);
- listViewTimeline.setOnRefreshListener(this);
-
- tabHost = (TabHost) v.findViewById(android.R.id.tabhost);
- tabHost.setup();
- TabHost.TabSpec tab1 = tabHost.newTabSpec("tab1").setContent(R.id.tab1).setIndicator(getString(R.string.user_detail_tab_info));
- tabHost.addTab(tab1);
- TabHost.TabSpec tab2 = tabHost.newTabSpec("tab2").setContent(R.id.tab2).setIndicator(getString(R.string.user_detail_tab_timeline));
- tabHost.addTab(tab2);
- tabHost.setCurrentTab(0);
-
- initUserData();
-
- return new AlertDialog.Builder(activity)
- .setView(v)
- .setCancelable(true)
- .create();
- }
-
- private void executeUserTimelineTask(final TimelineAdapter adapter) {
- Account account = getWorld().getAccount();
- tabHost.getTabWidget().getChildTabViewAt(1).setVisibility(View.GONE);
- new Timelines.UserTimelineTask(account, user.getId())
- .setCount(200)
- .onFail(x -> getWorld().notifyError(R.string.notice_error_get_user_timeline))
- .onDoneUI(tweets -> {
- adapter.addAll(tweets);
- adapter.updateForce();
- tabHost.getTabWidget().getChildTabViewAt(1).setVisibility(View.VISIBLE);
- })
- .execute();
- }
-
- private String getHtmlDescription() {
- String description = user.getDescription();
- if (TextUtils.isEmpty(description)) {
- return "";
- }
- String html = description;
- html = html.replaceAll("https?://[\\w/:%#$&?()~.=+-]+", "<a href=\"$0\">$0</a>");
- html = html.replaceAll("@([a-zA-Z0-9_]+)", "<a href=\"https://twitter.com/$1\">$0</a>");
- html = html.replaceAll("\r\n", "<br />");
- return html;
- }
-
- private void updateUserDataBasic() {
- textViewName.setText(user.getName());
- textViewScreenName.setText(user.getScreenName());
- textViewProtected.setVisibility(user.isProtected() ? View.VISIBLE : View.GONE);
- imageViewIcon.setImageUrl(user.getProfileImageUrlOriginal(), ImageCache.getImageLoader());
- }
-
- private void updateUserDataDetail() {
- if (TextUtils.isEmpty(user.getLocation())) {
- textViewLocate.setVisibility(View.GONE);
- } else {
- textViewLocate.setText(user.getLocation());
- textViewLocate.setVisibility(View.VISIBLE);
- }
- if (TextUtils.isEmpty(user.getUrl())) {
- textViewURL.setVisibility(View.GONE);
- } else {
- textViewURL.setText(user.getUrl());
- textViewURL.setVisibility(View.VISIBLE);
- }
- textViewDescription.setText(Html.fromHtml(getHtmlDescription()));
-
- textViewTweetCount.setText(String.valueOf(user.getStatusesCount()));
- textViewFriendCount.setText(String.valueOf(user.getFriendsCount()));
- textViewFollowerCount.setText(String.valueOf(user.getFollowersCount()));
- textViewFavoriteCount.setText(String.valueOf(user.getFavoritesCount()));
-
- imageViewHeader.setImageUrl(user.getProfileBannerUrl(), ImageCache.getImageLoader());
- }
-
- private void initUserData() {
- updateUserDataBasic();
- updateUserDataDetail();
-
- MainActivity activity = (MainActivity) getActivity();
- adapter = new TimelineAdapter(activity);
- listViewTimeline.setAdapter(adapter);
- executeUserTimelineTask(adapter);
- updateRelationship();
-
- observerBundle.attach(user, changes -> {
- if (getActivity() != null) {
- if (changes.contains(RBinding.BASIC))
- updateUserDataBasic();
- if (changes.contains(RBinding.DETAIL))
- updateUserDataDetail();
- }
- });
- }
-
- private void openUserMenu() {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle("@" + user.getScreenName())
- .setItems(R.array.user_commands, (dialog, which) -> {
- // XXX
- new UIHandler().postDelayed(() -> {
- if (UserDetailDialogFragment.this.isAdded()) {
- updateRelationship();
- }
- }, 1000);
- switch (which) {
- case 0:
- String text = String.format("@%s ", user.getScreenName());
- getWorld().getPostState().beginTransaction().insertText(0, text).moveCursor(text.length()).commit();
- getWorld().notify(R.string.notice_add_to_reply);
- break;
- case 1:
- DialogHelper.showDialog(getActivity(), SendMessageDialogFragment.newInstance(user));
- break;
- case 2:
- ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () ->
- new Users.BlockTask(getWorld().getAccount(), user.getId())
- .onDone(user -> getWorld().notify(R.string.notice_block_succeeded))
- .onFail(ex -> getWorld().notifyError(R.string.notice_block_failed))
- .execute());
- break;
- case 3:
- ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () ->
- new Users.UnblockTask(getWorld().getAccount(), user.getId())
- .onDone(user -> getWorld().notify(R.string.notice_unblock_succeeded))
- .onFail(x -> getWorld().notifyError(R.string.notice_unblock_failed))
- .execute());
- break;
- case 4:
- ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_commands), () ->
- new Users.ReportForSpamTask(getWorld().getAccount(), user.getId())
- .onDone(user -> getWorld().notify(R.string.notice_r4s_succeeded))
- .onFail(ex -> getWorld().notifyError(R.string.notice_r4s_failed))
- .execute());
- break;
- case 5:
- IntentUtils.openUri(getActivity(), user.getAclogTimelineURL());
- break;
- default:
- throw new IllegalStateException();
- }
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- }
-
- private void setFollowButtonState(boolean isFollowing) {
- MainActivity mainActivity = (MainActivity) getActivity();
- if (mainActivity != null) {
- buttonFollow.setState(isFollowing ? ThreeStateButton.STATE_ON : ThreeStateButton.STATE_OFF);
- }
- }
-
- private void toggleFollowing() {
- Account account = getWorld().getAccount();
- Boolean isFollowing = buttonFollow.getState() == ThreeStateButton.STATE_ON;
- buttonFollow.setState(ThreeStateButton.STATE_LOCKED);
- if (isFollowing) {
- new Users.UnfollowTask(account, user.getId())
- .onDoneUI(result -> {
- getWorld().notify(R.string.notice_unfollow_succeeded);
- updateRelationship();
- })
- .onFail(x ->
- getWorld().notifyError(R.string.notice_unfollow_failed))
- .execute();
- } else {
- new Users.FollowTask(account, user.getId())
- .onDoneUI(result -> {
- getWorld().notify(R.string.notice_follow_succeeded);
- updateRelationship();
- })
- .onFail(x -> getWorld().notifyError(R.string.notice_follow_failed))
- .execute();
- }
- }
-
- private void updateListView(AbsListView absListView, TimelineAdapter adapter, boolean addedToTop) {
- int before = adapter.getCount();
- adapter.notifyDataSetChanged(); // synchronized call (not adapter#updateForce())
- int after = adapter.getCount();
- int increments = after - before;
- if (increments > 0) {
- if (addedToTop) {
- absListView.setSelection(increments + 1);
- absListView.smoothScrollToPositionFromTop(increments, 0);
- absListView.setSelection(increments);
- } else {
- absListView.smoothScrollToPositionFromTop(before, 0);
- }
- }
- }
-
- private void updateRelationship() {
- Account account = getWorld().getAccount();
- if (user == account.getUser()) {
- textViewFollowed.setText(R.string.user_detail_followed_is_me);
- buttonFollow.setVisibility(View.GONE);
- } else {
- buttonFollow.setState(ThreeStateButton.STATE_LOCKED);
- textViewFollowed.setText(R.string.user_detail_loading);
- new Users.ShowFriendshipTask(account, user.getId()).onDoneUI(relationship -> {
- boolean isFollowing = relationship.isSourceFollowingTarget();
- boolean isFollowed = relationship.isSourceFollowedByTarget();
- setFollowButtonState(isFollowing);
- textViewFollowed.setText(isFollowed ? R.string.user_detail_followed : R.string.user_detail_not_followed);
- }).execute();
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt
new file mode 100644
index 00000000..228a000a
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt
@@ -0,0 +1,390 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.dialog
+
+import android.app.AlertDialog
+import android.app.Dialog
+import android.os.Bundle
+import android.text.Html
+import android.text.TextUtils
+import android.text.method.LinkMovementMethod
+import android.view.View
+import android.widget.AbsListView
+import android.widget.ListView
+import android.widget.TabHost
+import android.widget.TextView
+import com.android.volley.toolbox.NetworkImageView
+import com.handmark.pulltorefresh.library.PullToRefreshBase
+import com.handmark.pulltorefresh.library.PullToRefreshListView
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.data.ImageCache
+import net.lacolaco.smileessence.entity.RBinding
+import net.lacolaco.smileessence.entity.User
+import net.lacolaco.smileessence.twitter.task.Timelines
+import net.lacolaco.smileessence.twitter.task.Users
+import net.lacolaco.smileessence.util.IntentUtils
+import net.lacolaco.smileessence.util.UIHandler
+import net.lacolaco.smileessence.util.UIObserverBundle
+import net.lacolaco.smileessence.view.DialogHelper
+import net.lacolaco.smileessence.view.ThreeStateButton
+import net.lacolaco.smileessence.view.adapter.TimelineAdapter
+
+class UserDetailDialogFragment : StackableDialogFragment(), View.OnClickListener, PullToRefreshBase.OnRefreshListener2<ListView> {
+ private lateinit var adapter: TimelineAdapter
+ private lateinit var textViewScreenName: TextView
+ private lateinit var textViewName: TextView
+ private lateinit var textViewURL: TextView
+ private lateinit var textViewLocate: TextView
+ private lateinit var textViewFollowed: TextView
+ private lateinit var textViewProtected: TextView
+ private lateinit var textViewDescription: TextView
+ private lateinit var textViewTweetCount: TextView
+ private lateinit var textViewFriendCount: TextView
+ private lateinit var textViewFollowerCount: TextView
+ private lateinit var textViewFavoriteCount: TextView
+ private lateinit var imageViewIcon: NetworkImageView
+ private lateinit var imageViewHeader: NetworkImageView
+ private lateinit var buttonFollow: ThreeStateButton
+ private lateinit var listViewTimeline: PullToRefreshListView
+ private lateinit var tabHost: TabHost
+ private lateinit var observerBundle: UIObserverBundle
+ private lateinit var user: User
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.imageview_user_detail_menu -> {
+ openUserMenu()
+ }
+ R.id.imageview_user_detail_icon -> {
+ IntentUtils.openUri(activity, user.profileImageUrl!!)
+ }
+ R.id.textview_user_detail_screenname, R.id.textview_user_detail_tweet_count -> {
+ IntentUtils.openUri(activity, user.userHomeURL)
+ }
+ R.id.textview_user_detail_friend_count -> {
+ IntentUtils.openUri(activity, String.format("%s/following", user.userHomeURL))
+ }
+ R.id.textview_user_detail_follower_count -> {
+ IntentUtils.openUri(activity, String.format("%s/followers", user.userHomeURL))
+ }
+ R.id.textview_user_detail_favorite_count -> {
+ IntentUtils.openUri(activity, String.format("%s/favorites", user.userHomeURL))
+ }
+ R.id.button_user_detail_follow -> {
+ ConfirmDialogFragment.show(activity, getString(R.string.dialog_confirm_commands)) { this.toggleFollowing() }
+ }
+ }
+ }
+
+ // --------------------- Interface OnRefreshListener2 ---------------------
+
+ override fun onPullDownToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ val currentAccount = world.account
+ Timelines.UserTimelineTask(currentAccount, user.id)
+ .setCount(200)
+ .setSinceId(adapter.topID)
+ .onFail { x -> world.notifyError(R.string.notice_error_get_user_timeline) }
+ .onDoneUI { tweets ->
+ adapter.addAll(tweets)
+ updateListView(refreshView.refreshableView, adapter, true)
+ refreshView.onRefreshComplete()
+ }
+ .execute()
+ }
+
+ override fun onPullUpToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ val currentAccount = world.account
+ Timelines.UserTimelineTask(currentAccount, user.id)
+ .setCount(200)
+ .setMaxId(adapter.lastID - 1)
+ .onFail { x -> world.notifyError(R.string.notice_error_get_user_timeline) }
+ .onDoneUI { tweets ->
+ adapter.addAll(tweets)
+ updateListView(refreshView.refreshableView, adapter, false)
+ refreshView.onRefreshComplete()
+ }
+ .execute()
+ }
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun onCreate(savedInstanceState: Bundle) {
+ super.onCreate(savedInstanceState)
+ observerBundle = UIObserverBundle()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ observerBundle.detachAll()
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val activity = activity as MainActivity
+ val found = User.fetch(arguments.getLong(KEY_USER_ID))
+ if (found == null) {
+ world.notify(R.string.notice_error_show_user)
+ return DisposeDialog(activity)
+ }
+ user = found
+
+ val v = activity.layoutInflater.inflate(R.layout.dialog_user_detail, null)
+ val menu = v.findViewById(R.id.imageview_user_detail_menu)
+ menu.setOnClickListener(this)
+ textViewScreenName = v.findViewById(R.id.textview_user_detail_screenname) as TextView
+ textViewScreenName.setOnClickListener(this)
+ textViewName = v.findViewById(R.id.textview_user_detail_name) as TextView
+ textViewURL = v.findViewById(R.id.textview_user_detail_url) as TextView
+ textViewLocate = v.findViewById(R.id.textview_user_detail_locate) as TextView
+ textViewFollowed = v.findViewById(R.id.textview_user_detail_followed) as TextView
+ textViewProtected = v.findViewById(R.id.texttview_user_detail_protected) as TextView
+ textViewDescription = v.findViewById(R.id.textview_user_detail_description) as TextView
+ textViewDescription.movementMethod = LinkMovementMethod.getInstance()
+ textViewTweetCount = v.findViewById(R.id.textview_user_detail_tweet_count) as TextView
+ textViewTweetCount.setOnClickListener(this)
+ textViewFriendCount = v.findViewById(R.id.textview_user_detail_friend_count) as TextView
+ textViewFriendCount.setOnClickListener(this)
+ textViewFollowerCount = v.findViewById(R.id.textview_user_detail_follower_count) as TextView
+ textViewFollowerCount.setOnClickListener(this)
+ textViewFavoriteCount = v.findViewById(R.id.textview_user_detail_favorite_count) as TextView
+ textViewFavoriteCount.setOnClickListener(this)
+ imageViewIcon = v.findViewById(R.id.imageview_user_detail_icon) as NetworkImageView
+ imageViewIcon.setOnClickListener(this)
+ imageViewHeader = v.findViewById(R.id.imageview_user_detail_header) as NetworkImageView
+ buttonFollow = v.findViewById(R.id.button_user_detail_follow) as ThreeStateButton
+ buttonFollow.setOnClickListener(this)
+ listViewTimeline = v.findViewById(R.id.listview_user_detail_timeline) as PullToRefreshListView
+ listViewTimeline.setOnRefreshListener(this)
+
+ tabHost = v.findViewById(android.R.id.tabhost) as TabHost
+ tabHost.setup()
+ val tab1 = tabHost.newTabSpec("tab1").setContent(R.id.tab1).setIndicator(getString(R.string.user_detail_tab_info))
+ tabHost.addTab(tab1)
+ val tab2 = tabHost.newTabSpec("tab2").setContent(R.id.tab2).setIndicator(getString(R.string.user_detail_tab_timeline))
+ tabHost.addTab(tab2)
+ tabHost.currentTab = 0
+
+ initUserData()
+
+ return AlertDialog.Builder(activity)
+ .setView(v)
+ .setCancelable(true)
+ .create()
+ }
+
+ private fun executeUserTimelineTask(adapter: TimelineAdapter) {
+ val account = world.account
+ tabHost.tabWidget.getChildTabViewAt(1).visibility = View.GONE
+ Timelines.UserTimelineTask(account, user.id)
+ .setCount(200)
+ .onFail { x -> world.notifyError(R.string.notice_error_get_user_timeline) }
+ .onDoneUI { tweets ->
+ adapter.addAll(tweets)
+ adapter.updateForce()
+ tabHost.tabWidget.getChildTabViewAt(1).visibility = View.VISIBLE
+ }
+ .execute()
+ }
+
+ private val htmlDescription: String?
+ get() {
+ val description = user.description
+ if (TextUtils.isEmpty(description)) {
+ return ""
+ }
+ var html = description
+ html = html!!.replace("https?://[\\w/:%#$&?()~.=+-]+".toRegex(), "<a href=\"$0\">$0</a>")
+ html = html.replace("@([a-zA-Z0-9_]+)".toRegex(), "<a href=\"https://twitter.com/$1\">$0</a>")
+ html = html.replace("\r\n".toRegex(), "<br />")
+ return html
+ }
+
+ private fun updateUserDataBasic() {
+ textViewName.text = user.name
+ textViewScreenName.text = user.screenName
+ textViewProtected.visibility = if (user.isProtected) View.VISIBLE else View.GONE
+ imageViewIcon.setImageUrl(user.profileImageUrl, ImageCache.getImageLoader())
+ }
+
+ private fun updateUserDataDetail() {
+ if (TextUtils.isEmpty(user.location)) {
+ textViewLocate.visibility = View.GONE
+ } else {
+ textViewLocate.text = user.location
+ textViewLocate.visibility = View.VISIBLE
+ }
+ if (TextUtils.isEmpty(user.url)) {
+ textViewURL.visibility = View.GONE
+ } else {
+ textViewURL.text = user.url
+ textViewURL.visibility = View.VISIBLE
+ }
+ textViewDescription.text = Html.fromHtml(htmlDescription)
+
+ textViewTweetCount.text = user.statusesCount.toString()
+ textViewFriendCount.text = user.friendsCount.toString()
+ textViewFollowerCount.text = user.followersCount.toString()
+ textViewFavoriteCount.text = user.favoritesCount.toString()
+
+ imageViewHeader.setImageUrl(user.profileBannerUrl, ImageCache.getImageLoader())
+ }
+
+ private fun initUserData() {
+ updateUserDataBasic()
+ updateUserDataDetail()
+
+ val activity = activity as MainActivity
+ adapter = TimelineAdapter(activity)
+ listViewTimeline.setAdapter(adapter)
+ executeUserTimelineTask(adapter)
+ updateRelationship()
+
+ observerBundle.attach(user) { changes ->
+ if (getActivity() != null) {
+ if (changes.contains(RBinding.BASIC))
+ updateUserDataBasic()
+ if (changes.contains(RBinding.DETAIL))
+ updateUserDataDetail()
+ }
+ }
+ }
+
+ private fun openUserMenu() {
+ val builder = AlertDialog.Builder(activity)
+ builder.setTitle("@" + user.screenName)
+ .setItems(R.array.user_commands) { dialog, which ->
+ // XXX
+ UIHandler().postDelayed({
+ if (this@UserDetailDialogFragment.isAdded) {
+ updateRelationship()
+ }
+ }, 1000)
+ when (which) {
+ 0 -> {
+ val text = String.format("@%s ", user.screenName)
+ world.postState.beginTransaction().insertText(0, text).moveCursor(text.length).commit()
+ world.notify(R.string.notice_add_to_reply)
+ }
+ 1 -> DialogHelper.showDialog(activity, SendMessageDialogFragment.newInstance(user))
+ 2 -> ConfirmDialogFragment.show(activity, getString(R.string.dialog_confirm_commands)) {
+ Users.BlockTask(world.account, user.id)
+ .onDone { user -> world.notify(R.string.notice_block_succeeded) }
+ .onFail { ex -> world.notifyError(R.string.notice_block_failed) }
+ .execute()
+ }
+ 3 -> ConfirmDialogFragment.show(activity, getString(R.string.dialog_confirm_commands)) {
+ Users.UnblockTask(world.account, user.id)
+ .onDone { user -> world.notify(R.string.notice_unblock_succeeded) }
+ .onFail { x -> world.notifyError(R.string.notice_unblock_failed) }
+ .execute()
+ }
+ 4 -> ConfirmDialogFragment.show(activity, getString(R.string.dialog_confirm_commands)) {
+ Users.ReportForSpamTask(world.account, user.id)
+ .onDone { user -> world.notify(R.string.notice_r4s_succeeded) }
+ .onFail { ex -> world.notifyError(R.string.notice_r4s_failed) }
+ .execute()
+ }
+ 5 -> IntentUtils.openUri(activity, user.aclogTimelineURL)
+ else -> throw IllegalStateException()
+ }
+ }
+ val dialog = builder.create()
+ dialog.show()
+ }
+
+ private fun setFollowButtonState(isFollowing: Boolean) {
+ if (activity != null) {
+ buttonFollow.state = if (isFollowing) ThreeStateButton.STATE_ON else ThreeStateButton.STATE_OFF
+ }
+ }
+
+ private fun toggleFollowing() {
+ val account = world.account
+ val isFollowing = buttonFollow.state == ThreeStateButton.STATE_ON
+ buttonFollow.state = ThreeStateButton.STATE_LOCKED
+ if (isFollowing) {
+ Users.UnfollowTask(account, user.id)
+ .onDoneUI { result ->
+ world.notify(R.string.notice_unfollow_succeeded)
+ updateRelationship()
+ }
+ .onFail { x -> world.notifyError(R.string.notice_unfollow_failed) }
+ .execute()
+ } else {
+ Users.FollowTask(account, user.id)
+ .onDoneUI { result ->
+ world.notify(R.string.notice_follow_succeeded)
+ updateRelationship()
+ }
+ .onFail { x -> world.notifyError(R.string.notice_follow_failed) }
+ .execute()
+ }
+ }
+
+ private fun updateListView(absListView: AbsListView, adapter: TimelineAdapter, addedToTop: Boolean) {
+ val before = adapter.count
+ adapter.notifyDataSetChanged() // synchronized call (not adapter#updateForce())
+ val after = adapter.count
+ val increments = after - before
+ if (increments > 0) {
+ if (addedToTop) {
+ absListView.setSelection(increments + 1)
+ absListView.smoothScrollToPositionFromTop(increments, 0)
+ absListView.setSelection(increments)
+ } else {
+ absListView.smoothScrollToPositionFromTop(before, 0)
+ }
+ }
+ }
+
+ private fun updateRelationship() {
+ val account = world.account
+ if (user === account.user) {
+ textViewFollowed.setText(R.string.user_detail_followed_is_me)
+ buttonFollow.visibility = View.GONE
+ } else {
+ buttonFollow.state = ThreeStateButton.STATE_LOCKED
+ textViewFollowed.setText(R.string.user_detail_loading)
+ Users.ShowFriendshipTask(account, user.id).onDoneUI { relationship ->
+ val isFollowing = relationship.isSourceFollowingTarget
+ val isFollowed = relationship.isSourceFollowedByTarget
+ setFollowButtonState(isFollowing)
+ textViewFollowed.setText(if (isFollowed) R.string.user_detail_followed else R.string.user_detail_not_followed)
+ }.execute()
+ }
+ }
+
+ companion object {
+ private val KEY_USER_ID = "userID"
+
+ fun newInstance(user: User): UserDetailDialogFragment {
+ val obj = UserDetailDialogFragment()
+ val bundle = Bundle()
+ bundle.putLong(KEY_USER_ID, user.id)
+ obj.arguments = bundle
+ return obj
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.java b/app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.kt
index 22d6180f..20404c63 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.java
+++ b/app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.kt
@@ -22,42 +22,35 @@
* SOFTWARE.
*/
-package net.lacolaco.smileessence.view.listener;
+package net.lacolaco.smileessence.view.listener
-import android.app.Activity;
-import android.graphics.drawable.ColorDrawable;
-import android.support.v4.content.ContextCompat;
-import android.view.View;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.util.UIHandler;
+import android.app.Activity
+import android.graphics.drawable.ColorDrawable
+import android.support.v4.content.ContextCompat
+import android.view.View
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.util.UIHandler
-public class ListItemClickListener implements View.OnClickListener {
+class ListItemClickListener
+// --------------------------- CONSTRUCTORS ---------------------------
- // ------------------------------ FIELDS ------------------------------
+(
+ // ------------------------------ FIELDS ------------------------------
- private final Activity activity;
- private final Runnable callback;
-
- // --------------------------- CONSTRUCTORS ---------------------------
-
- public ListItemClickListener(Activity activity, Runnable callback) {
- this.activity = activity;
- this.callback = callback;
- }
+ private val activity: Activity, private val callback: () -> Unit) : View.OnClickListener {
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface OnClickListener ---------------------
- @Override
- public void onClick(final View v) {
- final int currentBgColor = ((ColorDrawable) v.getBackground()).getColor();
- v.setBackgroundColor(ContextCompat.getColor(activity, R.color.metro_blue));
- v.invalidate();
- new UIHandler().post(() -> {
- v.setBackgroundColor(currentBgColor);
- callback.run();
- });
+ override fun onClick(v: View) {
+ val currentBgColor = (v.background as ColorDrawable).color
+ v.setBackgroundColor(ContextCompat.getColor(activity, R.color.metro_blue))
+ v.invalidate()
+ UIHandler().post {
+ v.setBackgroundColor(currentBgColor)
+ callback()
+ }
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.java
deleted file mode 100644
index 0dd24e67..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.page;
-
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.ListView;
-import com.handmark.pulltorefresh.library.PullToRefreshBase;
-import com.handmark.pulltorefresh.library.PullToRefreshListView;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.World;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.view.adapter.CustomListAdapter;
-
-public abstract class CustomListFragment<T extends CustomListAdapter> extends PageFragment<T> implements AbsListView.OnScrollListener,
- PullToRefreshBase.OnRefreshListener2<ListView> {
-
- // --------------------- GETTER / SETTER METHODS ---------------------
-
- protected PullToRefreshBase.Mode getRefreshMode() {
- return PullToRefreshBase.Mode.DISABLED;
- }
-
- // ------------------------ INTERFACE METHODS ------------------------
-
-
- // --------------------- Interface OnRefreshListener2 ---------------------
-
- @Override
- public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
- }
-
- @Override
- public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
- }
-
- // --------------------- Interface OnScrollListener ---------------------
-
- @Override
- public void onScrollStateChanged(AbsListView absListView, int scrollState) {
- T adapter = getAdapter();
- if (scrollState != SCROLL_STATE_TOUCH_SCROLL &&
- absListView.getFirstVisiblePosition() == 0 && (absListView.getChildAt(0) == null || absListView.getChildAt(0).getTop() == 0)) {
- adapter.setNotifiable(true);
- updateListViewWithNotice(absListView, true);
- } else {
- adapter.setNotifiable(false);
- }
- }
-
- @Override
- public void onScroll(AbsListView absListView, int i, int i2, int i3) {
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View page = inflater.inflate(R.layout.fragment_list, container, false);
- PullToRefreshListView listView = getListView(page);
- listView.setAdapter(getAdapter());
- listView.setOnScrollListener(this);
- listView.setOnRefreshListener(this);
- listView.setMode(getRefreshMode());
- return page;
- }
-
- protected PullToRefreshListView getListView(View page) {
- return (PullToRefreshListView) page.findViewById(R.id.fragment_list_listview);
- }
-
- protected void updateListViewWithNotice(AbsListView absListView, boolean addedToTop) {
- T adapter = getAdapter();
- int before = adapter.getCount();
- adapter.notifyDataSetChanged(); // synchronized call (not adapter#updateForce())
- int after = adapter.getCount();
- int increments = after - before;
- if (increments > 0) {
- if (addedToTop) {
- absListView.setSelection(increments + 1);
- absListView.smoothScrollToPositionFromTop(increments, 0);
- absListView.setSelection(increments);
- } else {
- absListView.smoothScrollToPositionFromTop(before, 0);
- }
-
- if (increments > 1) {
- adapter.setNotifiable(false);
- }
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.kt
new file mode 100644
index 00000000..d8536263
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.kt
@@ -0,0 +1,107 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.page
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AbsListView
+import android.widget.ListView
+import com.handmark.pulltorefresh.library.PullToRefreshBase
+import com.handmark.pulltorefresh.library.PullToRefreshListView
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.view.adapter.CustomListAdapter
+
+abstract class CustomListFragment<T : CustomListAdapter<*>> : PageFragment<T>(), AbsListView.OnScrollListener, PullToRefreshBase.OnRefreshListener2<ListView> {
+
+ // --------------------- GETTER / SETTER METHODS ---------------------
+
+ protected open val refreshMode: PullToRefreshBase.Mode
+ get() = PullToRefreshBase.Mode.DISABLED
+
+ // ------------------------ INTERFACE METHODS ------------------------
+
+
+ // --------------------- Interface OnRefreshListener2 ---------------------
+
+ override fun onPullDownToRefresh(refreshView: PullToRefreshBase<ListView>) {}
+
+ override fun onPullUpToRefresh(refreshView: PullToRefreshBase<ListView>) {}
+
+ // --------------------- Interface OnScrollListener ---------------------
+
+ override fun onScrollStateChanged(absListView: AbsListView, scrollState: Int) {
+ val adapter = adapter
+ if (scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL &&
+ absListView.firstVisiblePosition == 0 && (absListView.getChildAt(0) == null || absListView.getChildAt(0).top == 0)) {
+ adapter.setNotifiable(true)
+ updateListViewWithNotice(absListView, true)
+ } else {
+ adapter.setNotifiable(false)
+ }
+ }
+
+ override fun onScroll(absListView: AbsListView, i: Int, i2: Int, i3: Int) {}
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
+ val page = inflater.inflate(R.layout.fragment_list, container, false)
+ val listView = getListView(page)
+ listView.setAdapter(adapter)
+ listView.setOnScrollListener(this)
+ listView.setOnRefreshListener(this)
+ listView.mode = refreshMode
+ return page
+ }
+
+ protected open fun getListView(page: View): PullToRefreshListView {
+ return page.findViewById(R.id.fragment_list_listview) as PullToRefreshListView
+ }
+
+ protected fun updateListViewWithNotice(absListView: AbsListView, addedToTop: Boolean) {
+ val adapter = adapter
+ val before = adapter.count
+ adapter.notifyDataSetChanged() // synchronized call (not adapter#updateForce())
+ val after = adapter.count
+ val increments = after - before
+ if (increments > 0) {
+ if (addedToTop) {
+ absListView.setSelection(increments + 1)
+ absListView.smoothScrollToPositionFromTop(increments, 0)
+ absListView.setSelection(increments)
+ } else {
+ absListView.smoothScrollToPositionFromTop(before, 0)
+ }
+
+ if (increments > 1) {
+ adapter.setNotifiable(false)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.kt
new file mode 100644
index 00000000..70cae02f
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.kt
@@ -0,0 +1,41 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.page
+
+import android.os.Bundle
+import com.handmark.pulltorefresh.library.PullToRefreshBase
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.view.adapter.EventListAdapter
+
+class HistoryFragment : CustomListFragment<EventListAdapter>() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ adapter = EventListAdapter(world, activity)
+ world.addEventNotifier(this) { adapter.update() } // XXX
+ }
+
+ override fun refresh() {}
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.java
deleted file mode 100644
index e00f69c6..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.page;
-
-import android.os.Bundle;
-import android.widget.ListView;
-import com.handmark.pulltorefresh.library.PullToRefreshBase;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.twitter.task.TimelineTask;
-import net.lacolaco.smileessence.twitter.task.Timelines;
-import net.lacolaco.smileessence.util.UIHandler;
-import net.lacolaco.smileessence.view.adapter.TimelineAdapter;
-
-public class HomeFragment extends CustomListFragment<TimelineAdapter> {
- @Override
- protected PullToRefreshBase.Mode getRefreshMode() {
- return PullToRefreshBase.Mode.BOTH;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- TimelineAdapter adapter = new TimelineAdapter(getActivity());
- setAdapter(adapter);
-
- getWorld().addTimeline(this, tweet -> {
- adapter.add(tweet);
- adapter.update();
- });
-
- refresh();
- }
-
- @Override
- public void refresh() {
- runRefreshTask(new Timelines.HomeTimelineTask(getWorld().getAccount()), () -> getAdapter().updateForce());
- }
-
- // --------------------- Interface OnRefreshListener2 ---------------------
-
- @Override
- public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) {
- if (getWorld().isStreaming()) {
- new UIHandler().post(() -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), true);
- refreshView.onRefreshComplete();
- });
- } else {
- runRefreshTask(
- new Timelines.HomeTimelineTask(getWorld().getAccount())
- .setSinceId(getAdapter().getTopID()),
- () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), true);
- refreshView.onRefreshComplete();
- });
- }
- }
-
- @Override
- public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) {
- runRefreshTask(
- new Timelines.HomeTimelineTask(getWorld().getAccount())
- .setMaxId(getAdapter().getLastID() - 1),
- () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), false);
- refreshView.onRefreshComplete();
- });
- }
-
- private void runRefreshTask(TimelineTask<Tweet> task, Runnable onFinish) {
- task
- .setCount(200)
- .onFail(e -> getWorld().notifyError(R.string.notice_error_get_home))
- .onDoneUI(tweets -> getWorld().addTweetAll(tweets))
- .onFinishUI(onFinish)
- .execute();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.kt
new file mode 100644
index 00000000..a9bd8fe4
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.kt
@@ -0,0 +1,97 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.page
+
+import android.os.Bundle
+import android.widget.ListView
+import com.handmark.pulltorefresh.library.PullToRefreshBase
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.twitter.task.TimelineTask
+import net.lacolaco.smileessence.twitter.task.Timelines
+import net.lacolaco.smileessence.util.UIHandler
+import net.lacolaco.smileessence.view.adapter.TimelineAdapter
+
+class HomeFragment : CustomListFragment<TimelineAdapter>() {
+ override val refreshMode: PullToRefreshBase.Mode
+ get() = PullToRefreshBase.Mode.BOTH
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ adapter = TimelineAdapter(activity)
+
+ world.addTimeline(this) { tweet ->
+ adapter.add(tweet)
+ adapter.update()
+ }
+
+ refresh()
+ }
+
+ override fun refresh() {
+ runRefreshTask(Timelines.HomeTimelineTask(world.account), { adapter.updateForce() })
+ }
+
+ // --------------------- Interface OnRefreshListener2 ---------------------
+
+ override fun onPullDownToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ if (world.isStreaming) {
+ UIHandler().post {
+ updateListViewWithNotice(refreshView.refreshableView, true)
+ refreshView.onRefreshComplete()
+ }
+ } else {
+ runRefreshTask(
+ Timelines.HomeTimelineTask(world.account)
+ .setSinceId(adapter.topID),
+ {
+ updateListViewWithNotice(refreshView.refreshableView, true)
+ refreshView.onRefreshComplete()
+ })
+ }
+ }
+
+ override fun onPullUpToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ runRefreshTask(
+ Timelines.HomeTimelineTask(world.account)
+ .setMaxId(adapter.lastID - 1),
+ {
+ updateListViewWithNotice(refreshView.refreshableView, false)
+ refreshView.onRefreshComplete()
+ })
+ }
+
+ private fun runRefreshTask(task: TimelineTask<Tweet>, onFinish: () -> Unit) {
+ task
+ .setCount(200)
+ .onFail { e -> world.notifyError(R.string.notice_error_get_home) }
+ .onDoneUI { tweets -> world.addTweetAll(tweets) }
+ .onFinishUI(onFinish)
+ .execute()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.java
deleted file mode 100644
index 21ae1169..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.page;
-
-import android.os.Bundle;
-import android.widget.ListView;
-import com.handmark.pulltorefresh.library.PullToRefreshBase;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.data.ExtractionWord;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.entity.User;
-import net.lacolaco.smileessence.twitter.task.TimelineTask;
-import net.lacolaco.smileessence.twitter.task.Timelines;
-import net.lacolaco.smileessence.view.adapter.TimelineAdapter;
-
-public class MentionsFragment extends CustomListFragment<TimelineAdapter> {
-
- // --------------------- GETTER / SETTER METHODS ---------------------
-
- @Override
- protected PullToRefreshBase.Mode getRefreshMode() {
- return PullToRefreshBase.Mode.BOTH;
- }
-
- // ------------------------ INTERFACE METHODS ------------------------
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final TimelineAdapter adapter = new TimelineAdapter(getActivity());
- setAdapter(adapter);
-
- // Prevent calling getWorld() on null
- final User self = getWorld().getAccount().getUser();
- getWorld().addTimeline(this, tweet -> {
- if (tweet.getMentions().contains(self.getScreenName())) {
- adapter.add(tweet);
- adapter.update();
- } else {
- for (ExtractionWord word : ExtractionWord.cached()) {
- if (word.getPattern().matcher(tweet.getOriginalTweet().getText()).find()) {
- adapter.add(tweet);
- adapter.update();
- }
- }
- }
- });
-
- refresh();
- }
-
- @Override
- public void refresh() {
- runRefreshTask(new Timelines.MentionsTimelineTask(getWorld().getAccount()), () -> getAdapter().updateForce());
- }
-
- // --------------------- Interface OnRefreshListener2 ---------------------
-
- @Override
- public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) {
- runRefreshTask(
- new Timelines.MentionsTimelineTask(getWorld().getAccount())
- .setSinceId(getAdapter().getTopID()),
- () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), true);
- refreshView.onRefreshComplete();
- });
- }
-
- @Override
- public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) {
- runRefreshTask(
- new Timelines.MentionsTimelineTask(getWorld().getAccount())
- .setMaxId(getAdapter().getLastID() - 1),
- () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), false);
- refreshView.onRefreshComplete();
- });
- }
-
- private void runRefreshTask(TimelineTask<Tweet> task, Runnable onFinish) {
- task
- .setCount(200)
- .onFail(x -> getWorld().notifyError(R.string.notice_error_get_mentions))
- .onDoneUI(tweets -> getWorld().addTweetAll(tweets))
- .onFinishUI(onFinish)
- .execute();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.kt
new file mode 100644
index 00000000..d8442ac7
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.kt
@@ -0,0 +1,102 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.page
+
+import android.os.Bundle
+import android.widget.ListView
+import com.handmark.pulltorefresh.library.PullToRefreshBase
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.data.ExtractionWord
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.entity.User
+import net.lacolaco.smileessence.twitter.task.TimelineTask
+import net.lacolaco.smileessence.twitter.task.Timelines
+import net.lacolaco.smileessence.view.adapter.TimelineAdapter
+
+class MentionsFragment : CustomListFragment<TimelineAdapter>() {
+ override val refreshMode: PullToRefreshBase.Mode
+ get() = PullToRefreshBase.Mode.BOTH
+
+ // ------------------------ INTERFACE METHODS ------------------------
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ adapter = TimelineAdapter(activity)
+
+ // Prevent calling getWorld() on null
+ val self = world.account.user
+ world.addTimeline(this) { tweet ->
+ if (tweet.mentions.contains(self.screenName)) {
+ adapter.add(tweet)
+ adapter.update()
+ } else {
+ for (word in ExtractionWord.cached()) {
+ if (word.pattern.matcher(tweet.originalTweet.text).find()) {
+ adapter.add(tweet)
+ adapter.update()
+ }
+ }
+ }
+ }
+
+ refresh()
+ }
+
+ override fun refresh() {
+ runRefreshTask(Timelines.MentionsTimelineTask(world.account), { adapter.updateForce() })
+ }
+
+ // --------------------- Interface OnRefreshListener2 ---------------------
+
+ override fun onPullDownToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ runRefreshTask(
+ Timelines.MentionsTimelineTask(world.account)
+ .setSinceId(adapter.topID),
+ {
+ updateListViewWithNotice(refreshView.refreshableView, true)
+ refreshView.onRefreshComplete()
+ })
+ }
+
+ override fun onPullUpToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ runRefreshTask(
+ Timelines.MentionsTimelineTask(world.account)
+ .setMaxId(adapter.lastID - 1),
+ {
+ updateListViewWithNotice(refreshView.refreshableView, false)
+ refreshView.onRefreshComplete()
+ })
+ }
+
+ private fun runRefreshTask(task: TimelineTask<Tweet>, onFinish: () -> Unit) {
+ task
+ .setCount(200)
+ .onFail { x -> world.notifyError(R.string.notice_error_get_mentions) }
+ .onDoneUI { tweets -> world.addTweetAll(tweets) }
+ .onFinishUI(onFinish)
+ .execute()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.java
deleted file mode 100644
index 291f4cfc..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.page;
-
-import android.os.Bundle;
-import android.widget.ListView;
-import com.handmark.pulltorefresh.library.PullToRefreshBase;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.entity.DirectMessage;
-import net.lacolaco.smileessence.twitter.task.Messages;
-import net.lacolaco.smileessence.twitter.task.TimelineTask;
-import net.lacolaco.smileessence.view.adapter.MessageListAdapter;
-
-public class MessagesFragment extends CustomListFragment<MessageListAdapter> {
- @Override
- protected PullToRefreshBase.Mode getRefreshMode() {
- return PullToRefreshBase.Mode.BOTH;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- MessageListAdapter adapter = new MessageListAdapter(getActivity());
- setAdapter(adapter);
-
- getWorld().addDirectMessageTimeline(this, message -> {
- adapter.add(message);
- adapter.update();
- });
-
- refresh();
- }
-
- @Override
- public void refresh() {
- runRefreshTask(new Messages.GetAllReceived(getWorld().getAccount()), () -> getAdapter().updateForce());
- runRefreshTask(new Messages.GetAllSent(getWorld().getAccount()), () -> getAdapter().updateForce());
- }
-
- @Override
- public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) {
- runRefreshTask(
- new Messages.GetAllReceived(getWorld().getAccount())
- .setSinceId(getAdapter().getTopID()),
- () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), true);
- refreshView.onRefreshComplete();
- }); // TODO: sent?
- }
-
- @Override
- public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) {
- runRefreshTask(
- new Messages.GetAllReceived(getWorld().getAccount())
- .setMaxId(getAdapter().getLastID() - 1),
- () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), false);
- refreshView.onRefreshComplete();
- }); // TODO: sent?
- }
-
- private void runRefreshTask(TimelineTask<DirectMessage> task, Runnable onFinish) {
- task
- .setCount(200)
- .onFail(x -> getWorld().notifyError(R.string.notice_error_get_messages))
- .onDoneUI(messages -> {
- for (DirectMessage message : messages) {
- getWorld().addDirectMessage(message);
- }
- })
- .onFinishUI(onFinish)
- .execute();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.kt
new file mode 100644
index 00000000..ea756d09
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.kt
@@ -0,0 +1,90 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.page
+
+import android.os.Bundle
+import android.widget.ListView
+import com.handmark.pulltorefresh.library.PullToRefreshBase
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.entity.DirectMessage
+import net.lacolaco.smileessence.twitter.task.Messages
+import net.lacolaco.smileessence.twitter.task.TimelineTask
+import net.lacolaco.smileessence.view.adapter.MessageListAdapter
+
+class MessagesFragment : CustomListFragment<MessageListAdapter>() {
+ override val refreshMode: PullToRefreshBase.Mode
+ get() = PullToRefreshBase.Mode.BOTH
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ adapter = MessageListAdapter(activity)
+
+ world.addDirectMessageTimeline(this) { message ->
+ adapter.add(message)
+ adapter.update()
+ }
+
+ refresh()
+ }
+
+ override fun refresh() {
+ runRefreshTask(Messages.GetAllReceived(world.account), { adapter.updateForce() })
+ runRefreshTask(Messages.GetAllSent(world.account), { adapter.updateForce() })
+ }
+
+ override fun onPullDownToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ runRefreshTask(
+ Messages.GetAllReceived(world.account)
+ .setSinceId(adapter.topID),
+ {
+ updateListViewWithNotice(refreshView.refreshableView, true)
+ refreshView.onRefreshComplete()
+ }) // TODO: sent?
+ }
+
+ override fun onPullUpToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ runRefreshTask(
+ Messages.GetAllReceived(world.account)
+ .setMaxId(adapter.lastID - 1),
+ {
+ updateListViewWithNotice(refreshView.refreshableView, false)
+ refreshView.onRefreshComplete()
+ }) // TODO: sent?
+ }
+
+ private fun runRefreshTask(task: TimelineTask<DirectMessage>, onFinish: () -> Unit) {
+ task
+ .setCount(200)
+ .onFail { x -> world.notifyError(R.string.notice_error_get_messages) }
+ .onDoneUI { messages ->
+ for (message in messages) {
+ world.addDirectMessage(message)
+ }
+ }
+ .onFinishUI(onFinish)
+ .execute()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.java
deleted file mode 100644
index c1299298..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package net.lacolaco.smileessence.view.page;
-
-import android.app.Fragment;
-import android.os.Bundle;
-import android.widget.Adapter;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.World;
-import net.lacolaco.smileessence.activity.MainActivity;
-
-public abstract class PageFragment<T extends Adapter> extends Fragment {
- public static final String KEY_USER_ID = "KEY_USER_ID";
- private T adapter;
- private World world;
-
- protected final T getAdapter() {
- if (adapter == null) throw new IllegalStateException("adapter is not initialized");
- return adapter;
- }
-
- protected final void setAdapter(T _adapter) {
- adapter = _adapter;
- }
-
- public abstract void refresh();
-
- protected final World getWorld() {
- if (world == null) {
- world = Application.getWorld(getArguments().getLong(KEY_USER_ID));
- }
- return world;
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt
new file mode 100644
index 00000000..596f4107
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt
@@ -0,0 +1,25 @@
+package net.lacolaco.smileessence.view.page
+
+import android.app.Fragment
+import android.os.Bundle
+import android.widget.Adapter
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.activity.MainActivity
+
+abstract class PageFragment<T : Adapter> : Fragment() {
+ private var _adapter: T? = null
+ protected var adapter: T
+ get() = _adapter ?: throw IllegalStateException("adapter is not initialized")
+ set(value) { _adapter = value }
+
+ protected val world: World by lazy {
+ Application.getWorld(arguments.getLong(KEY_USER_ID))
+ }
+
+ abstract fun refresh()
+
+ companion object {
+ val KEY_USER_ID = "KEY_USER_ID"
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.java
deleted file mode 100644
index c8426383..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.page;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.content.ContextCompat;
-import android.text.Editable;
-import android.text.Spannable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.text.method.ArrowKeyMovementMethod;
-import android.view.*;
-import android.widget.*;
-import com.twitter.Validator;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.World;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.data.PostState;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.logging.Logger;
-import net.lacolaco.smileessence.preference.UserPreferenceHelper;
-import net.lacolaco.smileessence.twitter.task.Tweets;
-import net.lacolaco.smileessence.util.BitmapThumbnailTask;
-import net.lacolaco.smileessence.util.IntentUtils;
-import net.lacolaco.smileessence.util.SystemServiceHelper;
-import net.lacolaco.smileessence.util.UIHandler;
-import net.lacolaco.smileessence.view.Partials;
-
-import java.io.File;
-
-public class PostFragment extends PageFragment implements TextWatcher, View.OnFocusChangeListener, View.OnClickListener,
- PostState.OnPostStateChangeListener {
- // ------------------------------ FIELDS ------------------------------
-
- private EditText editText;
- private TextView textViewCount;
- private Button buttonTweet;
- private ViewGroup viewGroupReply;
- private ViewGroup viewGroupMedia;
-
- @Override
- public void refresh() {
- }
-
- // --------------------- Interface OnClickListener ---------------------
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.button_post_delete: {
- deletePost();
- break;
- }
- case R.id.button_post_media: {
- setImage();
- break;
- }
- case R.id.button_post_tweet: {
- submitPost();
- break;
- }
- case R.id.button_post_reply_delete: {
- deleteReply();
- break;
- }
- case R.id.button_post_media_delete: {
- removeImage();
- break;
- }
- case R.id.image_post_media: {
- displayImage();
- break;
- }
- }
- }
-
- // --------------------- Interface OnFocusChangeListener ---------------------
-
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- if (hasFocus) {
- SystemServiceHelper.showIM(getActivity(), editText);
- } else {
- SystemServiceHelper.hideIM(getActivity(), editText);
- }
- }
-
- // --------------------- Interface OnPostStateChangeListener ---------------------
-
-
- @Override
- public void onPostStateChange(final PostState postState) {
- Logger.debug("onPostStateChange");
- final MainActivity activity = (MainActivity) getActivity();
- if (editText != null) {
- final int start = postState.getSelectionStart();
- final int end = postState.getSelectionEnd();
- editText.removeTextChangedListener(this);
- editText.setTextKeepState(postState.getText());
- editText.addTextChangedListener(this);
- updateTextCount(editText.getText());
- new UIHandler().postAtFrontOfQueue(() -> editText.setSelection(start, end));
- }
- if (viewGroupReply != null) {
- if (postState.getInReplyTo() != null) {
- viewGroupReply.setVisibility(View.VISIBLE);
- ImageButton imageButtonDeleteReply = (ImageButton) viewGroupReply.findViewById(R.id.button_post_reply_delete);
- imageButtonDeleteReply.setOnClickListener(this);
-
- Tweet tweet = postState.getInReplyTo();
- View header = viewGroupReply.findViewById(R.id.layout_post_reply_status);
- header = Partials.getTweetView(tweet, activity, header, true);
- header.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.transparent));
- header.setClickable(false);
- } else {
- viewGroupReply.setVisibility(View.GONE);
- }
- }
- if (viewGroupMedia != null) {
- ImageView imageViewMedia = (ImageView) viewGroupMedia.findViewById(R.id.image_post_media);
- if (TextUtils.isEmpty(postState.getMediaFilePath())) {
- viewGroupMedia.setVisibility(View.GONE);
- } else {
- viewGroupMedia.setVisibility(View.VISIBLE);
-
- }
- new BitmapThumbnailTask(postState.getMediaFilePath(), imageViewMedia).execute();
- }
- }
-
- // --------------------- Interface 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) {
- updateTextCount(s);
- }
-
- private void updateTextCount(CharSequence s) {
- Validator validator = new Validator();
- int remainingCount = 140 - validator.getTweetLength(s.toString());
- if (!TextUtils.isEmpty(getWorld().getPostState().getMediaFilePath())) {
- remainingCount -= validator.getShortUrlLength();
- }
- textViewCount.setText(String.valueOf(remainingCount));
- if (remainingCount == 140 || remainingCount < 0) {
- textViewCount.setTextColor(ContextCompat.getColor(getActivity(), R.color.red));
- } else {
- textViewCount.setTextAppearance(getActivity(), android.R.style.TextAppearance_Widget_TextView);
- }
- setStateFromView();
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- Logger.debug("onCreate");
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- SystemServiceHelper.showIM(getActivity(), editText);
- }
-
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- Logger.debug("onCreateView");
- getWorld().getPostState().setListener(this);
- View v = inflater.inflate(R.layout.fragment_post, null);
- buttonTweet = getTweetButton(v);
- buttonTweet.setOnClickListener(this);
- editText = getEditText(v);
- textViewCount = getCountTextView(v);
- int textSize = UserPreferenceHelper.getInstance().getTextSize();
- editText.addTextChangedListener(this);
- editText.setOnFocusChangeListener(this);
- editText.setTextSize(textSize + 4);
- editText.setMovementMethod(new ArrowKeyMovementMethod() {
- @Override
- protected boolean right(@NonNull TextView widget, Spannable buffer) {
- //Don't back to Home
- return widget.getSelectionEnd() == widget.length() || super.right(widget, buffer);
- }
- });
- ImageButton imageButtonDeleteText = (ImageButton) v.findViewById(R.id.button_post_delete);
- imageButtonDeleteText.setOnClickListener(this);
- ImageButton imageButtonMedia = (ImageButton) v.findViewById(R.id.button_post_media);
- imageButtonMedia.setOnClickListener(this);
- //Reply view
- viewGroupReply = getReplyViewGroup(v);
- ImageButton imageButtonDeleteReply = (ImageButton) viewGroupReply.findViewById(R.id.button_post_reply_delete);
- imageButtonDeleteReply.setOnClickListener(this);
- //Media view
- viewGroupMedia = getMediaViewGroup(v);
- ImageView imageViewMedia = (ImageView) viewGroupMedia.findViewById(R.id.image_post_media);
- ImageButton imageButtonDeleteMedia = (ImageButton) viewGroupMedia.findViewById(R.id.button_post_media_delete);
- imageViewMedia.setOnClickListener(this);
- imageButtonDeleteMedia.setOnClickListener(this);
- editText.requestFocus();
- return v;
- }
-
- @Override
- public void onDestroyView() {
- Logger.debug("onDestroyView");
- super.onDestroyView();
- setStateFromView();
- getWorld().getPostState().removeListener();
- }
-
- @Override
- public void onViewStateRestored(Bundle savedInstanceState) {
- Logger.debug("onViewStateRestored");
- super.onViewStateRestored(savedInstanceState);
- PostState state = getWorld().getPostState();
- onPostStateChange(state);
- }
-
- private void deletePost() {
- editText.setText("");
- getWorld().getPostState().beginTransaction().setText("").setCursor(0).commit();
- deleteReply();
- }
-
- private void deleteReply() {
- viewGroupReply.setVisibility(View.GONE);
- getWorld().getPostState().beginTransaction().setInReplyTo(null).commit();
- }
-
- private void displayImage() {
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_VIEW);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setDataAndType(Uri.fromFile(new File(getWorld().getPostState().getMediaFilePath())), "image/*");
- IntentUtils.startActivityIfFound(getActivity(), intent);
- }
-
- private TextView getCountTextView(View v) {
- return (TextView) v.findViewById(R.id.post_text_count);
- }
-
- private EditText getEditText(View v) {
- return (EditText) v.findViewById(R.id.post_edit_text);
- }
-
- private ViewGroup getMediaViewGroup(View v) {
- return (ViewGroup) v.findViewById(R.id.post_media_parent);
- }
-
- private ViewGroup getReplyViewGroup(View v) {
- return (ViewGroup) v.findViewById(R.id.post_inreplyto_parent);
- }
-
- private Button getTweetButton(View v) {
- return (Button) v.findViewById(R.id.button_post_tweet);
- }
-
- private void removeImage() {
- SystemServiceHelper.hideIM(getActivity(), editText);
- viewGroupMedia.setVisibility(View.GONE);
- ((ImageView) viewGroupMedia.findViewById(R.id.image_post_media)).setImageBitmap(null);
- getWorld().getPostState().beginTransaction().setMediaFilePath("").commit();
- }
-
- private void setImage() {
- setStateFromView();
- SystemServiceHelper.hideIM(getActivity(), editText);
-
- Intent intent = new Intent(Intent.ACTION_PICK);
- intent.setType("image/*");
- IntentUtils.startActivityForResultIfFound(getActivity(), intent, MainActivity.REQUEST_GET_PICTURE_FROM_GALLERY);
- }
-
- private void setStateFromView() {
- PostState state = getWorld().getPostState();
- state.removeListener();
- state.beginTransaction()
- .setText(editText.getText().toString())
- .setSelection(editText.getSelectionStart(), editText.getSelectionEnd())
- .commit();
- state.setListener(this);
- }
-
- private void submitPost() {
- SystemServiceHelper.hideIM(getActivity(), editText);
- setStateFromView();
- PostState state = getWorld().getPostState();
- MainActivity mainActivity = (MainActivity) getActivity();
- boolean resizeFlag = UserPreferenceHelper.getInstance().get(R.string.key_setting_resize_post_image, false);
- new Tweets.CreateTask(getWorld().getAccount(), state.toStatusUpdate(), state.getMediaFilePath(), resizeFlag)
- .onDoneUI(t -> {
- getWorld().notify(R.string.notice_tweet_succeeded);
- getWorld().getPostState().beginTransaction().clear().commit();
- })
- .onFail(e -> getWorld().notifyError(R.string.notice_tweet_failed, e))
- .execute();
- mainActivity.openHomePage();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.kt
new file mode 100644
index 00000000..8afeadd1
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.kt
@@ -0,0 +1,304 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.page
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.support.v4.content.ContextCompat
+import android.text.Editable
+import android.text.Spannable
+import android.text.TextUtils
+import android.text.TextWatcher
+import android.text.method.ArrowKeyMovementMethod
+import android.view.*
+import android.widget.*
+import com.twitter.Validator
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.data.PostState
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.preference.UserPreferenceHelper
+import net.lacolaco.smileessence.twitter.task.Tweets
+import net.lacolaco.smileessence.util.BitmapThumbnailTask
+import net.lacolaco.smileessence.util.IntentUtils
+import net.lacolaco.smileessence.util.SystemServiceHelper
+import net.lacolaco.smileessence.util.UIHandler
+import net.lacolaco.smileessence.view.Partials
+
+import java.io.File
+
+class PostFragment : PageFragment<BaseAdapter>(), TextWatcher, View.OnFocusChangeListener, View.OnClickListener, PostState.OnPostStateChangeListener {
+ private var editText: EditText? = null
+ private var textViewCount: TextView? = null
+ private var buttonTweet: Button? = null
+ private var viewGroupReply: ViewGroup? = null
+ private var viewGroupMedia: ViewGroup? = null
+
+ override fun refresh() {}
+
+ // --------------------- Interface OnClickListener ---------------------
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_post_delete -> {
+ deletePost()
+ }
+ R.id.button_post_media -> {
+ setImage()
+ }
+ R.id.button_post_tweet -> {
+ submitPost()
+ }
+ R.id.button_post_reply_delete -> {
+ deleteReply()
+ }
+ R.id.button_post_media_delete -> {
+ removeImage()
+ }
+ R.id.image_post_media -> {
+ displayImage()
+ }
+ }
+ }
+
+ // --------------------- Interface OnFocusChangeListener ---------------------
+
+ override fun onFocusChange(v: View, hasFocus: Boolean) {
+ if (hasFocus) {
+ SystemServiceHelper.showIM(activity, editText)
+ } else {
+ SystemServiceHelper.hideIM(activity, editText)
+ }
+ }
+
+ // --------------------- Interface OnPostStateChangeListener ---------------------
+
+
+ override fun onPostStateChange(postState: PostState) {
+ Logger.debug("onPostStateChange")
+ val activity = activity as MainActivity
+ if (editText != null) {
+ val start = postState.selectionStart
+ val end = postState.selectionEnd
+ editText!!.removeTextChangedListener(this)
+ editText!!.setTextKeepState(postState.text)
+ editText!!.addTextChangedListener(this)
+ updateTextCount(editText!!.text)
+ UIHandler().postAtFrontOfQueue { editText!!.setSelection(start, end) }
+ }
+ if (viewGroupReply != null) {
+ if (postState.inReplyTo != null) {
+ viewGroupReply!!.visibility = View.VISIBLE
+ val imageButtonDeleteReply = viewGroupReply!!.findViewById(R.id.button_post_reply_delete) as ImageButton
+ imageButtonDeleteReply.setOnClickListener(this)
+
+ val tweet = postState.inReplyTo
+ var header = viewGroupReply!!.findViewById(R.id.layout_post_reply_status)
+ header = Partials.getTweetView(tweet!!, activity, header, true)
+ header.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.transparent))
+ header.isClickable = false
+ } else {
+ viewGroupReply!!.visibility = View.GONE
+ }
+ }
+ if (viewGroupMedia != null) {
+ val imageViewMedia = viewGroupMedia!!.findViewById(R.id.image_post_media) as ImageView
+ if (TextUtils.isEmpty(postState.mediaFilePath)) {
+ viewGroupMedia!!.visibility = View.GONE
+ } else {
+ viewGroupMedia!!.visibility = View.VISIBLE
+
+ }
+ BitmapThumbnailTask(postState.mediaFilePath, imageViewMedia).execute()
+ }
+ }
+
+ // --------------------- Interface TextWatcher ---------------------
+
+ override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
+
+ override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+ updateTextCount(s)
+ }
+
+ private fun updateTextCount(s: CharSequence) {
+ val validator = Validator()
+ var remainingCount = 140 - validator.getTweetLength(s.toString())
+ if (!TextUtils.isEmpty(world.postState.mediaFilePath)) {
+ remainingCount -= validator.shortUrlLength
+ }
+ textViewCount!!.text = remainingCount.toString()
+ if (remainingCount == 140 || remainingCount < 0) {
+ textViewCount!!.setTextColor(ContextCompat.getColor(activity, R.color.red))
+ } else {
+ textViewCount!!.setTextAppearance(activity, android.R.style.TextAppearance_Widget_TextView)
+ }
+ setStateFromView()
+ }
+
+ override fun afterTextChanged(s: Editable) {}
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+ super.onCreateOptionsMenu(menu, inflater)
+ SystemServiceHelper.showIM(activity, editText)
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ Logger.debug("onCreateView")
+ setHasOptionsMenu(true)
+ world.postState.setListener(this)
+ val v = inflater.inflate(R.layout.fragment_post, container, false)
+ buttonTweet = getTweetButton(v)
+ buttonTweet!!.setOnClickListener(this)
+ editText = getEditText(v)
+ textViewCount = getCountTextView(v)
+ val textSize = UserPreferenceHelper.instance.textSize
+ editText!!.addTextChangedListener(this)
+ editText!!.onFocusChangeListener = this
+ editText!!.textSize = (textSize + 4).toFloat()
+ editText!!.movementMethod = object : ArrowKeyMovementMethod() {
+ override fun right(widget: TextView, buffer: Spannable): Boolean {
+ //Don't back to Home
+ return widget.selectionEnd == widget.length() || super.right(widget, buffer)
+ }
+ }
+ val imageButtonDeleteText = v.findViewById(R.id.button_post_delete) as ImageButton
+ imageButtonDeleteText.setOnClickListener(this)
+ val imageButtonMedia = v.findViewById(R.id.button_post_media) as ImageButton
+ imageButtonMedia.setOnClickListener(this)
+ //Reply view
+ viewGroupReply = getReplyViewGroup(v)
+ val imageButtonDeleteReply = viewGroupReply!!.findViewById(R.id.button_post_reply_delete) as ImageButton
+ imageButtonDeleteReply.setOnClickListener(this)
+ //Media view
+ viewGroupMedia = getMediaViewGroup(v)
+ val imageViewMedia = viewGroupMedia!!.findViewById(R.id.image_post_media) as ImageView
+ val imageButtonDeleteMedia = viewGroupMedia!!.findViewById(R.id.button_post_media_delete) as ImageButton
+ imageViewMedia.setOnClickListener(this)
+ imageButtonDeleteMedia.setOnClickListener(this)
+ editText!!.requestFocus()
+ return v
+ }
+
+ override fun onDestroyView() {
+ Logger.debug("onDestroyView")
+ super.onDestroyView()
+ setStateFromView()
+ world.postState.removeListener()
+ }
+
+ override fun onViewStateRestored(savedInstanceState: Bundle?) {
+ Logger.debug("onViewStateRestored")
+ super.onViewStateRestored(savedInstanceState)
+ val state = world.postState
+ onPostStateChange(state)
+ }
+
+ private fun deletePost() {
+ editText!!.setText("")
+ world.postState.beginTransaction().setText("").setCursor(0).commit()
+ deleteReply()
+ }
+
+ private fun deleteReply() {
+ viewGroupReply!!.visibility = View.GONE
+ world.postState.beginTransaction().setInReplyTo(null).commit()
+ }
+
+ private fun displayImage() {
+ val intent = Intent()
+ intent.action = Intent.ACTION_VIEW
+ intent.addCategory(Intent.CATEGORY_DEFAULT)
+ intent.setDataAndType(Uri.fromFile(File(world.postState.mediaFilePath)), "image/*")
+ IntentUtils.startActivityIfFound(activity, intent)
+ }
+
+ private fun getCountTextView(v: View): TextView {
+ return v.findViewById(R.id.post_text_count) as TextView
+ }
+
+ private fun getEditText(v: View): EditText {
+ return v.findViewById(R.id.post_edit_text) as EditText
+ }
+
+ private fun getMediaViewGroup(v: View): ViewGroup {
+ return v.findViewById(R.id.post_media_parent) as ViewGroup
+ }
+
+ private fun getReplyViewGroup(v: View): ViewGroup {
+ return v.findViewById(R.id.post_inreplyto_parent) as ViewGroup
+ }
+
+ private fun getTweetButton(v: View): Button {
+ return v.findViewById(R.id.button_post_tweet) as Button
+ }
+
+ private fun removeImage() {
+ SystemServiceHelper.hideIM(activity, editText)
+ viewGroupMedia!!.visibility = View.GONE
+ (viewGroupMedia!!.findViewById(R.id.image_post_media) as ImageView).setImageBitmap(null)
+ world.postState.beginTransaction().setMediaFilePath("").commit()
+ }
+
+ private fun setImage() {
+ setStateFromView()
+ SystemServiceHelper.hideIM(activity, editText)
+
+ val intent = Intent(Intent.ACTION_PICK)
+ intent.type = "image/*"
+ IntentUtils.startActivityForResultIfFound(activity, intent, MainActivity.REQUEST_GET_PICTURE_FROM_GALLERY)
+ }
+
+ private fun setStateFromView() {
+ val state = world.postState
+ state.removeListener()
+ state.beginTransaction()
+ .setText(editText!!.text.toString())
+ .setSelection(editText!!.selectionStart, editText!!.selectionEnd)
+ .commit()
+ state.setListener(this)
+ }
+
+ private fun submitPost() {
+ SystemServiceHelper.hideIM(activity, editText)
+ setStateFromView()
+ val state = world.postState
+ val mainActivity = activity as MainActivity
+ val resizeFlag = UserPreferenceHelper.instance.get(R.string.key_setting_resize_post_image, false)
+ Tweets.CreateTask(world.account, state.toStatusUpdate(), state.mediaFilePath, resizeFlag)
+ .onDoneUI { t ->
+ world.notify(R.string.notice_tweet_succeeded)
+ world.postState.beginTransaction().clear().commit()
+ }
+ .onFail { e -> world.notifyError(R.string.notice_tweet_failed, e) }
+ .execute()
+ mainActivity.openHomePage()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.java
deleted file mode 100644
index 84d10c21..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.page;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.text.Spannable;
-import android.text.TextUtils;
-import android.text.method.ArrowKeyMovementMethod;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.ListView;
-import android.widget.TextView;
-import com.handmark.pulltorefresh.library.PullToRefreshBase;
-import com.handmark.pulltorefresh.library.PullToRefreshListView;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.entity.SavedSearch;
-import net.lacolaco.smileessence.preference.InternalPreferenceHelper;
-import net.lacolaco.smileessence.twitter.task.Searches;
-import net.lacolaco.smileessence.util.ListUtils;
-import net.lacolaco.smileessence.util.SystemServiceHelper;
-import net.lacolaco.smileessence.util.UIHandler;
-import net.lacolaco.smileessence.view.adapter.TimelineAdapter;
-import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment;
-import twitter4j.Query;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class SearchFragment extends CustomListFragment<TimelineAdapter> implements View.OnClickListener, View.OnLongClickListener,
- View.OnFocusChangeListener {
-
- // ------------------------------ FIELDS ------------------------------
-
- private String queryString;
- private TimelineAdapter adapter;
- private EditText editText;
-
- // --------------------- GETTER / SETTER METHODS ---------------------
-
- @Override
- protected PullToRefreshBase.Mode getRefreshMode() {
- return PullToRefreshBase.Mode.BOTH;
- }
-
- // ------------------------ INTERFACE METHODS ------------------------
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setHasOptionsMenu(true);
-
- queryString = InternalPreferenceHelper.getInstance().get(R.string.key_last_used_search_query, "");
- android.app.Activity activity = getActivity();
- adapter = new TimelineAdapter(activity);
- setAdapter(adapter);
-
- refresh();
- }
-
- @Override
- public void refresh() { //TODO
- if (!TextUtils.isEmpty(queryString)) {
- startSearch(queryString);
- }
- }
-
- // --------------------- Interface OnClickListener ---------------------
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.button_search_queries: {
- openSearchQueryDialog();
- break;
- }
- case R.id.button_search_execute: {
- search();
- break;
- }
- case R.id.button_search_save: {
- saveQuery();
- }
- }
- }
-
- @Override
- public boolean onLongClick(View v) {
- switch (v.getId()) {
- case R.id.button_search_save: {
- String text = editText.getText().toString();
- for (SavedSearch ss : getWorld().getSavedSearches()) {
- if (ss.getQuery().equals(text)) {
- ConfirmDialogFragment.show(getActivity(), getString(R.string.dialog_confirm_delete_query), () -> new Searches.DestroySavedSearchTask(getWorld().getAccount(), ss.getId())
- .onDoneUI(x -> {
- getWorld().notify(R.string.notice_search_query_deleted);
- getWorld().refreshSavedSearches();
- })
- .onFailUI(x -> getWorld().notify("unable to delete search query"))
- .execute(), false);
- break;
- }
- }
- return true;
- }
- }
- return false;
- }
-
- // --------------------- Interface OnFocusChangeListener ---------------------
-
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- if (!hasFocus) {
- SystemServiceHelper.hideIM(getActivity(), editText);
- }
- }
-
- // --------------------- Interface OnRefreshListener2 ---------------------
-
- @Override
- public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) {
- if (TextUtils.isEmpty(queryString)) {
- new UIHandler().post(() -> {
- notifyTextEmpty();
- refreshView.onRefreshComplete();
- });
- return;
- }
- final Query query = new Query();
- query.setQuery(queryString);
- query.setCount(200);
- query.setResultType(Query.RECENT);
- if (adapter.getCount() > 0) {
- query.setSinceId(adapter.getTopID());
- }
- runRefreshTask(query, () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), true);
- refreshView.onRefreshComplete();
- });
- }
-
- @Override
- public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) {
- if (TextUtils.isEmpty(queryString)) {
- new UIHandler().post(() -> {
- notifyTextEmpty();
- refreshView.onRefreshComplete();
- });
- return;
- }
- final Query query = new Query();
- query.setQuery(queryString);
- query.setCount(200);
- query.setResultType(Query.RECENT);
- if (adapter.getCount() > 0) {
- query.setMaxId(adapter.getLastID() - 1);
- }
- runRefreshTask(query, () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), false);
- refreshView.onRefreshComplete();
- });
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected PullToRefreshListView getListView(View page) {
- return (PullToRefreshListView) page.findViewById(R.id.listview_search);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View page = inflater.inflate(R.layout.fragment_search, container, false);
- PullToRefreshListView listView = getListView(page);
- listView.setAdapter(adapter);
- listView.setOnScrollListener(this);
- listView.setOnRefreshListener(this);
- listView.setMode(getRefreshMode());
- ImageButton buttonQueries = getQueriesButton(page);
- buttonQueries.setOnClickListener(this);
- ImageButton buttonExecute = getExecuteButton(page);
- buttonExecute.setOnClickListener(this);
- ImageButton buttonSave = getSaveButton(page);
- buttonSave.setOnClickListener(this);
- editText = getEditText(page);
- editText.setOnFocusChangeListener(this);
- editText.setText(queryString);
- editText.setOnEditorActionListener((textView, i, keyEvent) -> {
- if (i == EditorInfo.IME_ACTION_SEARCH ||
- keyEvent != null &&
- keyEvent.getAction() == KeyEvent.ACTION_DOWN &&
- keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
- search();
- }
- return true;
- });
- editText.setMovementMethod(new ArrowKeyMovementMethod() {
- @Override
- protected boolean right(@NonNull TextView widget, Spannable buffer) {
- //Don't move page
- return widget.getSelectionEnd() == widget.length() || super.right(widget, buffer);
- }
-
- @Override
- protected boolean left(@NonNull TextView widget, Spannable buffer) {
- //Don't move page
- return widget.getSelectionStart() == 0 || super.left(widget, buffer);
- }
- });
- return page;
- }
-
- private EditText getEditText(View page) {
- return (EditText) page.findViewById(R.id.edittext_search);
- }
-
- private ImageButton getExecuteButton(View page) {
- return (ImageButton) page.findViewById(R.id.button_search_execute);
- }
-
- private ImageButton getQueriesButton(View page) {
- return (ImageButton) page.findViewById(R.id.button_search_queries);
- }
-
- private ImageButton getSaveButton(View page) {
- return (ImageButton) page.findViewById(R.id.button_search_save);
- }
-
- private void notifyTextEmpty() {
- getWorld().notifyError(R.string.notice_search_text_empty);
- }
-
- private void openSearchQueryDialog() {
- List<SavedSearch> sss = new ArrayList<>(getWorld().getSavedSearches());
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setItems(ListUtils.map(sss, SavedSearch::getQuery).toArray(new String[]{}), (dialog, which) -> {
- SavedSearch ss = sss.get(which);
- ((MainActivity) getActivity()).openSearchPage(ss.getQuery());
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- }
-
- private void saveQuery() {
- String text = editText.getText().toString();
- if (TextUtils.isEmpty(text)) {
- getWorld().notifyError(R.string.notice_query_is_empty);
- } else {
- new Searches.CreateSavedSearchTask(getWorld().getAccount(), text).onDoneUI(cb -> {
- getWorld().notify(R.string.notice_query_saved);
- getWorld().refreshSavedSearches();
- }).onFailUI(ex -> getWorld().notifyError("Query is not saved")).execute();
- }
- }
-
- private void search() {
- if (editText != null) {
- String text = editText.getText().toString();
- if (TextUtils.isEmpty(text)) {
- getWorld().notifyError(R.string.notice_query_is_empty);
- } else {
- startSearch(text);
- SystemServiceHelper.hideIM(getActivity(), editText);
- }
- }
- }
-
- public void startSearch(final String queryString) {
- InternalPreferenceHelper.getInstance().set(R.string.key_last_used_search_query, queryString);
- if (editText != null)
- editText.setText(queryString);
- this.queryString = queryString;
- adapter.clear();
- adapter.updateForce();
- if (!TextUtils.isEmpty(queryString)) {
- final Query query = new Query();
- query.setQuery(queryString);
- query.setCount(200);
- query.setResultType(Query.RECENT);
- runRefreshTask(query, adapter::updateForce);
- }
- }
-
- private void runRefreshTask(Query query, Runnable onFinish) {
- new Searches.SearchTask(getWorld().getAccount(), query)
- .onFail(x -> getWorld().notifyError(R.string.notice_error_search))
- .onDoneUI(tweets -> adapter.addAll(ListUtils.filter(tweets, t -> !t.isRetweet())))
- .onFinishUI(onFinish)
- .execute();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.kt
new file mode 100644
index 00000000..de06a133
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.kt
@@ -0,0 +1,299 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.page
+
+import android.app.AlertDialog
+import android.os.Bundle
+import android.text.Spannable
+import android.text.TextUtils
+import android.text.method.ArrowKeyMovementMethod
+import android.view.KeyEvent
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.EditorInfo
+import android.widget.EditText
+import android.widget.ImageButton
+import android.widget.ListView
+import android.widget.TextView
+import com.handmark.pulltorefresh.library.PullToRefreshBase
+import com.handmark.pulltorefresh.library.PullToRefreshListView
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.preference.InternalPreferenceHelper
+import net.lacolaco.smileessence.twitter.task.Searches
+import net.lacolaco.smileessence.util.SystemServiceHelper
+import net.lacolaco.smileessence.util.UIHandler
+import net.lacolaco.smileessence.view.adapter.TimelineAdapter
+import net.lacolaco.smileessence.view.dialog.ConfirmDialogFragment
+import twitter4j.Query
+
+import java.util.ArrayList
+
+class SearchFragment : CustomListFragment<TimelineAdapter>(), View.OnClickListener, View.OnLongClickListener, View.OnFocusChangeListener {
+
+ // ------------------------------ FIELDS ------------------------------
+
+ private lateinit var queryString: String
+ private var editText: EditText? = null
+
+ // --------------------- GETTER / SETTER METHODS ---------------------
+
+ override val refreshMode: PullToRefreshBase.Mode
+ get() = PullToRefreshBase.Mode.BOTH
+
+ // ------------------------ INTERFACE METHODS ------------------------
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setHasOptionsMenu(true)
+
+ queryString = InternalPreferenceHelper.instance.get(R.string.key_last_used_search_query, "")
+ adapter = TimelineAdapter(activity)
+
+ refresh()
+ }
+
+ override fun refresh() { //TODO
+ if (!TextUtils.isEmpty(queryString)) {
+ startSearch(queryString)
+ }
+ }
+
+ // --------------------- Interface OnClickListener ---------------------
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_search_queries -> {
+ openSearchQueryDialog()
+ }
+ R.id.button_search_execute -> {
+ search()
+ }
+ R.id.button_search_save -> {
+ saveQuery()
+ }
+ }
+ }
+
+ override fun onLongClick(v: View): Boolean {
+ when (v.id) {
+ R.id.button_search_save -> {
+ val text = editText!!.text.toString()
+ for (ss in world.savedSearches.values) {
+ if (ss.query == text) {
+ ConfirmDialogFragment.show(activity, getString(R.string.dialog_confirm_delete_query), {
+ Searches.DestroySavedSearchTask(world.account, ss.id)
+ .onDoneUI { x ->
+ world.notify(R.string.notice_search_query_deleted)
+ world.refreshSavedSearches()
+ }
+ .onFailUI { x -> world.notify("unable to delete search query") }
+ .execute()
+ }, false)
+ break
+ }
+ }
+ return true
+ }
+ }
+ return false
+ }
+
+ // --------------------- Interface OnFocusChangeListener ---------------------
+
+ override fun onFocusChange(v: View, hasFocus: Boolean) {
+ if (!hasFocus) {
+ SystemServiceHelper.hideIM(activity, editText)
+ }
+ }
+
+ // --------------------- Interface OnRefreshListener2 ---------------------
+
+ override fun onPullDownToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ if (TextUtils.isEmpty(queryString)) {
+ UIHandler().post {
+ notifyTextEmpty()
+ refreshView.onRefreshComplete()
+ }
+ return
+ }
+ val query = Query()
+ query.query = queryString
+ query.count = 200
+ query.resultType = Query.RECENT
+ if (adapter.count > 0) {
+ query.sinceId = adapter.topID
+ }
+ runRefreshTask(query, {
+ updateListViewWithNotice(refreshView.refreshableView, true)
+ refreshView.onRefreshComplete()
+ })
+ }
+
+ override fun onPullUpToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ if (TextUtils.isEmpty(queryString)) {
+ UIHandler().post {
+ notifyTextEmpty()
+ refreshView.onRefreshComplete()
+ }
+ return
+ }
+ val query = Query()
+ query.query = queryString
+ query.count = 200
+ query.resultType = Query.RECENT
+ if (adapter.count > 0) {
+ query.maxId = adapter.lastID - 1
+ }
+ runRefreshTask(query, {
+ updateListViewWithNotice(refreshView.refreshableView, false)
+ refreshView.onRefreshComplete()
+ })
+ }
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun getListView(page: View): PullToRefreshListView {
+ return page.findViewById(R.id.listview_search) as PullToRefreshListView
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
+ val page = inflater.inflate(R.layout.fragment_search, container, false)
+ val listView = getListView(page)
+ listView.setAdapter(adapter)
+ listView.setOnScrollListener(this)
+ listView.setOnRefreshListener(this)
+ listView.mode = refreshMode
+ val buttonQueries = getQueriesButton(page)
+ buttonQueries.setOnClickListener(this)
+ val buttonExecute = getExecuteButton(page)
+ buttonExecute.setOnClickListener(this)
+ val buttonSave = getSaveButton(page)
+ buttonSave.setOnClickListener(this)
+ editText = getEditText(page)
+ editText!!.onFocusChangeListener = this
+ editText!!.setText(queryString)
+ editText!!.setOnEditorActionListener { textView, i, keyEvent ->
+ if (i == EditorInfo.IME_ACTION_SEARCH || keyEvent != null &&
+ keyEvent.action == KeyEvent.ACTION_DOWN &&
+ keyEvent.keyCode == KeyEvent.KEYCODE_ENTER) {
+ search()
+ }
+ true
+ }
+ editText!!.movementMethod = object : ArrowKeyMovementMethod() {
+ override fun right(widget: TextView, buffer: Spannable): Boolean {
+ //Don't move page
+ return widget.selectionEnd == widget.length() || super.right(widget, buffer)
+ }
+
+ override fun left(widget: TextView, buffer: Spannable): Boolean {
+ //Don't move page
+ return widget.selectionStart == 0 || super.left(widget, buffer)
+ }
+ }
+ return page
+ }
+
+ private fun getEditText(page: View): EditText {
+ return page.findViewById(R.id.edittext_search) as EditText
+ }
+
+ private fun getExecuteButton(page: View): ImageButton {
+ return page.findViewById(R.id.button_search_execute) as ImageButton
+ }
+
+ private fun getQueriesButton(page: View): ImageButton {
+ return page.findViewById(R.id.button_search_queries) as ImageButton
+ }
+
+ private fun getSaveButton(page: View): ImageButton {
+ return page.findViewById(R.id.button_search_save) as ImageButton
+ }
+
+ private fun notifyTextEmpty() {
+ world.notifyError(R.string.notice_search_text_empty)
+ }
+
+ private fun openSearchQueryDialog() {
+ val sss = ArrayList(world.savedSearches.values)
+ val builder = AlertDialog.Builder(activity)
+ builder.setItems(sss.map { it.query }.toTypedArray()) { dialog, which ->
+ val ss = sss[which]
+ (activity as MainActivity).openSearchPage(ss.query)
+ }
+ val dialog = builder.create()
+ dialog.show()
+ }
+
+ private fun saveQuery() {
+ val text = editText!!.text.toString()
+ if (TextUtils.isEmpty(text)) {
+ world.notifyError(R.string.notice_query_is_empty)
+ } else {
+ Searches.CreateSavedSearchTask(world.account, text).onDoneUI { cb ->
+ world.notify(R.string.notice_query_saved)
+ world.refreshSavedSearches()
+ }.onFailUI { ex -> world.notifyError("Query is not saved") }.execute()
+ }
+ }
+
+ private fun search() {
+ if (editText != null) {
+ val text = editText!!.text.toString()
+ if (TextUtils.isEmpty(text)) {
+ world.notifyError(R.string.notice_query_is_empty)
+ } else {
+ startSearch(text)
+ SystemServiceHelper.hideIM(activity, editText)
+ }
+ }
+ }
+
+ fun startSearch(queryString: String) {
+ InternalPreferenceHelper.instance.set(R.string.key_last_used_search_query, queryString)
+ if (editText != null)
+ editText!!.setText(queryString)
+ this.queryString = queryString
+ adapter.clear()
+ adapter.updateForce()
+ if (!TextUtils.isEmpty(queryString)) {
+ val query = Query()
+ query.query = queryString
+ query.count = 200
+ query.resultType = Query.RECENT
+ runRefreshTask(query) { adapter.updateForce() }
+ }
+ }
+
+ private fun runRefreshTask(query: Query, onFinish: () -> Unit) {
+ Searches.SearchTask(world.account, query)
+ .onFail { x -> world.notifyError(R.string.notice_error_search) }
+ .onDoneUI { tweets -> adapter.addAll(tweets.filter { t -> !t.isRetweet }) }
+ .onFinishUI(onFinish)
+ .execute()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.java b/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.java
deleted file mode 100644
index 3d19c5d6..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2014 lacolaco.net
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package net.lacolaco.smileessence.view.page;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.ListView;
-import android.widget.TextView;
-import com.handmark.pulltorefresh.library.PullToRefreshBase;
-import com.handmark.pulltorefresh.library.PullToRefreshListView;
-import net.lacolaco.smileessence.Application;
-import net.lacolaco.smileessence.R;
-import net.lacolaco.smileessence.activity.MainActivity;
-import net.lacolaco.smileessence.entity.Tweet;
-import net.lacolaco.smileessence.preference.InternalPreferenceHelper;
-import net.lacolaco.smileessence.twitter.task.TimelineTask;
-import net.lacolaco.smileessence.twitter.task.Timelines;
-import net.lacolaco.smileessence.util.UIHandler;
-import net.lacolaco.smileessence.view.adapter.TimelineAdapter;
-
-public class UserListFragment extends CustomListFragment<TimelineAdapter> implements View.OnClickListener {
- private TextView textListName;
- private String listFullName;
-
- @Override
- protected PullToRefreshBase.Mode getRefreshMode() {
- return PullToRefreshBase.Mode.BOTH;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- TimelineAdapter adapter = new TimelineAdapter(getActivity());
- setAdapter(adapter);
-
- refresh();
- }
-
- @Override
- public void refresh() {//TODO
- String lastUserList = InternalPreferenceHelper.getInstance().get(R.string.key_last_used_user_list, "");
- if (!TextUtils.isEmpty(lastUserList)) {
- startUserList(lastUserList);
- }
- }
-
- @Override
- public void onClick(View v) {
- int id = v.getId();
- switch (id) {
- case R.id.button_userlist_lists: {
- openUserListsDialog();
- break;
- }
- }
- }
-
- @Override
- public void onPullDownToRefresh(final PullToRefreshBase<ListView> refreshView) {
- if (listFullName == null) {
- new UIHandler().post(() -> {
- notifyTextEmpty();
- refreshView.onRefreshComplete();
- });
- return;
- }
- runRefreshTask(
- new Timelines.UserListStatusesTask(getWorld().getAccount(), listFullName)
- .setSinceId(getAdapter().getTopID()),
- () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), true);
- refreshView.onRefreshComplete();
- });
- }
-
- @Override
- public void onPullUpToRefresh(final PullToRefreshBase<ListView> refreshView) {
- if (listFullName == null) {
- new UIHandler().post(() -> {
- notifyTextEmpty();
- refreshView.onRefreshComplete();
- });
- return;
- }
- runRefreshTask(
- new Timelines.UserListStatusesTask(getWorld().getAccount(), listFullName)
- .setMaxId(getAdapter().getLastID() - 1),
- () -> {
- updateListViewWithNotice(refreshView.getRefreshableView(), false);
- refreshView.onRefreshComplete();
- });
- }
-
- // ------------------------ OVERRIDE METHODS ------------------------
-
- @Override
- protected PullToRefreshListView getListView(View page) {
- return (PullToRefreshListView) page.findViewById(R.id.listview_userlist);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View page = inflater.inflate(R.layout.fragment_userlist, container, false);
- PullToRefreshListView listView = getListView(page);
- TimelineAdapter adapter = getAdapter();
- listView.setAdapter(adapter);
- listView.setOnScrollListener(this);
- listView.setOnRefreshListener(this);
- listView.setMode(getRefreshMode());
- ImageButton buttonUserLists = getUserListsButton(page);
- buttonUserLists.setOnClickListener(this);
- textListName = getTextListName(page);
- textListName.setText(listFullName != null ? listFullName : "<none>");
- return page;
- }
-
- private TextView getTextListName(View page) {
- return (TextView) page.findViewById(R.id.textview_userlist_name);
- }
-
- private ImageButton getUserListsButton(View page) {
- return (ImageButton) page.findViewById(R.id.button_userlist_lists);
- }
-
- private void notifyTextEmpty() {
- getWorld().notifyError(R.string.notice_userlist_not_selected);
- }
-
- private void openUserListsDialog() {
- final String[] ary = getWorld().getListSubscriptions().toArray(new String[]{});
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle(R.string.dialog_title_select_userlist)
- .setItems(ary, (dialog, which) -> {
- MainActivity activity = (MainActivity) getActivity();
- activity.openUserListPage(ary[which]);
- textListName.setText(ary[which]);
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- }
-
- public void startUserList(String listFullName) {
- InternalPreferenceHelper.getInstance().set(R.string.key_last_used_user_list, listFullName);
- final TimelineAdapter adapter = getAdapter();
- this.listFullName = listFullName;
- adapter.clear();
- adapter.updateForce();
- runRefreshTask(
- new Timelines.UserListStatusesTask(getWorld().getAccount(), listFullName),
- adapter::updateForce);
- }
-
- private void runRefreshTask(TimelineTask<Tweet> task, Runnable onFinish) {
- final TimelineAdapter adapter = getAdapter();
- task
- .setCount(200)
- .onFail(x -> getWorld().notifyError(R.string.notice_error_get_list))
- .onDoneUI(tweets -> {
- getWorld().addTweetAll(tweets);
- adapter.addAll(tweets);
- })
- .onFinishUI(onFinish)
- .execute();
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.kt
new file mode 100644
index 00000000..3fb7ef49
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.kt
@@ -0,0 +1,179 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2012-2014 lacolaco.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package net.lacolaco.smileessence.view.page
+
+import android.app.AlertDialog
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageButton
+import android.widget.ListView
+import android.widget.TextView
+import com.handmark.pulltorefresh.library.PullToRefreshBase
+import com.handmark.pulltorefresh.library.PullToRefreshListView
+import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.entity.Tweet
+import net.lacolaco.smileessence.preference.InternalPreferenceHelper
+import net.lacolaco.smileessence.twitter.task.TimelineTask
+import net.lacolaco.smileessence.twitter.task.Timelines
+import net.lacolaco.smileessence.util.UIHandler
+import net.lacolaco.smileessence.view.adapter.TimelineAdapter
+
+class UserListFragment : CustomListFragment<TimelineAdapter>(), View.OnClickListener {
+ private var textListName: TextView? = null
+ private var listFullName: String? = null
+
+ override val refreshMode: PullToRefreshBase.Mode
+ get() = PullToRefreshBase.Mode.BOTH
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ adapter = TimelineAdapter(activity)
+
+ refresh()
+ }
+
+ override fun refresh() {//TODO
+ val lastUserList = InternalPreferenceHelper.instance.get(R.string.key_last_used_user_list, "")
+ if (!TextUtils.isEmpty(lastUserList)) {
+ startUserList(lastUserList)
+ }
+ }
+
+ override fun onClick(v: View) {
+ val id = v.id
+ when (id) {
+ R.id.button_userlist_lists -> {
+ openUserListsDialog()
+ }
+ }
+ }
+
+ override fun onPullDownToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ if (listFullName == null) {
+ UIHandler().post {
+ notifyTextEmpty()
+ refreshView.onRefreshComplete()
+ }
+ return
+ }
+ runRefreshTask(
+ Timelines.UserListStatusesTask(world.account, listFullName!!)
+ .setSinceId(adapter.topID),
+ {
+ updateListViewWithNotice(refreshView.refreshableView, true)
+ refreshView.onRefreshComplete()
+ })
+ }
+
+ override fun onPullUpToRefresh(refreshView: PullToRefreshBase<ListView>) {
+ if (listFullName == null) {
+ UIHandler().post {
+ notifyTextEmpty()
+ refreshView.onRefreshComplete()
+ }
+ return
+ }
+ runRefreshTask(
+ Timelines.UserListStatusesTask(world.account, listFullName!!)
+ .setMaxId(adapter.lastID - 1),
+ {
+ updateListViewWithNotice(refreshView.refreshableView, false)
+ refreshView.onRefreshComplete()
+ })
+ }
+
+ // ------------------------ OVERRIDE METHODS ------------------------
+
+ override fun getListView(page: View): PullToRefreshListView {
+ return page.findViewById(R.id.listview_userlist) as PullToRefreshListView
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
+ val page = inflater.inflate(R.layout.fragment_userlist, container, false)
+ val listView = getListView(page)
+ val adapter = adapter
+ listView.setAdapter(adapter)
+ listView.setOnScrollListener(this)
+ listView.setOnRefreshListener(this)
+ listView.mode = refreshMode
+ val buttonUserLists = getUserListsButton(page)
+ buttonUserLists.setOnClickListener(this)
+ textListName = getTextListName(page)
+ textListName!!.text = if (listFullName != null) listFullName else "<none>"
+ return page
+ }
+
+ private fun getTextListName(page: View): TextView {
+ return page.findViewById(R.id.textview_userlist_name) as TextView
+ }
+
+ private fun getUserListsButton(page: View): ImageButton {
+ return page.findViewById(R.id.button_userlist_lists) as ImageButton
+ }
+
+ private fun notifyTextEmpty() {
+ world.notifyError(R.string.notice_userlist_not_selected)
+ }
+
+ private fun openUserListsDialog() {
+ val ary = world.listSubscriptions.toTypedArray<String>()
+ val builder = AlertDialog.Builder(activity)
+ builder.setTitle(R.string.dialog_title_select_userlist)
+ .setItems(ary) { dialog, which ->
+ val activity = activity as MainActivity
+ activity.openUserListPage(ary[which])
+ textListName!!.text = ary[which]
+ }
+ val dialog = builder.create()
+ dialog.show()
+ }
+
+ fun startUserList(listFullName: String) {
+ InternalPreferenceHelper.instance.set(R.string.key_last_used_user_list, listFullName)
+ val adapter = adapter
+ this.listFullName = listFullName
+ adapter.clear()
+ adapter.updateForce()
+ runRefreshTask(Timelines.UserListStatusesTask(world.account, listFullName)) { adapter.updateForce() }
+ }
+
+ private fun runRefreshTask(task: TimelineTask<Tweet>, onFinish: () -> Unit) {
+ val adapter = adapter
+ task
+ .setCount(200)
+ .onFail { x -> world.notifyError(R.string.notice_error_get_list) }
+ .onDoneUI { tweets ->
+ world.addTweetAll(tweets)
+ adapter.addAll(tweets)
+ }
+ .onFinishUI(onFinish)
+ .execute()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerEditTextPreference.java b/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerEditTextPreference.java
deleted file mode 100644
index 88ad0879..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerEditTextPreference.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package net.lacolaco.smileessence.view.preference;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.os.Build;
-import android.preference.EditTextPreference;
-import android.util.AttributeSet;
-
-public class IntegerEditTextPreference extends EditTextPreference {
- public IntegerEditTextPreference(Context context) {
- super(context);
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public IntegerEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- public IntegerEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public IntegerEditTextPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected boolean persistString(String value) {
- return persistInt(Integer.valueOf(value));
- }
-
- @Override
- protected String getPersistedString(String defaultReturnValue) {
- return String.valueOf(getPersistedInt(-1));
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerEditTextPreference.kt b/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerEditTextPreference.kt
new file mode 100644
index 00000000..e6a23696
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerEditTextPreference.kt
@@ -0,0 +1,26 @@
+package net.lacolaco.smileessence.view.preference
+
+import android.annotation.TargetApi
+import android.content.Context
+import android.os.Build
+import android.preference.EditTextPreference
+import android.util.AttributeSet
+
+class IntegerEditTextPreference : EditTextPreference {
+ constructor(context: Context) : super(context)
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
+
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+
+ override fun persistString(value: String): Boolean {
+ return persistInt(Integer.valueOf(value)!!)
+ }
+
+ override fun getPersistedString(defaultReturnValue: String?): String {
+ return getPersistedInt(-1).toString()
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.java b/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.java
deleted file mode 100644
index f04a3b89..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package net.lacolaco.smileessence.view.preference;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.os.Build;
-import android.preference.ListPreference;
-import android.util.AttributeSet;
-
-public class IntegerListPreference extends ListPreference {
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public IntegerListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public IntegerListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public IntegerListPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public IntegerListPreference(Context context) {
- super(context);
- }
-
- @Override
- protected boolean persistString(String value) {
- return persistInt(Integer.valueOf(value));
- }
-
- @Override
- protected String getPersistedString(String defaultReturnValue) {
- return String.valueOf(getPersistedInt(-1));
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.kt b/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.kt
new file mode 100644
index 00000000..7dbe3297
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.kt
@@ -0,0 +1,27 @@
+package net.lacolaco.smileessence.view.preference
+
+import android.annotation.TargetApi
+import android.content.Context
+import android.os.Build
+import android.preference.ListPreference
+import android.util.AttributeSet
+
+class IntegerListPreference : ListPreference {
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+
+ constructor(context: Context) : super(context)
+
+ override fun persistString(value: String): Boolean {
+ return persistInt(Integer.valueOf(value)!!)
+ }
+
+ override fun getPersistedString(defaultReturnValue: String?): String {
+ return getPersistedInt(-1).toString()
+ }
+}
diff --git a/build.gradle b/build.gradle
index a3ca24b9..06ebf25f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+ ext.kotlin_version = '1.1.51'
repositories {
jcenter()
mavenCentral()
@@ -10,6 +11,7 @@ buildscript {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'me.tatarka:gradle-retrolambda:3.7.0'
classpath 'io.fabric.tools:gradle:1.+'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}