-
Notifications
You must be signed in to change notification settings - Fork 58
/
ComposeFragment.kt
153 lines (135 loc) · 5.75 KB
/
ComposeFragment.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.materialstudies.reply.ui.compose
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.materialstudies.reply.R
import com.materialstudies.reply.data.Account
import com.materialstudies.reply.data.AccountStore
import com.materialstudies.reply.data.Email
import com.materialstudies.reply.data.EmailStore
import com.materialstudies.reply.databinding.ComposeRecipientChipBinding
import com.materialstudies.reply.databinding.FragmentComposeBinding
import kotlin.LazyThreadSafetyMode.NONE
/**
* A [Fragment] which allows for the composition of a new email.
*/
class ComposeFragment : Fragment() {
private lateinit var binding: FragmentComposeBinding
private val args: ComposeFragmentArgs by navArgs()
// The new email being composed.
private val composeEmail: Email by lazy(NONE) {
// Get the id of the email being replied to, if any, and either create an new empty email
// or a new reply email.
val id = args.replyToEmailId
if (id == -1L) EmailStore.create() else EmailStore.createReplyTo(id)
}
// Handle closing an expanded recipient card when on back is pressed.
private val closeRecipientCardOnBackPressed = object : OnBackPressedCallback(false) {
var expandedChip: View? = null
override fun handleOnBackPressed() {
expandedChip?.let { collapseChip(it) }
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requireActivity().onBackPressedDispatcher.addCallback(this, closeRecipientCardOnBackPressed)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentComposeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.run {
closeIcon.setOnClickListener { findNavController().navigateUp() }
email = composeEmail
composeEmail.nonUserAccountRecipients.forEach { addRecipientChip(it) }
senderSpinner.adapter = ArrayAdapter(
senderSpinner.context,
R.layout.spinner_item_layout,
AccountStore.getAllUserAccounts().map { it.email }
)
// TODO: Set up MaterialContainerTransform enterTransition and Slide returnTransition.
}
}
/**
* Add a chip for the given [Account] to the recipients chip group.
*
* This method also sets up the ability for expanding/collapsing the chip into a recipient
* address selection dialog.
*/
private fun addRecipientChip(acnt: Account) {
binding.recipientChipGroup.run {
val chipBinding = ComposeRecipientChipBinding.inflate(
LayoutInflater.from(context),
this,
false
).apply {
account = acnt
root.setOnClickListener {
// Bind the views in the expanded card view to this account's details when
// clicked and expand.
binding.focusedRecipient = acnt
expandChip(it)
}
}
addView(chipBinding.root)
}
}
/**
* Expand the recipient [chip] into a popup with a list of contact addresses to choose from.
*/
private fun expandChip(chip: View) {
// Configure the analogous collapse transform back to the recipient chip. This should
// happen when the card is clicked, any region outside of the card (the card's transparent
// scrim) is clicked, or when the back button is pressed.
binding.run {
recipientCardView.setOnClickListener { collapseChip(chip) }
recipientCardScrim.visibility = View.VISIBLE
recipientCardScrim.setOnClickListener { collapseChip(chip) }
}
closeRecipientCardOnBackPressed.expandedChip = chip
closeRecipientCardOnBackPressed.isEnabled = true
// TODO: Set up MaterialContainerTransform beginDelayedTransition.
binding.recipientCardView.visibility = View.VISIBLE
// Using INVISIBLE instead of GONE ensures the chip's parent layout won't shift during
// the transition due to chips being effectively removed.
chip.visibility = View.INVISIBLE
}
/**
* Collapse the recipient card back into its [chip] form.
*/
private fun collapseChip(chip: View) {
// Remove the scrim view and on back pressed callbacks
binding.recipientCardScrim.visibility = View.GONE
closeRecipientCardOnBackPressed.expandedChip = null
closeRecipientCardOnBackPressed.isEnabled = false
// TODO: Set up MaterialContainerTransform beginDelayedTransition.
chip.visibility = View.VISIBLE
binding.recipientCardView.visibility = View.INVISIBLE
}
}