diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 278490e41..3383207b7 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -23,6 +23,7 @@
tools:ignore="MissingLeanbackLauncher">
+
diff --git a/src/main/java/org/amahi/anywhere/AmahiModule.java b/src/main/java/org/amahi/anywhere/AmahiModule.java
index a888bf068..c0b8f89fc 100644
--- a/src/main/java/org/amahi/anywhere/AmahiModule.java
+++ b/src/main/java/org/amahi/anywhere/AmahiModule.java
@@ -22,7 +22,6 @@
import android.app.Application;
import android.content.Context;
-import org.amahi.anywhere.activity.AuthenticationActivity;
import org.amahi.anywhere.activity.NativeVideoActivity;
import org.amahi.anywhere.activity.NavigationActivity;
import org.amahi.anywhere.activity.OfflineFilesActivity;
@@ -36,7 +35,9 @@
import org.amahi.anywhere.activity.WebViewActivity;
import org.amahi.anywhere.cache.CacheModule;
import org.amahi.anywhere.fragment.AudioListFragment;
+import org.amahi.anywhere.fragment.MainLoginFragment;
import org.amahi.anywhere.fragment.NavigationFragment;
+import org.amahi.anywhere.fragment.PINAccessFragment;
import org.amahi.anywhere.fragment.ServerAppsFragment;
import org.amahi.anywhere.fragment.ServerFileAudioFragment;
import org.amahi.anywhere.fragment.ServerFileDownloadingFragment;
@@ -76,7 +77,6 @@
CacheModule.class
},
injects = {
- AuthenticationActivity.class,
NavigationActivity.class,
ServerAppActivity.class,
OfflineFilesActivity.class,
@@ -87,6 +87,8 @@
NativeVideoActivity.class,
RecentFilesActivity.class,
ServerFileWebActivity.class,
+ MainLoginFragment.class,
+ PINAccessFragment.class,
NavigationFragment.class,
ServerSharesFragment.class,
ServerAppsFragment.class,
diff --git a/src/main/java/org/amahi/anywhere/account/AmahiAccount.java b/src/main/java/org/amahi/anywhere/account/AmahiAccount.java
index cb940e13e..ea6fbb2aa 100644
--- a/src/main/java/org/amahi/anywhere/account/AmahiAccount.java
+++ b/src/main/java/org/amahi/anywhere/account/AmahiAccount.java
@@ -26,6 +26,9 @@
*/
public class AmahiAccount extends Account {
public static final String TYPE = "org.amahi";
+ public static final String TYPE_LOCAL = "org.amahi.local";
+
+ public static String accountType = AmahiAccount.TYPE;
public static final String TYPE_TOKEN = String.format("%s.FULL", TYPE);
diff --git a/src/main/java/org/amahi/anywhere/activity/AuthenticationActivity.java b/src/main/java/org/amahi/anywhere/activity/AuthenticationActivity.java
index b4d4ec702..771b147b9 100644
--- a/src/main/java/org/amahi/anywhere/activity/AuthenticationActivity.java
+++ b/src/main/java/org/amahi/anywhere/activity/AuthenticationActivity.java
@@ -21,44 +21,33 @@
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.text.method.LinkMovementMethod;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.widget.EditText;
-import android.widget.TextView;
import androidx.appcompat.app.AppCompatDelegate;
+import androidx.fragment.app.Fragment;
-import com.dd.processbutton.iml.ActionProcessButton;
-import com.google.android.material.textfield.TextInputLayout;
import com.squareup.otto.Subscribe;
import org.amahi.anywhere.AmahiApplication;
import org.amahi.anywhere.R;
import org.amahi.anywhere.account.AccountAuthenticatorAppCompatActivity;
import org.amahi.anywhere.account.AmahiAccount;
-import org.amahi.anywhere.bus.AuthenticationConnectionFailedEvent;
-import org.amahi.anywhere.bus.AuthenticationFailedEvent;
import org.amahi.anywhere.bus.AuthenticationSucceedEvent;
import org.amahi.anywhere.bus.BusProvider;
-import org.amahi.anywhere.server.client.AmahiClient;
+import org.amahi.anywhere.bus.PINAccessEvent;
+import org.amahi.anywhere.fragment.MainLoginFragment;
+import org.amahi.anywhere.fragment.PINAccessFragment;
+import org.amahi.anywhere.util.Constants;
+import org.amahi.anywhere.util.Fragments;
import org.amahi.anywhere.util.LocaleHelper;
-import org.amahi.anywhere.util.ViewDirector;
-
-import javax.inject.Inject;
+import org.amahi.anywhere.util.Preferences;
/**
* Authentication activity. Allows user authentication. If operation succeed
* the authentication token is saved at the {@link android.accounts.AccountManager}.
*/
-public class AuthenticationActivity extends AccountAuthenticatorAppCompatActivity implements TextWatcher {
- @Inject
- AmahiClient amahiClient;
+public class AuthenticationActivity extends AccountAuthenticatorAppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -70,183 +59,64 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_authentication);
- setUpInjections();
-
- setUpAuthentication();
-
- }
-
- private void setUpInjections() {
- AmahiApplication.from(this).inject(this);
- }
-
- private void setUpAuthentication() {
- setUpAuthenticationMessages();
- setUpAuthenticationListeners();
- }
-
- private String getUsername() {
- return getUsernameEdit().getText().toString();
- }
-
- private EditText getUsernameEdit() {
- TextInputLayout username_layout = findViewById(R.id.username_layout);
- return username_layout.getEditText();
- }
-
- private String getPassword() {
- return getPasswordEdit().getText().toString();
- }
-
- private EditText getPasswordEdit() {
- TextInputLayout password_layout = findViewById(R.id.password_layout);
- return password_layout.getEditText();
- }
-
- private ActionProcessButton getAuthenticationButton() {
- return findViewById(R.id.button_authentication);
- }
-
- private void setUpAuthenticationMessages() {
- TextView forgotPassword = findViewById(R.id.text_forgot_password);
- TextView authenticationConnectionFailureMessage = findViewById(R.id.text_message_authentication_connection);
- forgotPassword.setMovementMethod(LinkMovementMethod.getInstance());
- authenticationConnectionFailureMessage.setMovementMethod(LinkMovementMethod.getInstance());
- }
-
- private void setUpAuthenticationListeners() {
- setUpAuthenticationTextListener();
- setUpAuthenticationActionListener();
- }
-
- private void setUpAuthenticationTextListener() {
- getUsernameEdit().addTextChangedListener(this);
- getPasswordEdit().addTextChangedListener(this);
- getPasswordEdit().setOnEditorActionListener((v, actionId, event) -> {
- boolean handled = false;
- if (actionId == EditorInfo.IME_ACTION_GO) {
- onClick(getAuthenticationButton());
- handled = true;
- }
- return handled;
- });
+ setUpAuthenticationFragment();
}
@Override
- public void onTextChanged(CharSequence text, int after, int before, int count) {
- hideAuthenticationFailureMessage();
- }
-
- private void hideAuthenticationFailureMessage() {
- ViewDirector.of(this, R.id.animator_message).show(R.id.view_message_empty);
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ AmahiAccount.accountType = savedInstanceState.getString(State.ACCOUNT_TYPE, AmahiAccount.TYPE);
}
- @Override
- public void afterTextChanged(Editable text) {
- }
-
- @Override
- public void beforeTextChanged(CharSequence text, int start, int count, int before) {
- }
-
- private void setUpAuthenticationActionListener() {
- getAuthenticationButton().setOnClickListener(this::onClick);
- }
-
- public void onClick(View view) {
- if (getUsername().trim().isEmpty() || getPassword().trim().isEmpty()) {
- ViewDirector.of(this, R.id.animator_message).show(R.id.text_message_authentication_empty);
-
- if (getUsername().trim().isEmpty())
- getUsernameEdit().requestFocus();
-
- if (getPassword().trim().isEmpty())
- getPasswordEdit().requestFocus();
-
- if (getUsername().trim().isEmpty() && getPassword().trim().isEmpty())
- getUsernameEdit().requestFocus();
-
+ private void setUpAuthenticationFragment() {
+ if (AmahiAccount.accountType.equals(AmahiAccount.TYPE)) {
+ MainLoginFragment f = (MainLoginFragment) getSupportFragmentManager().findFragmentByTag(MainLoginFragment.TAG);
+ if (f == null) {
+ showMainLoginFragment();
+ }
} else {
- startAuthentication();
-
- authenticate();
+ PINAccessFragment f = (PINAccessFragment) getSupportFragmentManager().findFragmentByTag(PINAccessFragment.TAG);
+ if (f == null) {
+ showPINAccessFragment();
+ }
}
}
- private void startAuthentication() {
- hideAuthenticationText();
-
- showProgress();
-
- hideAuthenticationFailureMessage();
- }
-
- private void hideAuthenticationText() {
- getUsernameEdit().setEnabled(false);
- getPasswordEdit().setEnabled(false);
- }
-
- private void showProgress() {
- ActionProcessButton authenticationButton = getAuthenticationButton();
-
- authenticationButton.setMode(ActionProcessButton.Mode.ENDLESS);
- authenticationButton.setProgress(1);
- }
-
- private void authenticate() {
- amahiClient.authenticate(getUsername().trim(), getPassword());
- }
-
- @Subscribe
- public void onAuthenticationFailed(AuthenticationFailedEvent event) {
- finishAuthentication();
-
- showAuthenticationFailureMessage();
- }
-
- private void finishAuthentication() {
- showAuthenticationText();
-
- hideProgress();
- }
-
- private void showAuthenticationText() {
- getUsernameEdit().setEnabled(true);
- getPasswordEdit().setEnabled(true);
- }
-
- private void hideProgress() {
- getAuthenticationButton().setProgress(0);
- }
-
- private void showAuthenticationFailureMessage() {
- ViewDirector.of(this, R.id.animator_message).show(R.id.text_message_authentication);
+ private void showMainLoginFragment() {
+ Fragment fragment = Fragments.Builder.buildMainLoginFragment();
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.main_container, fragment, MainLoginFragment.TAG)
+ .commit();
}
@Subscribe
- public void onAuthenticationConnectionFailed(AuthenticationConnectionFailedEvent event) {
- finishAuthentication();
-
- showAuthenticationConnectionFailureMessage();
- }
+ public void onAuthenticationSucceed(AuthenticationSucceedEvent event) {
+ if (AmahiAccount.accountType.equals(AmahiAccount.TYPE)) {
+ MainLoginFragment fragment = (MainLoginFragment) getSupportFragmentManager().findFragmentByTag(MainLoginFragment.TAG);
- private void showAuthenticationConnectionFailureMessage() {
- ViewDirector.of(this, R.id.animator_message).show(R.id.text_message_authentication_connection);
- }
+ finishAuthentication(event.getAuthentication().getToken(), fragment.getUsername(), fragment.getPassword());
+ } else {
+ PINAccessFragment fragment = (PINAccessFragment) getSupportFragmentManager().findFragmentByTag(PINAccessFragment.TAG);
- @Subscribe
- public void onAuthenticationSucceed(AuthenticationSucceedEvent event) {
- finishAuthentication(event.getAuthentication().getToken());
+ finishAuthentication(event.getAuthentication().getToken(), Constants.pinAccessUsername, fragment.getPIN());
+ }
}
- private void finishAuthentication(String authenticationToken) {
+ private void finishAuthentication(String authenticationToken, String username, String password) {
AccountManager accountManager = AccountManager.get(this);
Bundle authenticationBundle = new Bundle();
- Account account = new AmahiAccount(getUsername());
+ Account account = new AmahiAccount(username);
+ if (AmahiAccount.accountType.equals(AmahiAccount.TYPE_LOCAL)) {
+ authenticationBundle.putString("ip", Preferences.getLocalServerIP(this));
+ authenticationBundle.putString("is_local", "T");
+ } else {
+ authenticationBundle.putString("is_local", "F");
+ }
- if (accountManager.addAccountExplicitly(account, getPassword(), null)) {
+ if (accountManager.addAccountExplicitly(account, password, authenticationBundle)) {
authenticationBundle.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
authenticationBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
authenticationBundle.putString(AccountManager.KEY_AUTHTOKEN, authenticationToken);
@@ -256,20 +126,42 @@ private void finishAuthentication(String authenticationToken) {
setAccountAuthenticatorResult(authenticationBundle);
- setResult(Activity.RESULT_OK);
+ setResult(RESULT_OK);
finish();
}
+ @Subscribe
+ public void onPINAccess(PINAccessEvent event) {
+ AmahiAccount.accountType = AmahiAccount.TYPE_LOCAL;
+ showPINAccessFragment();
+ }
+
+ private void showPINAccessFragment() {
+ Fragment fragment = Fragments.Builder.buildPINFragment();
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.main_container, fragment, PINAccessFragment.TAG)
+ .addToBackStack(MainLoginFragment.TAG)
+ .commit();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ outState.putString(State.ACCOUNT_TYPE, AmahiAccount.accountType);
+ }
+
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
BusProvider.getBus().register(this);
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
BusProvider.getBus().unregister(this);
@@ -277,11 +169,18 @@ protected void onPause() {
@Override
public void onBackPressed() {
- finishAffinity();
+ super.onBackPressed();
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(LocaleHelper.onAttach(newBase));
}
+
+ private static final class State {
+ static final String ACCOUNT_TYPE = "account_type";
+
+ private State() {
+ }
+ }
}
diff --git a/src/main/java/org/amahi/anywhere/activity/IntroductionActivity.java b/src/main/java/org/amahi/anywhere/activity/IntroductionActivity.java
index 618bc2a65..3c7523a5c 100644
--- a/src/main/java/org/amahi/anywhere/activity/IntroductionActivity.java
+++ b/src/main/java/org/amahi/anywhere/activity/IntroductionActivity.java
@@ -23,6 +23,7 @@
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
+
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.core.content.ContextCompat;
@@ -62,7 +63,7 @@ public void onSkipPressed(Fragment currentFragment) {
}
private void launchTv() {
- if(!CheckTV.isATV(this) && Preferences.getFirstRun(this)) {
+ if (!CheckTV.isATV(this) && Preferences.getFirstRun(this)) {
Preferences.setFirstRun(this);
launchNavigation();
}
diff --git a/src/main/java/org/amahi/anywhere/activity/SplashActivity.java b/src/main/java/org/amahi/anywhere/activity/SplashActivity.java
index 4101f61a8..bc822b4d7 100644
--- a/src/main/java/org/amahi/anywhere/activity/SplashActivity.java
+++ b/src/main/java/org/amahi/anywhere/activity/SplashActivity.java
@@ -22,10 +22,13 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
+import org.amahi.anywhere.util.CheckTV;
import org.amahi.anywhere.util.LocaleHelper;
+import org.amahi.anywhere.util.Preferences;
public class SplashActivity extends AppCompatActivity {
@@ -39,15 +42,24 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
}
private void setUpActivity() {
- launchNavigation();
+ if (Preferences.getFirstRun(this) && !CheckTV.isATV(this)) {
+ launchIntro();
+ } else {
+ launchNavigation();
+ }
}
private void launchNavigation() {
startActivity(new Intent(this, NavigationActivity.class));
}
+ private void launchIntro() {
+ startActivity(new Intent(this, IntroductionActivity.class));
+ }
+
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(LocaleHelper.onAttach(newBase));
}
+
}
diff --git a/src/main/java/org/amahi/anywhere/bus/PINAccessEvent.java b/src/main/java/org/amahi/anywhere/bus/PINAccessEvent.java
new file mode 100644
index 000000000..a8c3fcfb6
--- /dev/null
+++ b/src/main/java/org/amahi/anywhere/bus/PINAccessEvent.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 Amahi
+ *
+ * This file is part of Amahi.
+ *
+ * Amahi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Amahi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Amahi. If not, see .
+ */
+
+package org.amahi.anywhere.bus;
+
+public class PINAccessEvent implements BusEvent {
+}
diff --git a/src/main/java/org/amahi/anywhere/fragment/LocalLoginDialogFragment.java b/src/main/java/org/amahi/anywhere/fragment/LocalLoginDialogFragment.java
new file mode 100644
index 000000000..ceda4bb89
--- /dev/null
+++ b/src/main/java/org/amahi/anywhere/fragment/LocalLoginDialogFragment.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014 Amahi
+ *
+ * This file is part of Amahi.
+ *
+ * Amahi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Amahi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Amahi. If not, see .
+ */
+
+package org.amahi.anywhere.fragment;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.os.Bundle;
+
+import androidx.fragment.app.DialogFragment;
+
+public class LocalLoginDialogFragment extends DialogFragment {
+
+ private ProgressDialog dialog;
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ dialog = new ProgressDialog(getActivity());
+ dialog.setTitle("Logging In");
+ dialog.setCancelable(false);
+ dialog.setIndeterminate(false);
+ dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ return dialog;
+ }
+
+ public void setProgress(int progress) {
+ dialog.setProgress(progress);
+ }
+}
diff --git a/src/main/java/org/amahi/anywhere/fragment/MainLoginFragment.java b/src/main/java/org/amahi/anywhere/fragment/MainLoginFragment.java
new file mode 100644
index 000000000..c611a765c
--- /dev/null
+++ b/src/main/java/org/amahi/anywhere/fragment/MainLoginFragment.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2014 Amahi
+ *
+ * This file is part of Amahi.
+ *
+ * Amahi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Amahi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Amahi. If not, see .
+ */
+
+package org.amahi.anywhere.fragment;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.text.method.LinkMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.dd.processbutton.iml.ActionProcessButton;
+import com.google.android.material.textfield.TextInputLayout;
+import com.squareup.otto.Subscribe;
+
+import org.amahi.anywhere.AmahiApplication;
+import org.amahi.anywhere.R;
+import org.amahi.anywhere.account.AmahiAccount;
+import org.amahi.anywhere.bus.AuthenticationConnectionFailedEvent;
+import org.amahi.anywhere.bus.AuthenticationFailedEvent;
+import org.amahi.anywhere.bus.BusProvider;
+import org.amahi.anywhere.bus.PINAccessEvent;
+import org.amahi.anywhere.server.client.AmahiClient;
+import org.amahi.anywhere.util.ViewDirector;
+
+import java.util.Objects;
+
+import javax.inject.Inject;
+
+/**
+ * A simple {@link Fragment } subclass.
+ */
+
+public class MainLoginFragment extends Fragment implements TextWatcher,
+ View.OnClickListener {
+
+ public static final String TAG = MainLoginFragment.class.getSimpleName();
+ @Inject
+ AmahiClient amahiClient;
+ TextInputLayout username_layout, password_layout;
+ ActionProcessButton signInButton;
+ TextView pinLoginButton;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.layout_authentication, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ setUpInjections();
+ setUpLayout(view);
+ setUpAuthentication(view);
+ }
+
+ private void setUpInjections() {
+ AmahiApplication.from(getActivity()).inject(this);
+ }
+
+
+ private void setUpLayout(View view) {
+ username_layout = view.findViewById(R.id.username_layout);
+ password_layout = view.findViewById(R.id.password_layout);
+ signInButton = view.findViewById(R.id.button_authentication);
+ pinLoginButton = view.findViewById(R.id.text_pin_access);
+ }
+
+ private void setUpAuthentication(View view) {
+ setUpAuthenticationMessages(view);
+ setUpAuthenticationListeners();
+ }
+
+ private void setUpAuthenticationMessages(View view) {
+ TextView forgotPassword = view.findViewById(R.id.text_forgot_password);
+ TextView authenticationConnectionFailureMessage = view.findViewById(R.id.text_message_authentication_connection);
+
+ forgotPassword.setMovementMethod(LinkMovementMethod.getInstance());
+ authenticationConnectionFailureMessage.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+
+ private void setUpAuthenticationListeners() {
+ setUpAuthenticationTextListener();
+ setUpPINAccessListener();
+ }
+
+ private void setUpAuthenticationTextListener() {
+ getUsernameEditText().addTextChangedListener(this);
+ getPasswordEditText().addTextChangedListener(this);
+
+ getPasswordEditText().setOnEditorActionListener((v, actionId, event) -> {
+ boolean handled = false;
+ if (actionId == EditorInfo.IME_ACTION_GO) {
+ signInButton.callOnClick();
+ handled = true;
+ }
+ return handled;
+ });
+ signInButton.setOnClickListener(this);
+ }
+
+ private EditText getUsernameEditText() {
+ return username_layout.getEditText();
+ }
+
+ private EditText getPasswordEditText() {
+ return password_layout.getEditText();
+ }
+
+ @Override
+ public void onClick(View view) {
+ if(view.getId()==signInButton.getId()) {
+
+ InputMethodManager imm = (InputMethodManager) Objects.requireNonNull(getContext()).getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+
+ if (getUsername().trim().isEmpty() || getPassword().trim().isEmpty()) {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.text_message_authentication_empty);
+
+ if (getUsername().trim().isEmpty())
+ getUsernameEditText().requestFocus();
+
+ if (getPassword().trim().isEmpty())
+ getPasswordEditText().requestFocus();
+
+ if (getUsername().trim().isEmpty() && getPassword().trim().isEmpty())
+ getUsernameEditText().requestFocus();
+
+ } else if (getUsername().contains(" ")) {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.text_message_authentication);
+
+ } else {
+ startAuthentication();
+
+ authenticate();
+ }
+ }
+ }
+
+ public String getUsername() {
+ return username_layout.getEditText().getText().toString();
+ }
+
+ public String getPassword() {
+ return password_layout.getEditText().getText().toString();
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ hideAuthenticationFailureMessage();
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) { }
+
+ private void startAuthentication() {
+ hideAuthenticationText();
+
+ showProgress();
+
+ hideAuthenticationFailureMessage();
+ }
+
+ private void hideAuthenticationFailureMessage() {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.view_message_empty);
+ }
+
+ private void hideAuthenticationText() {
+ getUsernameEditText().setEnabled(false);
+ getPasswordEditText().setEnabled(false);
+ }
+
+ private void showProgress() {
+ signInButton.setMode(ActionProcessButton.Mode.ENDLESS);
+ signInButton.setProgress(1);
+ }
+
+ private void authenticate() {
+ AmahiAccount.accountType = AmahiAccount.TYPE;
+ amahiClient.authenticate(getUsername(), getPassword());
+ }
+
+ @Subscribe
+ public void onAuthenticationFailed(AuthenticationFailedEvent event) {
+ finishAuthentication();
+
+ showAuthenticationFailureMessage();
+ }
+
+ private void finishAuthentication() {
+ showAuthenticationText();
+
+ hideProgress();
+ }
+
+ private void showAuthenticationText() {
+ getUsernameEditText().setEnabled(true);
+ getPasswordEditText().setEnabled(true);
+ }
+
+ private void hideProgress() {
+ signInButton.setProgress(0);
+ }
+
+ private void showAuthenticationFailureMessage() {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.text_message_authentication);
+ }
+
+ @Subscribe
+ public void onAuthenticationConnectionFailed(AuthenticationConnectionFailedEvent event) {
+ finishAuthentication();
+
+ showAuthenticationConnectionFailureMessage();
+ }
+
+ private void showAuthenticationConnectionFailureMessage() {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.text_message_authentication_connection);
+ }
+
+ private void setUpPINAccessListener() {
+ pinLoginButton.setOnClickListener((v) -> BusProvider.getBus().post(new PINAccessEvent()));
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ BusProvider.getBus().register(this);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ BusProvider.getBus().unregister(this);
+ }
+}
diff --git a/src/main/java/org/amahi/anywhere/fragment/NavigationFragment.java b/src/main/java/org/amahi/anywhere/fragment/NavigationFragment.java
index e29cce08d..5683131b7 100644
--- a/src/main/java/org/amahi/anywhere/fragment/NavigationFragment.java
+++ b/src/main/java/org/amahi/anywhere/fragment/NavigationFragment.java
@@ -55,7 +55,6 @@
import org.amahi.anywhere.AmahiApplication;
import org.amahi.anywhere.R;
import org.amahi.anywhere.account.AmahiAccount;
-import org.amahi.anywhere.activity.IntroductionActivity;
import org.amahi.anywhere.adapter.NavigationDrawerAdapter;
import org.amahi.anywhere.bus.AppsSelectedEvent;
import org.amahi.anywhere.bus.BusProvider;
@@ -91,13 +90,16 @@
/**
* Navigation fragments. Shows main application sections and servers list as well.
*/
-public class NavigationFragment extends Fragment implements AccountManagerCallback,
- OnAccountsUpdateListener {
+public class NavigationFragment extends Fragment implements AccountManagerCallback, OnAccountsUpdateListener {
+
@Inject
AmahiClient amahiClient;
+
@Inject
ServerClient serverClient;
+
View view;
+
private Intent tvIntent;
private Context mContext;
private Activity mActivity;
@@ -105,6 +107,8 @@ public class NavigationFragment extends Fragment implements AccountManagerCallba
private boolean areServersVisible;
private List serversList;
+ public static final String TAG = NavigationFragment.class.getSimpleName();
+
@Override
public void onAttach(Context context) {
super.onAttach(context);
@@ -155,21 +159,11 @@ private AccountManager getAccountManager() {
@Override
public void onAccountsUpdated(Account[] accounts) {
-
- if (Preferences.getFirstRun(mContext)) {
- launchIntro();
- }
-
if (getAccounts().isEmpty()) {
setUpAccount();
}
}
- private void launchIntro() {
- startActivity(new Intent(mContext, IntroductionActivity.class));
- mActivity.finishAffinity();
- }
-
private void setUpContentRefreshing() {
SwipeRefreshLayout refreshLayout = getRefreshLayout();
@@ -201,11 +195,20 @@ private void setUpAuthenticationToken() {
public void run(AccountManagerFuture accountManagerFuture) {
try {
Bundle accountManagerResult = accountManagerFuture.getResult();
+ Account account = getAccountManager().getAccounts()[0];
+
+ String isLocalUser = checkIfLocalUser();
+ String ip = getAccountManager().getUserData(account, "ip");
String authenticationToken = accountManagerResult.getString(AccountManager.KEY_AUTHTOKEN);
if (authenticationToken != null) {
- setUpServers(authenticationToken);
+ if (isLocalUser.equals("F")) {
+ setUpServers(authenticationToken);
+ } else {
+ BusProvider.getBus().post(new SharesSelectedEvent());
+ setUpLocalServerApi(authenticationToken, ip);
+ }
} else {
setUpAuthenticationToken();
}
@@ -216,6 +219,11 @@ public void run(AccountManagerFuture accountManagerFuture) {
}
}
+ private String checkIfLocalUser() {
+ Account account = getAccountManager().getAccounts()[0];
+ return getAccountManager().getUserData(account, "is_local");
+ }
+
private void tearDownActivity() {
mActivity.finish();
}
@@ -329,9 +337,6 @@ private void setUpAuthentication() {
if (getAccounts().isEmpty()) {
setUpAccount();
} else {
- if (Preferences.getFirstRun(mActivity) && !checkIsATV()) {
- launchIntro();
- }
setUpAuthenticationToken();
}
}
@@ -435,17 +440,19 @@ private TextView getServerNameTextView() {
}
private void setUpNavigationListener() {
- getNavigationListView().addOnItemTouchListener(new RecyclerItemClickListener(mContext, (view, position) -> {
- getNavigationListView().dispatchSetActivated(false);
+ if (checkIfLocalUser().equals("F")) {
+ getNavigationListView().addOnItemTouchListener(new RecyclerItemClickListener(mContext, (view, position) -> {
+ getNavigationListView().dispatchSetActivated(false);
- view.setActivated(true);
+ view.setActivated(true);
- if (!areServersVisible) {
- selectedServerListener(position);
- } else {
- serverClicked(position);
- }
- }));
+ if (!areServersVisible) {
+ selectedServerListener(position);
+ } else {
+ serverClicked(position);
+ }
+ }));
+ }
getOfflineFilesLayout().setOnClickListener(view -> showOfflineFiles());
@@ -534,8 +541,10 @@ private void showNavigationItems() {
areServersVisible = false;
setUpNavigationAdapter();
- getServerNameTextView().setCompoundDrawablesWithIntrinsicBounds(
- 0, 0, R.drawable.nav_arrow_down, 0);
+ if (checkIfLocalUser().equals("F")) {
+ getServerNameTextView().setCompoundDrawablesWithIntrinsicBounds(
+ 0, 0, R.drawable.nav_arrow_down, 0);
+ }
getOfflineFilesLayout().setVisibility(View.VISIBLE);
getRecentFilesLayout().setVisibility(View.VISIBLE);
@@ -654,6 +663,11 @@ private void showRecentFiles() {
BusProvider.getBus().post(new RecentFilesSelectedEvent());
}
+ private void setUpLocalServerApi(String auth, String ip) {
+ serverClient.connectLocalServer(auth, ip);
+ setUpServersContent(auth);
+ }
+
@Subscribe
public void onServerConnectionChanged(ServerConnectionChangedEvent event) {
areServersVisible = false;
@@ -720,7 +734,6 @@ private void tearDownAuthenticationListener() {
getAccountManager().removeOnAccountsUpdatedListener(this);
}
- /*Sets the adapter for navigation drawer after getting server names*/
public void showServers() {
areServersVisible = true;
getNavigationListView().setAdapter(null);
diff --git a/src/main/java/org/amahi/anywhere/fragment/PINAccessFragment.java b/src/main/java/org/amahi/anywhere/fragment/PINAccessFragment.java
new file mode 100644
index 000000000..f763cd275
--- /dev/null
+++ b/src/main/java/org/amahi/anywhere/fragment/PINAccessFragment.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2014 Amahi
+ *
+ * This file is part of Amahi.
+ *
+ * Amahi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Amahi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Amahi. If not, see .
+ */
+
+package org.amahi.anywhere.fragment;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.text.method.LinkMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.dd.processbutton.iml.ActionProcessButton;
+import com.google.android.material.textfield.TextInputLayout;
+import com.squareup.otto.Subscribe;
+
+import org.amahi.anywhere.R;
+import org.amahi.anywhere.account.AmahiAccount;
+import org.amahi.anywhere.bus.AuthenticationConnectionFailedEvent;
+import org.amahi.anywhere.bus.AuthenticationFailedEvent;
+import org.amahi.anywhere.bus.BusProvider;
+import org.amahi.anywhere.task.LocalServerProbingTask;
+import org.amahi.anywhere.util.ViewDirector;
+
+import java.util.Objects;
+
+public class PINAccessFragment extends Fragment {
+
+ public static final String TAG = PINAccessFragment.class.getSimpleName();
+
+ private TextInputLayout pinLayout;
+ private ActionProcessButton pinLoginButton;
+ private View view;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_pin_access, container, false);
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ this.view = view;
+ setUpPINAuthentication(view);
+ }
+
+ private void setUpPINAuthentication(View view) {
+ setUpPINViews(view);
+ setUpAuthenticationMessages(view);
+ setUpAuthenticationListeners();
+ }
+
+ private void setUpPINViews(View view) {
+ pinLayout = view.findViewById(R.id.pin_layout);
+ pinLoginButton = view.findViewById(R.id.button_pin_sign_in);
+ }
+
+ private void setUpAuthenticationMessages(View view) {
+ TextView pinWrongMessage = view.findViewById(R.id.text_message_pin);
+ TextView connectionFailureMessage = view.findViewById(R.id.text_message_connection);
+ TextView pinEmptyMessage = view.findViewById(R.id.text_message_pin_empty);
+
+ pinWrongMessage.setMovementMethod(LinkMovementMethod.getInstance());
+ connectionFailureMessage.setMovementMethod(LinkMovementMethod.getInstance());
+ pinEmptyMessage.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+
+ private EditText getPINEditText() {
+ return pinLayout.getEditText();
+ }
+
+ public String getPIN() {
+ return getPINEditText().getText().toString();
+ }
+
+ private void setUpAuthenticationListeners() {
+ getPINEditText().addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.view_message_empty);
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+
+ }
+ });
+
+ getPINEditText().setOnEditorActionListener((v, actionId, event) -> pinLoginButton.callOnClick());
+
+ pinLoginButton.setOnClickListener(v -> {
+ if (getPIN().trim().isEmpty()) {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.text_message_pin_empty);
+ return;
+ } else if (getPIN().length() > 5 || getPIN().length() < 3) {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.text_message_pin);
+ return;
+ }
+ showProgress();
+ startAuthentication(getPIN());
+ });
+ }
+
+ private void showProgress() {
+
+ InputMethodManager imm = (InputMethodManager) Objects.requireNonNull(getContext()).getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+
+ if(pinLoginButton!=null) {
+ pinLoginButton.setMode(ActionProcessButton.Mode.ENDLESS);
+ pinLoginButton.setProgress(1);
+ }
+ }
+
+ private void hideProgress() {
+ if(pinLoginButton!=null) {
+ pinLoginButton.setProgress(0);
+ }
+ }
+
+ private void startAuthentication(String pin) {
+ AmahiAccount.accountType = AmahiAccount.TYPE_LOCAL;
+ new LocalServerProbingTask(getActivity(), pin).execute();
+ }
+
+ @Subscribe
+ public void onAuthenticationFailed(AuthenticationFailedEvent event) {
+ hideProgress();
+ enableUIControls();
+ showAuthenticationFailMessage();
+ }
+
+ private void enableUIControls() {
+ pinLayout.setEnabled(true);
+ pinLoginButton.setEnabled(true);
+ }
+
+ private void showAuthenticationFailMessage() {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.text_message_pin);
+ }
+
+ @Subscribe
+ public void onAuthenticationConnectionFail(AuthenticationConnectionFailedEvent event) {
+ hideProgress();
+ enableUIControls();
+ showAuthenticationConnectionFailMessage();
+ }
+
+ private void showAuthenticationConnectionFailMessage() {
+ ViewDirector.of(getActivity(), R.id.animator_message).show(R.id.text_message_connection);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ BusProvider.getBus().register(this);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ BusProvider.getBus().unregister(this);
+ }
+}
diff --git a/src/main/java/org/amahi/anywhere/server/client/ServerClient.java b/src/main/java/org/amahi/anywhere/server/client/ServerClient.java
index 32d705c58..c25b05121 100644
--- a/src/main/java/org/amahi/anywhere/server/client/ServerClient.java
+++ b/src/main/java/org/amahi/anywhere/server/client/ServerClient.java
@@ -69,7 +69,6 @@
import static org.amahi.anywhere.util.Android.loadServersFromAsset;
-
/**
* Server API implementation. Wraps {@link org.amahi.anywhere.server.api.ProxyApi} and
* {@link org.amahi.anywhere.server.api.ServerApi}. Reacts to network connection changes as well.
@@ -87,6 +86,8 @@ public class ServerClient {
private int network;
+ public static final String TAG = ServerClient.class.getSimpleName();
+
@Inject
public ServerClient(ApiAdapter apiAdapter) {
this.apiAdapter = apiAdapter;
@@ -156,7 +157,9 @@ public boolean isConnected() {
}
public boolean isConnected(Server server) {
- return (this.server != null) && (this.serverRoute != null) && (this.server.getSession().equals(server.getSession()));
+ return (this.server != null) && (this.serverRoute != null)
+ && (this.server.getSession().equals(server.getSession())
+ && server.getAuthToken() != null);
}
public boolean isConnectedLocal() {
@@ -339,4 +342,17 @@ public Uri getFileThumbnailUri(ServerShare share, ServerFile file) {
.build();
}
+
+ public void connectLocalServer(String auth, String ip) {
+ serverRoute = new ServerRoute();
+ serverRoute.setLocalAddress(getLocalAddress(ip));
+ serverAddress = serverRoute.getLocalAddress();
+ server = new Server(auth);
+ server.setAuthToken(auth);
+ serverApi = buildServerApi();
+ }
+
+ private String getLocalAddress(String ip) {
+ return "http://" + ip + ":4563/";
+ }
}
diff --git a/src/main/java/org/amahi/anywhere/server/model/Authentication.java b/src/main/java/org/amahi/anywhere/server/model/Authentication.java
index 37ec3b38a..cf787e0ea 100644
--- a/src/main/java/org/amahi/anywhere/server/model/Authentication.java
+++ b/src/main/java/org/amahi/anywhere/server/model/Authentication.java
@@ -25,7 +25,7 @@
* Authentication API resource.
*/
public class Authentication {
- @SerializedName("access_token")
+ @SerializedName(value = "access_token", alternate = "auth_token")
private String token;
public String getToken() {
diff --git a/src/main/java/org/amahi/anywhere/server/model/Server.java b/src/main/java/org/amahi/anywhere/server/model/Server.java
index 07f0f48c2..8575abddc 100644
--- a/src/main/java/org/amahi/anywhere/server/model/Server.java
+++ b/src/main/java/org/amahi/anywhere/server/model/Server.java
@@ -48,6 +48,8 @@ public Server[] newArray(int size) {
private String session;
@SerializedName("active")
private boolean active;
+
+ private String authToken;
private boolean debug = false;
private int index;
@@ -69,6 +71,14 @@ public Server(Parcel parcel) {
this.active = Boolean.valueOf(parcel.readString());
}
+ public void setAuthToken(String authToken) {
+ this.authToken = authToken;
+ }
+
+ public String getAuthToken() {
+ return authToken;
+ }
+
public static List filterActiveServers(List servers) {
List activeServers = new ArrayList<>();
for (Server server : servers) {
diff --git a/src/main/java/org/amahi/anywhere/task/LocalServerProbingTask.java b/src/main/java/org/amahi/anywhere/task/LocalServerProbingTask.java
new file mode 100644
index 000000000..2735ce971
--- /dev/null
+++ b/src/main/java/org/amahi/anywhere/task/LocalServerProbingTask.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2014 Amahi
+ *
+ * This file is part of Amahi.
+ *
+ * Amahi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Amahi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Amahi. If not, see .
+ */
+
+package org.amahi.anywhere.task;
+
+import android.content.Context;
+import android.net.DhcpInfo;
+import android.net.wifi.WifiManager;
+import android.os.AsyncTask;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.google.gson.Gson;
+
+import org.amahi.anywhere.bus.AuthenticationConnectionFailedEvent;
+import org.amahi.anywhere.bus.AuthenticationFailedEvent;
+import org.amahi.anywhere.bus.AuthenticationSucceedEvent;
+import org.amahi.anywhere.bus.BusEvent;
+import org.amahi.anywhere.bus.BusProvider;
+import org.amahi.anywhere.server.model.Authentication;
+import org.amahi.anywhere.util.Preferences;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.net.InetAddress;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+public class LocalServerProbingTask extends AsyncTask {
+
+ private static final String TAG = LocalServerProbingTask.class.getSimpleName();
+
+ private WeakReference context;
+ private OkHttpClient httpClient;
+ private RequestBody body;
+
+ public LocalServerProbingTask(Context context, @NonNull String pin) {
+ this.context = new WeakReference<>(context);
+ this.httpClient = buildHttpClient();
+ this.body = buildRequestBody(pin);
+ }
+
+ private OkHttpClient buildHttpClient() {
+ OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
+ clientBuilder.connectTimeout(1, TimeUnit.SECONDS);
+ httpClient = clientBuilder.build();
+ return httpClient;
+ }
+
+ private RequestBody buildRequestBody(String pin) {
+ MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+ return RequestBody.create(JSON, "{\"pin\":\"" + pin + "\"}");
+ }
+
+ @Override
+ protected BusEvent doInBackground(Void... voids) {
+ WifiManager wm = (WifiManager) context.get().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ if (wm != null) {
+ DhcpInfo d = wm.getDhcpInfo();
+ String ip = intToIp(d.dns1);
+ String prefix = ip.substring(0, ip.lastIndexOf(".") + 1);
+ for (int i = 0; i < 255; i++) {
+ String testIp = prefix + String.valueOf(i);
+ try {
+ InetAddress ipAddress = InetAddress.getByName(testIp);
+ String hostName = ipAddress.getCanonicalHostName();
+ Log.v(TAG, "Trying Connection: " + hostName);
+ if (ipAddress.isReachable(200)) {
+ Request httpRequest = new Request.Builder()
+ .url(getConnectionUrl(hostName))
+ .post(body)
+ .build();
+
+ Response response = httpClient
+ .newCall(httpRequest)
+ .execute();
+
+ if (response.code() == 200) {
+ Gson gson = new Gson();
+ String json = response.body().string();
+ Authentication authentication = gson.fromJson(json, Authentication.class);
+ Preferences.setLocalServerIP(context.get().getApplicationContext(), testIp);
+ return new AuthenticationSucceedEvent(authentication);
+ } else if (response.code() == 403) {
+ return new AuthenticationFailedEvent();
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return new AuthenticationConnectionFailedEvent();
+ }
+
+ private String intToIp(int i) {
+ return (i & 0xFF) + "." +
+ ((i >> 8) & 0xFF) + "." +
+ ((i >> 16) & 0xFF) + "." +
+ ((i >> 24) & 0xFF);
+ }
+
+ private String getConnectionUrl(String hostName) {
+ return "http://" + hostName + ":4563/auth";
+ }
+
+ @Override
+ protected void onPostExecute(BusEvent busEvent) {
+ super.onPostExecute(busEvent);
+
+ BusProvider.getBus().post(busEvent);
+ }
+}
diff --git a/src/main/java/org/amahi/anywhere/util/Constants.java b/src/main/java/org/amahi/anywhere/util/Constants.java
index 24adff395..f413eb4a7 100644
--- a/src/main/java/org/amahi/anywhere/util/Constants.java
+++ b/src/main/java/org/amahi/anywhere/util/Constants.java
@@ -43,6 +43,7 @@ public class Constants {
public static final String sharesPathAppendLoc = "shares";
+ public static final String pinAccessUsername = "Server";
public static final String welcomeToAmahi = "Welcome to Amahi";
public static final String amahiAndroidUrl = "https://www.amahi.org/android";
diff --git a/src/main/java/org/amahi/anywhere/util/Fragments.java b/src/main/java/org/amahi/anywhere/util/Fragments.java
index 990955450..fa4076837 100644
--- a/src/main/java/org/amahi/anywhere/util/Fragments.java
+++ b/src/main/java/org/amahi/anywhere/util/Fragments.java
@@ -30,8 +30,10 @@
import org.amahi.anywhere.fragment.AudioListFragment;
import org.amahi.anywhere.fragment.FileOptionsDialogFragment;
+import org.amahi.anywhere.fragment.MainLoginFragment;
import org.amahi.anywhere.fragment.FileSortOptionsDialogFragment;
import org.amahi.anywhere.fragment.NavigationFragment;
+import org.amahi.anywhere.fragment.PINAccessFragment;
import org.amahi.anywhere.fragment.ServerAppsFragment;
import org.amahi.anywhere.fragment.ServerFileAudioFragment;
import org.amahi.anywhere.fragment.ServerFileImageFragment;
@@ -69,6 +71,14 @@ public static final class Builder {
private Builder() {
}
+ public static Fragment buildMainLoginFragment() {
+ return new MainLoginFragment();
+ }
+
+ public static Fragment buildPINFragment() {
+ return new PINAccessFragment();
+ }
+
public static Fragment buildNavigationFragment() {
return new NavigationFragment();
}
diff --git a/src/main/java/org/amahi/anywhere/util/Preferences.java b/src/main/java/org/amahi/anywhere/util/Preferences.java
index 290e70cef..3cdfe6960 100644
--- a/src/main/java/org/amahi/anywhere/util/Preferences.java
+++ b/src/main/java/org/amahi/anywhere/util/Preferences.java
@@ -94,6 +94,14 @@ public static String getServerName(Context context) {
return context.getSharedPreferences(Constants.preference, MODE_PRIVATE).getString(context.getString(R.string.pref_server_select_key), null);
}
+ public static void setLocalServerIP(Context context, String ip) {
+ context.getSharedPreferences(context.getString(R.string.preference), MODE_PRIVATE).edit().putString(context.getString(R.string.local_server_ip), ip).apply();
+ }
+
+ public static String getLocalServerIP(Context context) {
+ return context.getSharedPreferences(context.getString(R.string.preference), MODE_PRIVATE).getString(context.getString(R.string.local_server_ip), null);
+ }
+
public static Preferences ofCookie(Context context) {
return new Preferences(context, Locations.COOKIE);
}
diff --git a/src/main/res/layout-land/layout_authentication.xml b/src/main/res/layout-land/layout_authentication.xml
index 39f496e16..cac2e53e1 100644
--- a/src/main/res/layout-land/layout_authentication.xml
+++ b/src/main/res/layout-land/layout_authentication.xml
@@ -154,6 +154,14 @@
+
+
diff --git a/src/main/res/layout/activity_authentication.xml b/src/main/res/layout/activity_authentication.xml
index 1937ff775..5fa1daa1b 100644
--- a/src/main/res/layout/activity_authentication.xml
+++ b/src/main/res/layout/activity_authentication.xml
@@ -21,6 +21,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
-
+
-
\ No newline at end of file
+
diff --git a/src/main/res/layout/fragment_pin_access.xml b/src/main/res/layout/fragment_pin_access.xml
new file mode 100644
index 000000000..fed583118
--- /dev/null
+++ b/src/main/res/layout/fragment_pin_access.xml
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/layout/layout_authentication.xml b/src/main/res/layout/layout_authentication.xml
index 4c0c4ff7d..f7bfed8d0 100644
--- a/src/main/res/layout/layout_authentication.xml
+++ b/src/main/res/layout/layout_authentication.xml
@@ -17,134 +17,168 @@
~ along with Amahi. If not, see .
-->
-
-
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:orientation="vertical">
-
+
-
+
-
+ android:layout_height="wrap_content">
-
+
-
+
-
+
-
-
-
+ app:passwordToggleEnabled="true"
+ app:passwordToggleTint="@color/accent">
+
-
-
-
+
-
+
+
+
-
-
+
-
+
+ android:layout_height="8dp" />
-
+ android:orientation="horizontal">
+
+
+
+
+
+
-
+ android:layout_height="16dp" />
-
-
-
-
-
+ android:inAnimation="@anim/slide_down_text"
+ android:outAnimation="@anim/slide_up_text">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml
index 19b984069..46ac721e4 100644
--- a/src/main/res/values-fr/strings.xml
+++ b/src/main/res/values-fr/strings.xml
@@ -225,6 +225,13 @@
Veuillez vous connecter à Internet et réessayer.
Veuillez vous connecter à votre serveur et réessayer.
+
+ PIN
+ Accès PIN
+ Le champ PIN ne peut pas être laissé vide.
+ Le code PIN n\'est pas correct. Veuillez réessayer.
+ Il semble que vous n\'êtes pas connecté au même Wifi que votre serveur.
+
Notez Amahi
Si vous aimez utiliser Amahi, pourriez-vous prendre un moment pour le noter? Merci pour votre aide!
Évaluer Maintenant
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 30dd1c9e7..c81611c27 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -40,6 +40,13 @@
Password
Username
+
+ PIN
+ PIN Access
+ PIN field cannot be left empty.
+ PIN is not correct. Please try again.
+ It seems that you are not connected to the same Wifi as your server.
+
Back
Forward
Close navigation
@@ -64,8 +71,10 @@
Account already exists.
We haven’t found any supported apps for this file.
+
Forgot your password?
- The username or password are not correct. Please try again.
+ The username or password is not correct. Please try again.
+
Connection error. Check your settings and try again.
Username or password field cannot be left empty.
Connection Error
@@ -127,7 +136,11 @@
Use Camera
Upload File
-
+
+ PREFERENCE
+ SERVER_IP
+
+
Amahi TV
Exit
Are you sure you want to quit?