Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/oppia/oppia-android into o…
Browse files Browse the repository at this point in the history
  • Loading branch information
XichengSpencer committed Oct 25, 2024
2 parents 8391237 + 2301a52 commit 78aeea5
Show file tree
Hide file tree
Showing 89 changed files with 2,902 additions and 379 deletions.
73 changes: 73 additions & 0 deletions .github/workflows/developer_onboarding_notification.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Celebrating Initial Contributions

on:
pull_request_target:
types: [closed]

permissions:
pull-requests: write

jobs:
comment_on_merged_pull_request:
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop'
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Set Environment Variables
env:
AUTHOR: ${{ github.event.pull_request.user.login }}
REPO: ${{ github.event.repository.name }}
OWNER: ${{ github.event.repository.owner.login }}
run: |
echo "AUTHOR=${AUTHOR}" >> $GITHUB_ENV
echo "REPO=${REPO}" >> $GITHUB_ENV
echo "OWNER=${OWNER}" >> $GITHUB_ENV
- name: Count Merged Pull Requests
id: count_merged_pull_requests
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const author = process.env.AUTHOR;
const repo = process.env.REPO;
const owner = process.env.OWNER;
const { data } = await github.rest.search.issuesAndPullRequests({
q: `repo:${owner}/${repo} type:pr state:closed author:${author}`
});
const prCount = data.items.filter(pr => pr.pull_request.merged_at).length;
core.exportVariable('PR_COUNT', prCount);
- name: Comment on the Merged Pull Request
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prCount = parseInt(process.env.PR_COUNT);
const author = process.env.AUTHOR;
const mention = 'adhiamboperes';
const prNumber = context.payload.pull_request.number;
let message;
if (prCount === 1) {
message = `✨ **Fantastic work @${author}!** Your very first PR to Oppia has been merged! 🎉🥳\n\n` +
`You've just taken your first step into open-source, and we couldn’t be happier to have you onboard. 🙌\n` +
`If you're feeling adventurous, why not dive into another issue and keep contributing? The community would love to see more from you! 🚀\n\n` +
`For any support, feel free to reach out to the developer onboarding lead: @${mention}. Happy coding! 👩‍💻👨‍💻`;
} else if (prCount === 2) {
message = `👏 **Well done @${author}!** Two PRs merged already! 🎉🥳\n\n` +
`With your second PR, you're on a roll, and your contributions are already making a difference. 🌟\n` +
`This means you may be eligible to join the Oppia dev team as a collaborator! 🎉 If you're interested, please fill out [this form](https://forms.gle/NxPjimCMqsSTNUgu5) and become an even more integral part of the community. 🌱\n\n` +
`Looking forward to seeing even more contributions from you. The developer onboarding lead: @${mention} is here if you need any help! Keep up the great work! 🚀`;
}
if (prCount === 1 || prCount === 2) {
await github.rest.issues.createComment({
owner: process.env.OWNER,
repo: process.env.REPO,
issue_number: prNumber,
body: message
});
}
27 changes: 26 additions & 1 deletion .github/workflows/wiki.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
name: Deploy to Wiki
on:
pull_request:
paths:
- 'wiki/**'
push:
branches:
- develop
paths:
- 'wiki/**'
# Triggers this workflow when the wiki is changed
# Triggers this workflow when the wiki is changed.
# (see https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#gollum).
gollum:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

jobs:
table_of_contents_check:
# To verify that the wiki's table of contents matches the headers accurately.
name: Check Wiki Table of Contents
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2

- name: Set up Bazel
uses: abhinavsingh/setup-bazel@v3
with:
version: 6.5.0

