diff --git a/app/src/main/java/com/zulip/android/ZulipApp.java b/app/src/main/java/com/zulip/android/ZulipApp.java index 2505d1d06..26a2481d4 100644 --- a/app/src/main/java/com/zulip/android/ZulipApp.java +++ b/app/src/main/java/com/zulip/android/ZulipApp.java @@ -60,6 +60,16 @@ public class ZulipApp extends Application { private Set mutedTopics; private static final String MUTED_TOPIC_KEY = "mutedTopics"; + private final static String GLOBAL_SETTINGS = "HumbugActivity"; + private final static String SERVER_SETTINGS = "serverSettings"; + private final static String GLOBAL_SETTINGS_CURRENT = "currentRealm"; + private static final String GLOBAL_SETTINGS_REALMS = "REALMS"; + + + public int currentRealm = 0; + + public HashSet serverStringSet; + private SharedPreferences globalSettings; /** * Handler to manage batching of unread messages */ @@ -98,15 +108,11 @@ public void onCreate() { // This used to be from HumbugActivity.getPreferences, so we keep that // file name. - this.settings = getSharedPreferences("HumbugActivity", - Context.MODE_PRIVATE); - - max_message_id = settings.getInt("max_message_id", -1); - eventQueueId = settings.getString("eventQueueId", null); - lastEventId = settings.getInt("lastEventId", -1); - pointer = settings.getInt("pointer", -1); - + globalSettings = getSharedPreferences(GLOBAL_SETTINGS, Context.MODE_PRIVATE); + currentRealm = globalSettings.getInt(GLOBAL_SETTINGS_CURRENT, currentRealm); + serverStringSet = new HashSet(globalSettings.getStringSet(GLOBAL_SETTINGS_REALMS, new HashSet())); + switchToRealm(currentRealm); this.api_key = settings.getString(API_KEY, null); if (api_key != null) { @@ -223,7 +229,7 @@ public void addToMutedTopics(JSONArray jsonArray) { } public void setEmail(String email) { - databaseHelper = new DatabaseHelper(this, email); + databaseHelper = new DatabaseHelper(this, SERVER_SETTINGS + currentRealm); this.you = Person.getOrUpdate(this, email, null, null); } @@ -379,4 +385,50 @@ private static void setInstance(ZulipApp instance) { public boolean isTopicMute(int id, String subject) { return mutedTopics.contains(id + subject); } + + public void saveServerName(String serverName) { + String username=null; + try { + username = you.getEmail(); + } catch (Exception e) { + //SQL Exception can occur if name is not updated! + ZLog.logException(e); + } + Editor globalEditor = this.globalSettings.edit(); + serverStringSet.add((username != null) ? serverName + " - " + username : serverName); + globalEditor.putStringSet(GLOBAL_SETTINGS_REALMS, new HashSet(serverStringSet)); + globalEditor.apply(); + } + public void createNewRealm() { + SharedPreferences.Editor editor = this.globalSettings.edit(); + currentRealm = serverStringSet.size(); + editor.putInt(GLOBAL_SETTINGS_CURRENT, currentRealm); + editor.apply(); + + databaseHelper = new DatabaseHelper(this, SERVER_SETTINGS + serverStringSet.size()); + + this.settings = getSharedPreferences(SERVER_SETTINGS + serverStringSet.size(), Context.MODE_PRIVATE); + max_message_id = settings.getInt("max_message_id", -1); + eventQueueId = settings.getString("eventQueueId", null); + lastEventId = settings.getInt("lastEventId", -1); + pointer = settings.getInt("pointer", -1); + } + + public void switchToRealm(int position) { + databaseHelper = new DatabaseHelper(this, SERVER_SETTINGS + position); + this.settings = getSharedPreferences(SERVER_SETTINGS + position, Context.MODE_PRIVATE); + this.api_key = settings.getString("api_key", null); + max_message_id = settings.getInt("max_message_id", -1); + eventQueueId = settings.getString("eventQueueId", null); + lastEventId = settings.getInt("lastEventId", -1); + pointer = settings.getInt("pointer", -1); + if (settings.contains("email")) + this.you = Person.getOrUpdate(this, settings.getString("email", null), null, null); + currentRealm = position; + if (position != currentRealm) { + SharedPreferences.Editor edit = globalSettings.edit(); + edit.putInt(GLOBAL_SETTINGS_CURRENT, position); + edit.apply(); + } + } } diff --git a/app/src/main/java/com/zulip/android/activities/DevAuthActivity.java b/app/src/main/java/com/zulip/android/activities/DevAuthActivity.java index 560f986df..f50fa55f8 100644 --- a/app/src/main/java/com/zulip/android/activities/DevAuthActivity.java +++ b/app/src/main/java/com/zulip/android/activities/DevAuthActivity.java @@ -10,6 +10,8 @@ import com.zulip.android.R; import com.zulip.android.networking.AsyncDevGetEmails; import com.zulip.android.networking.AsyncLogin; +import com.zulip.android.networking.LoginInterface; +import com.zulip.android.networking.ZulipAsyncPushTask; import com.zulip.android.util.AuthClickListener; import com.zulip.android.util.ZLog; @@ -23,16 +25,19 @@ /** * Activity where the Emails for the DevAuthBackend are displayed. */ -public class DevAuthActivity extends Activity { +public class DevAuthActivity extends Activity implements LoginInterface { private RecyclerView recyclerView; private ProgressDialog connectionProgressDialog; - + public static final int ADD_REALM_REQUEST = 566; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_dev_auth); String json = getIntent().getStringExtra(AsyncDevGetEmails.EMAIL_JSON); + final String realmName = getIntent().getStringExtra(AsyncDevGetEmails.REALM_NAME_JSON); + final String serverURL = getIntent().getStringExtra(AsyncDevGetEmails.SERVER_URL_JSON); + final boolean startedFromAddRealm = getIntent().getBooleanExtra(AsyncDevGetEmails.ADD_REALM_BOOLEAN_JSON, false); recyclerView = (RecyclerView) findViewById(R.id.devAuthRecyclerView); List emails = new ArrayList<>(); int directAdminSize = 1; @@ -58,15 +63,27 @@ protected void onCreate(Bundle savedInstanceState) { authEmailAdapter.setOnItemClickListener(new AuthClickListener() { @Override public void onItemClick(String email) { - AsyncLogin asyncLogin = new AsyncLogin(DevAuthActivity.this, email, null, true); + AsyncLogin asyncLogin = new AsyncLogin(DevAuthActivity.this, email, null, realmName, startedFromAddRealm, serverURL, true); asyncLogin.execute(); connectionProgressDialog.show(); + asyncLogin.setCallback(new ZulipAsyncPushTask.AsyncTaskCompleteListener() { + @Override + public void onTaskComplete(String result, JSONObject jsonObject) { + connectionProgressDialog.dismiss(); + } + + @Override + public void onTaskFailure(String result) { + connectionProgressDialog.dismiss(); + } + }); } }); recyclerView.setLayoutManager(new LinearLayoutManager(DevAuthActivity.this) { }); } + @Override public void openHome() { // Cancel before leaving activity to avoid leaking windows connectionProgressDialog.dismiss(); diff --git a/app/src/main/java/com/zulip/android/activities/LoginActivity.java b/app/src/main/java/com/zulip/android/activities/LoginActivity.java index ca7be23ce..5d9a6c641 100644 --- a/app/src/main/java/com/zulip/android/activities/LoginActivity.java +++ b/app/src/main/java/com/zulip/android/activities/LoginActivity.java @@ -1,5 +1,6 @@ package com.zulip.android.activities; +import android.app.Activity; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; @@ -9,10 +10,15 @@ import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.text.TextUtils; import android.util.Log; import android.util.Patterns; import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.EditText; +import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.auth.api.Auth; @@ -25,6 +31,7 @@ import com.zulip.android.R; import com.zulip.android.networking.AsyncDevGetEmails; import com.zulip.android.networking.AsyncGetBackends; +import com.zulip.android.networking.LoginInterface; import com.zulip.android.util.AnimationHelper; import com.zulip.android.util.ZLog; import com.zulip.android.ZulipApp; @@ -34,25 +41,31 @@ import org.json.JSONException; import org.json.JSONObject; +import java.net.URI; +import java.net.URISyntaxException; import java.util.List; +import static com.zulip.android.activities.DevAuthActivity.ADD_REALM_REQUEST; + /** * Activity to Login through various backends on a specified server. * Currently supported LoginAuths are Emailbackend and DevAuthBackend. */ public class LoginActivity extends AppCompatActivity implements View.OnClickListener, - GoogleApiClient.OnConnectionFailedListener { + GoogleApiClient.OnConnectionFailedListener, LoginInterface { private static final String TAG = "LoginActivity"; private static final int REQUEST_CODE_RESOLVE_ERR = 9000; private static final int REQUEST_CODE_SIGN_IN = 9001; + private boolean startedFromAddRealm = false; private ProgressDialog connectionProgressDialog; private GoogleApiClient mGoogleApiClient; private EditText mServerEditText; private EditText mUserName; private EditText mPassword; private EditText serverIn; - + private EditText realmNameET; + private String serverURL; private View mGoogleSignInButton; @Override @@ -100,6 +113,12 @@ public void onClick(View view) { private void showLoginFields() { AnimationHelper.showView(findViewById(R.id.serverInput), 201); AnimationHelper.hideView(findViewById(R.id.serverFieldLayout), 100); + realmNameET = (EditText) findViewById(R.id.realmName); + if (getIntent().getBooleanExtra("FROM_ADDREALM", false)) { + startedFromAddRealm = true; + ((TextView) findViewById(R.id.welcome_zulip)).setText(R.string.add_realm); + ((Button) findViewById(R.id.zulip_login)).setText(R.string.add_realm_login); + } } @Override @@ -110,6 +129,11 @@ protected void onActivityResult(int requestCode, int resultCode, Intent intent) GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(intent); handleSignInResult(result); break; + case ADD_REALM_REQUEST: + if (resultCode == Activity.RESULT_OK) { + setResult(Activity.RESULT_OK, intent); + finish(); + } default: break; } @@ -156,6 +180,7 @@ private void checkForError() { } } + private void showBackends(String httpScheme, String serverURL) { Uri serverUri = Uri.parse(serverURL); @@ -169,8 +194,8 @@ private void showBackends(String httpScheme, String serverURL) { serverIn.setText(serverUri.toString()); mServerEditText.setText(serverUri.toString()); mServerEditText.setEnabled(false); - ((ZulipApp) getApplication()).setServerURL(serverUri.toString()); - AsyncGetBackends asyncGetBackends = new AsyncGetBackends(ZulipApp.get()); + this.serverURL = serverUri.toString(); + AsyncGetBackends asyncGetBackends = new AsyncGetBackends(ZulipApp.get(), this.serverURL); asyncGetBackends.setCallback(new AsyncTaskCompleteListener() { @Override public void onTaskComplete(String result, JSONObject jsonObject) { @@ -242,7 +267,7 @@ private void handleSignInResult(GoogleSignInResult result) { return; } - final AsyncLogin loginTask = new AsyncLogin(LoginActivity.this, "google-oauth2-token", account.getIdToken(), false); + final AsyncLogin loginTask = new AsyncLogin(LoginActivity.this, "google-oauth2-token", account.getIdToken(), getRealmName(), startedFromAddRealm, serverURL, false); loginTask.setCallback(new AsyncTaskCompleteListener() { @Override public void onTaskComplete(String result, JSONObject object) { @@ -270,11 +295,26 @@ public void onTaskFailure(String result) { } } - private void openLegal() { + private String getRealmName() { + if (TextUtils.isEmpty(realmNameET.getText())) { + String server = serverURL; + URI uri = null; + try { + uri = new URI(server); + } catch (URISyntaxException e) { + return server; + } + return uri.getHost(); + } + return realmNameET.getText().toString(); + } + + protected void openLegal() { Intent i = new Intent(this, LegalActivity.class); startActivityForResult(i, 0); } + @Override public void openHome() { // Cancel before leaving activity to avoid leaking windows connectionProgressDialog.dismiss(); @@ -341,10 +381,14 @@ public void onClick(View v) { if (!isInputValid()) { return; } + if (!isInputValid()) return; + if (serverURL == null) return; connectionProgressDialog.show(); AsyncLogin alog = new AsyncLogin(LoginActivity.this, - mUserName.getText().toString(), mPassword.getText().toString(), false); + mUserName.getText().toString(), mPassword.getText().toString(), + getRealmName(), startedFromAddRealm, serverURL, false); + // Remove the CPD when done alog.setCallback(new AsyncTaskCompleteListener() { @Override @@ -366,7 +410,7 @@ public void onTaskFailure(String result) { case R.id.local_server_button: if (!isInputValidForDevAuth()) return; connectionProgressDialog.show(); - AsyncDevGetEmails asyncDevGetEmails = new AsyncDevGetEmails(LoginActivity.this); + AsyncDevGetEmails asyncDevGetEmails = new AsyncDevGetEmails(LoginActivity.this, serverURL, getRealmName(), startedFromAddRealm); asyncDevGetEmails.setCallback(new AsyncTaskCompleteListener() { @Override public void onTaskComplete(String result, JSONObject jsonObject) { diff --git a/app/src/main/java/com/zulip/android/activities/RealmDialog.java b/app/src/main/java/com/zulip/android/activities/RealmDialog.java new file mode 100644 index 000000000..3f812d766 --- /dev/null +++ b/app/src/main/java/com/zulip/android/activities/RealmDialog.java @@ -0,0 +1,102 @@ +package com.zulip.android.activities; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.Toast; + +import com.zulip.android.R; +import com.zulip.android.ZulipApp; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; + +public class RealmDialog extends DialogFragment { + private ZulipApp app; + private ArrayAdapter realmsAdapter; + private Context context; + + static RealmDialog newInstance() { + return new RealmDialog(); + } + + public RealmDialog() { + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + LayoutInflater inflater = getActivity().getLayoutInflater(); + builder.setTitle(R.string.realm_title); + View rootView = inflater.inflate(R.layout.realm_dialog_list, null); + List realmsList = new ArrayList<>(); + context = getActivity(); + app = ZulipApp.get(); + ListView listView = (ListView) rootView.findViewById(R.id.realmListView); + realmsList = new ArrayList(app.serverStringSet); + realmsAdapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, realmsList); + listView.setAdapter(realmsAdapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, final int position, long id) { + new AlertDialog.Builder(context) + .setTitle(R.string.realm_switch) + .setMessage(context.getString(R.string.realm_switch_confirm, realmsAdapter.getItem(position))) + .setPositiveButton(getResources().getString(android.R.string.yes), new DialogInterface.OnClickListener() { + public void onClick(final DialogInterface dialog, int whichButton) { + if (position == app.currentRealm) { + Toast.makeText(context, R.string.realm_this_is_current, Toast.LENGTH_LONG).show(); + return; + } + final ProgressDialog progressDialog = new ProgressDialog(getActivity()); + progressDialog.setCancelable(false); + progressDialog.setTitle(app.getString(R.string.realm_switching)); + progressDialog.setMessage(app.getString(R.string.please_wait)); + progressDialog.show(); + ((ZulipActivity) getActivity()).switchRealm(progressDialog, position); + if (RealmDialog.this.getDialog() != null) + RealmDialog.this.getDialog().cancel(); + } + }) + .setNegativeButton(getResources().getString(android.R.string.cancel), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + dialog.dismiss(); + } + }) + .show(); + } + }); + builder.setView(rootView) + .setPositiveButton(R.string.realm_add, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + Intent newIntent = new Intent(context, LoginActivity.class); + newIntent.putExtra("FROM_ADDREALM", true); + getActivity().startActivityForResult(newIntent, ZulipActivity.ADDREALM_REQUEST_CODE); + RealmDialog.this.getDialog().cancel(); + } + }) + .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + RealmDialog.this.getDialog().cancel(); + } + }); + return builder.create(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zulip/android/activities/ZulipActivity.java b/app/src/main/java/com/zulip/android/activities/ZulipActivity.java index 2ab3f8080..2dcff9204 100644 --- a/app/src/main/java/com/zulip/android/activities/ZulipActivity.java +++ b/app/src/main/java/com/zulip/android/activities/ZulipActivity.java @@ -10,7 +10,9 @@ import android.animation.Animator; import android.annotation.SuppressLint; import android.annotation.TargetApi; +import android.app.Activity; import android.app.AlertDialog; +import android.app.ProgressDialog; import android.app.SearchManager; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -151,6 +153,7 @@ public class ZulipActivity extends AppCompatActivity implements private SimpleCursorAdapter streamActvAdapter; private SimpleCursorAdapter subjectActvAdapter; private SimpleCursorAdapter emailActvAdapter; + public static final int ADDREALM_REQUEST_CODE = 201; private BroadcastReceiver onGcmMessage = new BroadcastReceiver() { public void onReceive(Context contenxt, Intent intent) { @@ -1340,6 +1343,10 @@ public void onClick( break; case R.id.today: doNarrow(new NarrowFilterToday()); + case R.id.menu_realm: + FragmentManager fm = getSupportFragmentManager(); + RealmDialog dialogFragment = RealmDialog.newInstance(); + dialogFragment.show(fm, "fragment_realm"); break; case R.id.logout: logout(); @@ -1487,4 +1494,64 @@ public void onNewMessages(Message[] messages) { narrowedList.onNewMessages(messages); } } + + void switchRealm(final ProgressDialog progressDialog, final int position) { + if (event_poll != null) { + event_poll.abort(); + event_poll = null; + } + statusUpdateHandler.removeMessages(0); + unregisterReceiver(onGcmMessage); + app.clearConnectionState(); + app.switchToRealm(position); + app.resetDatabase(); + app.setEmail(app.getYou().getEmail()); + event_poll = new AsyncGetEvents(ZulipActivity.this); + event_poll.start(); + IntentFilter filter = new IntentFilter(GcmBroadcastReceiver.getGCMReceiverAction(getApplicationContext())); + filter.setPriority(2); + registerReceiver(onGcmMessage, filter); + progressDialog.dismiss(); + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == ADDREALM_REQUEST_CODE && resultCode == Activity.RESULT_OK) { + this.currentList.adapter.clear(); + this.currentList.adapter.setHeaderShowing(true); + final String realmName = data.getStringExtra("realmName"); + final String apiKey = data.getStringExtra("api_key"); + final String email = data.getStringExtra("email"); + final String serverURL = data.getStringExtra("serverURL"); + notifications.logOut(new Runnable() { + @Override + public void run() { + if (event_poll != null) { + event_poll.abort(); + event_poll = null; + } + statusUpdateHandler.removeMessages(0); + try { + unregisterReceiver(onGcmMessage); + } catch (IllegalArgumentException e) { + ZLog.logException(e); + } + + app.clearConnectionState(); + app.createNewRealm(); + app.setEmail(email); + app.setServerURL(serverURL); + app.saveServerName(realmName); + app.setLoggedInApiKey(apiKey); + IntentFilter filter = new IntentFilter(GcmBroadcastReceiver.getGCMReceiverAction(getApplicationContext())); + filter.setPriority(2); + registerReceiver(onGcmMessage, filter); + onRefresh(); + } + }); + + } + this.currentList.adapter.setHeaderShowing(false); + } } diff --git a/app/src/main/java/com/zulip/android/networking/AsyncDevGetEmails.java b/app/src/main/java/com/zulip/android/networking/AsyncDevGetEmails.java index b171c6061..d982bd39f 100644 --- a/app/src/main/java/com/zulip/android/networking/AsyncDevGetEmails.java +++ b/app/src/main/java/com/zulip/android/networking/AsyncDevGetEmails.java @@ -13,6 +13,9 @@ import org.json.JSONException; import org.json.JSONObject; + +import static com.zulip.android.activities.DevAuthActivity.ADD_REALM_REQUEST; + /** * A background task which asynchronously fetches the Emails (Admins or Users) for the devAuthBackend * Mainly used Development builds. @@ -20,11 +23,21 @@ public class AsyncDevGetEmails extends ZulipAsyncPushTask { private static final String DISABLED = "dev_disabled"; private Context context; + public static final String SERVER_URL_JSON = "server_url"; + public static final String REALM_NAME_JSON = "realm_json"; + public static final String ADD_REALM_BOOLEAN_JSON = "add_realm_bool_json"; public final static String EMAIL_JSON = "emails_json"; + private String serverURL; + private String realmName; + private boolean startedFromAddRealm; - public AsyncDevGetEmails(LoginActivity loginActivity) { + public AsyncDevGetEmails(LoginActivity loginActivity, String serverURL, String realmName, boolean startedFromAddRealm) { super((ZulipApp) loginActivity.getApplication()); context = loginActivity; + this.serverURL = serverURL; + this.realmName = realmName; + this.startedFromAddRealm = startedFromAddRealm; + this.setServerURL(serverURL); } public final void execute() { @@ -38,7 +51,10 @@ protected void onPostExecute(String result) { if (obj.getString("result").equals("success")) { Intent intent = new Intent(context, DevAuthActivity.class); intent.putExtra(EMAIL_JSON, result); - context.startActivity(intent); + intent.putExtra(REALM_NAME_JSON, realmName); + intent.putExtra(SERVER_URL_JSON, serverURL); + intent.putExtra(ADD_REALM_BOOLEAN_JSON, startedFromAddRealm); + ((LoginActivity) context).startActivityForResult(intent, ADD_REALM_REQUEST); } } catch (JSONException e) { ZLog.logException(e); diff --git a/app/src/main/java/com/zulip/android/networking/AsyncGetBackends.java b/app/src/main/java/com/zulip/android/networking/AsyncGetBackends.java index dac689aad..7be703fc9 100644 --- a/app/src/main/java/com/zulip/android/networking/AsyncGetBackends.java +++ b/app/src/main/java/com/zulip/android/networking/AsyncGetBackends.java @@ -8,8 +8,12 @@ */ public class AsyncGetBackends extends ZulipAsyncPushTask { - public AsyncGetBackends(ZulipApp app) { + private String serverURL; + + public AsyncGetBackends(ZulipApp app, String url) { super(app); + this.serverURL = url; + this.setServerURL(serverURL); } //Json Format - {"msg":"","password":false,"google":false,"result":"success","dev":true} diff --git a/app/src/main/java/com/zulip/android/networking/AsyncLogin.java b/app/src/main/java/com/zulip/android/networking/AsyncLogin.java index ba1eb4740..97e9e943e 100644 --- a/app/src/main/java/com/zulip/android/networking/AsyncLogin.java +++ b/app/src/main/java/com/zulip/android/networking/AsyncLogin.java @@ -4,11 +4,13 @@ import org.json.JSONObject; import android.app.Activity; +import android.content.Intent; import android.util.Log; import android.widget.Toast; import com.zulip.android.activities.DevAuthActivity; import com.zulip.android.activities.LoginActivity; +import com.zulip.android.activities.ZulipActivity; import com.zulip.android.util.ZLog; import com.zulip.android.ZulipApp; @@ -22,18 +24,25 @@ public class AsyncLogin extends ZulipAsyncPushTask { private Activity activity; private boolean devServer = true; //If this is a DevAuthBackend server! - private LoginActivity context; + private Activity context; private boolean userDefinitelyInvalid = false; + boolean startedFromAddRealm = false; + private String realmName; + private String username; + private String serverURL; + LoginInterface loginInterface; /** * @param activity Reference to the activity from this is called mainly {@link LoginActivity} and {@link DevAuthActivity} * @param username Stores the E-Mail of the user or a string "google-oauth2-token" if this is for Google Authentication * @param password Stores the password if EmailBackend, ID Token if GoogleMobileOauth2Backend, and blank if DevAuthBackend */ - public AsyncLogin(Activity activity, String username, String password, boolean devServer) { + public AsyncLogin(Activity loginActivity, String username, String password, String realmName, boolean startedFromAddRealm, String serverURL, boolean devServer) { super(ZulipApp.get()); - this.activity = activity; - if (username.contains("@")) { + this.startedFromAddRealm = startedFromAddRealm; + context = loginActivity; + this.username = username; + if (username.contains("@") && !startedFromAddRealm) { // @-less usernames are used as indicating special cases, for // example in OAuth2 authentication this.app.setEmail(username); @@ -43,6 +52,11 @@ public AsyncLogin(Activity activity, String username, String password, boolean d this.setProperty("password", password); this.devServer = false; } + this.setProperty("password", password); + this.realmName = realmName; + this.setServerURL(serverURL); + this.serverURL = serverURL; + loginInterface = (LoginInterface) context; } public final void execute() { @@ -57,10 +71,15 @@ protected void onPostExecute(String result) { JSONObject obj = new JSONObject(result); if (obj.getString("result").equals("success")) { - this.app.setLoggedInApiKey(obj.getString("api_key")); - if (devServer) ((DevAuthActivity) activity).openHome(); - else ((LoginActivity) activity).openHome(); - callback.onTaskComplete(result, obj); + if (startedFromAddRealm) { + loginThroughAddRealm(obj); + callback.onTaskComplete(result, obj); + } else { + this.app.setServerURL(serverURL); + this.app.setLoggedInApiKey(obj.getString("api_key")); + ZulipApp.get().saveServerName(realmName); + loginInterface.openHome(); + } return; } } catch (JSONException e) { @@ -71,6 +90,27 @@ protected void onPostExecute(String result) { Log.wtf("login", "We shouldn't have gotten this far."); } + private void loginThroughAddRealm(JSONObject jsonObject) { + try { + Intent intent = null; + //This is done to start ZulipActivity from DevAuthActivity which cannot be done directly as DevAuthActivity was called from LoginActivity + //And Therefore we have to finish two activities (DevAuthActivity and LoginActivity) if started from DevAuthActivity. + if (context instanceof DevAuthActivity) { + intent = new Intent(); + } else if (context instanceof LoginActivity) { + intent = new Intent(context, ZulipActivity.class); + } + intent.putExtra("realmName", realmName); + intent.putExtra("api_key", jsonObject.getString("api_key")); + intent.putExtra("email", username); + intent.putExtra("serverURL", serverURL); + context.setResult(Activity.RESULT_OK, intent); + context.finish(); + } catch (JSONException e) { + ZLog.logException(e); + } + } + @Override protected void onCancelled(String result) { super.onCancelled(result); diff --git a/app/src/main/java/com/zulip/android/networking/HTTPRequest.java b/app/src/main/java/com/zulip/android/networking/HTTPRequest.java index f1b6af91e..a8e930d7f 100644 --- a/app/src/main/java/com/zulip/android/networking/HTTPRequest.java +++ b/app/src/main/java/com/zulip/android/networking/HTTPRequest.java @@ -33,6 +33,7 @@ public class HTTPRequest { private OkHttpClient okHttpClient; private Response response = null; private String method, path; + private String serverURL; public void setMethodAndUrl(String method, String URL) { this.method = method; @@ -43,8 +44,12 @@ public HTTPRequest(ZulipApp app) { properties = new HashMap<>(); this.app = app; okHttpClient = new OkHttpClient.Builder().readTimeout(60, TimeUnit.SECONDS).build(); + this.serverURL = app.getServerURI(); } + public void setServerURL(String serverURL) { + this.serverURL = serverURL; + } public void setProperty(String key, String value) { properties.put((key == null) ? "" : key, (value == null) ? "" : value); @@ -71,7 +76,7 @@ public Response execute() throws IOException { if (method == null) throw new IOException(app.getString(R.string.method_null)); Request.Builder requestBuilder = new Request.Builder(); - String url = app.getServerURI() + path; + String url = serverURL + path; requestBuilder.addHeader("client", "Android"); requestBuilder.addHeader("User-Agent", app.getUserAgent()); diff --git a/app/src/main/java/com/zulip/android/networking/LoginInterface.java b/app/src/main/java/com/zulip/android/networking/LoginInterface.java new file mode 100644 index 000000000..dd2b740cc --- /dev/null +++ b/app/src/main/java/com/zulip/android/networking/LoginInterface.java @@ -0,0 +1,6 @@ +package com.zulip.android.networking; + + +public interface LoginInterface { + void openHome(); +} diff --git a/app/src/main/java/com/zulip/android/networking/ZulipAsyncPushTask.java b/app/src/main/java/com/zulip/android/networking/ZulipAsyncPushTask.java index 2c210708d..50e999e2d 100644 --- a/app/src/main/java/com/zulip/android/networking/ZulipAsyncPushTask.java +++ b/app/src/main/java/com/zulip/android/networking/ZulipAsyncPushTask.java @@ -24,6 +24,10 @@ public abstract class ZulipAsyncPushTask extends AsyncTask diff --git a/app/src/main/res/layout-v21/login.xml b/app/src/main/res/layout-v21/login.xml index 9d9414f62..202a2432a 100644 --- a/app/src/main/res/layout-v21/login.xml +++ b/app/src/main/res/layout-v21/login.xml @@ -26,6 +26,7 @@ android:layout_marginTop="16dp" android:gravity="center|center_horizontal" android:padding="10dp" + android:id="@+id/welcome_zulip" android:text="@string/login_welcome_blurb" android:textAppearance="?android:attr/textAppearanceLarge" /> @@ -46,6 +47,12 @@ android:text="@string/enter_server" android:textAppearance="?android:attr/textAppearanceMedium" /> + + @@ -40,6 +41,12 @@ android:text="@string/enter_server" android:textAppearance="?android:attr/textAppearanceMedium" /> + + + + diff --git a/app/src/main/res/menu/options.xml b/app/src/main/res/menu/options.xml index 466382435..11537011b 100644 --- a/app/src/main/res/menu/options.xml +++ b/app/src/main/res/menu/options.xml @@ -9,6 +9,9 @@ app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="ifRoom" /> + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0b1a2a940..86d071246 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -40,13 +40,6 @@ Person Topic Stream - Message sent! - Error sending message - Please specify stream. - Stream does not exist. - Please specify topic. - Please specify recipient. - No message written. Dev backend testing server Zulip Dev login Administrators (None) @@ -73,4 +66,22 @@ Reply to Sender Narrow to this stream Narrow to this topic - + Message sent! + Error sending message + No stream specified. + Stream does not exists. + No subject specified. + No person specified. + No message written. + Realms + Switch to this realm + "Do you want to switch to %s ?" + This is the current realm only! + Switching realm + Please wait + Add Realm + Name of a realm (Optional) + Realm Name already exists, please change. + Add new Realm + Add + \ No newline at end of file