mirror of
https://github.com/accelforce/Yuito
synced 2025-02-02 00:47:02 +01:00
Refactor quick compose
* Stash visibility while composing reply * Remove announcements
This commit is contained in:
parent
bb5106a18d
commit
025ba68df4
@ -34,10 +34,10 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.view.menu.MenuBuilder
|
import androidx.appcompat.view.menu.MenuBuilder
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
@ -65,6 +65,7 @@ import com.keylesspalace.tusky.components.preference.PreferencesActivity
|
|||||||
import com.keylesspalace.tusky.components.scheduled.ScheduledTootActivity
|
import com.keylesspalace.tusky.components.scheduled.ScheduledTootActivity
|
||||||
import com.keylesspalace.tusky.components.search.SearchActivity
|
import com.keylesspalace.tusky.components.search.SearchActivity
|
||||||
import com.keylesspalace.tusky.db.AccountEntity
|
import com.keylesspalace.tusky.db.AccountEntity
|
||||||
|
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||||
import com.keylesspalace.tusky.entity.Account
|
import com.keylesspalace.tusky.entity.Account
|
||||||
import com.keylesspalace.tusky.fragment.NotificationsFragment
|
import com.keylesspalace.tusky.fragment.NotificationsFragment
|
||||||
import com.keylesspalace.tusky.fragment.SFragment
|
import com.keylesspalace.tusky.fragment.SFragment
|
||||||
@ -94,7 +95,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers
|
|||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import net.accelf.yuito.FooterDrawerItem
|
import net.accelf.yuito.FooterDrawerItem
|
||||||
import net.accelf.yuito.QuickTootHelper
|
import net.accelf.yuito.QuickTootViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector {
|
class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector {
|
||||||
@ -110,6 +111,11 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var conversationRepository: ConversationsRepository
|
lateinit var conversationRepository: ConversationsRepository
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var viewModelFactory: ViewModelFactory
|
||||||
|
|
||||||
|
private val quickTootViewModel: QuickTootViewModel by viewModels { viewModelFactory }
|
||||||
|
|
||||||
private lateinit var header: AccountHeaderView
|
private lateinit var header: AccountHeaderView
|
||||||
|
|
||||||
private var streamingTabsCount = 0
|
private var streamingTabsCount = 0
|
||||||
@ -182,10 +188,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||||||
window.statusBarColor = Color.TRANSPARENT // don't draw a status bar, the DrawerLayout and the MaterialDrawerLayout have their own
|
window.statusBarColor = Color.TRANSPARENT // don't draw a status bar, the DrawerLayout and the MaterialDrawerLayout have their own
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
val quickTootHelper = QuickTootHelper(this, quickTootContainer as ConstraintLayout?, accountManager, eventHub)
|
viewQuickToot.attachViewModel(quickTootViewModel, this)
|
||||||
composeButton.setOnClickListener {
|
composeButton.setOnClickListener(viewQuickToot::onFABClicked)
|
||||||
quickTootHelper.composeButton()
|
|
||||||
}
|
|
||||||
|
|
||||||
val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
|
val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
|
||||||
mainToolbar.visible(!hideTopToolbar)
|
mainToolbar.visible(!hideTopToolbar)
|
||||||
@ -238,7 +242,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||||||
is ProfileEditedEvent -> onFetchUserInfoSuccess(event.newProfileData)
|
is ProfileEditedEvent -> onFetchUserInfoSuccess(event.newProfileData)
|
||||||
is MainTabsChangedEvent -> setupTabs(false)
|
is MainTabsChangedEvent -> setupTabs(false)
|
||||||
}
|
}
|
||||||
quickTootHelper.handleEvent(event)
|
viewQuickToot.handleEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush old media that was cached for sharing
|
// Flush old media that was cached for sharing
|
||||||
@ -475,7 +479,6 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||||||
)
|
)
|
||||||
addStickyDrawerItems(
|
addStickyDrawerItems(
|
||||||
FooterDrawerItem().apply {
|
FooterDrawerItem().apply {
|
||||||
eventHub = this@MainActivity.eventHub
|
|
||||||
setSubscribeProxy(
|
setSubscribeProxy(
|
||||||
mastodonApi.getInstance()
|
mastodonApi.getInstance()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -4,10 +4,11 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.activity.viewModels
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.keylesspalace.tusky.appstore.EventHub
|
import com.keylesspalace.tusky.appstore.EventHub
|
||||||
|
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||||
import com.keylesspalace.tusky.fragment.TimelineFragment
|
import com.keylesspalace.tusky.fragment.TimelineFragment
|
||||||
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
|
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
|
||||||
import com.uber.autodispose.AutoDispose.autoDisposable
|
import com.uber.autodispose.AutoDispose.autoDisposable
|
||||||
@ -15,8 +16,10 @@ import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from
|
|||||||
import dagger.android.DispatchingAndroidInjector
|
import dagger.android.DispatchingAndroidInjector
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import kotlinx.android.synthetic.main.activity_main.viewQuickToot
|
||||||
|
import kotlinx.android.synthetic.main.activity_modal_timeline.*
|
||||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||||
import net.accelf.yuito.QuickTootHelper
|
import net.accelf.yuito.QuickTootViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ModalTimelineActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector {
|
class ModalTimelineActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector {
|
||||||
@ -40,6 +43,10 @@ class ModalTimelineActivity : BottomSheetActivity(), ActionButtonActivity, HasAn
|
|||||||
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
|
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var eventHub: EventHub
|
lateinit var eventHub: EventHub
|
||||||
|
@Inject
|
||||||
|
lateinit var viewModelFactory: ViewModelFactory
|
||||||
|
|
||||||
|
private val quickTootViewModel: QuickTootViewModel by viewModels { viewModelFactory }
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -62,15 +69,13 @@ class ModalTimelineActivity : BottomSheetActivity(), ActionButtonActivity, HasAn
|
|||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
val quickTootContainer = findViewById<ConstraintLayout>(R.id.quick_toot_container)
|
viewQuickToot.attachViewModel(quickTootViewModel, this)
|
||||||
val composeButton = findViewById<FloatingActionButton>(R.id.floating_btn)
|
|
||||||
val quickTootHelper = QuickTootHelper(this, quickTootContainer, accountManager, eventHub)
|
|
||||||
|
|
||||||
eventHub.events
|
eventHub.events
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.`as`(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
.`as`(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
||||||
.subscribe(quickTootHelper::handleEvent)
|
.subscribe(viewQuickToot::handleEvent)
|
||||||
composeButton.setOnClickListener { quickTootHelper.composeButton() }
|
floating_btn.setOnClickListener(viewQuickToot::onFABClicked)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getActionButton(): FloatingActionButton? = null
|
override fun getActionButton(): FloatingActionButton? = null
|
||||||
|
@ -19,11 +19,11 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.activity.viewModels
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
import com.keylesspalace.tusky.appstore.EventHub
|
import com.keylesspalace.tusky.appstore.EventHub
|
||||||
|
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||||
import com.keylesspalace.tusky.fragment.TimelineFragment
|
import com.keylesspalace.tusky.fragment.TimelineFragment
|
||||||
import com.keylesspalace.tusky.fragment.TimelineFragment.Kind
|
import com.keylesspalace.tusky.fragment.TimelineFragment.Kind
|
||||||
import com.uber.autodispose.AutoDispose
|
import com.uber.autodispose.AutoDispose
|
||||||
@ -33,8 +33,9 @@ import dagger.android.HasAndroidInjector
|
|||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import kotlinx.android.extensions.CacheImplementation
|
import kotlinx.android.extensions.CacheImplementation
|
||||||
import kotlinx.android.extensions.ContainerOptions
|
import kotlinx.android.extensions.ContainerOptions
|
||||||
|
import kotlinx.android.synthetic.main.activity_statuslist.*
|
||||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||||
import net.accelf.yuito.QuickTootHelper
|
import net.accelf.yuito.QuickTootViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
@ -43,6 +44,10 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||||||
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
|
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var eventHub: EventHub
|
lateinit var eventHub: EventHub
|
||||||
|
@Inject
|
||||||
|
lateinit var viewModelFactory: ViewModelFactory
|
||||||
|
|
||||||
|
private val quickTootViewModel: QuickTootViewModel by viewModels{ viewModelFactory }
|
||||||
|
|
||||||
private val kind: Kind
|
private val kind: Kind
|
||||||
get() = Kind.valueOf(intent.getStringExtra(EXTRA_KIND)!!)
|
get() = Kind.valueOf(intent.getStringExtra(EXTRA_KIND)!!)
|
||||||
@ -71,16 +76,13 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
|||||||
replace(R.id.fragment_container, fragment)
|
replace(R.id.fragment_container, fragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
val quickTootContainer = findViewById<ConstraintLayout>(R.id.quick_toot_container)
|
viewQuickToot.attachViewModel(quickTootViewModel, this)
|
||||||
val composeButton = findViewById<FloatingActionButton>(R.id.floating_btn)
|
|
||||||
val quickTootHelper = QuickTootHelper(this, quickTootContainer, accountManager, eventHub)
|
|
||||||
|
|
||||||
eventHub.events
|
eventHub.events
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.`as`(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_DESTROY)))
|
.`as`(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_DESTROY)))
|
||||||
.subscribe(quickTootHelper::handleEvent)
|
.subscribe(viewQuickToot::handleEvent)
|
||||||
composeButton.setOnClickListener { quickTootHelper.composeButton() }
|
floating_btn.setOnClickListener(viewQuickToot::onFABClicked)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
@ -23,15 +23,16 @@ import android.view.MenuItem;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
import androidx.lifecycle.Lifecycle;
|
import androidx.lifecycle.Lifecycle;
|
||||||
|
|
||||||
import com.keylesspalace.tusky.appstore.EventHub;
|
import com.keylesspalace.tusky.appstore.EventHub;
|
||||||
|
import com.keylesspalace.tusky.di.ViewModelFactory;
|
||||||
import com.keylesspalace.tusky.fragment.TimelineFragment;
|
import com.keylesspalace.tusky.fragment.TimelineFragment;
|
||||||
|
|
||||||
import net.accelf.yuito.QuickTootHelper;
|
import net.accelf.yuito.QuickTootView;
|
||||||
|
import net.accelf.yuito.QuickTootViewModel;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@ -53,6 +54,8 @@ public class ViewTagActivity extends BottomSheetActivity implements HasAndroidIn
|
|||||||
public DispatchingAndroidInjector<Object> dispatchingAndroidInjector;
|
public DispatchingAndroidInjector<Object> dispatchingAndroidInjector;
|
||||||
@Inject
|
@Inject
|
||||||
public EventHub eventHub;
|
public EventHub eventHub;
|
||||||
|
@Inject
|
||||||
|
public ViewModelFactory viewModelFactory;
|
||||||
|
|
||||||
public static Intent getIntent(Context context, String tag){
|
public static Intent getIntent(Context context, String tag){
|
||||||
Intent intent = new Intent(context,ViewTagActivity.class);
|
Intent intent = new Intent(context,ViewTagActivity.class);
|
||||||
@ -82,13 +85,14 @@ public class ViewTagActivity extends BottomSheetActivity implements HasAndroidIn
|
|||||||
fragmentTransaction.replace(R.id.fragment_container, fragment);
|
fragmentTransaction.replace(R.id.fragment_container, fragment);
|
||||||
fragmentTransaction.commit();
|
fragmentTransaction.commit();
|
||||||
|
|
||||||
ConstraintLayout quickTootContainer = findViewById(R.id.quick_toot_container);
|
QuickTootViewModel quickTootViewModel = viewModelFactory.create(QuickTootViewModel.class);
|
||||||
QuickTootHelper quickTootHelper = new QuickTootHelper(this, quickTootContainer, accountManager, eventHub);
|
QuickTootView quickTootView = findViewById(R.id.viewQuickToot);
|
||||||
|
quickTootView.attachViewModel(quickTootViewModel, this);
|
||||||
|
|
||||||
eventHub.getEvents()
|
eventHub.getEvents()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.as(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
.as(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
||||||
.subscribe(quickTootHelper::handleEvent);
|
.subscribe(quickTootView::handleEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -23,4 +23,3 @@ data class PollVoteEvent(val statusId: String, val poll: Poll) : Dispatchable
|
|||||||
data class DomainMuteEvent(val instance: String): Dispatchable
|
data class DomainMuteEvent(val instance: String): Dispatchable
|
||||||
data class QuickReplyEvent(val status: Status) : Dispatchable
|
data class QuickReplyEvent(val status: Status) : Dispatchable
|
||||||
data class StreamUpdateEvent(val status: Status, val targetKind: TimelineFragment.Kind, val targetIdentifier: String?, val first: Boolean) : Dispatchable
|
data class StreamUpdateEvent(val status: Status, val targetKind: TimelineFragment.Kind, val targetIdentifier: String?, val first: Boolean) : Dispatchable
|
||||||
data class DrawerFooterClickedEvent(val placeholder: Boolean) : Dispatchable
|
|
@ -17,6 +17,7 @@ import dagger.Binds
|
|||||||
import dagger.MapKey
|
import dagger.MapKey
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.multibindings.IntoMap
|
import dagger.multibindings.IntoMap
|
||||||
|
import net.accelf.yuito.QuickTootViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Provider
|
import javax.inject.Provider
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -85,5 +86,10 @@ abstract class ViewModelModule {
|
|||||||
@ViewModelKey(ScheduledTootViewModel::class)
|
@ViewModelKey(ScheduledTootViewModel::class)
|
||||||
internal abstract fun scheduledTootViewModel(viewModel: ScheduledTootViewModel): ViewModel
|
internal abstract fun scheduledTootViewModel(viewModel: ScheduledTootViewModel): ViewModel
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(QuickTootViewModel::class)
|
||||||
|
internal abstract fun quickTootViewModel(viewModel: QuickTootViewModel): ViewModel
|
||||||
|
|
||||||
//Add more ViewModels here
|
//Add more ViewModels here
|
||||||
}
|
}
|
@ -1,27 +0,0 @@
|
|||||||
package com.keylesspalace.tusky.entity
|
|
||||||
|
|
||||||
import android.text.Spanned
|
|
||||||
import com.google.gson.annotations.SerializedName
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
data class Announcement(
|
|
||||||
val id: String,
|
|
||||||
val content: Spanned,
|
|
||||||
@SerializedName("starts_at") val startsAt: Date,
|
|
||||||
@SerializedName("ends_at") val endsAt: Date,
|
|
||||||
@SerializedName("all_day") val allDay: Boolean,
|
|
||||||
val emojis: List<Emoji>,
|
|
||||||
val mentions: Array<Status.Mention>
|
|
||||||
) {
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other == null || javaClass != other.javaClass) return false
|
|
||||||
|
|
||||||
val announcement = other as Announcement?
|
|
||||||
return id == announcement?.id
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
return id.hashCode()
|
|
||||||
}
|
|
||||||
}
|
|
@ -505,9 +505,6 @@ interface MastodonApi {
|
|||||||
@Field("choices[]") choices: List<Int>
|
@Field("choices[]") choices: List<Int>
|
||||||
): Single<Poll>
|
): Single<Poll>
|
||||||
|
|
||||||
@GET("api/v1/announcements")
|
|
||||||
fun listAnnouncements(): Single<List<Announcement>>
|
|
||||||
|
|
||||||
@POST("api/v1/accounts/{id}/block")
|
@POST("api/v1/accounts/{id}/block")
|
||||||
fun blockAccountObservable(
|
fun blockAccountObservable(
|
||||||
@Path("id") accountId: String
|
@Path("id") accountId: String
|
||||||
|
@ -5,20 +5,15 @@ import android.view.View
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.keylesspalace.tusky.R
|
import com.keylesspalace.tusky.R
|
||||||
import com.keylesspalace.tusky.appstore.DrawerFooterClickedEvent
|
|
||||||
import com.keylesspalace.tusky.appstore.EventHub
|
|
||||||
import com.keylesspalace.tusky.entity.Instance
|
import com.keylesspalace.tusky.entity.Instance
|
||||||
import com.mikepenz.materialdrawer.model.AbstractDrawerItem
|
import com.mikepenz.materialdrawer.model.AbstractDrawerItem
|
||||||
import com.uber.autodispose.SingleSubscribeProxy
|
import com.uber.autodispose.SingleSubscribeProxy
|
||||||
|
import kotlinx.android.synthetic.main.item_drawer_footer.view.*
|
||||||
|
|
||||||
class FooterDrawerItem : AbstractDrawerItem<FooterDrawerItem, FooterDrawerItem.ViewHolder>() {
|
class FooterDrawerItem : AbstractDrawerItem<FooterDrawerItem, FooterDrawerItem.ViewHolder>() {
|
||||||
override val type: Int
|
override val type = R.id.instanceData
|
||||||
get() = R.id.instanceData
|
|
||||||
|
|
||||||
override val layoutRes: Int
|
override val layoutRes = R.layout.item_drawer_footer
|
||||||
get() = R.layout.item_drawer_footer
|
|
||||||
|
|
||||||
lateinit var eventHub: EventHub
|
|
||||||
|
|
||||||
private lateinit var context: Context
|
private lateinit var context: Context
|
||||||
private lateinit var instanceData: TextView
|
private lateinit var instanceData: TextView
|
||||||
@ -29,24 +24,9 @@ class FooterDrawerItem : AbstractDrawerItem<FooterDrawerItem, FooterDrawerItem.V
|
|||||||
instanceData = holder.instanceData
|
instanceData = holder.instanceData
|
||||||
holder.itemView.setPadding(0, 0, 0, 0)
|
holder.itemView.setPadding(0, 0, 0, 0)
|
||||||
instanceData.setTextColor(instanceData.hintTextColors)
|
instanceData.setTextColor(instanceData.hintTextColors)
|
||||||
onDrawerItemClickListener = { _, _, _ ->
|
|
||||||
var result = true
|
|
||||||
var text = instanceData.text.toString()
|
|
||||||
text += "?"
|
|
||||||
if (text.endsWith("???????")) {
|
|
||||||
text = text.substring(0, text.length - 7)
|
|
||||||
eventHub.dispatch(DrawerFooterClickedEvent(true))
|
|
||||||
isExpanded = false
|
|
||||||
result = false
|
|
||||||
}
|
|
||||||
instanceData.text = text
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getViewHolder(v: View): ViewHolder {
|
override fun getViewHolder(v: View) = ViewHolder(v)
|
||||||
return ViewHolder(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSubscribeProxy(subscribeProxy: SingleSubscribeProxy<Instance>) {
|
fun setSubscribeProxy(subscribeProxy: SingleSubscribeProxy<Instance>) {
|
||||||
subscribeProxy.subscribe(
|
subscribeProxy.subscribe(
|
||||||
@ -60,6 +40,6 @@ class FooterDrawerItem : AbstractDrawerItem<FooterDrawerItem, FooterDrawerItem.V
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder internal constructor(internal val view: View): RecyclerView.ViewHolder(view) {
|
class ViewHolder internal constructor(internal val view: View): RecyclerView.ViewHolder(view) {
|
||||||
internal val instanceData: TextView = view.findViewById(R.id.instanceData)
|
internal val instanceData = view.instanceData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,346 +0,0 @@
|
|||||||
package net.accelf.yuito;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.lifecycle.Lifecycle;
|
|
||||||
|
|
||||||
import com.keylesspalace.tusky.AccountActivity;
|
|
||||||
import com.keylesspalace.tusky.BottomSheetActivity;
|
|
||||||
import com.keylesspalace.tusky.PostLookupFallbackBehavior;
|
|
||||||
import com.keylesspalace.tusky.R;
|
|
||||||
import com.keylesspalace.tusky.ViewTagActivity;
|
|
||||||
import com.keylesspalace.tusky.appstore.DrawerFooterClickedEvent;
|
|
||||||
import com.keylesspalace.tusky.appstore.Event;
|
|
||||||
import com.keylesspalace.tusky.appstore.EventHub;
|
|
||||||
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent;
|
|
||||||
import com.keylesspalace.tusky.appstore.QuickReplyEvent;
|
|
||||||
import com.keylesspalace.tusky.components.compose.ComposeActivity;
|
|
||||||
import com.keylesspalace.tusky.components.compose.view.TootButton;
|
|
||||||
import com.keylesspalace.tusky.db.AccountEntity;
|
|
||||||
import com.keylesspalace.tusky.db.AccountManager;
|
|
||||||
import com.keylesspalace.tusky.entity.Announcement;
|
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
|
||||||
import com.keylesspalace.tusky.interfaces.LinkListener;
|
|
||||||
import com.keylesspalace.tusky.util.LinkHelper;
|
|
||||||
import com.keylesspalace.tusky.util.ListUtils;
|
|
||||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
|
|
||||||
import static com.keylesspalace.tusky.components.compose.ComposeActivity.CAN_USE_UNLEAKABLE;
|
|
||||||
import static com.keylesspalace.tusky.components.compose.ComposeActivity.PREF_DEFAULT_TAG;
|
|
||||||
import static com.keylesspalace.tusky.components.compose.ComposeActivity.PREF_USE_DEFAULT_TAG;
|
|
||||||
import static com.uber.autodispose.AutoDispose.autoDisposable;
|
|
||||||
import static com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from;
|
|
||||||
|
|
||||||
public class QuickTootHelper {
|
|
||||||
|
|
||||||
private Context context;
|
|
||||||
private TextView quickReplyInfo;
|
|
||||||
private TextView defaultTagInfo;
|
|
||||||
private ImageView visibilityButton;
|
|
||||||
private EditText tootEditText;
|
|
||||||
private ImageButton openAnnouncementsButton;
|
|
||||||
private TextView announcementsText;
|
|
||||||
private ImageButton prevButton;
|
|
||||||
private ImageButton nextButton;
|
|
||||||
private TextView announcementsCountText;
|
|
||||||
private TootButton quickTootButton;
|
|
||||||
|
|
||||||
private SharedPreferences defPrefs;
|
|
||||||
private String domain;
|
|
||||||
private String loggedInUsername;
|
|
||||||
private EventHub eventHub;
|
|
||||||
private LinkListener listener;
|
|
||||||
|
|
||||||
private Status inReplyTo;
|
|
||||||
private boolean open = false;
|
|
||||||
private int index = 0;
|
|
||||||
private List<Announcement> announcements;
|
|
||||||
|
|
||||||
private static final String PREF_CURRENT_VISIBILITY = "current_visibility";
|
|
||||||
|
|
||||||
public QuickTootHelper(BottomSheetActivity activity, ConstraintLayout root, AccountManager accountManager, EventHub eventHub) {
|
|
||||||
context = root.getContext();
|
|
||||||
quickReplyInfo = root.findViewById(R.id.quick_reply_info);
|
|
||||||
defaultTagInfo = root.findViewById(R.id.default_tag_info);
|
|
||||||
visibilityButton = root.findViewById(R.id.visibility_button);
|
|
||||||
tootEditText = root.findViewById(R.id.toot_edit_text);
|
|
||||||
openAnnouncementsButton = root.findViewById(R.id.button_open_announcements);
|
|
||||||
announcementsText = root.findViewById(R.id.text_view_announcements);
|
|
||||||
prevButton = root.findViewById(R.id.button_prev_announcements);
|
|
||||||
nextButton = root.findViewById(R.id.button_next_announcements);
|
|
||||||
announcementsCountText = root.findViewById(R.id.text_view_announcements_count);
|
|
||||||
quickTootButton = root.findViewById(R.id.toot_button);
|
|
||||||
|
|
||||||
context = root.getContext();
|
|
||||||
this.defPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
AccountEntity account = accountManager.getActiveAccount();
|
|
||||||
if (account != null) {
|
|
||||||
domain = account.getDomain();
|
|
||||||
loggedInUsername = account.getUsername();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.eventHub = eventHub;
|
|
||||||
|
|
||||||
updateVisibilityButton();
|
|
||||||
updateDefaultTagInfo();
|
|
||||||
visibilityButton.setOnClickListener(v -> setNextVisibility());
|
|
||||||
quickTootButton.setOnClickListener(v -> quickToot());
|
|
||||||
|
|
||||||
listener = new LinkListener() {
|
|
||||||
@Override
|
|
||||||
public void onViewTag(String tag) {
|
|
||||||
context.startActivity(ViewTagActivity.getIntent(context, tag));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewAccount(String id) {
|
|
||||||
context.startActivity(AccountActivity.getIntent(context, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewUrl(String url, String text) {
|
|
||||||
activity.viewUrl(url, PostLookupFallbackBehavior.OPEN_IN_BROWSER, text);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
activity.mastodonApi.listAnnouncements()
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.as(autoDisposable(from(activity, Lifecycle.Event.ON_DESTROY)))
|
|
||||||
.subscribe(
|
|
||||||
a -> {
|
|
||||||
announcements = a;
|
|
||||||
updateAnnouncements();
|
|
||||||
},
|
|
||||||
Throwable::printStackTrace
|
|
||||||
);
|
|
||||||
updateAnnouncements();
|
|
||||||
openAnnouncementsButton.setOnClickListener(v -> toggleOpenAnnouncements());
|
|
||||||
announcementsText.setOnClickListener(v -> toggleOpenAnnouncements());
|
|
||||||
prevButton.setOnClickListener(v -> prevAnnouncement());
|
|
||||||
nextButton.setOnClickListener(v -> nextAnnouncement());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void composeButton() {
|
|
||||||
if (tootEditText.getText().length() == 0 && inReplyTo == null) {
|
|
||||||
context.startActivity(getComposeIntent(context, true, false));
|
|
||||||
} else {
|
|
||||||
startComposeWithQuickComposeData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleEvent(Event event) {
|
|
||||||
if (event instanceof QuickReplyEvent) {
|
|
||||||
reply(((QuickReplyEvent) event).getStatus());
|
|
||||||
} else if (event instanceof PreferenceChangedEvent) {
|
|
||||||
switch (((PreferenceChangedEvent) event).getPreferenceKey()) {
|
|
||||||
case PREF_CURRENT_VISIBILITY: {
|
|
||||||
updateVisibilityButton();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PREF_DEFAULT_TAG:
|
|
||||||
case PREF_USE_DEFAULT_TAG: {
|
|
||||||
updateDefaultTagInfo();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (event instanceof DrawerFooterClickedEvent) {
|
|
||||||
tootEditText.setText("にゃーん");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reply(Status status) {
|
|
||||||
inReplyTo = status;
|
|
||||||
updateQuickReplyInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startComposeWithQuickComposeData() {
|
|
||||||
Intent intent = getComposeIntent(context, false, false);
|
|
||||||
resetQuickCompose();
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void quickToot() {
|
|
||||||
if (tootEditText.getText().toString().length() > 0) {
|
|
||||||
Intent intent = getComposeIntent(context, false, true);
|
|
||||||
resetQuickCompose();
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Intent getComposeIntent(Context context, boolean onlyVisibility, boolean tootRightNow) {
|
|
||||||
ComposeActivity.ComposeOptions options = new ComposeActivity.ComposeOptions();
|
|
||||||
options.setVisibility(getCurrentVisibility());
|
|
||||||
if (onlyVisibility) {
|
|
||||||
return ComposeActivity.startIntent(context, options);
|
|
||||||
}
|
|
||||||
options.setTootText(tootEditText.getText().toString());
|
|
||||||
options.setTootRightNow(tootRightNow);
|
|
||||||
|
|
||||||
if (inReplyTo != null) {
|
|
||||||
Status.Mention[] mentions = inReplyTo.getMentions();
|
|
||||||
Set<String> mentionedUsernames = new LinkedHashSet<>();
|
|
||||||
mentionedUsernames.add(inReplyTo.getAccount().getUsername());
|
|
||||||
for (Status.Mention mention : mentions) {
|
|
||||||
mentionedUsernames.add(mention.getUsername());
|
|
||||||
}
|
|
||||||
mentionedUsernames.remove(loggedInUsername);
|
|
||||||
|
|
||||||
options.setInReplyToId(inReplyTo.getId());
|
|
||||||
options.setContentWarning(inReplyTo.getSpoilerText());
|
|
||||||
options.setMentionedUsernames(mentionedUsernames);
|
|
||||||
options.setReplyingStatusAuthor(inReplyTo.getAccount().getLocalUsername());
|
|
||||||
options.setReplyingStatusContent(inReplyTo.getContent().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return ComposeActivity.startIntent(context, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetQuickCompose() {
|
|
||||||
tootEditText.getText().clear();
|
|
||||||
inReplyTo = null;
|
|
||||||
updateQuickReplyInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateQuickReplyInfo() {
|
|
||||||
if (inReplyTo != null) {
|
|
||||||
quickReplyInfo.setText(String.format("Reply to : %s", inReplyTo.getAccount().getUsername()));
|
|
||||||
} else {
|
|
||||||
quickReplyInfo.setText("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDefaultTagInfo() {
|
|
||||||
boolean useDefaultTag = defPrefs.getBoolean(PREF_USE_DEFAULT_TAG, false);
|
|
||||||
String defaultText = defPrefs.getString(PREF_DEFAULT_TAG, "");
|
|
||||||
if (useDefaultTag) {
|
|
||||||
defaultTagInfo.setText(String.format("%s : %s", context.getString(R.string.hint_default_text), defaultText));
|
|
||||||
defaultTagInfo.setTextColor(ThemeUtils.getColor(context, R.attr.colorInfo));
|
|
||||||
} else {
|
|
||||||
defaultTagInfo.setText(String.format("%s inactive", context.getString(R.string.hint_default_text)));
|
|
||||||
defaultTagInfo.setTextColor(ThemeUtils.getColor(context, android.R.attr.textColorTertiary));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Status.Visibility getCurrentVisibility() {
|
|
||||||
Status.Visibility visibility = Status.Visibility.byNum(defPrefs.getInt(PREF_CURRENT_VISIBILITY, Status.Visibility.PUBLIC.getNum()));
|
|
||||||
if (!Arrays.asList(CAN_USE_UNLEAKABLE)
|
|
||||||
.contains(domain) && visibility == Status.Visibility.UNLEAKABLE) {
|
|
||||||
defPrefs.edit()
|
|
||||||
.putInt(PREF_CURRENT_VISIBILITY, Status.Visibility.PUBLIC.getNum())
|
|
||||||
.apply();
|
|
||||||
eventHub.dispatch(new PreferenceChangedEvent(PREF_CURRENT_VISIBILITY));
|
|
||||||
return Status.Visibility.PUBLIC;
|
|
||||||
}
|
|
||||||
return visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateVisibilityButton() {
|
|
||||||
Status.Visibility visibility = getCurrentVisibility();
|
|
||||||
quickTootButton.setStatusVisibility(visibility);
|
|
||||||
switch (visibility) {
|
|
||||||
case PUBLIC:
|
|
||||||
visibilityButton.setImageResource(R.drawable.ic_public_24dp);
|
|
||||||
break;
|
|
||||||
case UNLISTED:
|
|
||||||
visibilityButton.setImageResource(R.drawable.ic_lock_open_24dp);
|
|
||||||
break;
|
|
||||||
case PRIVATE:
|
|
||||||
visibilityButton.setImageResource(R.drawable.ic_lock_outline_24dp);
|
|
||||||
break;
|
|
||||||
case UNLEAKABLE:
|
|
||||||
visibilityButton.setImageResource(R.drawable.ic_low_vision_24dp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setNextVisibility() {
|
|
||||||
Status.Visibility visibility = getCurrentVisibility();
|
|
||||||
switch (visibility) {
|
|
||||||
case PUBLIC:
|
|
||||||
visibility = Status.Visibility.UNLISTED;
|
|
||||||
break;
|
|
||||||
case UNLISTED:
|
|
||||||
visibility = Status.Visibility.PRIVATE;
|
|
||||||
break;
|
|
||||||
case PRIVATE:
|
|
||||||
if (Arrays.asList(CAN_USE_UNLEAKABLE).contains(domain)) {
|
|
||||||
visibility = Status.Visibility.UNLEAKABLE;
|
|
||||||
} else {
|
|
||||||
visibility = Status.Visibility.PUBLIC;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UNLEAKABLE:
|
|
||||||
case UNKNOWN:
|
|
||||||
visibility = Status.Visibility.PUBLIC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
defPrefs.edit()
|
|
||||||
.putInt(PREF_CURRENT_VISIBILITY, visibility.getNum())
|
|
||||||
.apply();
|
|
||||||
eventHub.dispatch(new PreferenceChangedEvent(PREF_CURRENT_VISIBILITY));
|
|
||||||
updateVisibilityButton();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateAnnouncements() {
|
|
||||||
if (ListUtils.isEmpty(announcements)) {
|
|
||||||
openAnnouncementsButton.setVisibility(View.GONE);
|
|
||||||
announcementsText.setVisibility(View.GONE);
|
|
||||||
announcementsCountText.setVisibility(View.GONE);
|
|
||||||
prevButton.setVisibility(View.GONE);
|
|
||||||
nextButton.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
openAnnouncementsButton.setVisibility(View.VISIBLE);
|
|
||||||
announcementsText.setVisibility(View.VISIBLE);
|
|
||||||
announcementsCountText.setVisibility(View.VISIBLE);
|
|
||||||
if (open) {
|
|
||||||
prevButton.setVisibility(View.VISIBLE);
|
|
||||||
nextButton.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
prevButton.setVisibility(View.GONE);
|
|
||||||
nextButton.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
openAnnouncementsButton.setImageDrawable(ContextCompat.getDrawable(context, open ? R.drawable.ic_arrow_drop_down : R.drawable.ic_arrow_drop_up));
|
|
||||||
announcementsText.setSingleLine(!open);
|
|
||||||
announcementsCountText.setText(String.format(Locale.getDefault(), "(%d/%d)", index + 1, announcements.size()));
|
|
||||||
Announcement announcement = announcements.get(index);
|
|
||||||
LinkHelper.setClickableText(announcementsText, announcement.getContent(), announcement.getMentions(), listener, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleOpenAnnouncements() {
|
|
||||||
open = !open;
|
|
||||||
updateAnnouncements();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prevAnnouncement() {
|
|
||||||
if (index > 0) {
|
|
||||||
index--;
|
|
||||||
updateAnnouncements();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void nextAnnouncement() {
|
|
||||||
if (index < announcements.size() - 1) {
|
|
||||||
index++;
|
|
||||||
updateAnnouncements();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
98
app/src/main/java/net/accelf/yuito/QuickTootView.kt
Normal file
98
app/src/main/java/net/accelf/yuito/QuickTootView.kt
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package net.accelf.yuito
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.observe
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.keylesspalace.tusky.R
|
||||||
|
import com.keylesspalace.tusky.appstore.Event
|
||||||
|
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
|
||||||
|
import com.keylesspalace.tusky.appstore.QuickReplyEvent
|
||||||
|
import com.keylesspalace.tusky.components.compose.ComposeActivity
|
||||||
|
import com.keylesspalace.tusky.components.compose.ComposeActivity.Companion.PREF_DEFAULT_TAG
|
||||||
|
import com.keylesspalace.tusky.components.compose.ComposeActivity.Companion.PREF_USE_DEFAULT_TAG
|
||||||
|
import com.keylesspalace.tusky.util.ThemeUtils
|
||||||
|
import kotlinx.android.synthetic.main.view_quick_toot.view.*
|
||||||
|
|
||||||
|
class QuickTootView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
|
ConstraintLayout(context, attrs) {
|
||||||
|
|
||||||
|
private val preference by lazy { PreferenceManager.getDefaultSharedPreferences(context) }
|
||||||
|
|
||||||
|
private lateinit var viewModel: QuickTootViewModel
|
||||||
|
|
||||||
|
init {
|
||||||
|
LayoutInflater.from(context).inflate(R.layout.view_quick_toot, this, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun attachViewModel(viewModel: QuickTootViewModel, owner: LifecycleOwner) {
|
||||||
|
this.viewModel = viewModel
|
||||||
|
|
||||||
|
buttonVisibility.attachViewModel(viewModel, owner)
|
||||||
|
|
||||||
|
viewModel.content.observe(owner) {
|
||||||
|
if (editTextContent.text.toString() != it) {
|
||||||
|
editTextContent.setText(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
editTextContent.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
viewModel.content.value = s.toString()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.inReplyTo.observe(owner) {
|
||||||
|
textQuickReply.text = it?.let { "Reply to ${it.account.username}" } ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.defaultTag.observe(owner) {
|
||||||
|
textDefaultTag.text = it?.let { "${context.getString(R.string.hint_default_text)} : $it" }
|
||||||
|
?: "${context.getString(R.string.hint_default_text)} inactive"
|
||||||
|
textDefaultTag.setTextColor(ThemeUtils.getColor(context, it?.let { R.attr.colorInfo }
|
||||||
|
?: android.R.attr.textColorTertiary))
|
||||||
|
}
|
||||||
|
syncDefaultTag()
|
||||||
|
|
||||||
|
viewModel.visibility.observe(owner) {
|
||||||
|
buttonToot.setStatusVisibility(it)
|
||||||
|
}
|
||||||
|
buttonToot.setOnClickListener {
|
||||||
|
val intent = ComposeActivity.startIntent(it.context, viewModel.composeOptions(true))
|
||||||
|
viewModel.reset()
|
||||||
|
it.context.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun syncDefaultTag() {
|
||||||
|
viewModel.defaultTag.value = if (preference.getBoolean(PREF_USE_DEFAULT_TAG, false)) {
|
||||||
|
preference.getString(PREF_DEFAULT_TAG, null)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onFABClicked(view: View) {
|
||||||
|
val intent = ComposeActivity.startIntent(view.context, viewModel.composeOptions(false))
|
||||||
|
viewModel.reset()
|
||||||
|
view.context.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleEvent(event: Event?) {
|
||||||
|
when (event) {
|
||||||
|
is QuickReplyEvent -> viewModel.reply(event)
|
||||||
|
is PreferenceChangedEvent -> {
|
||||||
|
if (event.preferenceKey in arrayOf(PREF_DEFAULT_TAG, PREF_USE_DEFAULT_TAG)) {
|
||||||
|
syncDefaultTag()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
91
app/src/main/java/net/accelf/yuito/QuickTootViewModel.kt
Normal file
91
app/src/main/java/net/accelf/yuito/QuickTootViewModel.kt
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package net.accelf.yuito
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.keylesspalace.tusky.appstore.QuickReplyEvent
|
||||||
|
import com.keylesspalace.tusky.components.compose.ComposeActivity
|
||||||
|
import com.keylesspalace.tusky.components.compose.ComposeActivity.Companion.CAN_USE_UNLEAKABLE
|
||||||
|
import com.keylesspalace.tusky.components.compose.mutableLiveData
|
||||||
|
import com.keylesspalace.tusky.db.AccountManager
|
||||||
|
import com.keylesspalace.tusky.entity.Status
|
||||||
|
import com.keylesspalace.tusky.entity.Status.Visibility
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class QuickTootViewModel @Inject constructor(
|
||||||
|
accountManager: AccountManager
|
||||||
|
): ViewModel() {
|
||||||
|
|
||||||
|
private val account = accountManager.activeAccount!!
|
||||||
|
|
||||||
|
private val unleakableAllowed by lazy { CAN_USE_UNLEAKABLE.contains(account.domain) }
|
||||||
|
|
||||||
|
val content = mutableLiveData("")
|
||||||
|
|
||||||
|
private val visibilityMutable = mutableLiveData(Visibility.PUBLIC)
|
||||||
|
val visibility: LiveData<Visibility> = visibilityMutable
|
||||||
|
private var stashedVisibility: Visibility? = null
|
||||||
|
|
||||||
|
private val inReplyToMutable: MutableLiveData<Status?> = mutableLiveData(null)
|
||||||
|
val inReplyTo: LiveData<Status?> = inReplyToMutable
|
||||||
|
|
||||||
|
val defaultTag: MutableLiveData<String?> = mutableLiveData(null)
|
||||||
|
|
||||||
|
fun setInitialVisibility(num: Int) {
|
||||||
|
visibilityMutable.value = (Visibility.byNum(num)
|
||||||
|
.takeUnless { it == Visibility.UNKNOWN }
|
||||||
|
?: account.defaultPostPrivacy)
|
||||||
|
.takeUnless { it == Visibility.UNLEAKABLE && unleakableAllowed }
|
||||||
|
?: Visibility.PRIVATE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stepVisibility() {
|
||||||
|
visibilityMutable.value = when (visibility.value) {
|
||||||
|
Visibility.PUBLIC -> Visibility.UNLISTED
|
||||||
|
Visibility.UNLISTED -> Visibility.PRIVATE
|
||||||
|
Visibility.PRIVATE -> when (unleakableAllowed) {
|
||||||
|
true -> Visibility.UNLEAKABLE
|
||||||
|
false -> Visibility.PUBLIC
|
||||||
|
}
|
||||||
|
Visibility.UNLEAKABLE -> Visibility.PUBLIC
|
||||||
|
else -> Visibility.PUBLIC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun overrideVisibility(overrideTo: Visibility) {
|
||||||
|
stashedVisibility = visibility.value
|
||||||
|
visibilityMutable.value = overrideTo
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reply(event: QuickReplyEvent) {
|
||||||
|
val status = event.status.actionableStatus
|
||||||
|
inReplyToMutable.value = status
|
||||||
|
overrideVisibility(status.visibility)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun composeOptions(tootRightNow: Boolean): ComposeActivity.ComposeOptions {
|
||||||
|
return ComposeActivity.ComposeOptions(
|
||||||
|
tootText = content.value,
|
||||||
|
mentionedUsernames = inReplyTo.value
|
||||||
|
?.let {
|
||||||
|
linkedSetOf(it.account.username, *(it.mentions.map { mention -> mention.username }.toTypedArray()))
|
||||||
|
.apply { remove(account.username) }
|
||||||
|
},
|
||||||
|
inReplyToId = inReplyTo.value?.id,
|
||||||
|
visibility = visibility.value,
|
||||||
|
contentWarning = inReplyTo.value?.spoilerText,
|
||||||
|
replyingStatusAuthor = inReplyTo.value?.account?.name,
|
||||||
|
replyingStatusContent = inReplyTo.value?.content?.toString(),
|
||||||
|
tootRightNow = tootRightNow
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reset() {
|
||||||
|
content.value = ""
|
||||||
|
inReplyToMutable.value = null
|
||||||
|
stashedVisibility?.let {
|
||||||
|
visibilityMutable.value = stashedVisibility
|
||||||
|
stashedVisibility = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
app/src/main/java/net/accelf/yuito/VisibilityToggleButton.kt
Normal file
59
app/src/main/java/net/accelf/yuito/VisibilityToggleButton.kt
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package net.accelf.yuito
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.observe
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.keylesspalace.tusky.R
|
||||||
|
import com.keylesspalace.tusky.entity.Status.Visibility
|
||||||
|
|
||||||
|
class VisibilityToggleButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
|
AppCompatImageView(context, attrs) {
|
||||||
|
|
||||||
|
private val preference by lazy { PreferenceManager.getDefaultSharedPreferences(context) }
|
||||||
|
|
||||||
|
init {
|
||||||
|
isClickable = true
|
||||||
|
isFocusable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun attachViewModel(viewModel: QuickTootViewModel, owner: LifecycleOwner) {
|
||||||
|
viewModel.visibility.observe(owner, ::updateVisibility)
|
||||||
|
viewModel.setInitialVisibility(preference.getInt(PREF_CURRENT_VISIBILITY, Visibility.UNKNOWN.num))
|
||||||
|
setOnClickListener{ viewModel.stepVisibility() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateVisibility(visibility: Visibility) {
|
||||||
|
setImageResource(
|
||||||
|
when (visibility) {
|
||||||
|
Visibility.PUBLIC -> R.drawable.ic_public_24dp
|
||||||
|
Visibility.UNLISTED -> R.drawable.ic_lock_open_24dp
|
||||||
|
Visibility.PRIVATE -> R.drawable.ic_lock_outline_24dp
|
||||||
|
Visibility.DIRECT -> R.drawable.ic_email_24dp
|
||||||
|
Visibility.UNLEAKABLE -> R.drawable.ic_low_vision_24dp
|
||||||
|
else -> R.drawable.ic_lock_open_24dp
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
contentDescription = context.getString(
|
||||||
|
when (visibility) {
|
||||||
|
Visibility.UNKNOWN -> R.string.visibility_unknown
|
||||||
|
Visibility.PUBLIC -> R.string.visibility_public
|
||||||
|
Visibility.UNLISTED -> R.string.visibility_unlisted
|
||||||
|
Visibility.PRIVATE -> R.string.visibility_private
|
||||||
|
Visibility.DIRECT -> R.string.visibility_direct
|
||||||
|
Visibility.UNLEAKABLE -> R.string.visibility_unleakable
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
preference.edit()
|
||||||
|
.putInt(PREF_CURRENT_VISIBILITY, visibility.num)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val PREF_CURRENT_VISIBILITY = "current_visibility"
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M7,10l5,5 5,-5z"/>
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M7,14l5,-5 5,5z"/>
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/>
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
|
|
||||||
</vector>
|
|
@ -81,9 +81,8 @@
|
|||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<include
|
<net.accelf.yuito.QuickTootView
|
||||||
android:id="@+id/quickTootContainer"
|
android:id="@+id/viewQuickToot"
|
||||||
layout="@layout/view_quick_toot"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0" />
|
android:layout_weight="0" />
|
||||||
|
@ -35,9 +35,8 @@
|
|||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<include
|
<net.accelf.yuito.QuickTootView
|
||||||
android:id="@+id/quick_toot_container"
|
android:id="@+id/viewQuickToot"
|
||||||
layout="@layout/view_quick_toot"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0" />
|
android:layout_weight="0" />
|
||||||
|
@ -35,9 +35,8 @@
|
|||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<include
|
<net.accelf.yuito.QuickTootView
|
||||||
android:id="@+id/quick_toot_container"
|
android:id="@+id/viewQuickToot"
|
||||||
layout="@layout/view_quick_toot"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0"/>
|
android:layout_weight="0"/>
|
||||||
|
@ -25,9 +25,8 @@
|
|||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<include
|
<net.accelf.yuito.QuickTootView
|
||||||
android:id="@+id/quick_toot_container"
|
android:id="@+id/viewQuickToot"
|
||||||
layout="@layout/view_quick_toot"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0" />
|
android:layout_weight="0" />
|
||||||
|
@ -5,101 +5,32 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_open_announcements"
|
|
||||||
style="@style/TuskyImageButton"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:contentDescription="@string/action_more"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/quick_reply_info"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:srcCompat="@drawable/ic_arrow_drop_up" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_view_announcements"
|
android:id="@+id/textQuickReply"
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/quick_reply_info"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/button_open_announcements" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_prev_announcements"
|
|
||||||
style="@style/TuskyImageButton"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:contentDescription="@string/action_more"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/text_view_announcements_count"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/button_next_announcements"
|
|
||||||
app:srcCompat="@drawable/ic_chevron_left" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_next_announcements"
|
|
||||||
style="@style/TuskyImageButton"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:contentDescription="@string/action_more"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/text_view_announcements_count"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:srcCompat="@drawable/ic_chevron_right" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/text_view_announcements_count"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4dp"
|
app:layout_constraintBottom_toTopOf="@id/editTextContent"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/quick_reply_info"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/quick_reply_info"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/toot_edit_text"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/default_tag_info"
|
android:id="@+id/textDefaultTag"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintBottom_toTopOf="@id/toot_edit_text"
|
app:layout_constraintBottom_toTopOf="@id/editTextContent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
<ImageView
|
<net.accelf.yuito.VisibilityToggleButton
|
||||||
android:id="@+id/visibility_button"
|
android:id="@+id/buttonVisibility"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="12dp"
|
android:layout_marginEnd="12dp"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
android:clickable="true"
|
|
||||||
android:contentDescription="@null"
|
|
||||||
android:focusable="true"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
app:srcCompat="@drawable/ic_public_24dp" />
|
|
||||||
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/toot_edit_text"
|
android:id="@+id/editTextContent"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:autofillHints=""
|
android:autofillHints=""
|
||||||
@ -107,11 +38,11 @@
|
|||||||
android:inputType="textMultiLine"
|
android:inputType="textMultiLine"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@id/toot_button"
|
app:layout_constraintEnd_toStartOf="@id/buttonToot"
|
||||||
app:layout_constraintStart_toEndOf="@id/visibility_button" />
|
app:layout_constraintStart_toEndOf="@id/buttonVisibility" />
|
||||||
|
|
||||||
<com.keylesspalace.tusky.components.compose.view.TootButton
|
<com.keylesspalace.tusky.components.compose.view.TootButton
|
||||||
android:id="@+id/toot_button"
|
android:id="@+id/buttonToot"
|
||||||
style="@style/TuskyButton"
|
style="@style/TuskyButton"
|
||||||
android:layout_width="@dimen/toot_button_width"
|
android:layout_width="@dimen/toot_button_width"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -224,6 +224,7 @@
|
|||||||
<string name="visibility_private">Followers-Only: Post to followers only</string>
|
<string name="visibility_private">Followers-Only: Post to followers only</string>
|
||||||
<string name="visibility_unleakable">Unleakable: Post to followed user by you only.</string>
|
<string name="visibility_unleakable">Unleakable: Post to followed user by you only.</string>
|
||||||
<string name="visibility_direct">Direct: Post to mentioned users only</string>
|
<string name="visibility_direct">Direct: Post to mentioned users only</string>
|
||||||
|
<string name="visibility_unknown">Unknown visibility</string>
|
||||||
|
|
||||||
<string name="pref_title_edit_notification_settings">Notifications</string>
|
<string name="pref_title_edit_notification_settings">Notifications</string>
|
||||||
<string name="pref_title_notifications_enabled">Notifications</string>
|
<string name="pref_title_notifications_enabled">Notifications</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user