* For #5799: add architecture document outline for review * For 5799: update architecture doc outline - Remove references to old architecture (Soon it will all have been replaced. No need for the additional cognitive load) - Add some subheadings - 'Simplified Example' seems like a good idea. Update the language to clarify that it will be done * For 5799: add additional known limitations * For 5799: wrote first draft for architecture 'overview' and 'important objects' * For 5799: wrote first draft for arch doc 'important notes' * For 5799: wrote arch doc 'known limitations' section * For 5799: wrote example code for architecture doc * For 5799: added example app wireframe for arch docs * For 5799: update arch docs 'Simplified Example section' * For 5799: improve formatting for architecture docs * For 5799: minor tweaks to architecture docs * For 5799: link 'simplified example' section to example code * For 5799: update arch doc per reviewmaster
parent
4e3a3665d6
commit
a0ca8b84bb
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,25 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
// This is example code for the 'Simplified Example' section of
|
||||
// /docs/architecture-overview.md
|
||||
class ContactsController(
|
||||
private val store: ContactsStore,
|
||||
private val navController: NavController
|
||||
) {
|
||||
|
||||
fun contactRenamed(contactId: Int, newName: String) {
|
||||
store.dispatch(ContactsAction.ContactRenamed(contactId = contactId, newName = newName))
|
||||
}
|
||||
|
||||
fun chatSelected(contactId: Int) {
|
||||
// This is how we pass arguments between fragments using Google's navigation library.
|
||||
// See https://developer.android.com/guide/navigation/navigation-getting-started
|
||||
val directions = ContactsFragment.actionContactsFragmentToChatFragment(
|
||||
contactId = contactId
|
||||
)
|
||||
navController.nav(R.id.contactFragment, directions)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
// This is example code for the 'Simplified Example' section of
|
||||
// /docs/architecture-overview.md
|
||||
class ContactsFragment : Fragment() {
|
||||
|
||||
lateinit var contactsStore: ContactsStore
|
||||
lateinit var contactsView: ContactsView
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_contacts, container, false)
|
||||
|
||||
// Create the various components and hook them up to each other
|
||||
val initialState = ContactsState(
|
||||
contacts = emptyList(),
|
||||
theme = Theme.ORANGE
|
||||
)
|
||||
|
||||
contactsStore = ContactsStore(initialState = initialState)
|
||||
|
||||
val contactsController = ContactsController(
|
||||
store = store,
|
||||
navController = findNavController()
|
||||
)
|
||||
|
||||
val themeController = ThemeController(
|
||||
store = store
|
||||
)
|
||||
|
||||
val interactor = ContactsInteractor(
|
||||
contactsController = contactsController,
|
||||
themeController = themeController
|
||||
)
|
||||
|
||||
contactsView = ContactsView(view.contains_container, interactor)
|
||||
}
|
||||
|
||||
override onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
// Whenever State is updated, pass it to the View
|
||||
consumeFrom(contactsStore) { state ->
|
||||
contactsView.update(state)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
// This is example code for the 'Simplified Example' section of
|
||||
// /docs/architecture-overview.md
|
||||
class ContactsInteractor(
|
||||
private val contactsController: ContactsController,
|
||||
private val themeController: ThemeController
|
||||
) {
|
||||
|
||||
fun onThemeSelected(theme: Theme) {
|
||||
themeController.themeSelected(theme)
|
||||
}
|
||||
|
||||
fun onContactRenamed(contactId: Int, newName: String) {
|
||||
contactsController.contactRenamed(contactId, newName)
|
||||
}
|
||||
|
||||
fun onChatSelected(contactId: Int) {
|
||||
contactsController.chatSelected(contactId)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
// This is example code for the 'Simplified Example' section of
|
||||
// /docs/architecture-overview.md
|
||||
class ContactsStore(
|
||||
private val initialState: ContactsState
|
||||
) : Store<ContactsState, Reducer<ContactState, ContactsAction>>(initialState, ::reducer)
|
||||
|
||||
sealed class ContactsAction {
|
||||
data class ContactRenamed(val contactId: Int, val newName: String) : ContactsAction
|
||||
data class ThemeChanged(val newTheme: Theme) : ContactsAction
|
||||
}
|
||||
|
||||
data class ContactsState(
|
||||
val contacts: List<Contact>,
|
||||
val theme: Theme
|
||||
)
|
||||
|
||||
data class Contact(
|
||||
val name: String,
|
||||
val id: Int,
|
||||
val imageUrl: Uri
|
||||
)
|
||||
|
||||
enum class Theme {
|
||||
ORANGE, DARK
|
||||
}
|
||||
|
||||
fun reducer(oldState: ContactsState, action: ContactsAction): ContactsState = when (action) {
|
||||
is ContactsAction.ThemeChanged -> oldState.copy(theme = action.newTheme)
|
||||
is ContactsAction.ContactRenamed -> {
|
||||
val newContacts = oldState.contacts.map { contact ->
|
||||
// If this is the contact we want to change...
|
||||
if (contact.id == action.contactId) {
|
||||
// Update its name, but keep other values the same
|
||||
contact.copy(name = newName)
|
||||
} else {
|
||||
// Otherwise return the original contact
|
||||
return@map contact
|
||||
}
|
||||
}
|
||||
|
||||
return oldState.copy(contacts = newContacts)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
// This is example code for the 'Simplified Example' section of
|
||||
// /docs/architecture-overview.md
|
||||
class ContactsView(
|
||||
private val container: ViewGroup,
|
||||
private val interactor: ContactsInteractor
|
||||
) {
|
||||
|
||||
val view: View = LayoutInflater.from(container.context)
|
||||
.inflate(R.layout.contact_list, container, true)
|
||||
|
||||
private val contactAdapter: ContactAdapter
|
||||
|
||||
init {
|
||||
// Setup view constraints and anything else that will not change as data updates
|
||||
view.select_theme_orange.setOnClickListener {
|
||||
interactor.onThemeSelected(Theme.ORANGE)
|
||||
}
|
||||
view.select_theme_dark.setOnClickListner {
|
||||
interactor.onThemeSelected(Theme.DARK)
|
||||
}
|
||||
// The RecyclerView.Adapter is passed the interactor, and will call it from its own listeners
|
||||
contactAdapter = ContactAdapter(view.contactRoot, interactor)
|
||||
view.contact_recycler.apply {
|
||||
adapter = contactAdapter
|
||||
}
|
||||
}
|
||||
|
||||
fun update(state: ContactsState) {
|
||||
view.toolbar.setColor(ContextCompat.getColor(this, R.color.state.toolbarColor))
|
||||
contactAdapter.update(state)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
// This is example code for the 'Simplified Example' section of
|
||||
// /docs/architecture-overview.md
|
||||
class ThemeController(
|
||||
private val ContactsStore
|
||||
) {
|
||||
fun themeSelected(newTheme: Theme) {
|
||||
store.dispatch(ContactsAction.ThemeChanged(newTheme = newTheme))
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Loading…
Reference in New Issue