aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2017-10-19 01:59:16 +0900
committerKazuki Yamaguchi <k@rhe.jp>2017-10-19 01:59:16 +0900
commit3ca62eec575da4200823662ac95f092c3271aa59 (patch)
treef6ef1f7671a33896dba1374f36b54b7c916b1d87
parenta45a6b24126d023f1ea2e28216c612860afd051f (diff)
downloadSmileEssence-3ca62eec575da4200823662ac95f092c3271aa59.tar.gz
uaua
-rw-r--r--app/build.gradle3
-rw-r--r--app/licenses.yml6
-rw-r--r--app/src/main/AndroidManifest.xml15
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/Application.kt21
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/World.kt229
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt200
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt89
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/activity/ManagePagesActivity.kt127
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/Account.kt113
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/DbHelper.kt9
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/data/Pages.kt137
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/entity/User.kt3
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.kt56
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt20
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.kt6
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.kt8
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.kt8
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.kt16
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.kt6
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.kt10
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.kt16
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.kt96
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.kt36
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/util/UIHelpers.kt9
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/MainFragmentPagerAdapter.kt47
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/OnOffImageView.kt24
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/Partials.kt93
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt45
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.kt34
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.kt7
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.kt2
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.kt62
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt3
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.kt21
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.kt14
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.kt38
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.kt61
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.kt64
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.kt36
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt18
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.kt41
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.kt156
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/TweetsPageFragment.kt27
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.kt82
-rw-r--r--app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.kt27
-rw-r--r--app/src/main/res/layout/activity_page_manage.xml36
-rw-r--r--app/src/main/res/layout/dialog_status_detail.xml28
-rw-r--r--app/src/main/res/layout/list_item_page.xml26
-rw-r--r--app/src/main/res/layout/list_item_status.xml91
-rw-r--r--app/src/main/res/layout/manage_pages_edit_dialog.xml44
-rw-r--r--app/src/main/res/menu/main.xml4
-rw-r--r--app/src/main/res/values/attrs.xml5
-rw-r--r--app/src/main/res/values/dimens.xml (renamed from app/src/main/res/values/dimen.xml)3
-rw-r--r--app/src/main/res/values/keys.xml4
-rw-r--r--app/src/main/res/values/strings.xml9
-rw-r--r--app/src/main/res/values/styles.xml6
-rw-r--r--app/src/main/res/xml/setting.xml18
-rw-r--r--gradle.properties2
58 files changed, 1161 insertions, 1256 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 082033f9..6add0b86 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -67,6 +67,9 @@ dependencies {
implementation 'org.twitter4j:twitter4j-media-support:4.0.6'
implementation 'org.twitter4j:twitter4j-stream:4.0.6'
+ // Klaxon
+ implementation 'com.beust:klaxon:0.30'
+
// LeakCanary
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
diff --git a/app/licenses.yml b/app/licenses.yml
index 4bcfa3aa..394900a2 100644
--- a/app/licenses.yml
+++ b/app/licenses.yml
@@ -10,6 +10,7 @@
name: kotlinx-coroutines-core
copyrightHolder: JetBrains s.r.o.
license: The Apache License, Version 2.0
+ licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: org.jetbrains.kotlinx:kotlinx-coroutines-android:+
skip: true
- artifact: org.jetbrains.kotlin:kotlin-android-extensions-runtime:+
@@ -53,6 +54,11 @@
license: Apache License 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0
url: http://twitter4j.org/
+- artifact: com.beust:klaxon:+
+ name: Klaxon
+ copyrightHolder: <><><><>
+ license: The Apache Software License, Version 2.0
+ licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: com.squareup.leakcanary:leakcanary-android-no-op:+
name: No op LeakCanary for Android
copyrightHolder: Square, Inc.
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b34c1a63..caca3a96 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,6 +20,7 @@
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
+
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:label="@string/intent_post">
@@ -35,11 +36,14 @@
</intent-filter>
<intent-filter android:label="@string/intent_post">
<action android:name="android.intent.action.SEND" />
+
<data android:mimeType="text/plain" />
+
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
+
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/jpeg" />
@@ -75,7 +79,6 @@
android:documentLaunchMode="intoExisting"
android:label="@string/app_name"
android:windowSoftInputMode="stateHidden|adjustResize">
-
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -93,23 +96,27 @@
android:excludeFromRecents="true"
android:label="@string/activity_setting"
android:launchMode="singleTask"
- android:parentActivityName="net.lacolaco.smileessence.activity.MainActivity" />
+ android:parentActivityName=".activity.MainActivity" />
<activity
android:name=".activity.EditExtractionActivity"
android:configChanges="keyboardHidden|orientation"
android:excludeFromRecents="true"
android:label="@string/activity_edit_extraction"
android:launchMode="singleTask"
- android:parentActivityName="net.lacolaco.smileessence.activity.MainActivity" />
+ android:parentActivityName=".activity.MainActivity" />
<activity
android:name=".activity.LicenseActivity"
android:label="@string/activity_licenses"
- android:parentActivityName="net.lacolaco.smileessence.activity.SettingActivity" />
+ android:parentActivityName=".activity.SettingActivity" />
<activity
android:name=".activity.OAuthActivity"
android:configChanges="keyboardHidden|orientation"
android:excludeFromRecents="false"
android:label="@string/activity_authenticate"
android:parentActivityName=".activity.ManageAccountsActivity" />
+ <activity
+ android:name=".activity.ManagePagesActivity"
+ android:label="@string/title_activity_page_manage" />
</application>
+
</manifest>
diff --git a/app/src/main/java/net/lacolaco/smileessence/Application.kt b/app/src/main/java/net/lacolaco/smileessence/Application.kt
index 075f134f..17c6e6d6 100644
--- a/app/src/main/java/net/lacolaco/smileessence/Application.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/Application.kt
@@ -3,11 +3,7 @@ package net.lacolaco.smileessence
import android.support.annotation.StringRes
import android.widget.Toast
import com.squareup.leakcanary.LeakCanary
-import net.lacolaco.smileessence.data.Account
import net.lacolaco.smileessence.data.DbHelper
-import net.lacolaco.smileessence.data.ExtractionWord
-import java.lang.ref.WeakReference
-import java.util.*
class Application : android.app.Application() {
override fun onCreate() {
@@ -18,15 +14,12 @@ class Application : android.app.Application() {
instance = this
DbHelper.setup(this)
- Account.load()
-
- // XXX
- ExtractionWord.load()}
+ World.load()
+ }
companion object {
lateinit var instance: Application
private set
- private val worlds = HashMap<Long, WeakReference<World>>() // XXX
fun toast(@StringRes id: Int) {
Toast.makeText(instance, id, Toast.LENGTH_LONG).show()
@@ -37,15 +30,5 @@ class Application : android.app.Application() {
}
var currentWorld: World? = null
-
- fun getWorld(id: Long): World {
- val w0 = worlds[id]?.get()
- if (w0 != null)
- return w0
- val w = World(Account[id])
- val ww = WeakReference(w)
- worlds.put(id, ww)
- return w
- }
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/World.kt b/app/src/main/java/net/lacolaco/smileessence/World.kt
index 80b04d31..bf748fe5 100644
--- a/app/src/main/java/net/lacolaco/smileessence/World.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/World.kt
@@ -1,22 +1,27 @@
package net.lacolaco.smileessence
+import android.content.ContentValues
import android.content.Intent
import android.support.annotation.StringRes
import android.support.design.widget.Snackbar
+import android.view.View
import net.lacolaco.smileessence.activity.MainActivity
import net.lacolaco.smileessence.compat.Twitter4J
-import net.lacolaco.smileessence.data.Account
-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.data.DbHelper
+import net.lacolaco.smileessence.data.PageInfo
+import net.lacolaco.smileessence.entity.*
import net.lacolaco.smileessence.logging.Logger
import net.lacolaco.smileessence.twitter.TwitterTaskException
import net.lacolaco.smileessence.twitter.UserStreamListener
import net.lacolaco.smileessence.twitter.task.*
import net.lacolaco.smileessence.util.launchBg
import net.lacolaco.smileessence.util.launchUi
+import twitter4j.Twitter
+import twitter4j.TwitterFactory
import twitter4j.TwitterStream
+import twitter4j.TwitterStreamFactory
+import twitter4j.auth.AccessToken
+import twitter4j.conf.ConfigurationBuilder
import java.lang.ref.WeakReference
import java.util.*
import java.util.concurrent.ConcurrentHashMap
@@ -24,7 +29,11 @@ import java.util.concurrent.ConcurrentHashMap
/**
* World contains data that are specific to an account.
*/
-class World(val account: Account) {
+class World private constructor(private val persistentData: PersistentData) {
+ val id = persistentData.id
+ val user: User by lazy {
+ User.fetch(id) ?: User._makeSkeleton(id, persistentData.screenName, persistentData.profileImageUrl)
+ }
// XXX: Workaround for a bug in Android
var mainActivityIntent: Intent? = null
// Timelines
@@ -48,6 +57,8 @@ class World(val account: Account) {
// Notification
private var mainActivity: WeakReference<MainActivity>? = null
private var isMainActivityActive: Boolean = false
+ // Pages
+ val pages = persistentData.pageInfos
// Startup
@@ -57,17 +68,75 @@ class World(val account: Account) {
return
initialized = true
- refreshListSubscriptions()
- refreshUserMuteList()
- refreshSavedSearches()
+ launchBg {
+ try {
+ val lists = getUserListsAsync().await()
+ listSubscriptions.clear()
+ listSubscriptions.addAll(lists)
+ } catch (e: TwitterTaskException) {
+ }
+ }
+ launchBg {
+ try {
+ val blockIds = getBlocksIdsAsync()
+ val muteIds = getMutesIdsAsync()
+ muteUserIds += blockIds.await()
+ muteUserIds += muteIds.await()
+ } catch (e: TwitterTaskException) {
+ }
+ }
+ launchBg {
+ try {
+ val ssl = getSavedSearchesAsync().await()
+ savedSearches.clear()
+ for (ss in ssl)
+ savedSearches.put(ss.id, ss)
+ } catch (e: TwitterTaskException) {
+ }
+ }
+ launchBg {
+ try {
+ val jobs = listOf(getHomeTimelineAsync(), getMentionsTimelineAsync())
+ jobs.forEach { addTweetAll(it.await()) }
+ } catch (e: TwitterTaskException) {
+ notifyError(R.string.notice_error_get_home)
+ }
+ }
- stream = account.twitterStream
+ val stream = TwitterStreamFactory().instance
+ stream.oAuthAccessToken = AccessToken(
+ persistentData.oauthToken, persistentData.oauthTokenSecret)
userStreamListener = UserStreamListener(this)
- Twitter4J.twitterStreamAddListener(stream!!, userStreamListener!!)
- stream!!.addConnectionLifeCycleListener(userStreamListener)
- stream!!.user()
+ Twitter4J.twitterStreamAddListener(stream, userStreamListener!!)
+ stream.addConnectionLifeCycleListener(userStreamListener)
+ stream.user()
}
+ fun checkpoint() {
+ persistentData.screenName = user.screenName
+ persistentData.profileImageUrl = user.profileImageUrl
+ persistentData.save()
+ }
+
+ val useDarkTheme
+ get() = persistentData.themeIndex == 0
+
+ var themeColor
+ get() = persistentData.themeColor
+ set(value) {
+ persistentData.themeColor = value
+ }
+
+ val twitter: Twitter
+ get() {
+ val cb = ConfigurationBuilder()
+ cb.setTweetModeExtended(true)
+ val twitter = TwitterFactory(cb.build()).instance
+ twitter.oAuthAccessToken = AccessToken(
+ persistentData.oauthToken, persistentData.oauthTokenSecret)
+ return twitter
+ }
+
// MainActivity holder
fun setMainActivity(activity: MainActivity) {
@@ -145,15 +214,6 @@ class World(val account: Account) {
// Lists
- fun refreshListSubscriptions() = launchBg {
- try {
- val lists = getUserListsAsync().await()
- listSubscriptions.clear()
- listSubscriptions.addAll(lists)
- } catch (e: TwitterTaskException) {
- }
- }
-
fun addListSubscription(fullName: String): Boolean {
return listSubscriptions.add(fullName)
}
@@ -162,34 +222,6 @@ class World(val account: Account) {
return listSubscriptions.remove(fullName)
}
- // Mute
-
- fun refreshUserMuteList() = launchBg {
- try {
- val blockIds = getBlocksIdsAsync()
- val muteIds = getMutesIdsAsync()
- muteUserIds += blockIds.await()
- muteUserIds += muteIds.await()
- } catch (e: TwitterTaskException) {
- }
- }
-
- fun isMutedUserListContains(id: Long): Boolean {
- return muteUserIds.contains(id)
- }
-
- // Saved search queries
-
- fun refreshSavedSearches() = launchBg {
- try {
- val ssl = getSavedSearchesAsync().await()
- savedSearches.clear()
- for (ss in ssl)
- savedSearches.put(ss.id, ss)
- } catch (e: TwitterTaskException) {
- }
- }
-
// Notifications
fun notify(text: String) {
@@ -221,9 +253,10 @@ class World(val account: Account) {
private fun doNotify(type: NotificationType, text: String) {
launchUi {
if (isMainActivityActive) {
+ val view: View = mainActivity!!.get()!!.findViewById(android.R.id.content)
// TODO: Make errors distinguishable
Logger.debug("notify(snackbar): $text")
- Snackbar.make(mainActivity!!.get()!!.findViewById(android.R.id.content), text, Snackbar.LENGTH_SHORT).show()
+ Snackbar.make(view, text, Snackbar.LENGTH_SHORT).show()
} else {
Logger.debug(String.format("notify(toast): %s", text))
Application.toast(text)
@@ -235,4 +268,98 @@ class World(val account: Account) {
INFO,
ALERT
}
+
+ companion object {
+ private val cache = LinkedHashMap<Long, World>()
+
+ operator fun get(i: Long) =
+ cache[i] ?: throw IllegalStateException("[BUG] Account with id == $i not found")
+
+ fun all() = ArrayList(cache.values)
+
+ fun load() {
+ if (cache.isNotEmpty())
+ throw IllegalStateException("World.load called twice")
+ PersistentData.fetchAll().forEach { cache[it.id] = World(it) }
+ Logger.info("Loaded ${cache.size} profiles")
+ }
+
+ fun register(token: String, tokenSecret: String, userId: Long, screenName: String): World {
+ val world = World(PersistentData(userId, token, tokenSecret, screenName).apply { save() })
+ cache[userId] = world
+ return world
+ }
+ }
+
+ private data class PersistentData(
+ val id: Long,
+ val oauthToken: String,
+ val oauthTokenSecret: String,
+ var screenName: String,
+ var profileImageUrl: String = "https://abs.twimg.com/sticky/default_profile_images/default_profile.png",
+ var pageInfos: List<PageInfo> = makeDefaultPageInfos(screenName),
+ var themeIndex: Int = 0,
+ var themeColor: Int = 0
+ ) {
+ fun save() {
+ val values = ContentValues()
+ values.put("id", id)
+ values.put("oauth_token", oauthToken)
+ values.put("oauth_token_secret", oauthTokenSecret)
+ values.put("screen_name", screenName)
+ values.put("profile_image_url", profileImageUrl)
+ Logger.error("pageinfo saving: ${PageInfo.stringifyList(pageInfos)}")
+ values.put("page_infos", PageInfo.stringifyList(pageInfos))
+ values.put("theme", themeIndex)
+ values.put("theme_color", themeColor)
+ if (DbHelper.db.replaceOrThrow("accounts", null, values) == -1L)
+ throw RuntimeException("SQLiteDatabase#replaceOrThrow failed")
+ }
+
+ companion object {
+ private fun makeDefaultPageInfos(screenName: String): List<PageInfo> {
+ val ret = arrayListOf<PageInfo>()
+ ret.add(PageInfo.ComposePageInfo())
+ ret.add(PageInfo.TweetsPageInfo("Home", arrayListOf("")))
+ ret.add(PageInfo.TweetsPageInfo("Mentions", arrayListOf("@$screenName")))
+ ret.add(PageInfo.EventsPageInfo())
+ ret.add(PageInfo.SearchPageInfo(""))
+ ret.add(PageInfo.ListPageInfo(null))
+ return ret
+ }
+
+ fun fetchAll(): List<PersistentData> {
+ val ret = arrayListOf<PersistentData>()
+ DbHelper.db.query("accounts", null, null, null, null, null, null).use { cursor ->
+ while (cursor != null && cursor.moveToNext()) {
+ val pd = PersistentData(
+ id = cursor.getLong(
+ cursor.getColumnIndexOrThrow("id")),
+ oauthToken = cursor.getString(
+ cursor.getColumnIndexOrThrow("oauth_token")),
+ oauthTokenSecret = cursor.getString(
+ cursor.getColumnIndexOrThrow("oauth_token_secret")),
+ screenName = cursor.getString(
+ cursor.getColumnIndexOrThrow("screen_name")),
+ profileImageUrl = cursor.getString(
+ cursor.getColumnIndexOrThrow("profile_image_url")),
+ pageInfos = PageInfo.parseList(cursor.getString(
+ cursor.getColumnIndexOrThrow("page_infos"))),
+ themeIndex = cursor.getInt(
+ cursor.getColumnIndexOrThrow("theme")),
+ themeColor = cursor.getInt(
+ cursor.getColumnIndexOrThrow("theme_color"))
+ )
+ // XXX: Remove this
+ if (pd.pageInfos.isEmpty()) {
+ pd.pageInfos = makeDefaultPageInfos(pd.screenName)
+ pd.save()
+ }
+ ret.add(pd)
+ }
+ }
+ return ret
+ }
+ }
+ }
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt
index 249121f5..caedbd6b 100644
--- a/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/MainActivity.kt
@@ -7,7 +7,6 @@ import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.os.Bundle
-import android.provider.MediaStore
import android.support.v4.view.ViewPager
import android.support.v7.app.AppCompatActivity
import android.support.v7.graphics.Palette
@@ -18,34 +17,38 @@ import kotlinx.android.synthetic.main.layout_main.*
import net.lacolaco.smileessence.Application
import net.lacolaco.smileessence.R
import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.data.PageInfo
import net.lacolaco.smileessence.entity.Tweet
import net.lacolaco.smileessence.entity.User
import net.lacolaco.smileessence.logging.Logger
import net.lacolaco.smileessence.twitter.TwitterTaskException
import net.lacolaco.smileessence.twitter.task.getTweetAsync
import net.lacolaco.smileessence.twitter.task.getUserAsync
-import net.lacolaco.smileessence.util.*
+import net.lacolaco.smileessence.util.bg
+import net.lacolaco.smileessence.util.browse
+import net.lacolaco.smileessence.util.getMainActivityOrCancel
+import net.lacolaco.smileessence.util.launchUi
import net.lacolaco.smileessence.view.DialogHelper
import net.lacolaco.smileessence.view.MainFragmentPagerAdapter
import net.lacolaco.smileessence.view.confirm
import net.lacolaco.smileessence.view.dialog.StatusDetailDialogFragment
import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment
-import net.lacolaco.smileessence.view.page.*
+import net.lacolaco.smileessence.view.page.PostFragment
import java.io.IOException
import java.io.InputStream
import java.net.URL
import java.util.regex.Pattern
-class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
- val world: World by lazy {
+class MainActivity : AppCompatActivity() {
+ val 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")
- Application.getWorld(userIdValue.toLong())
+ World[userIdValue.toLong()]
}
private lateinit var pagerAdapter: MainFragmentPagerAdapter
fun openHomePage() {
- viewPager.setCurrentItem(pagerAdapter.getPageIndex(TAG_PAGE_HOME), true)
+ viewPager.setCurrentItem(world.pages.indexOfFirst { it is PageInfo.TweetsPageInfo }, true)
}
private fun setSelectedPageIndex(position: Int, smooth: Boolean = true) {
@@ -53,55 +56,35 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
}
fun openPostPageAndReplyTo(tweet: Tweet, prefix: String) {
- val postPage = pagerAdapter.getPageFragment(TAG_PAGE_POST) as PostFragment
- postPage.setInReplyTo(tweet, prefix)
- setSelectedPageIndex(pagerAdapter.getPageIndex(TAG_PAGE_POST), true)
+ val postPagePosition = world.pages.indexOfFirst { it is PageInfo.ComposePageInfo }
+ assert(postPagePosition != -1)
+ (pagerAdapter.getPageFragmentAt(postPagePosition) as PostFragment).setInReplyTo(tweet, prefix)
+ setSelectedPageIndex(postPagePosition, true)
}
fun openPostPageAndReplyTo(user: User) {
- val postPage = pagerAdapter.getPageFragment(TAG_PAGE_POST) as PostFragment
- postPage.setInReplyTo(user)
- setSelectedPageIndex(pagerAdapter.getPageIndex(TAG_PAGE_POST), true)
+ val postPagePosition = world.pages.indexOfFirst { it is PageInfo.ComposePageInfo }
+ assert(postPagePosition != -1)
+ (pagerAdapter.getPageFragmentAt(postPagePosition) as PostFragment).setInReplyTo(user)
+ setSelectedPageIndex(postPagePosition, true)
}
fun openPostPageAndAppendText(text: String) {
- val postPage = pagerAdapter.getPageFragment(TAG_PAGE_POST) as PostFragment
- postPage.appendText(text)
- setSelectedPageIndex(pagerAdapter.getPageIndex(TAG_PAGE_POST), true)
- }
-
- private fun openPostPageWithImage(uri: Uri) {
- try {
- val c = contentResolver.query(uri, null, null, null, null)!!
- c.moveToFirst()
- val path = c.getString(c.getColumnIndex(MediaStore.MediaColumns.DATA))
- val postPage = pagerAdapter.getPageFragment(TAG_PAGE_POST) as PostFragment
- postPage.setMediaFilePath(path)
- 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.getPageFragment(TAG_PAGE_SEARCH) as SearchFragment
- fragment.startSearch(query)
- setSelectedPageIndex(pagerAdapter.getPageIndex(TAG_PAGE_SEARCH))
+ val postPagePosition = world.pages.indexOfFirst { it is PageInfo.ComposePageInfo }
+ assert(postPagePosition != -1)
+ (pagerAdapter.getPageFragmentAt(postPagePosition) as PostFragment).appendText(text)
+ setSelectedPageIndex(postPagePosition, true)
}
private fun setTitle() {
//title = String.format("%s / %s", world.account.user.screenName, pagerAdapter.getName(viewPager.currentItem))
- val label = getString(R.string.app_name) + " - @" + world.account.user.screenName
+ val label = getString(R.string.app_name) + " - @" + world.user.screenName
if (android.os.Build.VERSION.SDK_INT >= 21) {
- setTaskDescription(ActivityManager.TaskDescription(label, null, world.account.themeColor))
- window.statusBarColor = world.account.themeColor
+ setTaskDescription(ActivityManager.TaskDescription(label, null, world.themeColor))
+ window.statusBarColor = world.themeColor
}
- launchBg { world.account.syncProfileAndSaveIfNecessary() }
- if (!world.account.user.profileImageUrl.startsWith("http"))
+ if (!world.user.profileImageUrl.startsWith("http"))
return
// XXX: It doesn't seem possible to change scaleType of the ImageButton to fitXY
@@ -109,10 +92,8 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
val bitmap = bg {
var inputStream: InputStream? = null
try {
- inputStream = URL(world.account.user.profileImageUrl).openStream()
- val opt = BitmapFactory.Options()
- opt.inPurgeable = true // GC可能にする
- return@bg BitmapFactory.decodeStream(inputStream, null, opt)
+ inputStream = URL(world.user.profileImageUrl).openStream()
+ return@bg BitmapFactory.decodeStream(inputStream)
} catch (e: IOException) {
e.printStackTrace()
return@bg null
@@ -135,12 +116,12 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
toolbar.navigationIcon = BitmapDrawable(resources, scaledBitmap)
val palette = dPalette.await()
- val swatch = if (world.account.useDarkTheme)
+ val swatch = if (world.useDarkTheme)
palette.darkVibrantSwatch ?: palette.darkMutedSwatch ?: palette.dominantSwatch
else
palette.vibrantSwatch ?: palette.mutedSwatch ?: palette.dominantSwatch
if (swatch == null) {
- Logger.info("Unable to get a theme color of @${world.account.user.screenName}")
+ Logger.info("Unable to get a theme color of @${world.user.screenName}")
} else {
//actionBar.setBackgroundDrawable(ColorDrawable(swatch.rgb))
toolbar.setBackgroundColor(swatch.rgb)
@@ -148,14 +129,13 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
window.statusBarColor = swatch.rgb
setTaskDescription(ActivityManager.TaskDescription(label, bitmap, swatch.rgb))
}
- world.account.themeColor = swatch.rgb
- launchBg { world.account.save() }
+ world.themeColor = swatch.rgb
}
}
}
private fun processIntent(intent: Intent) {
- val uri = intent.getParcelableExtra<Uri>(KEY_ORIGINAL_DATA)
+ val uri = intent.data
if (uri != null) {
if (uri.host == "twitter.com") {
// /share and /intent/tweet: don't accept status parameter
@@ -171,9 +151,10 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
val via = uri.getQueryParameter("via")
if (!TextUtils.isEmpty(via))
text += " via @" + via
- val postPage = pagerAdapter.getPageFragment(TAG_PAGE_POST) as PostFragment
- postPage.setText(text)
- viewPager.setCurrentItem(pagerAdapter.getPageIndex(TAG_PAGE_POST), true)
+ val postPagePosition = world.pages.indexOfFirst { it is PageInfo.ComposePageInfo }
+ assert(postPagePosition != -1)
+ (pagerAdapter.getPageFragmentAt(postPagePosition) as PostFragment).setText(text)
+ setSelectedPageIndex(postPagePosition, true)
return
}
val statusMatcher = TWITTER_STATUS_PATTERN.matcher(uri.path)
@@ -201,7 +182,7 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
}
} else when (intent.action) {
Intent.ACTION_SEND -> {
- val type = intent.getStringExtra(KEY_ORIGINAL_TYPE)
+ val type = intent.type
if (type == "text/plain") {
val extra = intent.extras
if (extra != null) {
@@ -209,26 +190,28 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
if (!TextUtils.isEmpty(extra.getCharSequence(Intent.EXTRA_SUBJECT))) {
text = extra.getCharSequence(Intent.EXTRA_SUBJECT).toString() + " " + text
}
- val postPage = pagerAdapter.getPageFragment(TAG_PAGE_POST) as PostFragment
- postPage.setText(text)
- viewPager.setCurrentItem(pagerAdapter.getPageIndex(TAG_PAGE_POST), true)
+ val postPagePosition = world.pages.indexOfFirst { it is PageInfo.ComposePageInfo }
+ assert(postPagePosition != -1)
+ (pagerAdapter.getPageFragmentAt(postPagePosition) as PostFragment).setText(text)
+ setSelectedPageIndex(postPagePosition, true)
return
}
} else if (type != null && type.startsWith("image/")) {
- openPostPageWithImage(intent.getParcelableExtra(Intent.EXTRA_STREAM))
+ val postPagePosition = world.pages.indexOfFirst { it is PageInfo.ComposePageInfo }
+ assert(postPagePosition != -1)
+ (pagerAdapter.getPageFragmentAt(postPagePosition) as PostFragment)
+ .setMediaFile(intent.getParcelableExtra(Intent.EXTRA_STREAM))
}
}
}
}
- // ------------------------ OVERRIDE METHODS ------------------------
-
override fun onBackPressed() {
finish()
}
override fun finish() {
- val homeIndex = pagerAdapter.getPageIndex(TAG_PAGE_HOME)
+ val homeIndex = world.pages.indexOfFirst { it is PageInfo.TweetsPageInfo }
if (viewPager.currentItem != homeIndex)
viewPager.setCurrentItem(homeIndex, true)
else
@@ -237,53 +220,41 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
- REQUEST_GET_PICTURE_FROM_GALLERY -> {
- if (resultCode != RESULT_OK) {
- Logger.error(requestCode)
- world.notifyError(R.string.notice_select_image_failed)
- finish()
- return
+ REQUEST_CODE_MANAGE_PAGES -> {
+ if (resultCode == RESULT_OK) {
+ Application.toast("Restarting activity...")
+ super.finish()
+ startActivity(intent)
}
- openPostPageWithImage(data!!.data)
}
+ else -> super.onActivityResult(requestCode, resultCode, data)
}
}
- public override fun onCreate(savedInstanceState: Bundle?) {
+ override fun onCreate(savedInstanceState: Bundle?) {
Logger.debug("onCreate")
super.onCreate(savedInstanceState)
world.setMainActivity(this)
- setTheme(if (world.account.useDarkTheme) R.style.theme_dark else R.style.theme_light)
+ setTheme(if (world.useDarkTheme) R.style.theme_dark else R.style.theme_light)
setContentView(R.layout.layout_main)
setSupportActionBar(toolbar)
- val args = Bundle()
- args.putLong(PageFragment.KEY_WORLD_USER_ID, world.account.id)
- pagerAdapter = MainFragmentPagerAdapter(fragmentManager, viewPager)
- pagerAdapter.addPage(TAG_PAGE_POST, PostFragment::class.java, args)
- pagerAdapter.addPage(TAG_PAGE_HOME, HomeFragment::class.java, args)
- pagerAdapter.addPage(TAG_PAGE_MENTIONS, MentionsFragment::class.java, args)
- pagerAdapter.addPage(TAG_PAGE_EVENTS, HistoryFragment::class.java, args)
- pagerAdapter.addPage(TAG_PAGE_MESSAGES, MessagesFragment::class.java, args)
- pagerAdapter.addPage(TAG_PAGE_SEARCH, SearchFragment::class.java, args)
- pagerAdapter.addPage(TAG_PAGE_LIST, UserListFragment::class.java, args)
- pagerAdapter.notifyDataSetChanged()
-
- // TODO: tab order?
- getString(R.string.page_name_post)
- getString(R.string.page_name_home)
- getString(R.string.page_name_mentions)
- getString(R.string.page_name_history)
- getString(R.string.page_name_messages)
- getString(R.string.page_name_search)
- getString(R.string.page_name_list)
-
- viewPager.addOnPageChangeListener(this)
+ pagerAdapter = MainFragmentPagerAdapter(world, viewPager, fragmentManager)
viewPager.offscreenPageLimit = pagerAdapter.count
viewPager.adapter = pagerAdapter
- viewPager.setCurrentItem(pagerAdapter.getPageIndex(TAG_PAGE_HOME), false)
+ viewPager.setCurrentItem(world.pages.indexOfFirst { it is PageInfo.TweetsPageInfo }, false)
+ viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
+ override fun onPageScrollStateChanged(state: Int) {}
+
+ override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
+
+ override fun onPageSelected(position: Int) {
+ Logger.verbose("Page #$position selected (${world.pages[position].name})")
+ title = "${world.user.screenName} / ${world.pages[position].name}"
+ }
+ })
// Set application title
setTitle()
@@ -305,8 +276,12 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
startActivity(intent)
}
R.id.actionbar_setting -> startActivity(Intent(this, SettingActivity::class.java))
- R.id.actionbar_edit_extraction -> startActivity(Intent(this, EditExtractionActivity::class.java))
- R.id.actionbar_aclog -> browse(world.account.user.aclogTimelineURL)
+ R.id.actionbar_manage_pages -> {
+ val intent = Intent(this, ManagePagesActivity::class.java)
+ intent.putExtra(ManagePagesActivity.INTENT_KEY_WORLD_ID, world.id)
+ startActivityForResult(intent, REQUEST_CODE_MANAGE_PAGES)
+ }
+ R.id.actionbar_aclog -> browse(world.user.aclogTimelineURL)
else -> return super.onOptionsItemSelected(item)
}
return true
@@ -316,6 +291,7 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
Logger.debug("onPause")
super.onPause()
world.setMainActivityActive(false)
+ world.checkpoint()
}
override fun onResume() {
@@ -336,32 +312,10 @@ class MainActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
}
}
- // --------------------- Interface OnPageChangeListener ---------------------
-
- override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
-
- override fun onPageSelected(position: Int) {
- Logger.debug("Page selected: " + position)
- //title = String.format("%s / %s", world.account.user.screenName, pagerAdapter.getName(viewPager.currentItem))
- //setTitle()
- }
-
- override fun onPageScrollStateChanged(state: Int) {}
-
companion object {
- val REQUEST_GET_PICTURE_FROM_GALLERY = 11
- val KEY_ORIGINAL_DATA = "originalData"
- val KEY_ORIGINAL_TYPE = "originalType"
- private val TWITTER_POST_PATTERN = Pattern.compile("\\A/(intent/tweet|share)\\z", Pattern.CASE_INSENSITIVE)
- 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 TAG_PAGE_POST = "PAGE_POST"
- private val TAG_PAGE_HOME = "PAGE_HOME"
- private val TAG_PAGE_MENTIONS = "PAGE_MENTIONS"
- private val TAG_PAGE_EVENTS = "PAGE_EVENTS"
- private val TAG_PAGE_MESSAGES = "PAGE_MESSAGES"
- private val TAG_PAGE_SEARCH = "PAGE_SEARCH"
- private val TAG_PAGE_LIST = "PAGE_LIST"
+ private val REQUEST_CODE_MANAGE_PAGES = 12
+ private val TWITTER_POST_PATTERN = Pattern.compile("\\A/(intent/tweet|share)\\z")
+ private val TWITTER_STATUS_PATTERN = Pattern.compile("\\A(?:/#!)?/(?:\\w{1,15})/status(?:es)?/(\\d+)\\z")
+ private val TWITTER_USER_PATTERN = Pattern.compile("\\A(?:/#!)?/(\\w{1,15})/?\\z")
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt
index 0f5924b8..e3ca1818 100644
--- a/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/ManageAccountsActivity.kt
@@ -1,5 +1,6 @@
package net.lacolaco.smileessence.activity
+import android.Manifest
import android.content.ComponentName
import android.content.Intent
import android.content.pm.PackageManager
@@ -17,7 +18,6 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import android.widget.AdapterView
import android.widget.BaseAdapter
import android.widget.ImageView
import com.android.volley.toolbox.ImageRequest
@@ -26,7 +26,6 @@ import kotlinx.android.synthetic.main.list_item_account.view.*
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.util.launchBg
import net.lacolaco.smileessence.util.launchUi
@@ -44,9 +43,10 @@ class ManageAccountsActivity : AppCompatActivity() {
// If the activity is started from launcher
if (!intent.getBooleanExtra(INTENT_KEY_NOINIT, false)) {
- if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
- PackageManager.PERMISSION_GRANTED)
- ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED)
+ ActivityCompat.requestPermissions(this,
+ arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION)
else if (Application.currentWorld != null) {
// Skip this activity if app is already started
@@ -59,9 +59,9 @@ class ManageAccountsActivity : AppCompatActivity() {
setSupportActionBar(toolbar)
listview_edit_list.adapter = adapter
- listview_edit_list.setOnItemClickListener { adapterView: AdapterView<*>, view1: View, i: Int, l: Long ->
- val account = adapter.getItem(i)
- goToWorld(Application.getWorld(account.id))
+ listview_edit_list.setOnItemClickListener { _, _, i, _ ->
+ val world = adapter.getItem(i)
+ goToWorld(World[world.id])
}
}
@@ -70,10 +70,11 @@ class ManageAccountsActivity : AppCompatActivity() {
receivedIntent = Intent(intent)
}
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
+ grantResults: IntArray) {
when (requestCode) {
REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION -> {
- if (grantResults.size == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
if (Application.currentWorld != null) {
goToWorld(Application.currentWorld!!)
}
@@ -86,14 +87,10 @@ class ManageAccountsActivity : AppCompatActivity() {
}
private fun goToWorld(world: World) {
- // Continue the existing MainActivity
- receivedIntent.component = ComponentName(this, MainActivity::class.java)
- receivedIntent.putExtra(MainActivity.KEY_ORIGINAL_DATA, receivedIntent.data)
- receivedIntent.putExtra(MainActivity.KEY_ORIGINAL_TYPE, receivedIntent.type)
- val intent = Intent(this, MainActivity::class.java)
- intent.data = Uri.parse("smileessence://mainactivity/?user_id=" + world.account.id)
finish()
world.mainActivityIntent = receivedIntent
+ val intent = Intent(this, MainActivity::class.java)
+ intent.data = Uri.parse("smileessence://mainactivity/?user_id=" + world.id)
startActivity(intent)
}
@@ -132,7 +129,7 @@ class ManageAccountsActivity : AppCompatActivity() {
if (resultCode == RESULT_OK) {
launchBg {
data!!
- adapter.add(Account.register(
+ adapter.add(World.register(
data.getStringExtra(OAuthActivity.KEY_TOKEN),
data.getStringExtra(OAuthActivity.KEY_TOKEN_SECRET),
data.getLongExtra(OAuthActivity.KEY_USER_ID, -1L),
@@ -143,53 +140,61 @@ class ManageAccountsActivity : AppCompatActivity() {
}
private inner class EditAccountsAdapter : BaseAdapter() {
- private val accounts: MutableList<Account> = ArrayList(Account.all())
+ private val worlds: MutableList<World> = ArrayList(World.all())
- override fun getCount(): Int = accounts.size
+ override fun getCount(): Int = worlds.size
- override fun getItem(position: Int): Account = accounts[position]
+ override fun getItem(position: Int) = worlds[position]
- override fun getItemId(position: Int): Long = accounts[position].id
+ override fun getItemId(position: Int): Long = worlds[position].id
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
- val view = convertView ?: layoutInflater.inflate(R.layout.list_item_account, parent, false)
- val account = getItem(position)
-
- view.account_accent_color_view.setBackgroundColor(if (account.themeColor != -1) account.themeColor else Color.TRANSPARENT)
- view.account_icon.setImageUrl(account.user.profileImageUrl, ImageCache.getImageLoader())
- view.account_text_view.text = "@${account.user.screenName}"
+ val view = convertView ?: layoutInflater.inflate(R.layout.list_item_account, parent,
+ false)
+ val world = getItem(position)
+
+ if (world.themeColor != -1)
+ view.account_accent_color_view.setBackgroundColor(world.themeColor)
+ else
+ view.account_accent_color_view.setBackgroundColor(Color.TRANSPARENT)
+ view.account_icon.setImageUrl(world.user.profileImageUrl, ImageCache.getImageLoader())
+ view.account_text_view.text = "@${world.user.screenName}"
view.account_action_menu.clear()
view.account_action_menu.add("Remove") {
- confirm(R.string.dialog_confirm_clear_account, account.user.screenName) {
- accounts.removeAt(position)
+ confirm(R.string.dialog_confirm_clear_account, world.user.screenName) {
+ worlds.removeAt(position)
notifyDataSetChanged()
// TODO: Account.unregister(account.id)
// TODO: Stop the world
}
}
view.account_action_menu.add("Add to homescreen") {
- val shortcutIntent = Intent(Intent.ACTION_VIEW, Uri.parse("smileessence://mainactivity/?user_id=" + account.id))
- val intent = Intent("com.android.launcher.action.INSTALL_SHORTCUT")
- intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent)
-
- ImageCache.getRequestQueue().add(ImageRequest(account.user.profileImageUrl, { bitmap ->
- val shortcutInfo = ShortcutInfoCompat.Builder(this@ManageAccountsActivity, "mainactivity-${account.id}")
- .setShortLabel("@${account.user.screenName}")
- .setIcon(IconCompat.createWithAdaptiveBitmap(bitmap))
+ val data = Uri.parse("smileessence://mainactivity/?user_id=" + world.id)
+ val shortcutIntent = Intent(Intent.ACTION_VIEW, data)
+
+ ImageCache.getRequestQueue().add(ImageRequest(world.user.profileImageUrl, { b ->
+ if (isDestroyed)
+ return@ImageRequest
+ val id = "mainactivity-${world.id}"
+ val shortcutInfo = ShortcutInfoCompat.Builder(this@ManageAccountsActivity, id)
+ .setShortLabel("@${world.user.screenName}")
+ .setIcon(IconCompat.createWithAdaptiveBitmap(b))
.setIntent(shortcutIntent)
.build()
ShortcutManagerCompat.requestPinShortcut(this@ManageAccountsActivity, shortcutInfo, null)
- }, 0, 0, ImageView.ScaleType.CENTER, Bitmap.Config.ARGB_4444, { error -> error.printStackTrace() }))
+ }, 0, 0, ImageView.ScaleType.CENTER, Bitmap.Config.ARGB_4444, { error ->
+ error.printStackTrace()
+ }))
}
return view
}
- fun add(account: Account): Int = if (!accounts.contains(account)) {
- accounts.add(account)
+ fun add(world: World): Int = if (!worlds.contains(world)) {
+ worlds.add(world)
notifyDataSetChanged()
- accounts.size - 1
+ worlds.size - 1
} else {
- accounts.indexOf(account)
+ worlds.indexOf(world)
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/activity/ManagePagesActivity.kt b/app/src/main/java/net/lacolaco/smileessence/activity/ManagePagesActivity.kt
new file mode 100644
index 00000000..21b6462e
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/activity/ManagePagesActivity.kt
@@ -0,0 +1,127 @@
+package net.lacolaco.smileessence.activity
+
+import android.os.Bundle
+import android.support.design.widget.Snackbar
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.DividerItemDecoration
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.helper.ItemTouchHelper
+import android.view.View
+import android.view.ViewGroup
+
+import kotlinx.android.synthetic.main.activity_page_manage.*
+import kotlinx.android.synthetic.main.list_item_page.view.*
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.data.PageInfo
+
+class ManagePagesActivity : AppCompatActivity() {
+ private val world by lazy {
+ World[intent.getLongExtra(INTENT_KEY_WORLD_ID, -1)]
+ }
+ private lateinit var pages: MutableList<PageInfo>
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setTheme(if (world.useDarkTheme) R.style.theme_dark else R.style.theme_light)
+ setContentView(R.layout.activity_page_manage)
+ setSupportActionBar(toolbar)
+
+ pages = PageInfo.parseList(if (savedInstanceState == null)
+ PageInfo.stringifyList(world.pages)
+ else
+ savedInstanceState.getString(KEY_SAVED_PAGES)
+ ).toMutableList()
+
+ fab.setOnClickListener {
+ val item = PageInfo.TweetsPageInfo("Tweets", listOf())
+ pages.add(item)
+ recycler_view.adapter.notifyItemInserted(pages.size - 1)
+ openItemEditor(item)
+ }
+ val helper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
+ override fun getMovementFlags(recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder): Int {
+ return makeMovementFlags(ItemTouchHelper.DOWN or ItemTouchHelper.UP,
+ ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT)
+ }
+
+ override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder): Boolean {
+ return (recycler_view.adapter as PagesAdapter)
+ .move(viewHolder.adapterPosition, target.adapterPosition)
+ }
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ (recycler_view.adapter as PagesAdapter).remove(viewHolder.adapterPosition)
+ }
+ })
+ helper.attachToRecyclerView(recycler_view)
+ recycler_view.addItemDecoration(helper)
+ recycler_view.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
+ recycler_view.layoutManager = LinearLayoutManager(this)
+ recycler_view.adapter = PagesAdapter()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ outState.putString(KEY_SAVED_PAGES, PageInfo.stringifyList(pages))
+ }
+
+ override fun finish() {
+ // MainActivity will restart itself on RESULT_OK
+ if (PageInfo.stringifyList(world.pages) == PageInfo.stringifyList(pages))
+ setResult(RESULT_CANCELED)
+ else
+ setResult(RESULT_OK)
+ super.finish()
+ }
+
+ private fun openItemEditor(item: PageInfo) {
+ // TODO
+ }
+
+ companion object {
+ val INTENT_KEY_WORLD_ID = "WORLD_ID"
+ private val KEY_SAVED_PAGES = "SAVED_PAGES"
+ }
+
+ private inner class PagesAdapter : RecyclerView.Adapter<PagesAdapter.ViewHolder>() {
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val item = pages[position]
+ val view = holder.itemView
+ view.page_kind_text_view.text = item.name
+ view.page_name_text_view.text = item.describe()
+
+ view.setOnClickListener {
+ openItemEditor(item)
+ Snackbar.make(fab, "unya", Snackbar.LENGTH_SHORT).show()
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return pages.size
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder(layoutInflater.inflate(R.layout.list_item_page, parent, false))
+ }
+
+ fun move(before: Int, after: Int): Boolean {
+ val item = pages.removeAt(before)
+ pages.add(after, item)
+ notifyItemMoved(before, after)
+ return true
+ }
+
+ fun remove(position: Int) {
+ pages.removeAt(position)
+ notifyItemRemoved(position)
+ notifyItemRangeChanged(position, pages.size)
+ }
+
+ private inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
+ }
+}
+
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/Account.kt b/app/src/main/java/net/lacolaco/smileessence/data/Account.kt
deleted file mode 100644
index bf016d66..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/data/Account.kt
+++ /dev/null
@@ -1,113 +0,0 @@
-package net.lacolaco.smileessence.data
-
-import android.content.ContentValues
-import net.lacolaco.smileessence.entity.User
-import net.lacolaco.smileessence.logging.Logger
-import twitter4j.Twitter
-import twitter4j.TwitterFactory
-import twitter4j.TwitterStream
-import twitter4j.TwitterStreamFactory
-import twitter4j.auth.AccessToken
-import twitter4j.conf.ConfigurationBuilder
-
-class Account private constructor(
- val id: Long,
- private val oauthToken: String,
- private val oauthTokenSecret: String,
- private var screenName: String,
- private var profileImageUrl: String,
- private var themeIndex: Int,
- var themeColor: Int
-) {
- val user: User by lazy { User.fetch(id) ?: User._makeSkeleton(id, screenName, profileImageUrl) }
-
- 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
- }
-
- val useDarkTheme
- get() = themeIndex == 0
-
- fun syncProfileAndSaveIfNecessary() {
- if (user.screenName != screenName || user.profileImageUrl != profileImageUrl) {
- screenName = user.screenName
- profileImageUrl = user.profileImageUrl
- save()
- }
- }
-
- fun save() {
- val values = ContentValues()
- values.put("screen_name", screenName)
- values.put("profile_image_url", profileImageUrl)
- values.put("theme", themeIndex)
- values.put("theme_color", themeColor)
- DbHelper.db.update("accounts", values, "id = ?", arrayOf(id.toString()))
- }
-
- companion object {
- private val cache = LinkedHashMap<Long, Account>()
-
- operator fun get(i: Long) =
- cache[i] ?: throw IllegalStateException("[BUG] Account with id == $i not found")
-
- fun all(): List<Account> = ArrayList(cache.values)
-
- fun load() {
- if (cache.isNotEmpty())
- throw IllegalStateException("Account.load called twice")
- DbHelper.db.query("accounts", null, null, null, null, null, null).use { cursor ->
- while (cursor != null && cursor.moveToNext()) {
- val id = cursor.getLong(cursor.getColumnIndexOrThrow("id"))
- cache.put(id, Account(
- id = id,
- oauthToken = cursor.getString(cursor.getColumnIndexOrThrow("oauth_token")),
- oauthTokenSecret = cursor.getString(cursor.getColumnIndexOrThrow("oauth_token_secret")),
- screenName = cursor.getString(cursor.getColumnIndexOrThrow("screen_name")),
- profileImageUrl = cursor.getString(cursor.getColumnIndexOrThrow("profile_image_url")),
- themeIndex = cursor.getInt(cursor.getColumnIndexOrThrow("theme")),
- themeColor = cursor.getInt(cursor.getColumnIndexOrThrow("theme_color"))
- ))
- }
- }
- Logger.error(cache.size)
- }
-
- fun register(token: String, tokenSecret: String, userId: Long, screenName: String): Account {
- val account = Account(
- userId,
- token,
- tokenSecret,
- screenName,
- "https://abs.twimg.com/sticky/default_profile_images/default_profile.png",
- 0,
- 0)
-
- val values = ContentValues()
- values.put("id", account.id)
- values.put("oauth_token", account.oauthToken)
- values.put("oauth_token_secret", account.oauthTokenSecret)
- values.put("screen_name", account.screenName)
- values.put("profile_image_url", account.profileImageUrl)
- values.put("theme", account.themeIndex)
- values.put("theme_color", account.themeColor)
- DbHelper.db.insertOrThrow("accounts", null, values)
- Logger.error(cache.size)
- cache[userId] = account
-
- return account
- }
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/DbHelper.kt b/app/src/main/java/net/lacolaco/smileessence/data/DbHelper.kt
index 69ee9033..eb1b3a73 100644
--- a/app/src/main/java/net/lacolaco/smileessence/data/DbHelper.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/data/DbHelper.kt
@@ -37,11 +37,18 @@ class DbHelper private constructor(context: Context) :
)
""")
}
+
+ if (oldVersion < 5) {
+ // Add accounts.page_infos
+ db.execSQL("""
+ ALTER TABLE accounts ADD COLUMN page_infos TEXT NOT NULL DEFAULT "[]"
+ """)
+ }
}
companion object {
private val DATABASE_NAME = "main.db"
- private val DATABASE_VERSION = 4
+ private val DATABASE_VERSION = 5
// Lifetime is same as Application
private lateinit var instance: DbHelper
diff --git a/app/src/main/java/net/lacolaco/smileessence/data/Pages.kt b/app/src/main/java/net/lacolaco/smileessence/data/Pages.kt
new file mode 100644
index 00000000..5bde7b1f
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/data/Pages.kt
@@ -0,0 +1,137 @@
+package net.lacolaco.smileessence.data
+
+import com.beust.klaxon.*
+import net.lacolaco.smileessence.logging.Logger
+import net.lacolaco.smileessence.view.page.*
+
+sealed class PageInfo(val fragmentClass: Class<out PageFragment<*>>) {
+ abstract val name: String
+ abstract fun describe(): String
+ abstract fun toJson(): JsonObject
+
+ class ComposePageInfo() : PageInfo(PostFragment::class.java) {
+ override val name = "Compose"
+
+ override fun describe(): String {
+ return ""
+ }
+
+ constructor(json: JsonObject) : this()
+
+ override fun toJson() = json {
+ obj()
+ }
+ }
+
+ class TweetsPageInfo(override val name: String, val patternStrings: List<String>) :
+ PageInfo(TweetsPageFragment::class.java) {
+ val patterns = patternStrings.map { Regex(it) }
+
+ override fun describe(): String {
+ val sb = StringBuilder("Applied filters:")
+ patternStrings.forEach { sb.append("\n\t").append(it) }
+ return sb.toString()
+ }
+
+ constructor(json: JsonObject) : this(json.string("name")!!, json.array<String>("patterns")!!.toList())
+
+ override fun toJson() = json {
+ obj("name" to name, "patterns" to array(patternStrings))
+ }
+ }
+
+ class MessagesPageInfo() : PageInfo(MessagesFragment::class.java) {
+ override val name = "Messages"
+
+ override fun describe(): String {
+ return ""
+ }
+
+ constructor(json: JsonObject) : this()
+
+ override fun toJson() = json {
+ obj()
+ }
+ }
+
+ class EventsPageInfo() : PageInfo(HistoryFragment::class.java) {
+ override val name = "Events"
+
+ override fun describe(): String {
+ return ""
+ }
+
+ constructor(json: JsonObject) : this()
+
+ override fun toJson() = json {
+ obj()
+ }
+ }
+
+ class SearchPageInfo(var query: String) : PageInfo(SearchFragment::class.java) {
+ override val name
+ get() = "Search"
+
+ override fun describe(): String {
+ return "Search query:\n\t$query"
+ }
+
+ constructor(json: JsonObject) : this(json.string("query")!!)
+
+ override fun toJson() = json {
+ obj("query" to query)
+ }
+ }
+
+ class ListPageInfo(var fullName: String?) : PageInfo(UserListFragment::class.java) {
+ override val name
+ get() = "List (${fullName ?: "<not selected>"})"
+
+ override fun describe(): String {
+ return ""
+ }
+
+ constructor(json: JsonObject) : this(json.string("full_name"))
+
+ override fun toJson() = json {
+ obj("full_name" to fullName)
+ }
+ }
+
+ // XXX: Yucks
+ companion object {
+ fun parseList(input: String): List<PageInfo> {
+ Logger.error("parsing: $input")
+ val parser = Parser()
+ val json = parser.parse(StringBuilder(input)) as JsonArray<*>
+ return json.map {
+ val data: JsonObject = (it as JsonObject).obj("data")!!
+ when (it.string("kind")) {
+ "compose" -> ComposePageInfo(data)
+ "tweets" -> TweetsPageInfo(data)
+ "messages" -> MessagesPageInfo(data)
+ "events" -> EventsPageInfo(data)
+ "search" -> SearchPageInfo(data)
+ "list" -> ListPageInfo(data)
+ else -> throw RuntimeException("invalid kind")
+ }
+ }
+ }
+
+ fun stringifyList(input: List<PageInfo>): String {
+ return json {
+ array(input.map {
+ val kind = when (it) {
+ is ComposePageInfo -> "compose"
+ is TweetsPageInfo -> "tweets"
+ is MessagesPageInfo -> "messages"
+ is EventsPageInfo -> "events"
+ is SearchPageInfo -> "search"
+ is ListPageInfo -> "list"
+ }
+ obj("kind" to kind, "data" to it.toJson())
+ })
+ }.toJsonString()
+ }
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/entity/User.kt b/app/src/main/java/net/lacolaco/smileessence/entity/User.kt
index acc10653..97ae4865 100644
--- a/app/src/main/java/net/lacolaco/smileessence/entity/User.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/entity/User.kt
@@ -73,9 +73,6 @@ class User private constructor(override val id: Long, screenName: String, rawPro
val aclogTimelineURL: String
get() = String.format("https://aclog.rhe.jp/%s/timeline", screenName)
- val formattedName: String
- get() = screenName + " / " + name
-
// XXX
val decoratedDescription: String
get() {
diff --git a/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.kt b/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.kt
deleted file mode 100644
index 7d73423d..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/preference/UserPreferenceHelper.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package net.lacolaco.smileessence.preference
-
-import android.content.SharedPreferences
-import android.preference.PreferenceManager
-import net.lacolaco.smileessence.Application
-
-class UserPreferenceHelper private constructor() {
- private val preferences: SharedPreferences
- get() = PreferenceManager.getDefaultSharedPreferences(Application.instance)
-
- operator fun get(key: Int, defaultValue: String): String {
- return preferences.getString(getString(key), defaultValue)
- }
-
- operator fun get(key: Int, defaultValue: Int): Int {
- return try {
- preferences.getInt(getString(key), defaultValue)
- } catch (ex: ClassCastException) {
- val ret = Integer.parseInt(get(key, defaultValue.toString()))
- set(key, ret)
- ret
- }
-
- }
-
- operator fun get(key: Int, defaultValue: Boolean): Boolean {
- return preferences.getBoolean(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: Boolean): Boolean {
- return preferences.edit()
- .putBoolean(getString(key), value)
- .commit()
- }
-
- private fun getString(resID: Int): String? {
- return Application.instance.getString(resID)
-
- }
-
- companion object {
- val instance = UserPreferenceHelper()
- }
-}
diff --git a/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt b/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt
index fcc209dd..2c042081 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/UserStreamListener.kt
@@ -30,11 +30,11 @@ class UserStreamListener(private val world: World) : twitter4j.UserStreamListene
// --------------------- Interface StatusListener ---------------------
override fun onStatus(status: Status) {
- val user = world.account.user
+ val user = world.user
val tweet = Tweet.fromTwitter(status, user.id)
world.addTweet(tweet)
if (tweet.isRetweet) {
- if (tweet.originalTweet.user.id == user.id) {
+ if (tweet.originalTweet.user == user) {
addToHistory(Event(Event.EnumEvent.RETWEETED, tweet.user, tweet))
}
} else if (tweet.mentions.contains(user.screenName)) {
@@ -72,23 +72,23 @@ class UserStreamListener(private val world: World) : twitter4j.UserStreamListene
override fun onFriendList(friendIds: LongArray) {}
override fun onFavorite(source: twitter4j.User, target: twitter4j.User, favoritedStatus: Status) {
- val tweet = Tweet.fromTwitter(favoritedStatus, world.account.id)
+ val tweet = Tweet.fromTwitter(favoritedStatus, world.id)
tweet.addFavoriter(source.id)
- if (User.fromTwitter(target) === world.account.user) {
+ if (User.fromTwitter(target) === world.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.id)
+ val tweet = Tweet.fromTwitter(unfavoritedStatus, world.id)
tweet.removeFavoriter(source.id)
- if (User.fromTwitter(target) === world.account.user) {
+ if (User.fromTwitter(target) === world.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) {
+ if (User.fromTwitter(followedUser) === world.user) {
addToHistory(Event(Event.EnumEvent.FOLLOWED, User.fromTwitter(source)))
}
}
@@ -98,7 +98,7 @@ class UserStreamListener(private val world: World) : twitter4j.UserStreamListene
override fun onDirectMessage(directMessage: twitter4j.DirectMessage) {
val message = DirectMessage.fromTwitter(directMessage)
world.addDirectMessage(message)
- if (message.recipient === world.account.user) {
+ if (message.recipient === world.user) {
addToHistory(Event(Event.EnumEvent.RECEIVE_MESSAGE, message.sender))
}
}
@@ -134,13 +134,13 @@ class UserStreamListener(private val world: World) : twitter4j.UserStreamListene
override fun onUserDeletion(deletedUser: Long) {}
override fun onBlock(source: twitter4j.User, blockedUser: twitter4j.User) {
- if (User.fromTwitter(blockedUser) === world.account.user) {
+ if (User.fromTwitter(blockedUser) === world.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) {
+ if (User.fromTwitter(unblockedUser) === world.user) {
addToHistory(Event(Event.EnumEvent.UNBLOCKED, User.fromTwitter(source)))
}
}
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
index 2bc82511..90a66b07 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Accounts.kt
@@ -8,7 +8,7 @@ import java.util.*
// XXX
fun World.getUserListsAsync() = bg {
TwitterTaskException.wrap {
- account.twitter.list().getUserLists(account.id)
+ twitter.list().getUserLists(id)
}.map { it.fullName }
}
@@ -16,7 +16,7 @@ fun World.getBlocksIdsAsync() = bg {
val idList = ArrayList<Long>()
var cursor: Long = -1
while (cursor != 0L) {
- val blocksIds = TwitterTaskException.wrap { account.twitter.getBlocksIDs(cursor) }
+ val blocksIds = TwitterTaskException.wrap { twitter.getBlocksIDs(cursor) }
cursor = blocksIds.nextCursor
idList.addAll(blocksIds.iDs.asList())
}
@@ -27,7 +27,7 @@ fun World.getMutesIdsAsync() = bg {
val idList = ArrayList<Long>()
var cursor: Long = -1
while (cursor != 0L) {
- val mutesIds = TwitterTaskException.wrap { account.twitter.getMutesIDs(cursor) }
+ val mutesIds = TwitterTaskException.wrap { twitter.getMutesIDs(cursor) }
cursor = mutesIds.nextCursor
idList.addAll(mutesIds.iDs.asList())
}
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
index ea793cc3..bdf782a0 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Messages.kt
@@ -7,24 +7,24 @@ import net.lacolaco.smileessence.util.bg
fun World.createMessageAsync(recipient: Long, text: String) = bg {
DirectMessage.fromTwitter(TwitterTaskException.wrap {
- account.twitter.directMessages().sendDirectMessage(recipient, text)
+ twitter.directMessages().sendDirectMessage(recipient, text)
})
}
fun World.destroyMessageAsync(id: Long) = bg {
DirectMessage.fromTwitter(TwitterTaskException.wrap {
- account.twitter.directMessages().destroyDirectMessage(id)
+ twitter.directMessages().destroyDirectMessage(id)
})
}
fun World.getReceivedMessagesAsync(sinceId: Long? = null, maxId: Long? = null) = bg {
DirectMessage.fromTwitter(TwitterTaskException.wrap {
- account.twitter.directMessages().getDirectMessages(makePaging(sinceId, maxId))
+ twitter.directMessages().getDirectMessages(makePaging(sinceId, maxId))
})
}
fun World.getSentMessagesAsync(sinceId: Long? = null, maxId: Long? = null) = bg {
DirectMessage.fromTwitter(TwitterTaskException.wrap {
- account.twitter.directMessages().getSentDirectMessages(makePaging(sinceId, maxId))
+ twitter.directMessages().getSentDirectMessages(makePaging(sinceId, maxId))
})
}
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
index e46166de..a44d40f6 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Searches.kt
@@ -8,18 +8,18 @@ import net.lacolaco.smileessence.util.bg
import twitter4j.Query
fun World.createSavedSearchAsync(query: String) = bg {
- SavedSearch.fromTwitter(TwitterTaskException.wrap { account.twitter.savedSearches().createSavedSearch(query) })
+ SavedSearch.fromTwitter(TwitterTaskException.wrap { twitter.savedSearches().createSavedSearch(query) })
}
fun World.destroySavedSearchAsync(id: Long) = bg {
- TwitterTaskException.wrap { account.twitter.savedSearches().destroySavedSearch(id) }
+ TwitterTaskException.wrap { twitter.savedSearches().destroySavedSearch(id) }
}
fun World.getSavedSearchesAsync() = bg {
- TwitterTaskException.wrap { account.twitter.savedSearches().savedSearches }.map { SavedSearch.fromTwitter(it) }
+ TwitterTaskException.wrap { twitter.savedSearches().savedSearches }.map { SavedSearch.fromTwitter(it) }
}
// XXX
fun World.doSearch(query: Query) = bg {
- Tweet.fromTwitter(TwitterTaskException.wrap { account.twitter.search(query).tweets }, account.id)
+ Tweet.fromTwitter(TwitterTaskException.wrap { twitter.search(query).tweets }, id)
}
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
index a3fae8ed..80ea1640 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Timelines.kt
@@ -18,26 +18,26 @@ fun makePaging(sinceId: Long? = null, maxId: Long? = null): twitter4j.Paging {
fun World.getHomeTimelineAsync(sinceId: Long? = null, maxId: Long? = null) = bg {
Tweet.fromTwitter(TwitterTaskException.wrap {
- account.twitter.timelines().getHomeTimeline(makePaging(sinceId, maxId))
- }, account.id)
+ twitter.timelines().getHomeTimeline(makePaging(sinceId, maxId))
+ }, id)
}
fun World.getMentionsTimelineAsync(sinceId: Long? = null, maxId: Long? = null) = bg {
Tweet.fromTwitter(TwitterTaskException.wrap {
- account.twitter.timelines().getMentionsTimeline(makePaging(sinceId, maxId))
- }, account.id)
+ twitter.timelines().getMentionsTimeline(makePaging(sinceId, maxId))
+ }, id)
}
fun World.getUserTimelineAsync(id: Long, sinceId: Long? = null, maxId: Long? = null) = bg {
Tweet.fromTwitter(TwitterTaskException.wrap {
- account.twitter.timelines().getUserTimeline(id, makePaging(sinceId, maxId))
- }, account.id)
+ twitter.timelines().getUserTimeline(id, makePaging(sinceId, maxId))
+ }, id)
}
// XXX: Use numeric ID
fun World.getListTimelineAsync(listName: String, sinceId: Long? = null, maxId: Long? = null) = bg {
val strings = listName.split("/".toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()
Tweet.fromTwitter(TwitterTaskException.wrap {
- account.twitter.list().getUserListStatuses(strings[0], strings[1], makePaging(sinceId, maxId))
- }, account.id)
+ twitter.list().getUserListStatuses(strings[0], strings[1], makePaging(sinceId, maxId))
+ }, id)
}
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
index 2fab3eca..b130edf4 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/TweetReactions.kt
@@ -6,13 +6,13 @@ import net.lacolaco.smileessence.twitter.TwitterTaskException
import net.lacolaco.smileessence.util.bg
fun World.retweetAsync(id: Long) = bg {
- Tweet.fromTwitter(TwitterTaskException.wrap { account.twitter.tweets().retweetStatus(id) }, account.id)
+ Tweet.fromTwitter(TwitterTaskException.wrap { twitter.tweets().retweetStatus(id) }, id)
}
fun World.favoriteAsync(id: Long) = bg {
- Tweet.fromTwitter(TwitterTaskException.wrap { account.twitter.favorites().createFavorite(id) }, account.id)
+ Tweet.fromTwitter(TwitterTaskException.wrap { twitter.favorites().createFavorite(id) }, id)
}
fun World.unfavoriteAsync(id: Long) = bg {
- Tweet.fromTwitter(TwitterTaskException.wrap { account.twitter.favorites().destroyFavorite(id) }, account.id)
+ Tweet.fromTwitter(TwitterTaskException.wrap { twitter.favorites().destroyFavorite(id) }, id)
}
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
index da9de889..c6fe960b 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Tweets.kt
@@ -22,14 +22,14 @@ fun World.getTweetAsync(id: Long, fetchAlways: Boolean = true) = async(CommonPoo
} else {
null
} ?: TwitterTaskException.wrap {
- Tweet.fromTwitter(account.twitter.tweets().showStatus(id), account.id)
+ Tweet.fromTwitter(twitter.tweets().showStatus(id), id)
}
}
fun World.deleteTweetAsync(id: Long) = async(CommonPool) {
Tweet.fromTwitter(TwitterTaskException.wrap {
- account.twitter.tweets().destroyStatus(id)
- }, account.id)
+ twitter.tweets().destroyStatus(id)
+ }, id)
}
// XXX
@@ -78,8 +78,8 @@ fun World.createTweetAsync(update: StatusUpdate, mediaPath: String, resizeFlag:
}
}
Tweet.fromTwitter(TwitterTaskException.wrap {
- account.twitter.tweets().updateStatus(update)
- }, account.id)
+ twitter.tweets().updateStatus(update)
+ }, id)
} finally {
if (tempFilePath != null) {
File(tempFilePath).delete()
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
index 98f08db2..6ba6bf12 100644
--- a/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/twitter/task/Users.kt
@@ -6,33 +6,33 @@ import net.lacolaco.smileessence.twitter.TwitterTaskException
import net.lacolaco.smileessence.util.bg
fun World.getUserAsync(id: Long) = bg {
- User.fromTwitter(TwitterTaskException.wrap { account.twitter.users().showUser(id) })
+ User.fromTwitter(TwitterTaskException.wrap { twitter.users().showUser(id) })
}
fun World.getUserAsync(screenName: String) = bg {
- User.fromTwitter(TwitterTaskException.wrap { account.twitter.users().showUser(screenName) })
+ User.fromTwitter(TwitterTaskException.wrap { twitter.users().showUser(screenName) })
}
fun World.followAsync(id: Long) = bg {
- User.fromTwitter(TwitterTaskException.wrap { account.twitter.friendsFollowers().createFriendship(id) })
+ User.fromTwitter(TwitterTaskException.wrap { twitter.friendsFollowers().createFriendship(id) })
}
fun World.unfollowAsync(id: Long) = bg {
- User.fromTwitter(TwitterTaskException.wrap { account.twitter.friendsFollowers().destroyFriendship(id) })
+ User.fromTwitter(TwitterTaskException.wrap { twitter.friendsFollowers().destroyFriendship(id) })
}
fun World.blockAsync(id: Long) = bg {
- User.fromTwitter(TwitterTaskException.wrap { account.twitter.users().createBlock(id) })
+ User.fromTwitter(TwitterTaskException.wrap { twitter.users().createBlock(id) })
}
fun World.unblockAsync(id: Long) = bg {
- User.fromTwitter(TwitterTaskException.wrap { account.twitter.users().destroyBlock(id) })
+ User.fromTwitter(TwitterTaskException.wrap { twitter.users().destroyBlock(id) })
}
fun World.reportSpamAsync(id: Long) = bg {
- User.fromTwitter(TwitterTaskException.wrap { account.twitter.spamReporting().reportSpam(id) })
+ User.fromTwitter(TwitterTaskException.wrap { twitter.spamReporting().reportSpam(id) })
}
fun World.getRelationshipAsync(id: Long) = bg {
- account.twitter.friendsFollowers().showFriendship(account.twitter.id, id)
+ twitter.friendsFollowers().showFriendship(this@getRelationshipAsync.id, id)
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.kt b/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.kt
deleted file mode 100644
index 9b2fa385..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/BitmapOptimizer.kt
+++ /dev/null
@@ -1,96 +0,0 @@
-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)
- when (orientation) {
- ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
- ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
- 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/BitmapURLTask.kt b/app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.kt
deleted file mode 100644
index 65ca7b53..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/util/BitmapURLTask.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-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(private val url: String, private val imageView: ImageView) : AsyncTask<Void, Void, Bitmap>() {
- override fun onPostExecute(bitmap: Bitmap?) {
- if (bitmap != null)
- 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/UIHelpers.kt b/app/src/main/java/net/lacolaco/smileessence/util/UIHelpers.kt
index 99fd60eb..8d405eaf 100644
--- a/app/src/main/java/net/lacolaco/smileessence/util/UIHelpers.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/util/UIHelpers.kt
@@ -4,6 +4,7 @@ import android.util.Log
import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.android.UI
import net.lacolaco.smileessence.World
+import java.lang.ref.WeakReference
private val exceptionHandler = CoroutineExceptionHandler { c, throwable ->
val tag = "CoroutineContext:$c"
@@ -26,3 +27,11 @@ fun launchBg(block: suspend CoroutineScope.() -> Unit) =
fun World.getMainActivityOrCancel() =
getMainActivity() ?: throw CancellationException("MainActivity is gone")
+
+class CancellableReference<out T> internal constructor(obj: T) {
+ private val ref = WeakReference(obj)
+
+ fun get() = ref.get() ?: throw CancellationException("Object is gone")
+}
+
+fun <T> ref(obj: T) = CancellableReference(obj)
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/MainFragmentPagerAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/MainFragmentPagerAdapter.kt
index add4c958..a5ff3ef6 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/MainFragmentPagerAdapter.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/MainFragmentPagerAdapter.kt
@@ -4,38 +4,29 @@ import android.app.Fragment
import android.app.FragmentManager
import android.os.Bundle
import android.support.v13.app.FragmentPagerAdapter
-import android.support.v4.util.ArrayMap
import android.support.v4.view.ViewPager
import android.view.ViewGroup
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.data.PageInfo
import net.lacolaco.smileessence.view.page.PageFragment
+import java.util.*
-class MainFragmentPagerAdapter(fm: FragmentManager, private val viewPager: ViewPager) :
+class MainFragmentPagerAdapter(private val world: World, private val viewPager: ViewPager, fm: FragmentManager) :
FragmentPagerAdapter(fm) {
- private val pageTags = ArrayList<String>()
- private val pages = ArrayMap<String, PageInfo>()
+ private val pages = Collections.unmodifiableList(world.pages.map { Page(it) })
- fun addPage(tag: String, clazz: Class<out PageFragment>, args: Bundle? = null) {
- assert(pages[tag] == null)
- pages[tag] = PageInfo(clazz, args)
- pageTags.add(tag)
- }
-
- fun getPageFragment(tag: String): PageFragment {
- // XXX: This is really an ugly workaround.
- return pages[tag]!!.fragment ?: instantiateItem(viewPager, getPageIndex(tag)) as PageFragment
- }
-
- fun getPageIndex(tag: String): Int {
- return pageTags.indexOf(tag)
- }
+ @Suppress("UNCHECKED_CAST")
+ fun getPageFragmentAt(position: Int): PageFragment<*> =
+ pages[position].fragment ?: instantiateItem(viewPager, position) as PageFragment<*>
override fun getItem(position: Int): Fragment {
- val info = pages[pageTags[position]]!!
+ val args = Bundle()
+ args.putLong(PageFragment.KEY_WORLD_USER_ID, world.id)
+ args.putInt(PageFragment.KEY_PAGE_POSITION, position)
+
+ val info = pages[position]
assert(info.fragment == null)
- val fragment = info.clazz.newInstance()
- if (info.args != null)
- fragment.arguments = info.args
- return fragment
+ return info.pageInfo.fragmentClass.newInstance().apply { arguments = args }
}
override fun getCount(): Int {
@@ -43,9 +34,9 @@ class MainFragmentPagerAdapter(fm: FragmentManager, private val viewPager: ViewP
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
- val info = pages[pageTags[position]]!!
+ val info = pages[position]
val fragment = super.instantiateItem(container, position)
- info.fragment = fragment as PageFragment
+ info.fragment = fragment as PageFragment<*>
return fragment
}
@@ -53,9 +44,5 @@ class MainFragmentPagerAdapter(fm: FragmentManager, private val viewPager: ViewP
throw IllegalStateException("Fragments must not be destroyed by ViewPager")
}
- private class PageInfo(
- val clazz: Class<out PageFragment>,
- val args: Bundle?,
- var fragment: PageFragment? = null
- )
+ private class Page(var pageInfo: PageInfo, var fragment: PageFragment<*>? = null)
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/OnOffImageView.kt b/app/src/main/java/net/lacolaco/smileessence/view/OnOffImageView.kt
new file mode 100644
index 00000000..f5d01715
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/OnOffImageView.kt
@@ -0,0 +1,24 @@
+package net.lacolaco.smileessence.view
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.support.v7.widget.AppCompatImageView
+import android.util.AttributeSet
+import net.lacolaco.smileessence.R
+
+class OnOffImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
+ AppCompatImageView(context, attrs, defStyleAttr) {
+ private val onSrc: Drawable
+ private val offSrc: Drawable
+
+ init {
+ val ta = context.obtainStyledAttributes(attrs, R.styleable.OnOffImageView)
+ offSrc = ta.getDrawable(R.styleable.OnOffImageView_src_off)
+ onSrc = ta.getDrawable(R.styleable.OnOffImageView_src_on)
+ ta.recycle()
+ }
+
+ fun setState(isOn: Boolean) {
+ setImageDrawable(if (isOn) onSrc else offSrc)
+ }
+}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/Partials.kt b/app/src/main/java/net/lacolaco/smileessence/view/Partials.kt
index 2e91dc4e..8df541d2 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/Partials.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/Partials.kt
@@ -14,41 +14,39 @@ import net.lacolaco.smileessence.entity.Tweet
import net.lacolaco.smileessence.entity.User
import net.lacolaco.smileessence.twitter.task.getTweetAsync
import net.lacolaco.smileessence.util.StringUtils
-import net.lacolaco.smileessence.util.bg
+import net.lacolaco.smileessence.util.launchBg
import net.lacolaco.smileessence.view.adapter.UnorderedCustomListAdapter
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
object Partials {
fun getTweetView(tweet: Tweet, world: World, activity: Activity, convertView: View?, expandEmbeddedTweets: Boolean = true): View {
val view: View = convertView ?: activity.layoutInflater.inflate(R.layout.list_item_status, null)
- view.setOnClickListener(ListItemClickListener(activity) {
+ view.setOnClickListener {
DialogHelper.showDialog(activity, StatusDetailDialogFragment.newInstance(tweet))
- })
+ }
- (view as ColoredRelativeLayout).setAccentVisibility(tweet.user === world.account.user)
+ (view as ColoredRelativeLayout).setAccentVisibility(tweet.user === world.user)
updateViewUser(tweet.originalTweet.user, activity, view)
updateViewBody(tweet, world, activity, view)
- updateViewFavorited(tweet, world, view)
+ updateTweetReactionsViews(tweet, world, view)
updateViewEmbeddeds(tweet, world, activity, view, expandEmbeddedTweets)
return view
}
-
private fun updateViewEmbeddeds(tweet: Tweet, world: World, activity: Activity, view: View, expandEmbeddedTweets: Boolean) {
- if (expandEmbeddedTweets) {
+ if (expandEmbeddedTweets && tweet.embeddedStatusIDs.isNotEmpty()) {
val embeddedTweetsAdapter = object : UnorderedCustomListAdapter<Tweet>() {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
return Partials.getTweetView(getItem(position), world, activity, convertView, false)
}
}
- bg {
+ launchBg {
val tasks = tweet.embeddedStatusIDs.map { id -> world.getTweetAsync(id, false) }
for (task in tasks) {
val t = try {
@@ -69,64 +67,77 @@ object Partials {
}
private fun updateViewUser(user: User, activity: Activity, view: View) {
- val iconUrl = user.profileImageUrl
- view.imageview_status_icon.setImageUrl(iconUrl, ImageCache.getImageLoader())
- view.imageview_status_icon.setOnClickListener { v ->
+ view.imageview_status_icon.setImageUrl(user.profileImageUrl, ImageCache.getImageLoader())
+ view.imageview_status_icon.setOnClickListener {
DialogHelper.showDialog(activity, UserDetailDialogFragment.newInstance(user))
}
-
- view.textview_status_header.text = user.formattedName
+ view.textview_status_header.text = "${user.screenName} / ${user.name}"
}
private fun updateViewBody(tweet: Tweet, world: World, activity: Activity, view: View) {
view.textview_status_text.text = tweet.text
- view.textview_status_footer.text = getFooterText(tweet)
+ var footerText = "${StringUtils.dateToString(tweet.originalTweet.createdAt)}"
+ footerText += " via ${Html.fromHtml(tweet.originalTweet.source)}"
+ if (tweet.isRetweet)
+ footerText += " (RT by ${tweet.user.screenName})"
+ view.textview_status_footer.text = footerText
val typedView = view as ColoredRelativeLayout
when {
tweet.isRetweet -> typedView.setHighlight(2)
- tweet.mentions.contains(world.account.user.screenName) -> typedView.setHighlight(1)
+ tweet.mentions.contains(world.user.screenName) -> typedView.setHighlight(1)
else -> typedView.setHighlight(0)
}
}
- private fun updateViewFavorited(tweet: Tweet, world: World, view: View) {
- view.imageview_status_favorited.visibility = if (tweet.isFavoritedBy(world.account.id)) View.VISIBLE else View.GONE
- }
-
- private fun getFooterText(tweet: Tweet): String {
- val builder = StringBuilder()
- if (tweet.isRetweet) {
- builder
- .append("(RT: ")
- .append(tweet.user.screenName)
- .append(") ")
+ private fun updateTweetReactionsViews(tweet: Tweet, world: World, view: View) {
+ if (tweet.retweetCount > 0) {
+ view.tweet_retweet_count.visibility = View.VISIBLE
+ view.tweet_retweet_count.text = tweet.retweetCount.toString()
+ view.imageview_status_retweeted.visibility = View.VISIBLE
+ view.imageview_status_retweeted.setState(tweet.isRetweetedBy(world.id))
+ } else {
+ view.tweet_retweet_count.visibility = View.INVISIBLE
+ view.imageview_status_retweeted.visibility = View.INVISIBLE
+ }
+ if (tweet.favoriteCount > 0) {
+ view.tweet_favorite_count.visibility = View.VISIBLE
+ view.tweet_favorite_count.text = tweet.favoriteCount.toString()
+ view.imageview_status_favorited.visibility = View.VISIBLE
+ view.imageview_status_favorited.setState(tweet.isFavoritedBy(world.id))
+ } else {
+ view.tweet_favorite_count.visibility = View.INVISIBLE
+ view.imageview_status_favorited.visibility = View.INVISIBLE
}
- builder.append(StringUtils.dateToString(tweet.originalTweet.createdAt))
- builder.append(" via ")
- builder.append(Html.fromHtml(tweet.originalTweet.source))
- return builder.toString()
}
fun getDirectMessageView(directMessage: DirectMessage, world: World, activity: Activity, convertView: View?): View {
val view = convertView ?: activity.layoutInflater.inflate(R.layout.list_item_status, null)
- view.setOnClickListener(ListItemClickListener(activity) { DialogHelper.showDialog(activity, MessageDetailDialogFragment.newInstance(directMessage)) })
+ view.setOnClickListener {
+ DialogHelper.showDialog(activity, MessageDetailDialogFragment.newInstance(directMessage))
+ }
view.imageview_status_favorited.visibility = View.GONE
//view.textview_status_header.setTextColor(getStyledColor(activity, world, R.attr.color_message_text_header))
view.setBackgroundColor(getStyledColor(activity, world, R.attr.color_message_bg_normal))
- (view as ColoredRelativeLayout).setAccentVisibility(directMessage.sender === world.account.user)
+ (view as ColoredRelativeLayout).setAccentVisibility(directMessage.sender === world.user)
updateViewUser(directMessage.sender, activity, view)
- updateViewBody(directMessage, world, view)
+
+ view.textview_status_text.text = directMessage.text
+ var footerText = StringUtils.dateToString(directMessage.createdAt)
+ if (directMessage.sender == world.user) {
+ footerText += " to @${directMessage.recipient.screenName}"
+ }
+ view.textview_status_footer.text = footerText
return view
}
private fun getStyledColor(context: Context, world: World, resId: Int): Int {
- val themeresid = if (world.account.useDarkTheme) R.style.theme_dark else R.style.theme_light
+ val themeresid = if (world.useDarkTheme) R.style.theme_dark else R.style.theme_light
val array = context.obtainStyledAttributes(themeresid, arrayOf(resId).toIntArray())
val color = array.getColor(0, 0)
array.recycle()
@@ -137,18 +148,6 @@ object Partials {
}
}
- private fun getFooterText(directMessage: DirectMessage, world: World): String {
- val builder = StringBuilder()
- builder.append(StringUtils.dateToString(directMessage.createdAt))
- if (directMessage.sender == world.account.user) {
- builder.append(" to @").append(directMessage.recipient.screenName)
- }
- return builder.toString()
- }
-
-
private fun updateViewBody(directMessage: DirectMessage, world: World, view: View) {
- view.textview_status_text.text = directMessage.text
- view.textview_status_footer.text = getFooterText(directMessage, world)
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt
index 5f3b74c0..f7c06fcb 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/SettingFragment.kt
@@ -1,29 +1,16 @@
package net.lacolaco.smileessence.view
import android.content.Intent
-import android.content.SharedPreferences
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.os.Bundle
-import android.preference.ListPreference
import android.preference.Preference
import android.preference.PreferenceFragment
import android.support.v7.app.AlertDialog
import kotlinx.android.synthetic.main.dialog_app_info.view.*
-import net.lacolaco.smileessence.Application
import net.lacolaco.smileessence.BuildConfig
import net.lacolaco.smileessence.R
import net.lacolaco.smileessence.activity.LicenseActivity
-class SettingFragment : PreferenceFragment(), OnSharedPreferenceChangeListener, Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
- override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
- if (preference.key.contentEquals(getString(R.string.key_setting_theme))) {
- Application.toast(R.string.notice_theme_changed)
- }
- return true
- }
-
- // --------------------- Interface OnPreferenceClickListener ---------------------
-
+class SettingFragment : PreferenceFragment(), Preference.OnPreferenceClickListener {
override fun onPreferenceClick(preference: Preference): Boolean {
val key = preference.key
if (key.contentEquals(getString(R.string.key_setting_application_information))) {
@@ -33,20 +20,9 @@ class SettingFragment : PreferenceFragment(), OnSharedPreferenceChangeListener,
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 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 + ")"
@@ -54,20 +30,6 @@ class SettingFragment : PreferenceFragment(), OnSharedPreferenceChangeListener,
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 --------------------------
-
private fun findPreference(preferenceResID: Int): Preference {
return findPreference(getString(preferenceResID))
}
@@ -81,9 +43,4 @@ class SettingFragment : PreferenceFragment(), OnSharedPreferenceChangeListener,
.setView(contentView)
.show()
}
-
- private fun setSummaryCurrentValue() {
- 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/adapter/EventListAdapter.kt b/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.kt
deleted file mode 100644
index 4312c696..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/EventListAdapter.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.lacolaco.smileessence.view.adapter
-
-import android.app.Activity
-import android.view.View
-import android.view.ViewGroup
-import kotlinx.android.synthetic.main.list_item_status.view.*
-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.util.StringUtils
-import net.lacolaco.smileessence.view.DialogHelper
-import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment
-
-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 {
- val view = convertView ?: activity.layoutInflater.inflate(R.layout.list_item_status, parent, false)
- val event = getItem(position)
-
- view.imageview_status_icon.setImageUrl(event.source.profileImageUrl, ImageCache.getImageLoader())
- view.textview_status_header.text = event.formattedString
- view.textview_status_text.text = event.targetObject?.text ?: ""
- view.textview_status_footer.text = StringUtils.dateToString(event.createdAt)
- view.imageview_status_favorited.visibility = View.GONE
- view.setOnClickListener {
- DialogHelper.showDialog(activity, UserDetailDialogFragment.newInstance(event.source))
- }
-
- return view
- }
-}
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
index 6d80486f..c2c6a1cc 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/adapter/MessageListAdapter.kt
@@ -7,12 +7,13 @@ import net.lacolaco.smileessence.World
import net.lacolaco.smileessence.entity.DirectMessage
import net.lacolaco.smileessence.view.Partials
-class MessageListAdapter(private val activity: Activity, private val world: World) : OrderedCustomListAdapter<DirectMessage>() {
+class MessageListAdapter(private val activity: Activity, private val world: World) :
+ OrderedCustomListAdapter<DirectMessage>() {
val lastID: Long
- get() = if (count > 0) getItem(count - 1).id else -1
+ get() = getItem(count - 1).id
val topID: Long
- get() = if (count > 0) getItem(0).id else -1
+ get() = getItem(0).id
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
return Partials.getDirectMessageView(getItem(position), world, activity, convertView)
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
index 58e26cc0..93639ac2 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/MessageDetailDialogFragment.kt
@@ -114,8 +114,6 @@ class MessageDetailDialogFragment : StackableDialogFragment() {
view.detail_dialog_divider_top.visibility = View.GONE
view.button_status_detail_retweet.visibility = View.GONE
view.button_status_detail_favorite.visibility = View.GONE
- view.image_status_detail_fav_count.visibility = View.GONE
- view.image_status_detail_rt_count.visibility = View.GONE
val adapter = MessageListAdapter(activity, world)
view.listview_status_detail_reply_to.adapter = adapter
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
index 78c67ce6..a4be3a37 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/StatusDetailDialogFragment.kt
@@ -6,6 +6,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.dialog_status_detail.view.*
+import kotlinx.android.synthetic.main.menu_item_simple_text.view.*
import net.lacolaco.smileessence.R
import net.lacolaco.smileessence.activity.MainActivity
import net.lacolaco.smileessence.command.Command
@@ -29,9 +30,10 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val found = Tweet.fetch(arguments.getLong(KEY_STATUS_ID))
+ val id = arguments.getLong(KEY_STATUS_ID)
+ val found = Tweet.fetch(id)
if (found == null) {
- world.notifyError(R.string.notice_error_show_status)
+ world.notifyError("Tweet id=$id not found")
dismiss()
return
}
@@ -45,7 +47,8 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
statusHeader.isClickable = false
view.setBackgroundColor((statusHeader.background as ColorDrawable).color)
- updateViewReactions(view)
+ view.button_status_detail_favorite.setState(tweet.isFavoritedBy(world.id))
+ view.button_status_detail_retweet.setState(tweet.isRetweetedBy(world.id))
updateViewButtons(view)
setupViewMenu(view)
@@ -72,28 +75,6 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
return view
}
- private fun updateViewReactions(view: View) {
- if (tweet.favoriteCount > 0) {
- view.textview_status_detail_fav_count.text = Integer.toString(tweet.favoriteCount)
- view.image_status_detail_fav_count.visibility = View.VISIBLE
- view.textview_status_detail_fav_count.visibility = View.VISIBLE
- } else {
- view.image_status_detail_fav_count.visibility = View.GONE
- view.textview_status_detail_fav_count.visibility = View.GONE
- }
- view.button_status_detail_favorite.setState(tweet.isFavoritedBy(world.account.id))
-
- if (tweet.retweetCount > 0) {
- view.textview_status_detail_rt_count.text = Integer.toString(tweet.retweetCount)
- view.image_status_detail_rt_count.visibility = View.VISIBLE
- view.textview_status_detail_rt_count.visibility = View.VISIBLE
- } else {
- view.image_status_detail_rt_count.visibility = View.GONE
- view.textview_status_detail_rt_count.visibility = View.GONE
- }
- view.button_status_detail_retweet.setState(tweet.isRetweetedBy(world.account.id))
- }
-
private fun updateViewButtons(view: View) {
view.button_status_detail_reply.setOnClickListener {
val originalTweet = tweet.originalTweet
@@ -102,7 +83,7 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
builder.append("@${originalTweet.user.screenName} ")
for (screenName in originalTweet.mentions) {
- if (screenName != world.account.user.screenName)
+ if (screenName != world.user.screenName)
builder.append("@$screenName ")
}
val text = builder.toString()
@@ -111,12 +92,11 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
(activity as MainActivity).openPostPageAndReplyTo(originalTweet, text)
}
view.button_status_detail_retweet.setOnClickListener {
- val account = world.account
- confirm({
- if (tweet.isRetweetedBy(account.id)) {
+ confirm(R.string.dialog_confirm_commands) {
+ if (tweet.isRetweetedBy(world.id)) {
launchUi {
try {
- world.deleteTweetAsync(tweet.getRetweetIdBy(account.id)).await()
+ world.deleteTweetAsync(tweet.getRetweetIdBy(world.id)).await()
world.notify(R.string.notice_status_delete_succeeded)
updateViewButtons(view)
} catch (e: TwitterTaskException) {
@@ -126,7 +106,7 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
} else {
launchUi {
try {
- world.retweetAsync(tweet.getRetweetIdBy(account.id)).await()
+ world.retweetAsync(tweet.getRetweetIdBy(world.id)).await()
world.notify(R.string.notice_retweet_succeeded)
updateViewButtons(view)
} catch (e: TwitterTaskException) {
@@ -134,11 +114,10 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
}
}
}
- })
+ }
}
view.button_status_detail_favorite.setOnClickListener {
- val account = world.account
- val favoriting = !tweet.isFavoritedBy(account.id)
+ val favoriting = !tweet.isFavoritedBy(world.id)
launchUi {
try {
@@ -157,9 +136,12 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
}
}
}
- view.button_status_detail_delete.visibility = if (tweet.originalTweet.user === world.account.user) View.VISIBLE else View.GONE
+ if (tweet.originalTweet.user === world.user)
+ view.button_status_detail_delete.visibility = View.VISIBLE
+ else
+ view.button_status_detail_delete.visibility = View.GONE
view.button_status_detail_delete.setOnClickListener {
- confirm({
+ confirm(R.string.dialog_confirm_commands) {
launchBg {
try {
world.deleteTweetAsync(tweet.originalTweet.id).await()
@@ -169,7 +151,7 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
}
}
dismiss()
- })
+ }
}
view.button_status_detail_menu.setOnClickListener {
val popup = PopupMenu(activity, view.button_status_detail_menu)
@@ -216,7 +198,7 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
val adapter = object : UnorderedCustomListAdapter<Command>(commands) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val itemView = convertView ?: activity.layoutInflater.inflate(R.layout.menu_item_simple_text, parent, false)
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.itemView.list_item_textview.text = getItem(position).text
+ itemView.list_item_textview.text = getItem(position).text
return itemView
}
}
@@ -231,10 +213,6 @@ class StatusDetailDialogFragment : StackableDialogFragment() {
}
}
- private fun confirm(onYes: () -> Unit) {
- confirm(R.string.dialog_confirm_commands, onOk = onYes)
- }
-
companion object {
private val KEY_STATUS_ID = "status_id"
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
index d4bea45f..0cf2ea34 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/dialog/UserDetailDialogFragment.kt
@@ -229,8 +229,7 @@ class UserDetailDialogFragment : StackableDialogFragment() {
}
private fun updateRelationship() {
- val account = world.account
- if (user === account.user) {
+ if (user === world.user) {
textview_user_detail_followed.setText(R.string.user_detail_followed_is_me)
button_user_detail_follow.visibility = View.GONE
} else {
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.kt b/app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.kt
deleted file mode 100644
index 8a680eea..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/listener/ListItemClickListener.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-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
-
-// XXX
-class ListItemClickListener(private val activity: Activity, private val callback: () -> Unit) : View.OnClickListener {
- 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.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.kt
index 4e3fbc30..848fde52 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/CustomListFragment.kt
@@ -5,16 +5,16 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AbsListView
-import android.widget.ListView
import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout
import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayoutDirection
import kotlinx.android.synthetic.main.fragment_list.*
import kotlinx.android.synthetic.main.fragment_list.view.*
import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.data.PageInfo
import net.lacolaco.smileessence.view.adapter.CustomListAdapter
-abstract class CustomListFragment<out T : CustomListAdapter<*>> : PageFragment(),
- AbsListView.OnScrollListener {
+abstract class CustomListFragment<out TI : PageInfo, out T : CustomListAdapter<*>> :
+ PageFragment<TI>(), AbsListView.OnScrollListener {
protected abstract val adapter: T
override fun onScrollStateChanged(absListView: AbsListView, scrollState: Int) {
@@ -31,7 +31,8 @@ abstract class CustomListFragment<out T : CustomListAdapter<*>> : PageFragment()
override fun onScroll(absListView: AbsListView, i: Int, i2: Int, i3: Int) {}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup,
+ savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.fragment_list, container, false)
}
@@ -58,11 +59,6 @@ abstract class CustomListFragment<out T : CustomListAdapter<*>> : PageFragment()
protected open fun onSwipeUp(view: SwipyRefreshLayout) {}
- @Deprecated("dontuse")
- protected open fun getListView(page: View): ListView {
- return page.fragment_list_listview
- }
-
protected fun updateListViewWithNotice(addedToTop: Boolean) {
if (isDetached)
return
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
index 20831213..e2e0a273 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/HistoryFragment.kt
@@ -1,15 +1,26 @@
package net.lacolaco.smileessence.view.page
+import android.app.Activity
import android.os.Bundle
import android.view.View
-import net.lacolaco.smileessence.view.adapter.EventListAdapter
+import android.view.ViewGroup
+import kotlinx.android.synthetic.main.list_item_status.view.*
+import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.data.ImageCache
+import net.lacolaco.smileessence.data.PageInfo
+import net.lacolaco.smileessence.entity.Event
+import net.lacolaco.smileessence.util.StringUtils
+import net.lacolaco.smileessence.view.DialogHelper
+import net.lacolaco.smileessence.view.adapter.CustomListAdapter
+import net.lacolaco.smileessence.view.dialog.UserDetailDialogFragment
-class HistoryFragment : CustomListFragment<EventListAdapter>() {
+class HistoryFragment : CustomListFragment<PageInfo.EventsPageInfo, HistoryFragment.EventListAdapter>() {
override val adapter by lazy { EventListAdapter(world, activity) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- world.addEventNotifier(this) { adapter.update() } // XXX
+ world.addEventNotifier(this) { adapter.update() }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -17,5 +28,24 @@ class HistoryFragment : CustomListFragment<EventListAdapter>() {
setSwipeRefreshEnabled(false)
}
- override fun refresh() {}
+ class EventListAdapter(private val world: World, private val activity: Activity) : CustomListAdapter<Event>() {
+ override val list: List<Event>
+ get() = world.events.reversed()
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ val view = convertView ?: activity.layoutInflater.inflate(R.layout.list_item_status, parent, false)
+ val event = getItem(position)
+
+ view.imageview_status_icon.setImageUrl(event.source.profileImageUrl, ImageCache.getImageLoader())
+ view.textview_status_header.text = event.formattedString
+ view.textview_status_text.text = event.targetObject?.text ?: ""
+ view.textview_status_footer.text = StringUtils.dateToString(event.createdAt)
+ view.imageview_status_favorited.visibility = View.GONE
+ view.setOnClickListener {
+ DialogHelper.showDialog(activity, UserDetailDialogFragment.newInstance(event.source))
+ }
+
+ return view
+ }
+ }
}
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
deleted file mode 100644
index 169f3440..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/HomeFragment.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-package net.lacolaco.smileessence.view.page
-
-import android.os.Bundle
-import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout
-import kotlinx.coroutines.experimental.Deferred
-import net.lacolaco.smileessence.R
-import net.lacolaco.smileessence.entity.Tweet
-import net.lacolaco.smileessence.twitter.TwitterTaskException
-import net.lacolaco.smileessence.twitter.task.getHomeTimelineAsync
-import net.lacolaco.smileessence.util.launchUi
-import net.lacolaco.smileessence.view.adapter.TimelineAdapter
-
-class HomeFragment : CustomListFragment<TimelineAdapter>() {
- override val adapter by lazy { TimelineAdapter(activity, world) }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- world.addTimeline(this) { tweet ->
- adapter.add(tweet)
- adapter.update()
- }
-
- refresh()
-
- // TODO: Check for streaming API connection, and disable SwipeRefreshLayout as necessary
- }
-
- override fun refresh() {
- runRefreshTask(world.getHomeTimelineAsync(), { adapter.updateForce() })
- }
-
- override fun onSwipeDown(view: SwipyRefreshLayout) {
- if (world.isStreaming) {
- updateListViewWithNotice(true)
- view.isRefreshing = false
- } else {
- runRefreshTask(world.getHomeTimelineAsync(sinceId = adapter.topID)) {
- updateListViewWithNotice(true)
- view.isRefreshing = false
- }
- }
- }
-
- override fun onSwipeUp(view: SwipyRefreshLayout) {
- runRefreshTask(world.getHomeTimelineAsync(maxId = adapter.lastID - 1)) {
- updateListViewWithNotice(false)
- view.isRefreshing = false
- }
- }
-
- private fun runRefreshTask(task: Deferred<List<Tweet>>, onFinish: () -> Unit) = launchUi {
- try {
- val tweets = task.await()
- world.addTweetAll(tweets)
- } catch (e: TwitterTaskException) {
- world.notifyError(R.string.notice_error_get_home)
- }
- onFinish()
- }
-}
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
deleted file mode 100644
index 02f567a7..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/MentionsFragment.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package net.lacolaco.smileessence.view.page
-
-import android.os.Bundle
-import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout
-import kotlinx.coroutines.experimental.Deferred
-import net.lacolaco.smileessence.R
-import net.lacolaco.smileessence.data.ExtractionWord
-import net.lacolaco.smileessence.entity.Tweet
-import net.lacolaco.smileessence.twitter.TwitterTaskException
-import net.lacolaco.smileessence.twitter.task.getMentionsTimelineAsync
-import net.lacolaco.smileessence.util.launchUi
-import net.lacolaco.smileessence.view.adapter.TimelineAdapter
-
-class MentionsFragment : CustomListFragment<TimelineAdapter>() {
- override val adapter by lazy { TimelineAdapter(activity, world) }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- world.addTimeline(this) { tweet ->
- if (tweet.mentions.contains(world.account.user.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(world.getMentionsTimelineAsync(), { adapter.updateForce() })
- }
-
- override fun onSwipeDown(view: SwipyRefreshLayout) {
- runRefreshTask(world.getMentionsTimelineAsync(sinceId = adapter.topID)) {
- updateListViewWithNotice(true)
- view.isRefreshing = false
- }
- }
-
- override fun onSwipeUp(view: SwipyRefreshLayout) {
- runRefreshTask(world.getMentionsTimelineAsync(maxId = adapter.lastID - 1)) {
- updateListViewWithNotice(false)
- view.isRefreshing = false
- }
- }
-
- private fun runRefreshTask(task: Deferred<List<Tweet>>, onFinish: () -> Unit) = launchUi {
- try {
- val tweets = task.await()
- world.addTweetAll(tweets)
- } catch (e: TwitterTaskException) {
- world.notifyError(R.string.notice_error_get_mentions)
- }
- onFinish()
- }
-}
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
index be4c5ce1..ac4ca5db 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/MessagesFragment.kt
@@ -4,6 +4,7 @@ import android.os.Bundle
import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout
import kotlinx.coroutines.experimental.Deferred
import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.data.PageInfo
import net.lacolaco.smileessence.entity.DirectMessage
import net.lacolaco.smileessence.twitter.TwitterTaskException
import net.lacolaco.smileessence.twitter.task.getReceivedMessagesAsync
@@ -11,9 +12,15 @@ import net.lacolaco.smileessence.twitter.task.getSentMessagesAsync
import net.lacolaco.smileessence.util.launchUi
import net.lacolaco.smileessence.view.adapter.MessageListAdapter
-class MessagesFragment : CustomListFragment<MessageListAdapter>() {
+// TODO: Needs rework
+class MessagesFragment : CustomListFragment<PageInfo.MessagesPageInfo, MessageListAdapter>() {
override val adapter by lazy { MessageListAdapter(activity, world) }
+ override fun refresh() {
+ runRefreshTask(world.getReceivedMessagesAsync()) { adapter.updateForce() }
+ runRefreshTask(world.getSentMessagesAsync()) { adapter.updateForce() }
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -25,34 +32,29 @@ class MessagesFragment : CustomListFragment<MessageListAdapter>() {
refresh()
}
- override fun refresh() {
- runRefreshTask(world.getReceivedMessagesAsync()) { adapter.updateForce() }
- runRefreshTask(world.getSentMessagesAsync()) { adapter.updateForce() }
- }
-
override fun onSwipeDown(view: SwipyRefreshLayout) {
- runRefreshTask(world.getReceivedMessagesAsync(sinceId = adapter.topID)) {
+ val sinceId = if (adapter.count > 0) adapter.topID else null
+ runRefreshTask(world.getReceivedMessagesAsync(sinceId = sinceId)) {
updateListViewWithNotice(true)
view.isRefreshing = false
}
}
override fun onSwipeUp(view: SwipyRefreshLayout) {
- runRefreshTask(world.getReceivedMessagesAsync(maxId = adapter.lastID - 1)) {
+ val maxId = if (adapter.count > 0) adapter.lastID - 1 else null
+ runRefreshTask(world.getReceivedMessagesAsync(maxId = maxId)) {
updateListViewWithNotice(false)
view.isRefreshing = false
}
}
- private fun runRefreshTask(task: Deferred<List<DirectMessage>>, onFinish: () -> Unit) {
- launchUi {
- try {
- val messages = task.await()
- world.addDirectMessage(messages)
- } catch (e: TwitterTaskException) {
- world.notifyError(R.string.notice_error_get_messages)
- }
- onFinish()
+ private fun runRefreshTask(task: Deferred<List<DirectMessage>>, onFinish: () -> Unit) = launchUi {
+ try {
+ val messages = task.await()
+ world.addDirectMessage(messages)
+ } catch (e: TwitterTaskException) {
+ world.notifyError(R.string.notice_error_get_messages)
}
+ onFinish()
}
}
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
index f23a9edf..9f1f3dca 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/PageFragment.kt
@@ -1,19 +1,23 @@
package net.lacolaco.smileessence.view.page
import android.app.Fragment
-import net.lacolaco.smileessence.Application
+import net.lacolaco.smileessence.World
+import net.lacolaco.smileessence.data.PageInfo
-/**
- * A PageFragment is always attached to a MainActivity.
- */
-abstract class PageFragment : Fragment() {
+abstract class PageFragment<out T : PageInfo> : Fragment() {
protected val world by lazy {
- Application.getWorld(arguments.getLong(KEY_WORLD_USER_ID))
+ World[arguments.getLong(KEY_WORLD_USER_ID)]
+ }
+ protected val pageInfo by lazy {
+ @Suppress("UNCHECKED_CAST")
+ world.pages[arguments.getInt(KEY_PAGE_POSITION)] as T
}
- abstract fun refresh()
+ // Invoked when user click the refresh button.
+ open fun refresh() {}
companion object {
val KEY_WORLD_USER_ID = "KEY_WORLD_USER_ID"
+ val KEY_PAGE_POSITION = "KEY_PAGE_POSITION"
}
}
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
index 93cb670f..30a9821a 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/PostFragment.kt
@@ -1,10 +1,13 @@
package net.lacolaco.smileessence.view.page
import android.annotation.SuppressLint
+import android.app.Activity
+import android.app.Activity.RESULT_OK
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
+import android.provider.MediaStore
import android.support.v4.content.ContextCompat
import android.text.Editable
import android.text.Spannable
@@ -18,6 +21,7 @@ import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.fragment_post.*
import net.lacolaco.smileessence.R
import net.lacolaco.smileessence.activity.MainActivity
+import net.lacolaco.smileessence.data.PageInfo
import net.lacolaco.smileessence.entity.Tweet
import net.lacolaco.smileessence.entity.User
import net.lacolaco.smileessence.logging.Logger
@@ -31,14 +35,22 @@ import net.lacolaco.smileessence.view.Partials
import twitter4j.StatusUpdate
import java.io.File
-class PostFragment : PageFragment(), TextWatcher {
+class PostFragment : PageFragment<PageInfo.ComposePageInfo>(), TextWatcher {
private lateinit var postState: PostState
- override fun refresh() {}
-
- fun setMediaFilePath(path: String) {
- postState.mediaFilePath = path
- onPostStateChange()
+ fun setMediaFile(uri: Uri) {
+ try {
+ activity.contentResolver.query(uri, null, null, null, null).use { c ->
+ c.moveToFirst()
+ val path = c.getString(c.getColumnIndex(MediaStore.MediaColumns.DATA))
+ postState.mediaFilePath = path
+ onPostStateChange()
+ world.notify(R.string.notice_select_image_succeeded)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ world.notifyError(R.string.notice_select_image_failed)
+ }
}
fun setInReplyTo(tweet: Tweet, prefix: String) {
@@ -186,7 +198,7 @@ class PostFragment : PageFragment(), TextWatcher {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
- startActivityForResult(intent, MainActivity.REQUEST_GET_PICTURE_FROM_GALLERY)
+ startActivityForResult(intent, REQUEST_GET_PICTURE_FROM_GALLERY)
}
image_post_media.setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW)
@@ -204,7 +216,19 @@ class PostFragment : PageFragment(), TextWatcher {
onPostStateChange()
}
- // FIXME: Remove @SuppressList
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ when (requestCode) {
+ REQUEST_GET_PICTURE_FROM_GALLERY -> {
+ if (resultCode != Activity.RESULT_OK) {
+ world.notifyError(R.string.notice_select_image_failed)
+ return
+ }
+ setMediaFile(data!!.data)
+ }
+ else -> super.onActivityResult(requestCode, resultCode, data)
+ }
+ }
+
@SuppressLint("ParcelCreator")
@Parcelize
private class PostState(
@@ -230,6 +254,7 @@ class PostFragment : PageFragment(), TextWatcher {
}
companion object {
+ private val REQUEST_GET_PICTURE_FROM_GALLERY = 11
val KEY_POST_STATE = "POST_STATE"
}
}
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
index c57d92fb..4def85c7 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/SearchFragment.kt
@@ -2,7 +2,6 @@ package net.lacolaco.smileessence.view.page
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
@@ -13,14 +12,12 @@ import android.widget.TextView
import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout
import kotlinx.android.synthetic.main.fragment_search.*
import net.lacolaco.smileessence.R
-import net.lacolaco.smileessence.activity.MainActivity
-import net.lacolaco.smileessence.preference.UserPreferenceHelper
+import net.lacolaco.smileessence.data.PageInfo
import net.lacolaco.smileessence.twitter.TwitterTaskException
import net.lacolaco.smileessence.twitter.task.createSavedSearchAsync
import net.lacolaco.smileessence.twitter.task.destroySavedSearchAsync
import net.lacolaco.smileessence.twitter.task.doSearch
import net.lacolaco.smileessence.util.SystemServiceHelper
-import net.lacolaco.smileessence.util.UIHandler
import net.lacolaco.smileessence.util.launchUi
import net.lacolaco.smileessence.view.PopupMenu
import net.lacolaco.smileessence.view.adapter.TimelineAdapter
@@ -28,76 +25,30 @@ import net.lacolaco.smileessence.view.confirm
import twitter4j.Query
import java.util.*
-class SearchFragment : CustomListFragment<TimelineAdapter>() {
+class SearchFragment : CustomListFragment<PageInfo.SearchPageInfo, TimelineAdapter>() {
override val adapter by lazy { TimelineAdapter(activity, world) }
- private lateinit var queryString: String
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setHasOptionsMenu(true)
- queryString = UserPreferenceHelper.instance[R.string.key_last_used_search_query, ""]
- }
-
- override fun refresh() { //TODO
- if (!TextUtils.isEmpty(queryString)) {
- startSearch(queryString)
- }
- }
-
- override fun onSwipeDown(view: SwipyRefreshLayout) {
- if (TextUtils.isEmpty(queryString)) {
- UIHandler().post {
- notifyTextEmpty()
- view.isRefreshing = false
- }
- 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(true)
- view.isRefreshing = false
- }
- }
-
- override fun onSwipeUp(view: SwipyRefreshLayout) {
- if (TextUtils.isEmpty(queryString)) {
- UIHandler().post {
- notifyTextEmpty()
- view.isRefreshing = false
- }
- 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(false)
- view.isRefreshing = false
- }
+ override fun refresh() {
+ if (pageInfo.query.isNotBlank())
+ startSearch(pageInfo.query)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
- super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_search, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ setSwipeRefreshEnabled(pageInfo.query.isNotBlank())
+
button_search_queries.setOnClickListener {
val popup = PopupMenu(activity, button_search_queries)
val sss = ArrayList(world.savedSearches.values)
for (ss in sss) {
- popup.add(ss.query) { (activity as MainActivity).openSearchPage(ss.query) }
+ popup.add(ss.query) {
+ edittext_search.setText(ss.query)
+ startSearch(ss.query)
+ }
}
popup.show()
}
@@ -116,7 +67,7 @@ class SearchFragment : CustomListFragment<TimelineAdapter>() {
try {
world.destroySavedSearchAsync(ss.id).await()
world.notify(R.string.notice_search_query_deleted)
- world.refreshSavedSearches()
+ world.savedSearches.remove(ss.id)
} catch (e: TwitterTaskException) {
world.notifyError("unable to delete search query")
}
@@ -129,8 +80,8 @@ class SearchFragment : CustomListFragment<TimelineAdapter>() {
if (!hasFocus)
SystemServiceHelper.hideIM(activity, edittext_search)
}
- edittext_search.setText(queryString)
- edittext_search.setOnEditorActionListener { textView, i, keyEvent ->
+ edittext_search.setText(pageInfo.query)
+ edittext_search.setOnEditorActionListener { _, i, keyEvent ->
if (i == EditorInfo.IME_ACTION_SEARCH || keyEvent != null &&
keyEvent.action == KeyEvent.ACTION_DOWN &&
keyEvent.keyCode == KeyEvent.KEYCODE_ENTER) {
@@ -153,43 +104,56 @@ class SearchFragment : CustomListFragment<TimelineAdapter>() {
refresh()
}
- private fun notifyTextEmpty() {
- world.notifyError(R.string.notice_search_text_empty)
+ override fun onSwipeDown(view: SwipyRefreshLayout) {
+ val query = Query()
+ query.query = pageInfo.query
+ query.count = 200
+ query.resultType = Query.RECENT
+ if (adapter.count > 0) {
+ query.sinceId = adapter.topID
+ }
+ runRefreshTask(query) {
+ updateListViewWithNotice(true)
+ view.isRefreshing = false
+ }
}
- private fun saveQuery() = launchUi {
- val text = edittext_search.text.toString()
- if (TextUtils.isEmpty(text)) {
- world.notifyError(R.string.notice_query_is_empty)
- } else {
- try {
- world.createSavedSearchAsync(text).await()
- world.notify(R.string.notice_query_saved)
- world.refreshSavedSearches()
- } catch (e: TwitterTaskException) {
- world.notifyError("Query is not saved")
- }
+ override fun onSwipeUp(view: SwipyRefreshLayout) {
+ val query = Query()
+ query.query = pageInfo.query
+ query.count = 200
+ query.resultType = Query.RECENT
+ if (adapter.count > 0) {
+ query.maxId = adapter.lastID - 1
+ }
+ runRefreshTask(query) {
+ updateListViewWithNotice(false)
+ view.isRefreshing = false
}
}
- private fun search() {
+ private fun saveQuery() = launchUi {
val text = edittext_search.text.toString()
- if (TextUtils.isEmpty(text)) {
- world.notifyError(R.string.notice_query_is_empty)
- } else {
- startSearch(text)
- SystemServiceHelper.hideIM(activity, edittext_search)
+ try {
+ val ss = world.createSavedSearchAsync(text).await()
+ world.notify(R.string.notice_query_saved)
+ world.savedSearches.put(ss.id, ss)
+ } catch (e: TwitterTaskException) {
+ world.notifyError("Query is not saved")
}
+ }
+ private fun search() {
+ startSearch(edittext_search.text.toString())
+ SystemServiceHelper.hideIM(activity, edittext_search)
}
- fun startSearch(queryString: String) {
- UserPreferenceHelper.instance[R.string.key_last_used_search_query] = queryString
- edittext_search.setText(queryString)
- this.queryString = queryString
+ private fun startSearch(queryString: String) {
+ pageInfo.query = queryString
+ setSwipeRefreshEnabled(queryString.isNotBlank())
adapter.clear()
adapter.updateForce()
- if (!TextUtils.isEmpty(queryString)) {
+ if (queryString.isNotBlank()) {
val query = Query()
query.query = queryString
query.count = 200
@@ -198,15 +162,13 @@ class SearchFragment : CustomListFragment<TimelineAdapter>() {
}
}
- private fun runRefreshTask(query: Query, onFinish: () -> Unit) {
- launchUi {
- try {
- val tweets = world.doSearch(query).await()
- adapter.addAll(tweets.filter { !it.isRetweet })
- onFinish()
- } catch (e: TwitterTaskException) {
- world.notifyError(R.string.notice_error_search)
- }
+ private fun runRefreshTask(query: Query, onFinish: () -> Unit) = launchUi {
+ try {
+ val tweets = world.doSearch(query).await()
+ adapter.addAll(tweets.filter { !it.isRetweet })
+ onFinish()
+ } catch (e: TwitterTaskException) {
+ world.notifyError(R.string.notice_error_search)
}
}
}
diff --git a/app/src/main/java/net/lacolaco/smileessence/view/page/TweetsPageFragment.kt b/app/src/main/java/net/lacolaco/smileessence/view/page/TweetsPageFragment.kt
new file mode 100644
index 00000000..a9bcfc60
--- /dev/null
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/TweetsPageFragment.kt
@@ -0,0 +1,27 @@
+package net.lacolaco.smileessence.view.page
+
+import android.os.Bundle
+import android.view.View
+import net.lacolaco.smileessence.data.PageInfo
+import net.lacolaco.smileessence.view.adapter.TimelineAdapter
+
+class TweetsPageFragment : CustomListFragment<PageInfo.TweetsPageInfo, TimelineAdapter>() {
+ override val adapter by lazy { TimelineAdapter(activity, world) }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val patterns = pageInfo.patterns
+ world.addTimeline(this) { tweet ->
+ if (patterns.any { it.containsMatchIn(tweet.originalTweet.text) }) {
+ adapter.add(tweet)
+ adapter.update()
+ }
+ }
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setSwipeRefreshEnabled(false)
+ }
+}
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
index 55193aea..35bc4f7f 100644
--- a/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.kt
+++ b/app/src/main/java/net/lacolaco/smileessence/view/page/UserListFragment.kt
@@ -1,7 +1,6 @@
package net.lacolaco.smileessence.view.page
import android.os.Bundle
-import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -9,58 +8,22 @@ import com.omadahealth.github.swipyrefreshlayout.library.SwipyRefreshLayout
import kotlinx.android.synthetic.main.fragment_userlist.*
import kotlinx.coroutines.experimental.Deferred
import net.lacolaco.smileessence.R
+import net.lacolaco.smileessence.data.PageInfo
import net.lacolaco.smileessence.entity.Tweet
-import net.lacolaco.smileessence.preference.UserPreferenceHelper
import net.lacolaco.smileessence.twitter.TwitterTaskException
import net.lacolaco.smileessence.twitter.task.getListTimelineAsync
-import net.lacolaco.smileessence.util.UIHandler
import net.lacolaco.smileessence.util.launchUi
import net.lacolaco.smileessence.view.PopupMenu
import net.lacolaco.smileessence.view.adapter.TimelineAdapter
-class UserListFragment : CustomListFragment<TimelineAdapter>() {
+class UserListFragment : CustomListFragment<PageInfo.ListPageInfo, TimelineAdapter>() {
override val adapter by lazy { TimelineAdapter(activity, world) }
- private var listFullName: String? = null
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- refresh()
- }
-
- override fun refresh() {//TODO
- val lastUserList = UserPreferenceHelper.instance[R.string.key_last_used_user_list, ""]
- if (!TextUtils.isEmpty(lastUserList)) {
- startUserList(lastUserList)
- }
- }
-
- override fun onSwipeDown(view: SwipyRefreshLayout) {
- if (listFullName == null) {
- UIHandler().post {
- notifyTextEmpty()
- view.isRefreshing = false
+ override fun refresh() {
+ if (pageInfo.fullName != null)
+ runRefreshTask(world.getListTimelineAsync(pageInfo.fullName!!)) {
+ adapter.updateForce()
}
- return
- }
- runRefreshTask(world.getListTimelineAsync(listFullName!!, sinceId = adapter.topID)) {
- updateListViewWithNotice(true)
- view.isRefreshing = false
- }
- }
-
- override fun onSwipeUp(view: SwipyRefreshLayout) {
- if (listFullName == null) {
- UIHandler().post {
- notifyTextEmpty()
- view.isRefreshing = false
- }
- return
- }
- runRefreshTask(world.getListTimelineAsync(listFullName!!, maxId = adapter.lastID - 1)) {
- updateListViewWithNotice(false)
- view.isRefreshing = false
- }
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
@@ -69,30 +32,41 @@ class UserListFragment : CustomListFragment<TimelineAdapter>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ setSwipeRefreshEnabled(pageInfo.fullName != null)
+
button_userlist_lists.setOnClickListener {
val popup = PopupMenu(activity, button_userlist_lists)
for (name in world.listSubscriptions) {
popup.add(name) {
textview_userlist_name.text = name
- startUserList(name)
+ pageInfo.fullName = name
+ setSwipeRefreshEnabled(true)
+ adapter.clear()
+ adapter.updateForce()
+ refresh()
}
}
popup.show()
}
- textview_userlist_name.text = if (listFullName != null) listFullName else "<none selected>"
+ textview_userlist_name.text = pageInfo.fullName ?: "<none selected>"
+
+ refresh()
}
- private fun notifyTextEmpty() {
- world.notifyError(R.string.notice_userlist_not_selected)
+ override fun onSwipeDown(view: SwipyRefreshLayout) {
+ val sinceId = if (adapter.count > 0) adapter.topID else null
+ runRefreshTask(world.getListTimelineAsync(pageInfo.fullName!!, sinceId = sinceId)) {
+ updateListViewWithNotice(true)
+ view.isRefreshing = false
+ }
}
- fun startUserList(listFullName: String) {
- UserPreferenceHelper.instance[R.string.key_last_used_user_list] = listFullName
- val adapter = adapter
- this.listFullName = listFullName
- adapter.clear()
- adapter.updateForce()
- runRefreshTask(world.getListTimelineAsync(listFullName)) { adapter.updateForce() }
+ override fun onSwipeUp(view: SwipyRefreshLayout) {
+ val maxId = if (adapter.count > 0) adapter.lastID - 1 else null
+ runRefreshTask(world.getListTimelineAsync(pageInfo.fullName!!, maxId = maxId)) {
+ updateListViewWithNotice(false)
+ view.isRefreshing = false
+ }
}
private fun runRefreshTask(task: Deferred<List<Tweet>>, onFinish: () -> Unit) = launchUi {
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
deleted file mode 100644
index 7dbe3297..00000000
--- a/app/src/main/java/net/lacolaco/smileessence/view/preference/IntegerListPreference.kt
+++ /dev/null
@@ -1,27 +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
-
-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/app/src/main/res/layout/activity_page_manage.xml b/app/src/main/res/layout/activity_page_manage.xml
new file mode 100644
index 00000000..87af0c9d
--- /dev/null
+++ b/app/src/main/res/layout/activity_page_manage.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="net.lacolaco.smileessence.activity.ManagePagesActivity">
+
+ <android.support.design.widget.AppBarLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="?attr/colorPrimary"
+ android:elevation="4dp" />
+
+ </android.support.design.widget.AppBarLayout>
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/recycler_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="@dimen/fab_margin"
+ app:srcCompat="@android:drawable/ic_dialog_email" />
+
+</android.support.design.widget.CoordinatorLayout>
diff --git a/app/src/main/res/layout/dialog_status_detail.xml b/app/src/main/res/layout/dialog_status_detail.xml
index 28e774ea..d9140939 100644
--- a/app/src/main/res/layout/dialog_status_detail.xml
+++ b/app/src/main/res/layout/dialog_status_detail.xml
@@ -32,34 +32,6 @@
android:gravity="center_vertical"
android:orientation="horizontal">
- <ImageView
- android:id="@+id/image_status_detail_fav_count"
- style="@style/custom_button_transparent"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:scaleType="fitCenter"
- android:src="@drawable/icon_favorite_on" />
-
- <TextView
- android:id="@+id/textview_status_detail_fav_count"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="@color/orange" />
-
- <ImageView
- android:id="@+id/image_status_detail_rt_count"
- style="@style/custom_button_transparent"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:scaleType="fitCenter"
- android:src="@drawable/icon_retweet_on" />
-
- <TextView
- android:id="@+id/textview_status_detail_rt_count"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="@color/green" />
-
<ImageButton
android:id="@+id/button_status_detail_reply"
style="@style/custom_button_transparent"
diff --git a/app/src/main/res/layout/list_item_page.xml b/app/src/main/res/layout/list_item_page.xml
new file mode 100644
index 00000000..93f76c25
--- /dev/null
+++ b/app/src/main/res/layout/list_item_page.xml
@@ -0,0 +1,26 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:descendantFocusability="blocksDescendants">
+
+ <TextView
+ android:id="@+id/page_kind_text_view"
+ android:layout_width="120dp"
+ android:layout_height="match_parent"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:paddingTop="14dp"
+ android:paddingBottom="14dp"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <TextView
+ android:id="@+id/page_name_text_view"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:paddingTop="14dp"
+ android:paddingBottom="14dp"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+</LinearLayout>
diff --git a/app/src/main/res/layout/list_item_status.xml b/app/src/main/res/layout/list_item_status.xml
index f5f2d75b..77f52c50 100644
--- a/app/src/main/res/layout/list_item_status.xml
+++ b/app/src/main/res/layout/list_item_status.xml
@@ -2,7 +2,9 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:descendantFocusability="blocksDescendants"
android:padding="5dp"
+ android:foreground="?android:attr/selectableItemBackground"
app:accent_color="?attr/color_status_text_mine"
app:highlight_none="?attr/color_status_bg_normal"
app:highlight_type1="?attr/color_status_bg_mention"
@@ -10,60 +12,91 @@
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/imageview_status_icon"
- android:layout_width="36dp"
- android:layout_height="36dp"
- android:layout_alignParentTop="true" />
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_alignParentTop="true"
+ android:layout_marginRight="5dp" />
<TextView
android:id="@+id/textview_status_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
- android:layout_marginLeft="5dp"
- android:layout_toRightOf="@+id/imageview_status_icon"
- android:gravity="top"
- android:textSize="@dimen/status_text_size"
- android:textColor="?attr/color_status_text_header" />
+ android:layout_toRightOf="@id/imageview_status_icon"
+ android:text="mmmmmmmmmmmmmmm / !!!NAME!!!"
+ android:textColor="?attr/color_status_text_header"
+ android:textSize="@dimen/status_text_size" />
<TextView
android:id="@+id/textview_status_text"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/textview_status_header"
+ android:layout_below="@id/textview_status_header"
+ android:layout_alignLeft="@id/textview_status_header"
android:layout_alignParentRight="true"
- android:layout_below="@+id/textview_status_header"
- android:layout_marginBottom="3dp"
android:layout_marginTop="1dp"
- android:textSize="@dimen/status_text_size"
- android:textColor="?attr/color_status_text_normal" />
+ android:layout_marginBottom="3dp"
+ android:text="!!!TEXT!!!"
+ android:textColor="?attr/color_status_text_normal"
+ android:textSize="@dimen/status_text_size" />
<TextView
android:id="@+id/textview_status_footer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/textview_status_text"
- android:layout_below="@+id/textview_status_text"
- android:layout_marginRight="2dp"
- android:textSize="@dimen/status_meta_text_size"
- android:textColor="?attr/color_status_text_footer" />
+ android:layout_below="@id/textview_status_text"
+ android:layout_alignLeft="@id/textview_status_header"
+ android:text="2017-01-01 00:00:00 via Twitter Web Client"
+ android:textColor="?attr/color_status_text_footer"
+ android:textSize="@dimen/status_meta_text_size" />
+
+ <net.lacolaco.smileessence.view.OnOffImageView
+ android:id="@+id/imageview_status_retweeted"
+ android:layout_width="16dp"
+ android:layout_height="wrap_content"
+ android:layout_alignTop="@id/textview_status_footer"
+ android:layout_alignBottom="@id/textview_status_footer"
+ android:layout_toLeftOf="@id/tweet_retweet_count"
+ app:src_on="@drawable/icon_retweet_on"
+ app:src_off="?icon_retweet_off" />
- <ImageView
+ <TextView
+ android:id="@+id/tweet_retweet_count"
+ android:layout_width="16dp"
+ android:layout_height="wrap_content"
+ android:layout_alignTop="@id/textview_status_footer"
+ android:layout_alignBottom="@id/textview_status_footer"
+ android:layout_toLeftOf="@id/imageview_status_favorited"
+ android:text="999999"
+ android:textColor="?attr/color_status_text_footer"
+ android:textSize="@dimen/status_meta_text_size" />
+
+ <net.lacolaco.smileessence.view.OnOffImageView
android:id="@+id/imageview_status_favorited"
- android:layout_width="30dp"
+ android:layout_width="16dp"
android:layout_height="wrap_content"
- android:layout_alignBottom="@+id/textview_status_header"
+ android:layout_alignTop="@id/textview_status_footer"
+ android:layout_alignBottom="@id/textview_status_footer"
+ android:layout_toLeftOf="@id/tweet_favorite_count"
+ app:src_on="@drawable/icon_favorite_on"
+ app:src_off="?icon_favorite_off" />
+
+ <TextView
+ android:id="@+id/tweet_favorite_count"
+ android:layout_width="16dp"
+ android:layout_height="wrap_content"
+ android:layout_alignTop="@id/textview_status_footer"
+ android:layout_alignBottom="@id/textview_status_footer"
android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_alignTop="@+id/textview_status_header"
- android:contentDescription=""
- android:src="?attr/icon_status_favorite_on" />
+ android:text="999999"
+ android:textColor="?attr/color_status_text_footer"
+ android:textSize="@dimen/status_meta_text_size" />
<net.lacolaco.smileessence.view.ExpandedListView
android:id="@+id/listview_status_embedded_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignLeft="@+id/textview_status_text"
- android:layout_below="@+id/textview_status_footer"
- android:layout_marginRight="1dp"
+ android:layout_alignLeft="@id/textview_status_header"
+ android:layout_below="@id/textview_status_footer"
android:layout_marginTop="3dp" />
</net.lacolaco.smileessence.view.ColoredRelativeLayout>
diff --git a/app/src/main/res/layout/manage_pages_edit_dialog.xml b/app/src/main/res/layout/manage_pages_edit_dialog.xml
new file mode 100644
index 00000000..41dec21a
--- /dev/null
+++ b/app/src/main/res/layout/manage_pages_edit_dialog.xml
@@ -0,0 +1,44 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/textView"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:text="Type" />
+
+ <Spinner
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="3" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/textView2"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:text="Filters" />
+
+ <ListView
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="3" />
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml
index eea3bbb5..3e402b49 100644
--- a/app/src/main/res/menu/main.xml
+++ b/app/src/main/res/menu/main.xml
@@ -6,9 +6,9 @@
app:showAsAction="never"
android:title="@string/actionbar_setting" />
<item
- android:id="@+id/actionbar_edit_extraction"
+ android:id="@+id/actionbar_manage_pages"
app:showAsAction="never"
- android:title="@string/actionbar_edit_extraction" />
+ android:title="Manage pages" />
<item
android:id="@+id/actionbar_aclog"
android:icon="@drawable/icon_website"
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index f26b3e07..95c9d67e 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -10,7 +10,6 @@
<attr name="button_round_red" format="reference" />
<attr name="button_round_orange" format="reference" />
<attr name="custom_button_transparent" format="reference" />
- <attr name="icon_status_favorite_on" format="reference" />
<attr name="color_status_text_header" format="color" />
<attr name="color_status_text_normal" format="color" />
<attr name="color_status_text_footer" format="color" />
@@ -47,4 +46,8 @@
<attr name="offSrc" format="reference" />
<attr name="onSrc" format="reference" />
</declare-styleable>
+ <declare-styleable name="OnOffImageView">
+ <attr name="src_off" format="reference" />
+ <attr name="src_on" format="reference" />
+ </declare-styleable>
</resources>
diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimens.xml
index cdf1de98..97fb5c40 100644
--- a/app/src/main/res/values/dimen.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -1,5 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="status_text_size">11sp</dimen>
<dimen name="status_meta_text_size">9sp</dimen>
+
+ <dimen name="fab_margin">16dp</dimen>
</resources>
diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml
index 1f71fb27..9da6f6bd 100644
--- a/app/src/main/res/values/keys.xml
+++ b/app/src/main/res/values/keys.xml
@@ -1,8 +1,4 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
- <string name="key_setting_theme">theme</string>
<string name="key_setting_application_information">appInfo</string>
<string name="key_setting_licenses">licenseNotice</string>
- <string name="key_setting_resize_post_image">resizePostImage</string>
- <string name="key_last_used_search_query">lastUsedSearchQuery</string>
- <string name="key_last_used_user_list">lastUsedUserList</string>
</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 02958e7c..10ad6d82 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -24,14 +24,7 @@
<string name="page_name_list">List</string>
<string name="actionbar_setting">Settings</string>
<string name="actionbar_aclog">Aclog</string>
- <string name="actionbar_edit_extraction">Edit extraction</string>
- <string name="setting_category_display_title">Display Setting</string>
- <string name="setting_category_display_summary">Enable at next launch.</string>
- <string name="setting_theme_title">Theme</string>
- <string name="setting_theme_dialog_title">Choose theme</string>
<string name="setting_category_system_title">System Setting</string>
- <string name="setting_resize_post_image">Resize image</string>
- <string name="setting_resize_post_image_summary">Compress large image for tweet</string>
<string name="setting_category_about_title">About</string>
<string name="setting_application_information_title">Application information</string>
<string name="setting_licenses_title">Licenses</string>
@@ -89,7 +82,6 @@
<string name="notice_select_image_failed">Failed to select image</string>
<string name="notice_search_text_empty">Query is empty</string>
<string name="notice_add_to_reply">Added to reply</string>
- <string name="notice_theme_changed">Theme will be enabled on next launch</string>
<string name="notice_copy_clipboard">Copied to clipboard</string>
<string name="notice_userlist_not_selected">No List is selected</string>
<string name="notice_search_query_deleted">Query was deleted</string>
@@ -118,4 +110,5 @@
<string name="notice_error_get_list">Failed to get list timeline</string>
<string name="notice_cant_remove_last_account">You can\'t remove last account</string>
<string name="notice_error_storage_permission">Write access to external storage is required.</string>
+ <string name="title_activity_page_manage">PageManageActivity</string>
</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 6bc06af3..e15d6e7d 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -35,7 +35,6 @@
<item name="icon_message">@drawable/icon_message_white</item>
<item name="icon_retweet_off">@drawable/icon_retweet_white</item>
<item name="icon_favorite_off">@drawable/icon_favorite_off_white</item>
- <item name="icon_status_favorite_on">@drawable/icon_favorite_on</item>
<item name="icon_garbage">@drawable/icon_garbage_white</item>
<item name="icon_search">@drawable/icon_search_white</item>
<item name="icon_labels">@drawable/icon_labels_white</item>
@@ -57,7 +56,6 @@
<item name="button_round_red">@drawable/button_round_red_light</item>
<item name="button_round_orange">@drawable/button_round_orange_light</item>
<item name="custom_button_transparent">@style/custom_button_transparent</item>
- <item name="icon_status_favorite_on">@drawable/icon_favorite_on</item>
<item name="color_status_text_header">@color/dark_green</item>
<item name="color_status_text_normal">@color/gray_dark</item>
<item name="color_status_text_footer">@color/gray_dark_light</item>
@@ -85,4 +83,8 @@
<style name="custom_button_transparent">
<item name="android:background">?android:attr/selectableItemBackground</item>
</style>
+
+ <style name="theme_light.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <style name="theme_light.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>
diff --git a/app/src/main/res/xml/setting.xml b/app/src/main/res/xml/setting.xml
index f01a4bd5..c616ae85 100644
--- a/app/src/main/res/xml/setting.xml
+++ b/app/src/main/res/xml/setting.xml
@@ -1,22 +1,4 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
- <PreferenceCategory
- android:summary="@string/setting_category_display_summary"
- android:title="@string/setting_category_display_title">
- <net.lacolaco.smileessence.view.preference.IntegerListPreference
- android:defaultValue="0"
- android:dialogTitle="@string/setting_theme_dialog_title"
- android:entries="@array/setting_theme_names"
- android:entryValues="@array/setting_theme_ids"
- android:key="@string/key_setting_theme"
- android:title="@string/setting_theme_title" />
- </PreferenceCategory>
- <PreferenceCategory android:title="@string/setting_category_system_title">
- <SwitchPreference
- android:defaultValue="true"
- android:key="@string/key_setting_resize_post_image"
- android:summary="@string/setting_resize_post_image_summary"
- android:title="@string/setting_resize_post_image" />
- </PreferenceCategory>
<PreferenceCategory android:title="@string/setting_category_about_title">
<Preference
android:key="@string/key_setting_application_information"
diff --git a/gradle.properties b/gradle.properties
index aac7c9b4..869e8cea 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -9,7 +9,7 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx1536m
+org.gradle.jvmargs=-Xmx1024m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit