Finished (?) tutorials
This commit is contained in:
parent
40a3a9ba26
commit
9ebeda23a3
@ -171,7 +171,7 @@ dependencies {
|
||||
implementation 'androidx.hilt:hilt-common:1.2.0'
|
||||
implementation 'androidx.hilt:hilt-work:1.2.0'
|
||||
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.1'
|
||||
|
||||
/**
|
||||
* AndroidX dependencies:
|
||||
|
@ -12,7 +12,10 @@ import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
@ -34,6 +37,8 @@ import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||
import com.bumptech.glide.Glide
|
||||
import com.getkeepsafe.taptargetview.TapTarget
|
||||
import com.getkeepsafe.taptargetview.TapTargetView
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.google.android.material.navigation.NavigationBarView
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
@ -50,6 +55,7 @@ import com.mikepenz.materialdrawer.model.interfaces.nameText
|
||||
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
|
||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
||||
import com.mikepenz.materialdrawer.widget.AccountHeaderView
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.ligi.tracedroid.sending.sendTraceDroidStackTracesIfExist
|
||||
import org.pixeldroid.app.R
|
||||
@ -66,6 +72,7 @@ import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedPostsFragment
|
||||
import org.pixeldroid.app.profile.ProfileActivity
|
||||
import org.pixeldroid.app.searchDiscover.SearchDiscoverFragment
|
||||
import org.pixeldroid.app.settings.SettingsActivity
|
||||
import org.pixeldroid.app.settings.SettingsActivity.SettingsFragment
|
||||
import org.pixeldroid.app.settings.TutorialSettingsDialog.Companion.START_TUTORIAL
|
||||
import org.pixeldroid.app.utils.BaseActivity
|
||||
import org.pixeldroid.app.utils.Tab
|
||||
@ -88,6 +95,7 @@ import java.time.Instant
|
||||
|
||||
class MainActivity : BaseActivity() {
|
||||
|
||||
private lateinit var tabStored: List<Tab>
|
||||
private lateinit var header: AccountHeaderView
|
||||
private var user: UserDatabaseEntity? = null
|
||||
|
||||
@ -128,13 +136,12 @@ class MainActivity : BaseActivity() {
|
||||
setupTabs()
|
||||
|
||||
val showNotification: Boolean = intent.getBooleanExtra(SHOW_NOTIFICATION_TAG, false)
|
||||
|
||||
val showTutorial: Int = intent.getIntExtra(START_TUTORIAL, -1)
|
||||
|
||||
if(showNotification){
|
||||
binding.viewPager.currentItem = 3
|
||||
} else if(showTutorial > 0) {
|
||||
|
||||
} else if(showTutorial >= 0) {
|
||||
showTutorial(showTutorial)
|
||||
}
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(applicationContext,
|
||||
@ -147,6 +154,216 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showTutorial(showTutorial: Int) {
|
||||
when(showTutorial){
|
||||
0 -> tutorialOnTabs(Tab.HOME_FEED)
|
||||
1 -> tutorialOnTabs(Tab.CREATE_FEED)
|
||||
2 -> dmTutorial()
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
|
||||
private fun tutorialOnTabs(tab: Tab) {
|
||||
val target = (binding.tabs as? NavigationBarView)?.let{ findTab(it, tab) } ?: return //TODO tablet landscape not supported
|
||||
|
||||
when(tab){
|
||||
Tab.HOME_FEED -> homeTutorial(target)
|
||||
Tab.SEARCH_DISCOVER_FEED -> homeTutorialSearch(target)
|
||||
Tab.PUBLIC_FEED -> homeTutorialPublic(target)
|
||||
Tab.NOTIFICATIONS_FEED -> homeTutorialNotifications(target)
|
||||
Tab.CREATE_FEED -> createTutorial(target)
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
|
||||
private fun dmTutorial(){
|
||||
val target = (binding.tabs as? NavigationBarView)?.let{ findTab(it, Tab.DIRECT_MESSAGES) } ?: binding.mainDrawerButton ?: return //TODO tablet landscape not supported
|
||||
|
||||
if(target is ImageButton) {
|
||||
TapTargetView.showFor(
|
||||
this@MainActivity,
|
||||
TapTarget.forView(target, "First open the drawer menu")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
target.performClick()
|
||||
dmTutorial2(null)
|
||||
}
|
||||
})
|
||||
} else dmTutorial2(target)
|
||||
}
|
||||
private fun findViewWithText(root: ViewGroup, text: String?): View? {
|
||||
for (i in 0 until root.childCount) {
|
||||
val child = root.getChildAt(i)
|
||||
if (child is TextView) {
|
||||
if (child.text.toString().contains(text!!)) {
|
||||
return child
|
||||
}
|
||||
}
|
||||
if (child is ViewGroup) {
|
||||
val result = findViewWithText(child, text)
|
||||
if (result != null) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
private fun dmTutorial2(target: View?) {
|
||||
lifecycleScope.launch {
|
||||
var target = target ?: findViewWithText(binding.drawer as ViewGroup, getString(R.string.direct_messages))
|
||||
while (target == null) {
|
||||
target = findViewWithText(binding.drawer as ViewGroup, getString(R.string.direct_messages))
|
||||
delay(100)
|
||||
}
|
||||
TapTargetView.showFor(
|
||||
this@MainActivity,
|
||||
TapTarget.forView(target, "Direct Messages",
|
||||
"Send messages to other Pixelfed users: on your instance or on others")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
target.performClick()
|
||||
//tutorialOnTabs(Tab.NOTIFICATIONS_FEED)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun homeTutorialPublic(target: View) {
|
||||
TapTargetView.showFor(
|
||||
this@MainActivity,
|
||||
TapTarget.forView(target, "Public feed",
|
||||
"This feed contains all the posts on your instance! Maybe you can find some interesting posts here :)")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
target.performClick()
|
||||
tutorialOnTabs(Tab.NOTIFICATIONS_FEED)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun homeTutorialNotifications(target: View) {
|
||||
TapTargetView.showFor(
|
||||
this@MainActivity,
|
||||
TapTarget.forView(target, "Notifications keep you in the loop",
|
||||
"PixelDroid will also send you push notifications to make sure you don't miss anything!")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
target.performClick()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun homeTutorialSearch(target: View) {
|
||||
TapTargetView.showFor(
|
||||
this@MainActivity,
|
||||
TapTarget.forView(target, "This tab can get you started finding interesting accounts to follow",
|
||||
"Maybe take a look at the trending posts \uD83D\uDCC8, or discover some random posts every day to broaden your horizons and find the real gems! \uD83D\uDC8E")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
target.performClick()
|
||||
tutorialOnTabs(Tab.PUBLIC_FEED)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun homeTutorial(target: View) {
|
||||
TapTargetView.showFor(
|
||||
this@MainActivity,
|
||||
TapTarget.forView(target, "This is your home feed",
|
||||
"The posts of the people you follow will show up here. No algorithms, just chronological goodness. Only you decide what you want to see!")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
target.performClick()
|
||||
tutorialOnTabs(Tab.SEARCH_DISCOVER_FEED)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun createTutorial(target: View) {
|
||||
TapTargetView.showFor(
|
||||
this@MainActivity,
|
||||
TapTarget.forView(target, "This is where everything begins",
|
||||
"First, let's navigate to the create tab. Click here")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
target.performClick()
|
||||
lifecycleScope.launch {
|
||||
var targetCamera = findViewById<View>(R.id.camera_capture_button)
|
||||
while (targetCamera == null) {
|
||||
targetCamera = findViewById(R.id.camera_capture_button)
|
||||
delay(100)
|
||||
}
|
||||
TapTargetView.showFor(
|
||||
this@MainActivity,
|
||||
TapTarget.forView(targetCamera, "Take a picture to share",
|
||||
"It doesn't have to be very good for now")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60),
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
targetCamera.performClick()
|
||||
}
|
||||
|
||||
override fun onTargetCancel(view: TapTargetView?) {
|
||||
super.onTargetCancel(view)
|
||||
intent.removeExtra(START_TUTORIAL)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun findTab(navBar: NavigationBarView, tab: Tab): View? {
|
||||
val index = tabStored.indexOf(tab)
|
||||
for (i in 0 until navBar.childCount) {
|
||||
val child = navBar.getChildAt(i)
|
||||
if (child is ViewGroup) {
|
||||
return child.getChildAt(index)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private val notificationPermissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { isGranted: Boolean ->
|
||||
@ -521,6 +738,8 @@ class MainActivity : BaseActivity() {
|
||||
)
|
||||
}
|
||||
|
||||
tabStored = tabs
|
||||
|
||||
val bottomNavigationMenu: Menu? = (binding.tabs as? NavigationBarView)?.menu?.apply {
|
||||
clear()
|
||||
}
|
||||
|
@ -5,10 +5,19 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import com.getkeepsafe.taptargetview.TapTarget
|
||||
import com.getkeepsafe.taptargetview.TapTargetView
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.pixeldroid.app.R
|
||||
import org.pixeldroid.app.databinding.ActivityPostCreationBinding
|
||||
import org.pixeldroid.app.settings.TutorialSettingsDialog.Companion.START_TUTORIAL
|
||||
import org.pixeldroid.app.utils.BaseActivity
|
||||
|
||||
class PostCreationActivity : BaseActivity() {
|
||||
@ -58,6 +67,119 @@ class PostCreationActivity : BaseActivity() {
|
||||
supportFragmentManager.findFragmentById(R.id.postCreationContainer) as NavHostFragment
|
||||
navController = navHostFragment.navController
|
||||
navController.setGraph(R.navigation.post_creation_graph)
|
||||
|
||||
lifecycleScope.launch {
|
||||
var targetCamera = findViewById<View>(R.id.toggleStoryPost)
|
||||
while (targetCamera == null) {
|
||||
targetCamera = findViewById(R.id.toggleStoryPost)
|
||||
delay(100)
|
||||
}
|
||||
TapTargetView.showFor(
|
||||
this@PostCreationActivity, // `this` is an Activity
|
||||
TapTarget.forView(targetCamera, "Story or Post?",
|
||||
"Stories are short-lived: engage your followers and keep them coming back for more. Try them out!")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60),
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
findViewById<View>(R.id.buttonStory)?.performClick()
|
||||
TapTargetView.showFor(
|
||||
this@PostCreationActivity, // `this` is an Activity
|
||||
TapTarget.forView(findViewById(R.id.editPhotoButton), "Edit your picture to make it shine ✨",
|
||||
"You can add filters, draw or add text, edit video, and more! \uD83D\uDCF7")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60),
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
findViewById<View>(R.id.editPhotoButton)?.performClick()
|
||||
TapTargetView.showFor(
|
||||
this@PostCreationActivity, // `this` is an Activity
|
||||
TapTarget.forView(findViewById(R.id.tv_caption), "Don't forget to add a media description!",
|
||||
"This helps make Pixelfed accessible to everyone, and also lets you clarify what we're supposed to see in your pretty image ;)")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60),
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
findViewById<View>(R.id.tv_caption)?.performClick()
|
||||
lifecycleScope.launch {
|
||||
delay(1000)
|
||||
var tv_caption = findViewById<View>(R.id.tv_caption)
|
||||
while (tv_caption == null || tv_caption.visibility != View.VISIBLE) {
|
||||
tv_caption = findViewById(R.id.tv_caption)
|
||||
delay(100)
|
||||
}
|
||||
TapTargetView.showFor(
|
||||
this@PostCreationActivity, // `this` is an Activity
|
||||
TapTarget.forView(findViewById(R.id.post_creation_next_button), "Take a picture to share",
|
||||
"It doesn't have to be very good for now")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60),
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
findViewById<View>(R.id.post_creation_next_button)?.performClick()
|
||||
showAccountChooser()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun showAccountChooser() {
|
||||
lifecycleScope.launch {
|
||||
var toolbar = findViewById<View>(R.id.top_bar) as? MaterialToolbar
|
||||
while (toolbar == null) {
|
||||
toolbar = findViewById(R.id.top_bar) as? MaterialToolbar
|
||||
delay(100)
|
||||
}
|
||||
|
||||
TapTargetView.showFor(
|
||||
this@PostCreationActivity, // `this` is an Activity
|
||||
TapTarget.forToolbarMenuItem(
|
||||
toolbar,
|
||||
R.id.action_switch_accounts,
|
||||
"Switch accounts!",
|
||||
"PixelDroid supports using multiple Pixelfed accounts. Make sure you don't post those cat pics on the dog-only instance! \uD83D\uDE31"
|
||||
)
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60),
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
showPostButton()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPostButton() {
|
||||
TapTargetView.showFor(
|
||||
this@PostCreationActivity, // `this` is an Activity
|
||||
TapTarget.forView(findViewById(R.id.post_submission_send_button), "Final stretch! Post that picture",
|
||||
"Have fun sharing your pictures with the world! Click anywhere else to cancel and keep looking around :)")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60),
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
findViewById<View>(R.id.post_creation_next_button)?.performClick()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp() = navController.navigateUp() || super.onSupportNavigateUp()
|
||||
|
@ -37,6 +37,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.pixeldroid.app.databinding.FragmentCameraBinding
|
||||
import org.pixeldroid.app.postCreation.PostCreationActivity
|
||||
import org.pixeldroid.app.settings.TutorialSettingsDialog.Companion.START_TUTORIAL
|
||||
import org.pixeldroid.app.utils.BaseFragment
|
||||
import java.io.File
|
||||
import java.util.concurrent.ExecutorService
|
||||
@ -68,6 +69,7 @@ class CameraFragment : BaseFragment() {
|
||||
|
||||
private var inActivity by Delegates.notNull<Boolean>()
|
||||
private var addToStory by Delegates.notNull<Boolean>()
|
||||
private var tutorial by Delegates.notNull<Int>()
|
||||
|
||||
private var filePermissionDialogLaunched: Boolean = false
|
||||
|
||||
@ -90,6 +92,8 @@ class CameraFragment : BaseFragment() {
|
||||
inActivity = arguments?.getBoolean(CAMERA_ACTIVITY) ?: false
|
||||
addToStory = arguments?.getBoolean(CAMERA_ACTIVITY_STORY) ?: false
|
||||
|
||||
tutorial = arguments?.getInt(START_TUTORIAL) ?: -1
|
||||
|
||||
binding = FragmentCameraBinding.inflate(layoutInflater)
|
||||
|
||||
return binding.root
|
||||
@ -457,6 +461,9 @@ class CameraFragment : BaseFragment() {
|
||||
if(addToStory){
|
||||
intent.putExtra(CAMERA_ACTIVITY_STORY, addToStory)
|
||||
}
|
||||
if(!inActivity && tutorial != -1){
|
||||
intent.putExtra(START_TUTORIAL, true)
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
@ -16,13 +16,17 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.getkeepsafe.taptargetview.TapTarget
|
||||
import com.getkeepsafe.taptargetview.TapTargetView
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.checkbox.MaterialCheckBox
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.pixeldroid.app.R
|
||||
import org.pixeldroid.app.databinding.LayoutTabsArrangeBinding
|
||||
import org.pixeldroid.app.utils.Tab
|
||||
import org.pixeldroid.app.utils.db.AppDatabase
|
||||
import org.pixeldroid.app.utils.db.entities.TabsDatabaseEntity
|
||||
@ -31,20 +35,23 @@ import javax.inject.Inject
|
||||
@AndroidEntryPoint
|
||||
class ArrangeTabsFragment: DialogFragment() {
|
||||
|
||||
private lateinit var binding: LayoutTabsArrangeBinding
|
||||
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
private val model: ArrangeTabsViewModel by viewModels()
|
||||
|
||||
var showTutorial = false
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
|
||||
val inflater: LayoutInflater = requireActivity().layoutInflater
|
||||
val dialogView: View = inflater.inflate(R.layout.layout_tabs_arrange, null)
|
||||
binding = LayoutTabsArrangeBinding.inflate(layoutInflater)
|
||||
|
||||
val itemCount = model.initTabsChecked()
|
||||
model.initTabsButtons(itemCount, requireContext())
|
||||
|
||||
val listFeed: RecyclerView = dialogView.findViewById(R.id.tabs)
|
||||
val listFeed: RecyclerView = binding.tabs
|
||||
val listAdapter = ListViewAdapter(model)
|
||||
listFeed.adapter = listAdapter
|
||||
listFeed.layoutManager = LinearLayoutManager(requireActivity())
|
||||
@ -68,7 +75,7 @@ class ArrangeTabsFragment: DialogFragment() {
|
||||
val dialog = MaterialAlertDialogBuilder(requireContext()).apply {
|
||||
setIcon(R.drawable.outline_bottom_navigation)
|
||||
setTitle(R.string.arrange_tabs_summary)
|
||||
setView(dialogView)
|
||||
setView(binding.root)
|
||||
setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
// Save values into preferences
|
||||
@ -81,10 +88,76 @@ class ArrangeTabsFragment: DialogFragment() {
|
||||
}
|
||||
}
|
||||
}.create()
|
||||
|
||||
if (showTutorial) showTutorial(dialog)
|
||||
return dialog
|
||||
}
|
||||
|
||||
private fun showTutorial(dialog: Dialog){
|
||||
lifecycleScope.launch {
|
||||
var handle = binding.tabs.findViewHolderForLayoutPosition(0)?.itemView?.findViewById<ImageView>(R.id.dragHandle)
|
||||
while (handle == null) {
|
||||
handle = binding.tabs.findViewHolderForLayoutPosition(0)?.itemView?.findViewById(R.id.dragHandle)
|
||||
delay(100)
|
||||
}
|
||||
TapTargetView.showFor(
|
||||
dialog,
|
||||
TapTarget.forView(handle, """Drag this to change the order of the tabs""")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
val checkBox = binding.tabs.findViewHolderForLayoutPosition(0)?.itemView?.findViewById<View>(R.id.checkBox)
|
||||
TapTargetView.showFor(
|
||||
dialog,
|
||||
TapTarget.forView(checkBox, """De-activate tabs you don't need""")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
val index = (Tab.defaultTabs + Tab.otherTabs).size - 1
|
||||
binding.tabs.scrollToPosition(index)
|
||||
lifecycleScope.launch {
|
||||
var hashtag =
|
||||
binding.tabs.findViewHolderForLayoutPosition(index)?.itemView?.findViewById<View>(
|
||||
R.id.textView
|
||||
)
|
||||
while (hashtag == null) {
|
||||
hashtag =
|
||||
binding.tabs.findViewHolderForLayoutPosition(index)?.itemView?.findViewById(
|
||||
R.id.textView
|
||||
)
|
||||
delay(100)
|
||||
}
|
||||
TapTargetView.showFor(
|
||||
dialog,
|
||||
TapTarget.forView(
|
||||
hashtag,
|
||||
"""Create a custom feed with a hashtag you like""",
|
||||
"You really like cats? Try #caturday! Lakes? #lake! Or #hiking? And it will be right there in a tab"
|
||||
)
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
inner class ListViewAdapter(val model: ArrangeTabsViewModel):
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
|
@ -4,35 +4,45 @@ import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.addCallback
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceGroup
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.getkeepsafe.taptargetview.TapTarget
|
||||
import com.getkeepsafe.taptargetview.TapTargetView
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.pixeldroid.app.R
|
||||
import org.pixeldroid.app.databinding.SettingsBinding
|
||||
import org.pixeldroid.app.main.MainActivity
|
||||
import org.pixeldroid.app.utils.setThemeFromPreferences
|
||||
import org.pixeldroid.common.ThemedActivity
|
||||
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SettingsActivity : ThemedActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private var restartMainOnExit = false
|
||||
private lateinit var binding: SettingsBinding
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val binding = SettingsBinding.inflate(layoutInflater)
|
||||
binding = SettingsBinding.inflate(layoutInflater)
|
||||
|
||||
setContentView(binding.root)
|
||||
setSupportActionBar(binding.topBar)
|
||||
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.settings, SettingsFragment())
|
||||
.replace(R.id.settings, SettingsFragment(), "topsettingsfragment")
|
||||
.commit()
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
@ -98,6 +108,36 @@ class SettingsActivity : ThemedActivity(), SharedPreferences.OnSharedPreferenceC
|
||||
super.startActivity(intent)
|
||||
}
|
||||
|
||||
fun customTabsTutorial(){
|
||||
lifecycleScope.launch {
|
||||
var target =
|
||||
(supportFragmentManager.findFragmentByTag("topsettingsfragment") as? SettingsFragment)?.scrollToArrangeTabs()
|
||||
while (target == null) {
|
||||
target = (supportFragmentManager.findFragmentByTag("topsettingsfragment") as? SettingsFragment)?.scrollToArrangeTabs()
|
||||
delay(100)
|
||||
}
|
||||
TapTargetView.showFor(
|
||||
this@SettingsActivity,
|
||||
TapTarget.forView(target, """First open the "Arrange tabs" settings""")
|
||||
.transparentTarget(true)
|
||||
.targetRadius(60), // Specify the target radius (in dp)
|
||||
object : TapTargetView.Listener() {
|
||||
// The listener can listen for regular clicks, long clicks or cancels
|
||||
override fun onTargetClick(view: TapTargetView?) {
|
||||
super.onTargetClick(view) // This call is optional
|
||||
// Perform action for the current target
|
||||
val dialogFragment = ArrangeTabsFragment().apply { showTutorial = true }
|
||||
dialogFragment.setTargetFragment(
|
||||
(supportFragmentManager.findFragmentByTag("topsettingsfragment") as? SettingsFragment),
|
||||
0
|
||||
)
|
||||
dialogFragment.show(supportFragmentManager, "settings_fragment")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SettingsFragment : PreferenceFragmentCompat() {
|
||||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
var dialogFragment: DialogFragment? = null
|
||||
@ -117,6 +157,17 @@ class SettingsActivity : ThemedActivity(), SharedPreferences.OnSharedPreferenceC
|
||||
super.onDisplayPreferenceDialog(preference)
|
||||
}
|
||||
}
|
||||
fun scrollToArrangeTabs(): View? {
|
||||
//Hardcoded because it's too annoying to find!
|
||||
val position = 5
|
||||
|
||||
if (listView != null && position != -1) {
|
||||
listView.post {
|
||||
listView.smoothScrollToPosition(position)
|
||||
}
|
||||
}
|
||||
return listView.findViewHolderForAdapterPosition(position)?.itemView
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.root_preferences, rootKey)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.pixeldroid.app.settings;
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
@ -11,9 +10,12 @@ import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.getkeepsafe.taptargetview.TapTarget
|
||||
import com.getkeepsafe.taptargetview.TapTargetView
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.pixeldroid.app.R
|
||||
import org.pixeldroid.app.main.MainActivity
|
||||
import org.pixeldroid.app.utils.Tab
|
||||
|
||||
class TutorialSettingsDialog: DialogFragment() {
|
||||
|
||||
@ -21,8 +23,8 @@ class TutorialSettingsDialog: DialogFragment() {
|
||||
val items = arrayOf(
|
||||
Pair(R.string.feeds_tutorial, R.drawable.ic_home_white_24dp),
|
||||
Pair(R.string.create_tutorial, R.drawable.photo_camera),
|
||||
Pair(R.string.feeds_tutorial, R.drawable.notifications),
|
||||
Pair(R.string.feeds_tutorial, R.drawable.outline_bottom_navigation)
|
||||
Pair(R.string.dm_tutorial, R.drawable.message),
|
||||
Pair(R.string.custom_tabs_tutorial, R.drawable.outline_bottom_navigation)
|
||||
)
|
||||
|
||||
val adapter = object : ArrayAdapter<Pair<Int, Int>>(requireContext(), android.R.layout.simple_list_item_1, items) {
|
||||
@ -50,6 +52,10 @@ class TutorialSettingsDialog: DialogFragment() {
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(getString(R.string.tutorial_choice))
|
||||
.setAdapter(adapter) { _, which ->
|
||||
if(which == 3){
|
||||
customTabsTutorial()
|
||||
return@setAdapter
|
||||
}
|
||||
val intent = Intent(requireContext(), MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
intent.putExtra(START_TUTORIAL, which)
|
||||
@ -61,6 +67,10 @@ class TutorialSettingsDialog: DialogFragment() {
|
||||
.create()
|
||||
}
|
||||
|
||||
private fun customTabsTutorial() {
|
||||
(requireActivity() as SettingsActivity).customTabsTutorial()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val START_TUTORIAL = "tutorial_start_intent"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
|
||||
<path android:fillColor="?attr/colorOnBackground" android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
|
||||
|
||||
</vector>
|
||||
|
@ -366,4 +366,6 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
|
||||
<string name="feeds_tutorial">Feeds, how do they work? Where do they come from?</string>
|
||||
<string name="create_tutorial">A little walk through creating posts</string>
|
||||
<string name="tutorial_choice">What could you use some help with?</string>
|
||||
<string name="dm_tutorial">Direct Messages: keep in touch!</string>
|
||||
<string name="custom_tabs_tutorial">Customize what tabs show up on the main PixelDroid screen!</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user