- name: Check Wiki Table of Contents
id: checkWikiToc
run: |
bazel run //scripts:wiki_table_of_contents_check -- ${GITHUB_WORKSPACE}
wiki-deploy:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04]
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
steps:
- uses: actions/checkout@v3
with:
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@
android:name=".app.onboarding.IntroActivity"
android:label="@string/onboarding_learner_intro_activity_title"
android:theme="@style/OppiaThemeWithoutActionBar" />
<activity
android:name=".app.testing.TextInputLayoutBindingAdaptersTestActivity"
android:theme="@style/OppiaThemeWithoutActionBar" />
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import androidx.compose.ui.res.integerResource
import androidx.compose.ui.unit.dp
import androidx.databinding.ObservableList
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import org.oppia.android.R
import org.oppia.android.app.classroom.classroomlist.AllClassroomsHeaderText
import org.oppia.android.app.classroom.classroomlist.ClassroomList
Expand All @@ -46,7 +45,6 @@ import org.oppia.android.app.home.promotedlist.ComingSoonTopicListViewModel
import org.oppia.android.app.home.promotedlist.PromotedStoryListViewModel
import org.oppia.android.app.home.topiclist.AllTopicsViewModel
import org.oppia.android.app.home.topiclist.TopicSummaryViewModel
import org.oppia.android.app.model.AppStartupState
import org.oppia.android.app.model.ClassroomSummary
import org.oppia.android.app.model.LessonThumbnail
import org.oppia.android.app.model.LessonThumbnailGraphic
Expand All @@ -61,8 +59,6 @@ import org.oppia.android.domain.oppialogger.analytics.AnalyticsController
import org.oppia.android.domain.profile.ProfileManagementController
import org.oppia.android.domain.topic.TopicListController
import org.oppia.android.domain.translation.TranslationController
import org.oppia.android.util.data.AsyncResult
import org.oppia.android.util.data.DataProviders.Companion.toLiveData
import org.oppia.android.util.locale.OppiaLocale
import org.oppia.android.util.parser.html.StoryHtmlParserEntityType
import org.oppia.android.util.parser.html.TopicHtmlParserEntityType
Expand Down Expand Up @@ -159,8 +155,6 @@ class ClassroomListFragmentPresenter @Inject constructor(
}
)

logAppOnboardedEvent()

return binding.root
}

Expand Down Expand Up @@ -265,38 +259,6 @@ class ClassroomListFragmentPresenter @Inject constructor(
}
}

private fun logAppOnboardedEvent() {
val startupStateProvider = appStartupStateController.getAppStartupState()
val liveData = startupStateProvider.toLiveData()
liveData.observe(
activity,
object : Observer<AsyncResult<AppStartupState>> {
override fun onChanged(startUpStateResult: AsyncResult<AppStartupState>?) {
when (startUpStateResult) {
null, is AsyncResult.Pending -> {
// Do nothing.
}
is AsyncResult.Success -> {
liveData.removeObserver(this)

if (startUpStateResult.value.startupMode ==
AppStartupState.StartupMode.USER_NOT_YET_ONBOARDED
) {
analyticsController.logAppOnboardedEvent(profileId)
}
}
is AsyncResult.Failure -> {
oppiaLogger.e(
"ClassroomListFragment",
"Failed to retrieve app startup state"
)
}
}
}
}
)
}

