Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions demo-app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,24 @@
<!-- </intent-filter>-->
</activity>

<!-- Gravatar QE Activity -->
<!-- <activity-->
<!-- android:name="com.gravatar.quickeditor.ui.GravatarQuickEditorActivity"-->
<!-- tools:node="merge">-->

<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.VIEW" />-->

<!-- <category android:name="android.intent.category.DEFAULT" />-->
<!-- <category android:name="android.intent.category.BROWSABLE" />-->

<!-- <data-->
<!-- android:host="${DEMO_OAUTH_REDIRECT_URI_HOST}"-->
<!-- android:scheme="${DEMO_OAUTH_REDIRECT_URI_SCHEME}" />-->
<!-- </intent-filter>-->
<!-- </activity>-->


<!-- Lib activities -->
<activity
android:name="com.yalantis.ucrop.UCropActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,25 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.neverEqualPolicy
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.unit.dp
import com.gravatar.demoapp.BuildConfig
import com.gravatar.demoapp.R
import com.gravatar.quickeditor.GravatarQuickEditor
import com.gravatar.quickeditor.ui.GetQuickEditorResult
import com.gravatar.quickeditor.ui.GravatarQuickEditorActivity
import com.gravatar.quickeditor.ui.GravatarQuickEditorResult
import com.gravatar.quickeditor.ui.editor.AuthenticationMethod
import com.gravatar.quickeditor.ui.editor.AvatarPickerContentLayout
import com.gravatar.quickeditor.ui.editor.GravatarQuickEditorParams
Expand All @@ -30,8 +36,27 @@ import com.gravatar.services.ProfileService
import com.gravatar.types.Email
import com.gravatar.ui.components.ComponentState
import com.gravatar.ui.components.ProfileSummary
import com.gravatar.ui.components.atomic.Avatar

class QuickEditorTestActivity : AppCompatActivity() {
private var profileChanges by mutableStateOf(0)
private val getQEResult = registerForActivityResult(GetQuickEditorResult()) { quickEditorResult ->
when (quickEditorResult) {
GravatarQuickEditorResult.AVATAR_SELECTED -> {
profileChanges++
Toast.makeText(this, "Avatar selected", Toast.LENGTH_SHORT).show()
}

GravatarQuickEditorResult.DISMISSED -> {
Toast.makeText(this, "Dismissed", Toast.LENGTH_SHORT).show()
}

else -> {
Toast.makeText(this, "Unexpected...", Toast.LENGTH_SHORT).show()
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quick_editor_test)
Expand All @@ -41,9 +66,12 @@ class QuickEditorTestActivity : AppCompatActivity() {
private fun setupViews() {
val profileCard = findViewById<ComposeView>(R.id.profile_card)
val btnUpdateAvatar = findViewById<Button>(R.id.btn_update_avatar)
val btnUpdateAvatarWithQEActivity = findViewById<Button>(R.id.btn_update_avatar_qe_activity)

profileCard.setContent {
GravatarProfileSummary(emailAddress = BuildConfig.DEMO_EMAIL)
key(profileChanges) {
GravatarProfileSummary(emailAddress = BuildConfig.DEMO_EMAIL)
}
}

btnUpdateAvatar.setOnClickListener {
Expand All @@ -67,6 +95,23 @@ class QuickEditorTestActivity : AppCompatActivity() {
},
)
}

btnUpdateAvatarWithQEActivity.setOnClickListener {
getQEResult.launch(
GravatarQuickEditorActivity.GravatarEditorActivityArguments(
GravatarQuickEditorParams {
email = Email(BuildConfig.DEMO_EMAIL)
avatarPickerContentLayout = AvatarPickerContentLayout.Horizontal
},
AuthenticationMethod.OAuth(
OAuthParams {
clientId = BuildConfig.DEMO_OAUTH_CLIENT_ID
redirectUri = BuildConfig.DEMO_OAUTH_REDIRECT_URI
},
),
),
)
}
}
}

Expand Down Expand Up @@ -98,5 +143,13 @@ fun GravatarProfileSummary(emailAddress: String = "gravatar@automattic.com") {
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
avatar = {
Avatar(
state = profileState,
size = 72.dp,
modifier = Modifier.clip(CircleShape),
forceRefresh = true,
)
},
)
}
10 changes: 10 additions & 0 deletions demo-app/src/main/res/layout/activity_quick_editor_test.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/profile_container" />

<Button
android:id="@+id/btn_update_avatar_qe_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="Update Avatar with QuickEditor Activity"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_update_avatar" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
Expand Down
57 changes: 57 additions & 0 deletions docs/get-started/get-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ To do that the QuickEditor needs an authorization token to perform requests on b

### 1. Let the Quick Editor handle the OAuth flow

#### 1.1 Using you own activity with `android:launchMode="singleTask"` (Recommended)

Quick Editor can handle the heavy lifting of running the full OAuth flow, so you don't have to do that. We will still need a few things from you.
First, you have to go to [OAuth docs](https://docs.gravatar.com/oauth/) and create your Application. Define the `Redirect URLs`.

Expand Down Expand Up @@ -311,6 +313,61 @@ When the user logs out form the app, make sure to run:
GravatarQuickEditor.logout(Email("{USER_EMAIL}"))
```

#### 1.2 Using the provided activity

If using an activity with `android:launchMode="singleTask"` is not an option, you can use the provided activity. With this option, you don't need to modify how your activities are set up.

You need to add the provided activity to your `AndroidManifest.xml`:

```xml
<activity
android:name="com.gravatar.quickeditor.ui.GravatarQuickEditorActivity"
tools:node="merge">

<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:scheme="https"
android:host="yourhost.com"
android:pathPrefix="/redirect-url"
/>
</intent-filter>
</activity>
```

_Note the important difference here: the `tools:node="merge"` attribute. This is necessary to merge the intent filter with the one defined in the library._

The `GravatarQuickEditorActivity` defines an Activity Result contract that you can use to launch the Quick Editor and handle the result. Here's an example of how you can use it:

```kotlin
private val getQEResult = registerForActivityResult(GetQuickEditorResult()) { quickEditorResult ->
when (quickEditorResult) {
GravatarQuickEditorResult.AVATAR_SELECTED -> { ... }

GravatarQuickEditorResult.DISMISSED -> { ... }

else -> { ... }
}
}

getQEResult.launch(
GravatarQuickEditorActivity.GravatarEditorActivityArguments(
GravatarQuickEditorParams { ... },
AuthenticationMethod.OAuth(
OAuthParams { ... },
),
),
)
```

It's important to note that using the `GravatarQuickEditorActivity` you'll only receive the result of the Quick Editor when it's dismissed not instantly as with using the `@Composable` component from your `singleTask` activity (see [Section 1.1](#11-using-you-own-activity-with-androidlaunchmodesingletask-recommended)).

In the `demo-app` you can find a detailed implementation showing how to use the provided activity. See `QuickEditorTestActivity`.

#### Exclude Data Store files from Android backup (optional, but recommended)

Data Store files are subject to Android backups. Encrypted files from the backup won't work when restored on a different device so we have to exclude those files.
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,6 @@ dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
openapi-generator = { id = "org.openapi.generator", version.ref = "openapi" }
parcelize = { id = "kotlin-parcelize" }
publish-to-s3 = { id = "com.automattic.android.publish-to-s3", version.ref = "publishToS3" }
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
Loading