This commit is contained in:
tateisu 2019-08-23 21:50:04 +09:00
parent 80bdf09230
commit 959cb16a44
3 changed files with 382 additions and 370 deletions

View File

@ -40,7 +40,7 @@
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@ -7,9 +7,7 @@ import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.graphics.Rect
import android.graphics.Typeface
import android.graphics.drawable.StateListDrawable
import android.net.Uri
import android.os.AsyncTask
import android.os.Build
@ -19,7 +17,10 @@ import android.text.InputType
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.util.JsonReader
import android.view.*
import android.view.Gravity
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.widget.*
import androidx.appcompat.app.AlertDialog
@ -29,7 +30,6 @@ import androidx.drawerlayout.widget.DrawerLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import com.google.android.material.navigation.NavigationView
import jp.juggler.subwaytooter.action.*
import jp.juggler.subwaytooter.api.*
import jp.juggler.subwaytooter.api.entity.*
@ -45,7 +45,6 @@ import jp.juggler.subwaytooter.util.PostHelper
import jp.juggler.subwaytooter.view.*
import jp.juggler.util.*
import org.apache.commons.io.IOUtils
import org.jetbrains.anko.backgroundColor
import org.jetbrains.anko.backgroundDrawable
import java.io.File
import java.io.FileInputStream
@ -386,7 +385,7 @@ class ActMain : AppCompatActivity()
}
// 新しいカラムをどこに挿入するか
private val defaultInsertPosition : Int
val defaultInsertPosition : Int
get() = phoneTab(
{ it.pager.currentItem + 1 },
{ Integer.MAX_VALUE }
@ -1187,8 +1186,7 @@ class ActMain : AppCompatActivity()
drawer = findViewById(R.id.drawer_layout)
drawer.addDrawerListener(this)
val navigationView = findViewById<NavigationView>(R.id.nav_view)
initSideMenu(navigationView)
SideMenuAdapter( this, findViewById(R.id.nav_view), drawer )
btnMenu = findViewById(R.id.btnMenu)
btnToot = findViewById(R.id.btnToot)
@ -2938,365 +2936,4 @@ class ActMain : AppCompatActivity()
dialog.show()
}
class MyMenuItem(val title : Int, val icon : Int, val action : () -> Unit = {})
val sideMenuContents = ArrayList<MyMenuItem>().apply {
fun add(title : Int = 0, icon : Int = 0, action : () -> Unit = {}) {
add(MyMenuItem(title, icon, action))
}
add(title = R.string.account)
add(title = R.string.account_add, icon = R.drawable.ic_account_add) {
Action_Account.add(this@ActMain)
}
/* android:id="@+id/nav_account_setting" */
add(icon = R.drawable.ic_settings, title = R.string.account_setting) {
Action_Account.setting(this@ActMain)
}
add()
add(title = R.string.column)
/* android:id="@+id/nav_column_list" */
add(icon = R.drawable.ic_list_numbered, title = R.string.column_list) {
Action_App.columnList(this@ActMain)
}
/* android:id="@+id/nav_close_all_columns" */
add(
icon = R.drawable.ic_close, title = R.string.close_all_columns
) {
closeColumnAll()
}
/* android:id="@+id/nav_add_tl_home" */
add(icon = R.drawable.ic_home, title = R.string.home) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.HOME
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_add_notifications" */
add(icon = R.drawable.ic_announcement, title = R.string.notifications) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.NOTIFICATIONS
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_add_direct_message" */
add(icon = R.drawable.ic_mail, title = R.string.direct_messages) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.DIRECT_MESSAGES
, bAllowPseudo = false
, bAllowMisskey = false
)
}
/* android:id="@+id/nav_add_tl_misskey_hybrid" */
add(icon = R.drawable.ic_share, title = R.string.misskey_hybrid_timeline_long) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.MISSKEY_HYBRID
, bAllowPseudo = true
, bAllowMastodon = false
)
}
/* android:id="@+id/nav_add_tl_local" */
add(icon = R.drawable.ic_run, title = R.string.local_timeline) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.LOCAL
, bAllowPseudo = true
)
}
/* android:id="@+id/nav_add_tl_federate" */
add(icon = R.drawable.ic_bike, title = R.string.federate_timeline) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.FEDERATE
, bAllowPseudo = true
)
}
/* android:id="@+id/nav_add_list" */
add(icon = R.drawable.ic_list_list, title = R.string.lists) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.LIST_LIST
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_add_tl_search" */
add(icon = R.drawable.ic_search, title = R.string.search) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.SEARCH
, bAllowPseudo = false
, args = arrayOf("", false)
)
}
/* android:id="@+id/nav_trend_tag" */
add(icon = R.drawable.ic_hashtag, title = R.string.trend_tag) {
Action_Account.timeline(
this@ActMain,
defaultInsertPosition,
ColumnType.TREND_TAG,
bAllowPseudo = true,
bAllowMastodon = true,
bAllowMisskey = false
)
}
/* android:id="@+id/nav_add_favourites" */
add(icon = R.drawable.ic_star, title = R.string.favourites) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.FAVOURITES
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_add_statuses" */
add(icon = R.drawable.ic_account_box, title = R.string.profile) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.PROFILE
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_follow_requests" */
add(icon = R.drawable.ic_follow_wait, title = R.string.follow_requests) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.FOLLOW_REQUESTS
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_follow_suggestion" */
add(icon = R.drawable.ic_follow_plus, title = R.string.follow_suggestion) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.FOLLOW_SUGGESTION
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_endorsement" */
add(icon = R.drawable.ic_follow_plus, title = R.string.endorse_set) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.ENDORSEMENT
, bAllowPseudo = false
, bAllowMisskey = false
)
}
/* android:id="@+id/nav_add_mutes" */
add(icon = R.drawable.ic_volume_off, title = R.string.muted_users) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.MUTES
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_add_blocks" */
add(icon = R.drawable.ic_block, title = R.string.blocked_users) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.BLOCKS
, bAllowPseudo = false
)
}
/* android:id="@+id/nav_keyword_filter" */
add(icon = R.drawable.ic_volume_off, title = R.string.keyword_filters) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.KEYWORD_FILTER
, bAllowPseudo = false
, bAllowMisskey = false
)
}
/* android:id="@+id/nav_add_domain_blocks" */
add(icon = R.drawable.ic_cloud_off, title = R.string.blocked_domains) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.DOMAIN_BLOCKS
, bAllowPseudo = false
, bAllowMisskey = false
)
}
/* android:id="@+id/nav_scheduled_statuses_list" */
add(icon = R.drawable.ic_timer, title = R.string.scheduled_status_list) {
Action_Account.timeline(
this@ActMain
, defaultInsertPosition
, ColumnType.SCHEDULED_STATUS
, bAllowPseudo = false
, bAllowMisskey = false
)
}
add()
add(title = R.string.toot_search)
add(icon = R.drawable.ic_search, title = R.string.tootsearch) {
addColumn(
defaultInsertPosition
, SavedAccount.na
, ColumnType.SEARCH_TS
, ""
)
}
add()
add(title = R.string.setting)
add(icon = R.drawable.ic_settings, title = R.string.app_setting) {
ActAppSetting.open(this@ActMain, REQUEST_CODE_APP_SETTING)
}
add(icon = R.drawable.ic_settings, title = R.string.highlight_word) {
startActivity(Intent(this@ActMain, ActHighlightWordList::class.java))
}
add(icon = R.drawable.ic_volume_off, title = R.string.muted_app) {
startActivity(Intent(this@ActMain, ActMutedApp::class.java))
}
add(icon = R.drawable.ic_volume_off, title = R.string.muted_word) {
startActivity(Intent(this@ActMain, ActMutedWord::class.java))
}
add(icon = R.drawable.ic_volume_off, title = R.string.fav_muted_user) {
startActivity(Intent(this@ActMain, ActFavMute::class.java))
}
add(
icon = R.drawable.ic_volume_off,
title = R.string.muted_users_from_pseudo_account
) {
startActivity(Intent(this@ActMain, ActMutedPseudoAccount::class.java))
}
add(icon = R.drawable.ic_info, title = R.string.app_about) {
startActivityForResult(Intent(this@ActMain, ActAbout::class.java), REQUEST_APP_ABOUT)
}
add(icon = R.drawable.ic_info, title = R.string.oss_license) {
startActivity(Intent(this@ActMain, ActOSSLicense::class.java))
}
add(icon = R.drawable.ic_hot_tub, title = R.string.app_exit) {
finish()
}
}
inner class SideMenuAdapter : BaseAdapter() {
private val iconColor = getAttributeColor(this@ActMain, R.attr.colorTimeSmall)
override fun getCount() : Int =
sideMenuContents.size
override fun getItem(position : Int) : Any =
sideMenuContents[position]
override fun getItemId(position : Int) : Long = 0L
override fun getViewTypeCount() : Int = 3
override fun getItemViewType(position : Int) : Int {
val item = sideMenuContents[position]
return when {
item.title == 0 -> 0
item.icon == 0 -> 1
else -> 2
}
}
private inline fun <reified T : View> viewOrInflate(
view : View?,
parent : ViewGroup?,
resId : Int
) : T {
val v = view ?: layoutInflater.inflate(resId, parent, false)
return if(v is T) v else error("invalid view type! $v")
}
override fun getView(position : Int, view : View?, parent : ViewGroup?) : View {
val item = sideMenuContents[position]
return when {
item.title == 0 -> viewOrInflate(view, parent, R.layout.lv_sidemenu_separator)
item.icon == 0 -> viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_group)
.apply {
text = getString(item.title)
}
else -> viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item)
.apply {
isAllCaps = false
text = getString(item.title)
val drawable = createColoredDrawable(this@ActMain, item.icon, iconColor, 1f)
setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null)
setOnClickListener {
item.action()
drawer.closeDrawer(GravityCompat.START)
}
}
}
}
}
private fun initSideMenu(navigationView : NavigationView) {
navigationView.addView(ListView(this).apply {
adapter = SideMenuAdapter()
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
)
backgroundColor = getAttributeColor(this@ActMain, R.attr.colorWindowBackground)
selector = StateListDrawable()
divider = null
dividerHeight = 0
val pad_tb = (density *12f + 0.5f) .toInt()
setPadding(0,pad_tb,0,pad_tb)
clipToPadding = false
scrollBarStyle =ListView.SCROLLBARS_OUTSIDE_OVERLAY
})
}
}

