Skip to content

Commit 3572a3d

Browse files
committed
implemented onboarding
1 parent 6fa52c6 commit 3572a3d

28 files changed

+690
-147
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.nmc.android.onboarding
2+
3+
import androidx.test.espresso.Espresso.*
4+
import androidx.test.espresso.action.ViewActions.swipeLeft
5+
import androidx.test.espresso.action.ViewActions.swipeRight
6+
import androidx.test.espresso.assertion.ViewAssertions.matches
7+
import androidx.test.espresso.matcher.ViewMatchers.isClickable
8+
import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
9+
import androidx.test.espresso.matcher.ViewMatchers.withId
10+
import androidx.test.ext.junit.rules.ActivityScenarioRule
11+
import androidx.test.ext.junit.runners.AndroidJUnit4
12+
import com.nextcloud.client.onboarding.FirstRunActivity
13+
import com.owncloud.android.AbstractIT
14+
import com.owncloud.android.R
15+
import org.junit.Rule
16+
import org.junit.Test
17+
import org.junit.runner.RunWith
18+
19+
@RunWith(AndroidJUnit4::class)
20+
class OnBoardingIT : AbstractIT() {
21+
22+
@get:Rule
23+
var activityRule = ActivityScenarioRule(FirstRunActivity::class.java)
24+
25+
@Test
26+
fun runAllOnboardingTests() {
27+
verifyUIElements()
28+
29+
shortSleep()
30+
31+
verifyOnBoardingSwipe()
32+
}
33+
34+
private fun verifyUIElements() {
35+
onView(withId(R.id.contentPanel)).check(matches(isCompletelyDisplayed()))
36+
onView(withId(R.id.progressIndicator)).check(matches(isCompletelyDisplayed()))
37+
onView(withId(R.id.login)).check(matches(isCompletelyDisplayed()))
38+
onView(withId(R.id.login)).check(matches(isClickable()))
39+
}
40+
41+
private fun verifyOnBoardingSwipe() {
42+
onView(withId(R.id.contentPanel)).perform(swipeLeft())
43+
onView(withId(R.id.contentPanel)).perform(swipeLeft())
44+
onView(withId(R.id.contentPanel)).perform(swipeLeft())
45+
46+
onView(withId(R.id.contentPanel)).perform(swipeRight())
47+
onView(withId(R.id.contentPanel)).perform(swipeRight())
48+
}
49+
}

app/src/main/java/com/nextcloud/client/onboarding/FirstRunActivity.java

Lines changed: 46 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,32 @@
2626

2727
import android.accounts.Account;
2828
import android.accounts.AccountManager;
29+
import android.annotation.SuppressLint;
2930
import android.content.Intent;
31+
import android.content.pm.ActivityInfo;
3032
import android.content.res.Configuration;
3133
import android.os.Bundle;
32-
import android.view.View;
3334
import android.view.ViewGroup;
34-
import android.widget.LinearLayout;
3535

3636
import com.nextcloud.android.common.ui.theme.utils.ColorRole;
3737
import com.nextcloud.client.account.UserAccountManager;
3838
import com.nextcloud.client.appinfo.AppInfo;
3939
import com.nextcloud.client.di.Injectable;
4040
import com.nextcloud.client.preferences.AppPreferences;
41+
import com.nmc.android.helper.OnBoardingUtils;
42+
import com.nmc.android.helper.OnBoardingPagerAdapter;
4143
import com.owncloud.android.BuildConfig;
4244
import com.owncloud.android.R;
4345
import com.owncloud.android.authentication.AuthenticatorActivity;
4446
import com.owncloud.android.databinding.FirstRunActivityBinding;
45-
import com.owncloud.android.features.FeatureItem;
4647
import com.owncloud.android.ui.activity.BaseActivity;
4748
import com.owncloud.android.ui.activity.FileDisplayActivity;
48-
import com.owncloud.android.ui.adapter.FeaturesViewAdapter;
4949
import com.owncloud.android.utils.DisplayUtils;
5050
import com.owncloud.android.utils.theme.ViewThemeUtils;
5151

5252
import javax.inject.Inject;
5353

54+
import androidx.annotation.NonNull;
5455
import androidx.viewpager.widget.ViewPager;
5556