private fun logHomeActivityEvent() {
analyticsController.logImportantEvent(
oppiaLogger.createOpenHomeContext(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
package org.oppia.android.app.databinding;

import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.view.View;
import android.widget.AutoCompleteTextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.BindingAdapter;
import com.google.android.material.textfield.TextInputLayout;
import org.oppia.android.app.model.OppiaLanguage;
import org.oppia.android.app.translation.AppLanguageActivityInjectorProvider;
import org.oppia.android.app.translation.AppLanguageResourceHandler;

/** Holds all custom binding adapters that bind to [TextInputLayout]. */
public final class TextInputLayoutBindingAdapters {
Expand All @@ -15,4 +24,37 @@ public static void setErrorMessage(
) {
textInputLayout.setError(errorMessage);
}

/** Binding adapter for setting the text of an [AutoCompleteTextView]. */
@BindingAdapter({"languageSelection", "filter"})
public static void setLanguageSelection(
@NonNull AutoCompleteTextView textView,
@Nullable OppiaLanguage selectedItem,
Boolean filter) {
textView.setText(getAppLanguageResourceHandler(textView)
.computeLocalizedDisplayName(selectedItem), filter);
}

private static AppLanguageResourceHandler getAppLanguageResourceHandler(View view) {
AppLanguageActivityInjectorProvider provider =
(AppLanguageActivityInjectorProvider) getAttachedActivity(view);
return provider.getAppLanguageActivityInjector().getAppLanguageResourceHandler();
}

private static Activity getAttachedActivity(View view) {
Context context = view.getContext();
while (context != null && !(context instanceof Activity)) {
if (!(context instanceof ContextWrapper)) {
throw new IllegalStateException(
"Encountered context in view (" + view + ") that doesn't wrap a parent context: "
+ context
);
}
context = ((ContextWrapper) context).getBaseContext();
}
if (context == null) {
throw new IllegalStateException("Failed to find base Activity for view: " + view);
}
return (Activity) context;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager
import org.oppia.android.R
import org.oppia.android.app.fragment.FragmentScope
import org.oppia.android.app.home.promotedlist.ComingSoonTopicListViewModel
import org.oppia.android.app.home.promotedlist.PromotedStoryListViewModel
import org.oppia.android.app.home.topiclist.AllTopicsViewModel
import org.oppia.android.app.home.topiclist.TopicSummaryViewModel
import org.oppia.android.app.model.AppStartupState
import org.oppia.android.app.model.ProfileId
import org.oppia.android.app.model.TopicSummary
import org.oppia.android.app.recyclerview.BindableAdapter
Expand All @@ -25,14 +23,11 @@ import org.oppia.android.databinding.HomeFragmentBinding
import org.oppia.android.databinding.PromotedStoryListBinding
import org.oppia.android.databinding.TopicSummaryViewBinding
import org.oppia.android.databinding.WelcomeBinding
import org.oppia.android.domain.onboarding.AppStartupStateController
import org.oppia.android.domain.oppialogger.OppiaLogger
import org.oppia.android.domain.oppialogger.analytics.AnalyticsController
import org.oppia.android.domain.profile.ProfileManagementController
import org.oppia.android.domain.topic.TopicListController
import org.oppia.android.domain.translation.TranslationController
import org.oppia.android.util.data.AsyncResult
import org.oppia.android.util.data.DataProviders.Companion.toLiveData
import org.oppia.android.util.parser.html.StoryHtmlParserEntityType
import org.oppia.android.util.parser.html.TopicHtmlParserEntityType
import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId
Expand All @@ -53,7 +48,6 @@ class HomeFragmentPresenter @Inject constructor(
private val dateTimeUtil: DateTimeUtil,
private val translationController: TranslationController,
private val multiTypeBuilderFactory: BindableAdapter.MultiTypeBuilder.Factory,
private val appStartupStateController: AppStartupStateController
) {
private val routeToTopicPlayStoryListener = activity as RouteToTopicPlayStoryListener
private lateinit var binding: HomeFragmentBinding
Expand Down Expand Up @@ -103,45 +97,9 @@ class HomeFragmentPresenter @Inject constructor(
it.viewModel = homeViewModel
}

logAppOnboardedEvent()

return binding.root
}

private fun logAppOnboardedEvent() {
val startupStateProvider = appStartupStateController.getAppStartupState()
val liveData = startupStateProvider.toLiveData()
liveData.observe(
activity,
object : Observer<AsyncResult<AppStartupState>> {
override fun onChanged(startUpStateResult: AsyncResult<AppStartupState>?) {
when (startUpStateResult) {
null, is AsyncResult.Pending -> {
// Do nothing
}
is AsyncResult.Success -> {
liveData.removeObserver(this)

if (startUpStateResult.value.startupMode ==
AppStartupState.StartupMode.USER_NOT_YET_ONBOARDED
) {
analyticsController.logAppOnboardedEvent(
ProfileId.newBuilder().setInternalId(internalProfileId).build()
)
}
}
is AsyncResult.Failure -> {
oppiaLogger.e(
"HomeFragment",
"Failed to retrieve app startup state"
)
}
}
}
}
)
}

private fun createRecyclerViewAdapter(): BindableAdapter<HomeItemViewModel> {
return multiTypeBuilderFactory.create<HomeItemViewModel, ViewType> { viewModel ->
when (viewModel) {
Expand Down
Loading

0 comments on commit 78aeea5

Please sign in to comment.