View File

@ -0,0 +1,375 @@
package jp.juggler.subwaytooter
import android.content.Intent
import android.graphics.drawable.StateListDrawable
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.FrameLayout
import android.widget.ListView
import android.widget.TextView
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.navigation.NavigationView
import jp.juggler.subwaytooter.action.Action_Account
import jp.juggler.subwaytooter.action.Action_App
import jp.juggler.subwaytooter.table.SavedAccount
import jp.juggler.util.createColoredDrawable
import jp.juggler.util.getAttributeColor
import org.jetbrains.anko.backgroundColor
class SideMenuAdapter(
val activity : ActMain,
navigationView : NavigationView,
private val drawer : DrawerLayout
) : BaseAdapter() {
private class Item(
val title : Int = 0,
val icon : Int = 0,
val action : ActMain.() -> Unit = {}
)
/*
no title => section divider
else no icon => section header with title
else => menu item with icon and title
*/
private val list = arrayOf(
Item(title = R.string.account),
Item(title = R.string.account_add, icon = R.drawable.ic_account_add) {
Action_Account.add(this)
},
Item(icon = R.drawable.ic_settings, title = R.string.account_setting) {
Action_Account.setting(this)
},
Item(),
Item(title = R.string.column),
Item(icon = R.drawable.ic_list_numbered, title = R.string.column_list) {
Action_App.columnList(this)
},
Item(icon = R.drawable.ic_close, title = R.string.close_all_columns) {
closeColumnAll()
},
Item(icon = R.drawable.ic_home, title = R.string.home) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.HOME
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_announcement, title = R.string.notifications) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.NOTIFICATIONS
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_mail, title = R.string.direct_messages) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.DIRECT_MESSAGES
, bAllowPseudo = false
, bAllowMisskey = false
)
},
Item(icon = R.drawable.ic_share, title = R.string.misskey_hybrid_timeline_long) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.MISSKEY_HYBRID
, bAllowPseudo = true
, bAllowMastodon = false
)
},
Item(icon = R.drawable.ic_run, title = R.string.local_timeline) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.LOCAL
, bAllowPseudo = true
)
},
Item(icon = R.drawable.ic_bike, title = R.string.federate_timeline) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.FEDERATE
, bAllowPseudo = true
)
},
Item(icon = R.drawable.ic_list_list, title = R.string.lists) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.LIST_LIST
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_search, title = R.string.search) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.SEARCH
, bAllowPseudo = false
, args = arrayOf("", false)
)
},
Item(icon = R.drawable.ic_hashtag, title = R.string.trend_tag) {
Action_Account.timeline(
this,
defaultInsertPosition,
ColumnType.TREND_TAG,
bAllowPseudo = true,
bAllowMastodon = true,
bAllowMisskey = false
)
},
Item(icon = R.drawable.ic_star, title = R.string.favourites) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.FAVOURITES
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_account_box, title = R.string.profile) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.PROFILE
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_follow_wait, title = R.string.follow_requests) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.FOLLOW_REQUESTS
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_follow_plus, title = R.string.follow_suggestion) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.FOLLOW_SUGGESTION
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_follow_plus, title = R.string.endorse_set) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.ENDORSEMENT
, bAllowPseudo = false
, bAllowMisskey = false
)
},
Item(icon = R.drawable.ic_volume_off, title = R.string.muted_users) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.MUTES
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_block, title = R.string.blocked_users) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.BLOCKS
, bAllowPseudo = false
)
},
Item(icon = R.drawable.ic_volume_off, title = R.string.keyword_filters) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.KEYWORD_FILTER
, bAllowPseudo = false
, bAllowMisskey = false
)
},
Item(icon = R.drawable.ic_cloud_off, title = R.string.blocked_domains) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.DOMAIN_BLOCKS
, bAllowPseudo = false
, bAllowMisskey = false
)
},
Item(icon = R.drawable.ic_timer, title = R.string.scheduled_status_list) {
Action_Account.timeline(
this
, defaultInsertPosition
, ColumnType.SCHEDULED_STATUS
, bAllowPseudo = false
, bAllowMisskey = false
)
},
Item(),
Item(title = R.string.toot_search),
Item(icon = R.drawable.ic_search, title = R.string.tootsearch) {
addColumn(
defaultInsertPosition
, SavedAccount.na
, ColumnType.SEARCH_TS
, ""
)
},
Item(),
Item(title = R.string.setting),
Item(icon = R.drawable.ic_settings, title = R.string.app_setting) {
ActAppSetting.open(this, ActMain.REQUEST_CODE_APP_SETTING)
},
Item(icon = R.drawable.ic_settings, title = R.string.highlight_word) {
startActivity(Intent(this, ActHighlightWordList::class.java))
},
Item(icon = R.drawable.ic_volume_off, title = R.string.muted_app) {
startActivity(Intent(this, ActMutedApp::class.java))
},
Item(icon = R.drawable.ic_volume_off, title = R.string.muted_word) {
startActivity(Intent(this, ActMutedWord::class.java))
},
Item(icon = R.drawable.ic_volume_off, title = R.string.fav_muted_user) {
startActivity(Intent(this, ActFavMute::class.java))
},
Item(
icon = R.drawable.ic_volume_off,
title = R.string.muted_users_from_pseudo_account
) {
startActivity(Intent(this, ActMutedPseudoAccount::class.java))
},
Item(icon = R.drawable.ic_info, title = R.string.app_about) {
startActivityForResult(
Intent(this, ActAbout::class.java),
ActMain.REQUEST_APP_ABOUT
)
},
Item(icon = R.drawable.ic_info, title = R.string.oss_license) {
startActivity(Intent(this, ActOSSLicense::class.java))
},
Item(icon = R.drawable.ic_hot_tub, title = R.string.app_exit) {
finish()
}
)
private val iconColor = getAttributeColor(activity, R.attr.colorTimeSmall)
override fun getCount() : Int =
list.size
override fun getItem(position : Int) : Any =
list[position]
override fun getItemId(position : Int) : Long = 0L
override fun getViewTypeCount() : Int = 3
override fun getItemViewType(position : Int) : Int {
val item = list[position]
return when {
item.title == 0 -> 0
item.icon == 0 -> 1
else -> 2
}
}
private inline fun <reified T : View> viewOrInflate(
view : View?,
parent : ViewGroup?,
resId : Int
) : T {
val v = view ?: activity.layoutInflater.inflate(resId, parent, false)
return if(v is T) v else error("invalid view type! $v")
}
override fun getView(position : Int, view : View?, parent : ViewGroup?) : View {
val item = list[position]
return when {
item.title == 0 -> viewOrInflate(view, parent, R.layout.lv_sidemenu_separator)
item.icon == 0 -> viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_group)
.apply {
text = activity.getString(item.title)
}
else -> viewOrInflate<TextView>(view, parent, R.layout.lv_sidemenu_item)
.apply {
isAllCaps = false
text = activity.getString(item.title)
val drawable = createColoredDrawable(activity, item.icon, iconColor, 1f)
setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null)
setOnClickListener {
item.action(activity)
drawer.closeDrawer(GravityCompat.START)
}
}
}
}
init {
navigationView.addView(ListView(activity).apply {
adapter = this@SideMenuAdapter
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
)
backgroundColor = getAttributeColor(activity, R.attr.colorWindowBackground)
selector = StateListDrawable()
divider = null
dividerHeight = 0
val pad_tb = (activity.density * 12f + 0.5f).toInt()
setPadding(0, pad_tb, 0, pad_tb)
clipToPadding = false
scrollBarStyle = ListView.SCROLLBARS_OUTSIDE_OVERLAY
})
}
}