5657
/**
@@ -71,21 +72,25 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
7172

7273
private FirstRunActivityBinding binding;
7374
private ViewThemeUtils defaultViewThemeUtils;
75+
private int selectedPosition = 0;
7476

77+
@SuppressLint("SourceLockedOrientationActivity")
7578
@Override
7679
protected void onCreate(Bundle savedInstanceState) {
7780
enableAccountHandling = false;
7881

7982
super.onCreate(savedInstanceState);
8083
defaultViewThemeUtils = viewThemeUtilsFactory.withPrimaryAsBackground();
8184
defaultViewThemeUtils.platform.themeStatusBar(this, ColorRole.PRIMARY);
82-
this.binding = FirstRunActivityBinding.inflate(getLayoutInflater());
83-
setContentView(binding.getRoot());
84-
85-
boolean isProviderOrOwnInstallationVisible = getResources().getBoolean(R.bool.show_provider_or_own_installation);
8685

87-
setSlideshowSize(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
86+
//if device is not tablet then we have to lock it to Portrait mode
87+
//as we don't have images for that
88+
if (!com.nmc.android.utils.DisplayUtils.isTablet()) {
89+
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
90+
}
8891

92+
this.binding = FirstRunActivityBinding.inflate(getLayoutInflater());
93+
setContentView(binding.getRoot());
8994

9095
defaultViewThemeUtils.material.colorMaterialButtonFilledOnPrimary(binding.login);
9196
binding.login.setOnClickListener(v -> {
@@ -94,65 +99,52 @@ protected void onCreate(Bundle savedInstanceState) {
9499
authenticatorActivityIntent.putExtra(AuthenticatorActivity.EXTRA_USE_PROVIDER_AS_WEBLOGIN, false);
95100
startActivityForResult(authenticatorActivityIntent, FIRST_RUN_RESULT_CODE);
96101
} else {
102+
preferences.setOnBoardingComplete(true);
97103
finish();
98104
}
99105
});
100106

101-
102-
defaultViewThemeUtils.material.colorMaterialButtonOutlinedOnPrimary(binding.signup);
103-
binding.signup.setVisibility(isProviderOrOwnInstallationVisible ? View.VISIBLE : View.GONE);
104-
binding.signup.setOnClickListener(v -> {
105-
Intent authenticatorActivityIntent = new Intent(this, AuthenticatorActivity.class);
106-
authenticatorActivityIntent.putExtra(AuthenticatorActivity.EXTRA_USE_PROVIDER_AS_WEBLOGIN, true);
107-
108-
if (getIntent().getBooleanExtra(EXTRA_ALLOW_CLOSE, false)) {
109-
startActivityForResult(authenticatorActivityIntent, FIRST_RUN_RESULT_CODE);
110-
} else {
111-
authenticatorActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
112-
startActivity(authenticatorActivityIntent);
113-
}
114-
});
115-
116-
defaultViewThemeUtils.platform.colorTextView(binding.hostOwnServer, ColorRole.ON_PRIMARY);
117-
binding.hostOwnServer.setVisibility(isProviderOrOwnInstallationVisible ? View.VISIBLE : View.GONE);
118-
119-
if (isProviderOrOwnInstallationVisible) {
120-
binding.hostOwnServer.setOnClickListener(v -> DisplayUtils.startLinkIntent(this, R.string.url_server_install));
121-
}
122-
123-
124107
// Sometimes, accounts are not deleted when you uninstall the application so we'll do it now
125108
if (onboarding.isFirstRun()) {
126109
userAccountManager.removeAllAccounts();
127110
}
128111

129-
FeaturesViewAdapter featuresViewAdapter = new FeaturesViewAdapter(getSupportFragmentManager(), getFirstRun());
130-
binding.progressIndicator.setNumberOfSteps(featuresViewAdapter.getCount());
131-
binding.contentPanel.setAdapter(featuresViewAdapter);
112+
updateLoginButtonMargin();
113+
updateOnBoardingPager(selectedPosition);
132114

133115
binding.contentPanel.addOnPageChangeListener(this);
134116
}
135117

136-
private void setSlideshowSize(boolean isLandscape) {
137-
boolean isProviderOrOwnInstallationVisible = getResources().getBoolean(R.bool.show_provider_or_own_installation);
138-
139-
LinearLayout.LayoutParams layoutParams;
140-
141-
binding.buttonLayout.setOrientation(isLandscape ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
118+
private void updateOnBoardingPager(int selectedPosition) {
119+
OnBoardingPagerAdapter featuresViewAdapter = new OnBoardingPagerAdapter(this, OnBoardingUtils.Companion.getOnBoardingItems());
120+
binding.progressIndicator.setNumberOfSteps(featuresViewAdapter.getCount());
121+
binding.contentPanel.setAdapter(featuresViewAdapter);
122+
binding.contentPanel.setCurrentItem(selectedPosition);
123+
}
142124

143-
if (isProviderOrOwnInstallationVisible) {
144-
layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
125+
private void updateLoginButtonMargin() {
126+
if (com.nmc.android.utils.DisplayUtils.isLandscapeOrientation()) {
127+
if (binding.login.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
128+
((ViewGroup.MarginLayoutParams) binding.login.getLayoutParams()).setMargins(
129+
0, 0, 0, getResources().getDimensionPixelOffset(
130+
R.dimen.login_btn_bottom_margin_land));
131+
binding.login.requestLayout();
132+
}
145133
} else {
146-
layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.convertDpToPixel(isLandscape ? 100f : 150f, this));
134+
if (binding.login.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
135+
((ViewGroup.MarginLayoutParams) binding.login.getLayoutParams()).setMargins(
136+
0, 0, 0, getResources().getDimensionPixelOffset(
137+
R.dimen.login_btn_bottom_margin));
138+
binding.login.requestLayout();
139+
}
147140
}
148-
149-
binding.bottomLayout.setLayoutParams(layoutParams);
150141
}
151142

152143
@Override
153-
public void onConfigurationChanged(Configuration newConfig) {
144+
public void onConfigurationChanged(@NonNull Configuration newConfig) {
154145
super.onConfigurationChanged(newConfig);
155-
setSlideshowSize(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE);
146+
updateLoginButtonMargin();
147+
updateOnBoardingPager(selectedPosition);
156148
}
157149

158150
@Override
@@ -162,11 +154,7 @@ public void onBackPressed() {
162154
if (getIntent().getBooleanExtra(EXTRA_ALLOW_CLOSE, false)) {
163155
super.onBackPressed();
164156
} else {
165-
Intent intent = new Intent(getApplicationContext(), AuthenticatorActivity.class);
166-
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
167-
intent.putExtra(EXTRA_EXIT, true);
168-
startActivity(intent);
169-
finish();
157+
finishAffinity();
170158
}
171159
}
172160

@@ -188,7 +176,11 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse
188176

189177
@Override
190178
public void onPageSelected(int position) {
191-
binding.progressIndicator.animateToStep(position + 1);
179+
//-1 to position because this position doesn't start from 0
180+
selectedPosition = position - 1;
181+
182+
//pass directly the position here because this position will doesn't start from 0
183+
binding.progressIndicator.animateToStep(position);
192184
}
193185

194186
@Override
@@ -220,13 +212,4 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
220212
finish();
221213
}
222214
}
223-
224-
225-
public static FeatureItem[] getFirstRun() {
226-
return new FeatureItem[]{
227-
new FeatureItem(R.drawable.logo, R.string.first_run_1_text, R.string.empty, true, false),
228-
new FeatureItem(R.drawable.first_run_files, R.string.first_run_2_text, R.string.empty, true, false),
229-
new FeatureItem(R.drawable.first_run_groupware, R.string.first_run_3_text, R.string.empty, true, false),
230-
new FeatureItem(R.drawable.first_run_talk, R.string.first_run_4_text, R.string.empty, true, false)};
231-
}
232215
}

app/src/main/java/com/nextcloud/client/onboarding/OnboardingServiceImpl.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ internal class OnboardingServiceImpl constructor(
7272
}
7373

7474
override fun launchFirstRunIfNeeded(activity: Activity): Boolean {
75-
val isProviderOrOwnInstallationVisible = resources.getBoolean(R.bool.show_provider_or_own_installation)
76-
val canLaunch = isProviderOrOwnInstallationVisible && isFirstRun && activity is AuthenticatorActivity
75+
val canLaunch = !preferences.onBoardingComplete && activity is AuthenticatorActivity
7776
if (canLaunch) {
7877
val intent = Intent(activity, FirstRunActivity::class.java)
7978
activity.startActivityForResult(intent, AuthenticatorActivity.REQUEST_CODE_FIRST_RUN)

app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,10 @@ default void onDarkThemeModeChanged(DarkMode mode) {
377377

378378
void setCalendarLastBackup(long timestamp);
379379

380+
void setOnBoardingComplete(boolean isCompleted);
381+
382+
boolean getOnBoardingComplete();
383+
380384
void setPdfZoomTipShownCount(int count);
381385

382386
int getPdfZoomTipShownCount();

app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ public final class AppPreferencesImpl implements AppPreferences {
8888
private static final String PREF__FOLDER_SORT_ORDER = "folder_sort_order";
8989
private static final String PREF__FOLDER_LAYOUT = "folder_layout";
9090

91+
private static final String PREF__ON_BOARDING_COMPLETE = "on_boarding_complete";
92+
9193
private static final String PREF__LOCK_TIMESTAMP = "lock_timestamp";
9294
private static final String PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS = "show_media_scan_notifications";
9395
private static final String PREF__LOCK = SettingsActivity.PREFERENCE_LOCK;
@@ -705,6 +707,16 @@ public void setCalendarLastBackup(long timestamp) {
705707
preferences.edit().putLong(PREF__CALENDAR_LAST_BACKUP, timestamp).apply();
706708
}
707709

710+
@Override
711+
public void setOnBoardingComplete(boolean isCompleted) {
712+
preferences.edit().putBoolean(PREF__ON_BOARDING_COMPLETE, isCompleted).apply();
713+
}
714+
715+
@Override
716+
public boolean getOnBoardingComplete() {
717+
return preferences.getBoolean(PREF__ON_BOARDING_COMPLETE, false);
718+
}
719+
708720
@Override
709721
public void setPdfZoomTipShownCount(int count) {
710722
preferences.edit().putInt(PREF__PDF_ZOOM_TIP_SHOWN, count).apply();

0 commit comments

Comments
 (0)