Skip to content

Commit ea1112c

Browse files
authored
Merge pull request #136 from nhaarman/docs
Include docs module in main branch
2 parents 7a42f48 + 50841de commit ea1112c

File tree

247 files changed

+7027
-5
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

247 files changed

+7027
-5
lines changed

.ops/git.gradle

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
ext.git = [
22

33
versionName : {
4+
if (project.hasProperty("versionName")) {
5+
return project.getProperty("versionName")
6+
}
7+
48
def baseTag = git.latestTag() ?: "0.0.0"
59
def commitCount = git.numberOfCommitsSinceTag(baseTag)
610

@@ -78,4 +82,4 @@ ext.git = [
7882
return false
7983
}
8084
}
81-
]
85+
]

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ building blocks, building up your application into several composable flows.
1414
The view layer is decoupled from navigation and reacts to screen changes, giving
1515
you full control over transition animations.
1616

17-
![](https://cdn-images-1.medium.com/max/800/1*_PXlm-IPwZNH2mKeTIAizg.gif)
17+
![](/docs/src/orchid/resources/media/acorn_diagram_extended.svg)
1818

1919
You can read more about Acorn on the
20-
[documentation website](https://nhaarman.github.io/Acorn).
20+
[documentation website](https://nhaarman.github.io/acorn).
2121

2222
## Easy setup [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.nhaarman.acorn/acorn/badge.png)](https://maven-badges.herokuapp.com/maven-central/com.nhaarman.acorn/acorn)
2323

@@ -40,12 +40,12 @@ Using the dependencies above will transitively pull all other dependencies you
4040
need as well.
4141

4242
For more advanced configuration, see
43-
[Setup](https://nhaarman.github.io/Acorn/usage/setup.html).
43+
[Setup](https://nhaarman.github.io/acorn/wiki/setup.html).
4444

4545
## Getting started
4646

4747
Acorn has several [sample projects](samples) introducing the different concepts.
48-
You can also visit the [Getting started](https://nhaarman.github.io/Acorn/wiki/getting_started/)
48+
You can also visit the [Getting started](https://nhaarman.github.io/acorn/wiki/getting_started/)
4949
documentation page for more information.
5050

5151
## Building Acorn

docs/.old/Sending Data.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
Android has a great mechanism that allows applications to share data
2+
with each other.
3+
Web pages can be opened in a browser application, applications can
4+
request a camera application to take a picture for them, and plain text
5+
and image media can be shared to social media applications.
6+
7+
## Sending Data
8+
9+
Your application can share data with other applications.
10+
You can allow the user to share a picture with a messaging app, or you
11+
can start the Google Maps app to start driving to the nearest pizza
12+
place.
13+
Android supports this through the use of `Intent`s: specialized
14+
messaging objects that can be used to request an action from another app
15+
component.
16+
You can send an Intent to the Android system and the system will start
17+
the component that can handle the Intent.
18+
19+
### Navigation
20+
21+
In terms of your application's navigation state, sharing data by starting
22+
a third party application is just another destination in your app.
23+
You can navigate to a `Scene` that represents sharing the data.
24+
25+
```kotlin
26+
class ShareTextScene(
27+
val text: String,
28+
private val listener: Events
29+
) : Scene<Nothing> {
30+
31+
fun finished() {
32+
listener.finished()
33+
}
34+
35+
interface Events {
36+
fun finished()
37+
}
38+
}
39+
```
40+
41+
Since your application has no UI to show for this Scene, you can just
42+
pass `Nothing` as its container type.
43+
At the UI-layer of your application, instead of inflating a layout, you
44+
create an Intent to send to the Android system.
45+
Next to a `ViewFactory` instance, the `AcornActivityDelegate` accepts an
46+
`IntentProvider` instance you can implement for these scenario's.
47+
By returning a valid Intent from the IntentProvider, Acorn will route that intent
48+
to `Activity#startActivityForResult` instead of inflating a layout.
49+
50+
```kotlin
51+
object ShareTextIntentProvider: IntentProvider {
52+
53+
override fun intentFor(scene: Scene<out Container>, data: TransitionData?): Intent? {
54+
if (scene !is ShareTextScene) return null
55+
56+
return Intent().apply {
57+
action = Intent.ACTION_SEND
58+
type = "text/plain"
59+
putExtra(Intent.EXTRA_TEXT, scene.text)
60+
}
61+
}
62+
63+
override fun onActivityResult(scene: Scene<out Container>, resultCode: Int, data: Intent?): Boolean {
64+
if (scene !is ShareTextScene) return false
65+
66+
scene.finished()
67+
return true
68+
}
69+
}
70+
```
71+
72+
Acorn uses `startActivityForResult` to be able to get notified when the external
73+
application finishes.
74+
In `IntentProvider#onActivityResult` you can let the Scene know it is finished,
75+
and cause a change in navigation state again.
76+
77+
### Requesting Data
78+
79+
Your application can also request data from other applications.
80+
It can request a contact from the Contacts app, or ask the camera app
81+
to take a picture.
82+
For this, you can use the same mechanism as described above.

docs/.old/Testability.md

Whitespace-only changes.

docs/.old/_Sidebar.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
* [[Home]]
2+
* [[Motivation]]
3+
* [[Application Architecture]]
4+
* [[Application Flow]]
5+
* [[Saving and restoring state]]
6+
* [[Deep Linking]]
7+
* [[Scenes]]
8+
* [[Navigation]]
9+
* [[Scene Management]]
10+
* [[Restoring Navigator State]]
11+
* [[Navigator Results]]
12+
* [[Composing Navigators]]
13+
* [[Sending Data]]
14+
* [[Back Presses]]
15+
* [[User Interfaces]]
16+
* [[Displaying Scenes]]
17+
* [[View Factories]]
18+
* [[The Activity lifecycle and Scene transitions]]
19+
* [[Transition animations]]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
In Android, the Activity is the 'window' between the application and the user by
2+
hosting the user interface and intercepting input events.
3+
The user interface is typically implemented using View instances, which are
4+
attached to the Activity.
5+
Views can be instantiated manually, or inflated from an xml resource, after
6+
which it can be attached to the Activity.
7+
8+
## The Activity as the UI layer
9+
10+
Multitasking in Android means that you can switch quickly between different
11+
applications.
12+
13+
During the life of an Activity, it goes through several phases.
14+
Most interestingly, when the Activity is in its 'started' or 'resumed' state,
15+
one can assume the Activity is at least visible to the user.
16+
Activities can enter their 'started' or 'stopped' state any number of times,
17+
until it is destroyed by the system.
18+
19+
20+
21+
Once an Activity instance is destroyed, a new instance can be recreated and
22+
restored to the previous state.
23+
This typically happens on configuration changes, such as device rotation.
24+
25+
26+
27+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Application Architecture
2+
3+
The latest trend in Android application development is 'Clean Architecture',
4+
where developers use all sorts of 'Model-View-Presenter',
5+
'Model-ViewModel-Presenter' or 'Model-View-Intent' "architectures" to develop
6+
their Android apps.
7+
Databases are abstracted away behind repositories, but still a lot of business
8+
logic resides in the presentation layer of the application.
9+
10+
<!--Android's presentation layer however is riddled with classes that do way too -->
11+
<!--much, and make it quite hard to properly apply separation of concerns.-->
12+
13+
Clean Architecture is more than that.
14+
It is about having your business rules at the center of your application:
15+
they are the most important things to your software.
16+
Business rules that have nothing to do with lifecycles, Views or state
17+
restoration.
18+
Business rules that can be tested on a JVM without ever having to spin
19+
up an Android system.
20+
21+
Architecture is about carefully defining boundaries between components
22+
in your application to protect them from the details.
23+
The database is such a detail, but also any location providers, REST
24+
api's, and yes, the presentation and UI layer.
25+
The presentation layer here is concerned with navigation, the Activity
26+
lifecycle and with binding the business rules to the UI layer.
27+
The UI layer again is a detail to the presentation layer.
28+
29+
In the Android framework everything in the presentation layer is tightly
30+
coupled: the lifecycle, navigation and UI management are all handled by
31+
the Activity or the Fragment.
32+
33+
Acorn provides a way to actually decouple these concerns by introducing
34+
clear boundaries between the UI, presentation and navigation on top of
35+
your business rules, while still providing full control over state
36+
restoration, transition animations and lifecycles.
37+
38+
![](art/application_architecture/diagram_large.png)
39+
40+
_Separation of concerns. Notice how all arrows point toward the business
41+
rules._
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Application Flow
2+
3+
In a typical mobile application, a user can navigate from one screen to another
4+
and another, which can be regarded as a 'flow' through your application.
5+
The default way of managing a flow is to use a stack of screens where screens
6+
can be pushed on and popped off of, like the Activity back stack or the Fragment
7+
back stack.
8+
9+
### Multiple flows
10+
11+
Often, applications have more than one flow.
12+
Next to the application flow that is usually invoked when your application
13+
starts, there might be an onboarding experience or some login flow the user has
14+
to go through.
15+
Composing or editing content like writing an e-mail can also be regarded as a
16+
flow.
17+
These flows can be conditionally started at the start of the application, or at
18+
any time during the lifetime of the application.
19+
These combined flows make up the main application flow.
20+
21+
A second type of flow is when your app can handle share requests from other
22+
applications, or can be used to fetch a result, like selecting a photo or
23+
contact.
24+
These flows typically act parallel to your main application flow.
25+
When the user finishes this type of flow, the application is finished and the
26+
user returns to the application that started the flow.
27+
28+
### Flow results
29+
30+
Much like screens, flows can have results, like that logged in user from the
31+
login flow, or the picture the user had selected.
32+
Android's Activity class provides a way of yielding a result with the `setResult`
33+
method.
34+
This method takes a result code - like 'cancelled' or 'ok' - and optionally
35+
some data.
36+
Calling `finish` after `setResult` will return the result to the caller of the
37+
Activity.
38+
39+
## Modelling flows
40+
41+
The default way of managing these flows is to use a stack-like structure.
42+
Navigating to a new screen pushes the screen onto the stack, and pressing the
43+
back button pops it back off the stack.
44+
Next to just pushing and popping screens on and off the stack, one can also do
45+
more complex operations, like replacing the entire stack with a new stack, or
46+
replace the last `x` screens by a new screen.
47+
48+
Working with back stacks like this may work for simple applications, but for
49+
more complex scenarios manipulation of the back stack may become a real hassle.
50+
A flow might require popping two screens after a certain event, may need to pop
51+
back to the root screen, or may have to replace the entire stack as a whole.
52+
53+
### State machines
54+
55+
Another way of modelling flows is by using state machines.
56+
State machines provide a natural way of describing the way a user navigates
57+
through the application.
58+
The nodes of the state machine represent screens, and events such as button
59+
presses represent the edges between the nodes.
60+
Whenever such an event occurs, a state transition may occur based on the current
61+
state of the state machine.
62+
63+
Having a state machine as the model of your flow can greatly decrease complexity
64+
when determining a next screen based on state, or when having to deal with
65+
non-trivial flows.
66+
For example, a screen `B` can result in different subsequent screens depending
67+
on how it is started: either screen `C` or screen `D`
68+
When using a state machine, this screen `B` could be represented by two different
69+
nodes in the state machine (say `B1` and `B2`).
70+
When in state `B2`, the state machine just transitions to `C`; when in state
71+
`B2`, the state machine just transitions to `D`:
72+
73+
![](art/application_flow/state_machine.png)
74+
75+
## Navigation
76+
77+
Navigation is about how you apply your application flows in your app.
78+
Android's Activity class, which from its origin can be seen as a single screen,
79+
provides its own methods to navigate to a new screen, such as
80+
`startActivity(Intent)`.
81+
When a user selects a product from a products list for example, the Activity can
82+
request to start a new Activity that shows a detail page for the product.
83+
Android will take care of starting the new Activity, which in turn inflates the
84+
proper layout to show.
85+
86+
Managing navigation like this again may work for simple applications, but just
87+
as with manipulating back stacks, complex requirements can become difficult to
88+
implement.
89+
Determining the next screen in an application flow may depend on some current
90+
application state for example, or the resulting outcome of an event.
91+
92+
### Navigators
93+
94+
To make this easier, dedicated navigator classes can be used to take the
95+
responsibility of navigation away from the screens.
96+
Instead of a screen manipulating the back stack, or telling a navigation
97+
component to go to screen X, it just finishes with or publishes a result event.
98+
The navigator listens for this result and determines the next action to take in
99+
its navigation flow.
100+
When it makes a transition, it can then in turn publish the resulting new screen
101+
to the interested parties, such as the UI layer.
102+
103+
This way, screens become _real_ composable and reusable blocks that have no
104+
knowledge of the flow they are currently in.
105+
They can be shared in multiple flows without introducing the complexity of
106+
navigation state in them.
107+
108+
### Navigators as flows
109+
110+
Ultimately, a single navigator can be seen as a single flow in the application,
111+
like a login flow taking the user through several screens.
112+
Since navigators do no have to be tied to the default Activity or Fragment back
113+
stack, they can implement their own data structures to model their flow.
114+
This could still be a stack, but it can also be an actual state machine or
115+
something entirely different.
116+
117+
Since a navigator is ultimately simply a class that publishes events of screen
118+
changes, multiple navigators can be composed to a single Navigator, combining
119+
multiple flows into a single application flow.
120+
This again makes for composable and reusable navigation blocks that can be
121+
shared in other navigation flows.
122+
123+
Flow results, such as a selected picture or a logged in user become an event,
124+
much like the screens they host.
125+
An Activity can use this result to notify the system of it, or a composing
126+
navigator can use it to switch to another navigator.
127+
128+
![](art/application_flow/navigators.png)
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile userAgent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36" version="9.1.2" editor="www.draw.io" type="device"><diagram name="Page-1" id="6133507b-19e7-1e82-6fc7-422aa6c4b21f">7Vpbc5s4GP01ftwMIMD2o+0k3e60ncx4tts+KiBjbTBihfBlf/1KIHGRwHYdk2Sb9qXwSehyztGnIzkjsNjsP1CYrj+TEMUjxwr3I3A7chwbeFP+n4gcyog/9cpARHEoK9WBJf4XyaAlozkOUdaqyAiJGU7bwYAkCQpYKwYpJbt2tRWJ272mMEJGYBnA2Iz+hUO2llHbsuqC3xGO1rLriScLHmHwFFGSJ7K/kQNWxb+yeANVW7J+toYh2TVC4G4EFpQQVj5t9gsUC2wVbOV39z2l1bgpStg5H4gy8cUWxjlSQy4Gxg4KDD7GVDwGZJOSpGh4DmMcJTwWo5V4zVIY4CT6VLzdAp+HVjiOFyQmtGhEoQDm5gjloLeIMrRvhOSIPyCyQYweeJW9GrRET6rLUbTsGlxNZWzdoMmxpQyh1EdUtV1jxB8kTD0YW/9DyFz/NGRgMMhMkX3FaGegtmYb3sKtfSWVjNtTBsAzVWJ3TFmt5efMGBgzXpCEQZwgOnL8WAjgUTxFrJrsYEB4isLXAMI1gFgGFKFk4Dn701ck3+tIECXnKy4CsR/BoCzw/8lFpp8vSE6xkIb1RawLFa4F4sNNyh/i8s36OBIpUAZVFVl4X3bSIy2On4g30M4YJU9I5Z2Ep6sjqUglsYBTw8cL5oISzDfOmSzY4DAUfc13a8zQMi1nuuM2gceKjREJlKwrSdvTaHZMmt2urHYFlv3T2wBKwplwIwKwGGYZDtrQ84nTw7fmy3eBzY0nXveYfZNIiee6pBe3jKtICkutOwZphFgrJ6Gw5X1MbBvYeUdWCEUxZHjbdkxdgMoeHgguxK+o09KzZ2kbTTkb+VXTwmgN+ZobcD2toRIDo6GC32raZ1E+/iHKH2MSPPUQbvUTbhuE8zbvsRjU8WXTpN956/SDicba+EL6XaA15AxGv63yU83/A0UZ54EjQRLh70mYcyX83EnX1fbWymo391YwUNa1TS85zzPuq7KsH/9jdrwC9XXPMB4wQfS7QJxeA0TTnl6+d1k3E+C005ll280drEpv35vfPiCK+cgF9ufntY5tTSnijSQ2TztpeXo+Ontfs09kyCsmti7H2q8Hma4aYtAWyiMMJiEw0hwvcYDremFVoi5XRN2/8026lP1BKtTGl6tQXaGOIKfbIokdPSC8EQ24mi21x9ZlGnB1b+P6N+epgHMFD41qqaiQHRmyfqfiW8dHpjvviaeJsBzBxZL8MXv9S5InJDnx2pcA7uRCSdpTPS1pDV1JkOOJNmD3hCAtLe/arfrPF+S0Q5CtU32tTHV+FwW/ZcXt9oxXsK10bx7u//j6+X0e3ieWxrBlHt6HspGqjV9sDsVmZV9egk3zYHYdNmdJSAnv5V0yCjQn27U+h7pc67hA//Pjezlgc3PVAr7rgD0eCvixabO4g1EuiFC2JhFJYHxXRzUEmofE40fARlF1eBS2CzF2kD8Kw5wRHqr7/URI2vJcmsE6fTUmnWXzDOl283G25zobXdPVfoFbHEHGNXnB70KGpjpmf/ZvJE7HFcRwP5B12Pnn66zr7rT/xnVYnSk0mzor+X8BoQHwsy/jTnhfCl3TPc4C3gNmh4HXrP6j9pBrlr/Wf4hSnpjqv/YBd/8B</diagram></mxfile>
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile userAgent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36" version="9.1.2" editor="www.draw.io" type="device"><diagram name="Page-1" id="6133507b-19e7-1e82-6fc7-422aa6c4b21f">7VvbcqM4EP0aP24KEDc/xs5lZ2tmKlWpnZ15VEC22WDkFXJs79evBJIBSSQkBpxKNi9jWkKo+5xuulvMBMzX+1sCN6tvOEbpxLHi/QRcTRzHBt6U/cMlByHxXK+ULEkSC1kluE/+RUJoCek2iVHemEgxTmmyaQojnGUoog0ZJATvmtMWOG0+dQOXSBPcRzDVpX8lMV0JqW1Z1cDvKFmuxKNDTww8wOhxSfA2E8+bOGBR/JXDayjXEvPzFYzxriYC1xMwJxjT8td6P0cpN640W3nfTcvocd8EZbTLDXyM3/EE0y2SWy42Rg/SGGyPG/4zwusNzoqFZzBNlhmTpWjBL/MNjJJs+bW4ugI+Ey2SNJ3jFJNiEWkFMNN3KDb9hAhF+5pI7PgW4TWi5MCmiFFX0kTQy3XsC8GvXQ2tqZi1qgHFqChYIhiyPK5eWYn9EIYyG823Xzbaiq7Z7Vf2UWNNPYMR2jUO/KbGYKrraxv0lbw8SV1rdHX9sKmua4B3KHXtDuq+O5fwvS4uAQZzCRnxx+NIOG1yxHPBeBzxwvHVtZvqSjVGUTcYW93ADs4X8Dx/fHWb6I4a8DxvfDJPFXTDEdV1x1fXOR+6eoL3I0G7lzU+LUPzldeRZ8zQhtIZaDrPcUZhkiEycfyUv54f+K8lPao7mCkCyzunKdypph+KWa0jLjGhK7zEGUyvK+msKGAQX8FiVzV7oH1Cf3IxU6G8+iUmMQORQzkU+I4U8FH7wrKAFNwhkjAdEBG35RQSKuo/ftffiNKDuIZbipmo2uJXjDdiIzkl+BHVkimr+DuOyKqtApFr/bz/MiPhLYnELBEl2P6WSM5yzEgTlEKaPDWXPwk0jb/3EUEoG5iqYXhWqppeQ6WzLpj3spEFFOD4/2x5gTybM7wS7tPWdx7SpLjybB+uGWNmaXllfZnwclgI5RQxeFM+pCUmMAvSpis0GZixKuCZDF/WBhEDh3N/xkFJIpheioF1EseF6+1WCUX3m1LTHYEbzR37iEmuEp5dzwC0a8DZdk7HuUN2hbL4krdxuMlSmOdJpMQhGW3seqSpotJPGZVkhCpG3ur3wBhBdOvWbOc94yOdw4V4wh1OCvpL8JR3a+D4F0oFV+oj7nNq3R9lqVBppPiBtlRpB22pAuOj6p1g71BD1GB/SHH02AK61Q66rYHO1rxJ+Kaed546BZz3TgEvUHCbvpkCvqMs5Q5IAVnl1DhwR1DOsGDWwOz1Zq1xvGVs+Njh1w+V8Gsb37PA1Kzpo8GllwSzbc6S4zxvR+C5jtfRrCP3vBTqyvdV/RXmmGwY9GFEU8Orka1UxpN5CR/4LS+S20s2wbY2ez1p+ePHt8+ZlEynzezTr95r9RbmQE4h1/gfz/7wbLonsHT/HAxN0wlNH2heZjHB7CmfElFPOWQwe6ipbOgFU72r8+eXz5IyuEApzY0pQzCU6QPNvEM3kbxGC+kVnaGJKVF/OeUXRWk953fNiPTe7TEUxN/hU7KElLHyDe3K03rVSg/I80w+Plzn1lAUns40U1XYXksOyzT5yqszrWTACFQD4KM7stG8Y1lXzyEvI/aEhB4G9lr1vGVkr/VG8toxTgtq1LXAtBkdbPs4Qz3IeCNbPZ2tJ58ytDR6lAxCLYL76/IAvZF/BSl8gPnr2grtH9L04THqN2SGzylMzQO/D3exNTt8DHcJDY3ZHp0lGM9ZrCY77AG9Re+L397dv19HsU0fLwzmKZZmiIHTwQvLbZI4DKdtNH6/h9fya6mznF4DvTX6HdEdJo/vl9WO6XO6oVjtdvgCqXYUJjoVrZ2MdgK5ryDQuc6yXCXUAtXCXU+ybCt8YaX+grbb4ZO5T4OgD5p299+KoLrQkAC+7iOEjw2g95LjdAXwuNDJgLHL6j/BlNOr/2oErv8D</diagram></mxfile>
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile userAgent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36" version="9.1.2" editor="www.draw.io" type="device"><diagram id="3015f1b9-0ffd-addd-df5b-2913853f979e" name="Page-1">5Zpde5owFIB/jbd7CBHBy+m67WLtPrxYd5lChKyR+MRYdb9+AcJHCLh2RVDbm5KTT96cnHM4ZgTnq/0njtbRLQswHdlWsB/BDyPbBgBC+S+RHDKJ404zQchJoBqVggX5g5XQUtItCfBGaygYo4KsdaHP4hj7QpMhztlOb7ZkVJ91jUJsCBY+oqb0JwlElEk9xyrlnzEJo3xmYKmaB+Q/hpxtYzXfyIbL9C+rXqF8LNV+E6GA7SoieDOCc86YyJ5W+zmmCdscW9bvY0ttsW6OY/GcDraX9XhCdIvzJacLE4ccRvo6OOlgjeBsFxGBF2vkJ7U7uf1SFokVlSUgH5eE0jmjjKd985eHMzUN5gLvW9cKCgJSszBbYcEPsonqMFbMDnpxV27QxFOyqLI547whUkoRFiOXYOSDYtMCdnw5nMBEB+WZoAomVVBFv1eBggYXHMizpYqMi4iFLEb0ppTOdHIVSnhPxH3l+VfS5J2TlGK5sHvVIy2Udb+xEAdlVNBWMCkq5/3C2FqNmK00Wd5x0vJt2Jb7qpWj7BHiIVatvOb94JgiQZ700V8D1+lYCTtQNtvSlQ0AU9umTcoGOlA22+Cx8DnGsZTdDU8G1Mg4Jhm3gQzsAAxsB3N7fmAaDNSpwJhmvADz9fzA2P2BmRhg7tATCZGQHsq2TDsj31LoADaCs0ec+7SYxfiIm0OUhLGU+RINlpWzBByRAdh7VbEiQZD6hibs+sacgrz1PPJ2Fx5zeu0e0zM9Jpj05DJPHt/iie8b2i9rAnf6YHWknhAO6GTzMZps5rfBbSYcD+dMgBl/VI2mGQn/y2hW1aZN0c7Mchr8+7ScZjxc5Q9ezP+ynBZwdfRuj+TNcGFwSzB2hzSSbruR/N6pxwkQ9paNHmfie/ihq1yLN6BZNX129ViPr/xYG+h7tKjw6rM3RTq5EoxmX4U9BKP5GJcdjYKpoykohE5/hjYndp7RqG3paMaWieZUZrMh6fPmotE6f2g/j38XtrMhtzS4PtY/HPs9qmZ4ftExUf1Tp9fDfTw/57z4cF9WTFRH3+u5PhLa/xj+hNfJuD0q5dQgc4tI+utLqZtXrZe1X1qhGakX0XvnobqZ3riyUD2nqeWN+wrVoem83wDeNnXvHq+ZVDZ5U0rWm7azXKGLNuvsEtCS7BP6p7xcUUsyNSXdmu5W/McdFFks7wGldZXLVvDmLw==</diagram></mxfile>
Loading

0 commit comments

Comments
 (0)