SlideShare a Scribd company logo
1 of 23
Download to read offline
Creating a Facebook Clone - Part XXVIII
The sensible place to start is with the login & signup processes and the way they tie to the server.
Container logoContainer = BorderLayout.centerAbsolute(logo);
logoContainer.setUIID("LoginTitle");
signUp.addActionListener(e -> UIController.showSignup());
login.addActionListener(e -> {
User u = new User().password.set(password.getText());
if(user.getText().contains("@")) {
u.email.set(user.getText());
} else {
u.phone.set(user.getText());
}
Dialog d = new InfiniteProgress().showInifiniteBlocking();
ServerAPI.login(u, new Callback<User>() {
@Override
public void onSucess(User value) {
d.dispose();
UIController.showMainUI();
}
@Override
public void onError(Object sender, Throwable err,
int errorCode, String errorMessage) {
d.dispose();
ToastBar.showErrorMessage("Login Failed");
}
LoginForm
The login change is trivial, we need to replace the action listener of the login button with this new one
Container logoContainer = BorderLayout.centerAbsolute(logo);
logoContainer.setUIID("LoginTitle");
signUp.addActionListener(e -> UIController.showSignup());
login.addActionListener(e -> {
User u = new User().password.set(password.getText());
if(user.getText().contains("@")) {
u.email.set(user.getText());
} else {
u.phone.set(user.getText());
}
Dialog d = new InfiniteProgress().showInifiniteBlocking();
ServerAPI.login(u, new Callback<User>() {
@Override
public void onSucess(User value) {
d.dispose();
UIController.showMainUI();
}
@Override
public void onError(Object sender, Throwable err,
int errorCode, String errorMessage) {
d.dispose();
ToastBar.showErrorMessage("Login Failed");
}
LoginForm
We use the User object as a data transfer object, we set the password and phone/email to send them to the server
Container logoContainer = BorderLayout.centerAbsolute(logo);
logoContainer.setUIID("LoginTitle");
signUp.addActionListener(e -> UIController.showSignup());
login.addActionListener(e -> {
User u = new User().password.set(password.getText());
if(user.getText().contains("@")) {
u.email.set(user.getText());
} else {
u.phone.set(user.getText());
}
Dialog d = new InfiniteProgress().showInifiniteBlocking();
ServerAPI.login(u, new Callback<User>() {
@Override
public void onSucess(User value) {
d.dispose();
UIController.showMainUI();
}
@Override
public void onError(Object sender, Throwable err,
int errorCode, String errorMessage) {
d.dispose();
ToastBar.showErrorMessage("Login Failed");
}
LoginForm
The infinite progress UI is a bit of a shortcut but for a feature like login it makes some sense as we can't avoid a delay
login.addActionListener(e -> {
User u = new User().password.set(password.getText());
if(user.getText().contains("@")) {
u.email.set(user.getText());
} else {
u.phone.set(user.getText());
}
Dialog d = new InfiniteProgress().showInifiniteBlocking();
ServerAPI.login(u, new Callback<User>() {
@Override
public void onSucess(User value) {
d.dispose();
UIController.showMainUI();
}
@Override
public void onError(Object sender, Throwable err,
int errorCode, String errorMessage) {
d.dispose();
ToastBar.showErrorMessage("Login Failed");
}
});
});
add(NORTH, logoContainer);
LoginForm
A successful login shows the main UI whereas an error just shows the error message. Both dispose the infinite progress dialog

That's pretty simple and should work right away if we had a User object in place... To add a new user we need to overhaul the signup form.
public class SignupForm extends Form {
Container content = new Container(BoxLayout.y(), "PaddedContainer");
Container south = new Container(BoxLayout.y());
protected SignupForm(String title, String backLabel, Form previous) {
super(title, new BorderLayout());
setUIID("SignupForm");
content.setScrollableY(true);
add(CENTER, content);
getToolbar().setBackCommand(backLabel,
Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> previous.showBack());
getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape");
Button problem = new Button("Report a Problem", "BlueLink");
south.add(problem);
problem.addActionListener(e ->
sendMessage("Problem with Facebook Clone",
new Message("Details..."),
"mark@facebook.com"));
add(SOUTH, south);
SignupForm
As you may recall the SignupForm has a series of methods to create the wizard flow UI. This series of methods should generate a User object that we can use for signup
next.addActionListener(al);
return next;
}
public static SignupForm createTerms() {
SignupForm s = new SignupForm("Create Account", "Sign In",
getCurrentForm());
Label title = new Label("Terms & Conditions", "SignupSubHeader");
RichTextView rt = new RichTextView(
"By signing up you agree to our " +
"<a href="terms">Facebook Terms</a> and that you have " +
"read our <a href="data-policy">Data Policy</a>, including " +
"our <a href="cookie-use">Cookie Use</a>.");
rt.setAlignment(CENTER);
rt.setUIID("PaddedContainer");
Button next = s.createNextButton(e -> createName().show());
next.setText("I Agree");
rt.addLinkListener(e -> {
String link = (String) e.getSource();
execute("https://www.codenameone.com/");
});
s.content.addAll(title, rt, next);
return s;
}
SignupForm
The first in the series is the createTerms() method, since that method doesn't include any data there is no need for a User object there
s.content.addAll(title, rt, next);
return s;
}
public static SignupForm createName() {
SignupForm s = new SignupForm("Name", "Terms",
getCurrentForm());
Label title = new Label("What's Your Name?", "SignupSubHeader");
TextComponent first = new TextComponent().
label("First Name").columns(12);
TextComponent last = new TextComponent().
label("Last Name").columns(12);
User currentUser = new User();
UiBinding uib = new UiBinding();
uib.bind(currentUser.firstName, first);
uib.bind(currentUser.familyName, last);
TextModeLayout layout = new TextModeLayout(1, 2);
Container textContainer = new Container(layout, "PaddedContainer");
textContainer.add(layout.createConstraint().
widthPercentage(50), first);
textContainer.add(layout.createConstraint().
widthPercentage(50), last);
last.getField().setDoneListener(e ->
SignupForm
The second method is createName() and there we already have some work
s.content.addAll(title, rt, next);
return s;
}
public static SignupForm createName() {
SignupForm s = new SignupForm("Name", "Terms",
getCurrentForm());
Label title = new Label("What's Your Name?", "SignupSubHeader");
TextComponent first = new TextComponent().
label("First Name").columns(12);
TextComponent last = new TextComponent().
label("Last Name").columns(12);
User currentUser = new User();
UiBinding uib = new UiBinding();
uib.bind(currentUser.firstName, first);
uib.bind(currentUser.familyName, last);
TextModeLayout layout = new TextModeLayout(1, 2);
Container textContainer = new Container(layout, "PaddedContainer");
textContainer.add(layout.createConstraint().
widthPercentage(50), first);
textContainer.add(layout.createConstraint().
widthPercentage(50), last);
last.getField().setDoneListener(e ->
SignupForm
Since this is the first stage in the wizard we create the User & binding instances
s.content.addAll(title, rt, next);
return s;
}
public static SignupForm createName() {
SignupForm s = new SignupForm("Name", "Terms",
getCurrentForm());
Label title = new Label("What's Your Name?", "SignupSubHeader");
TextComponent first = new TextComponent().
label("First Name").columns(12);
TextComponent last = new TextComponent().
label("Last Name").columns(12);
User currentUser = new User();
UiBinding uib = new UiBinding();
uib.bind(currentUser.firstName, first);
uib.bind(currentUser.familyName, last);
TextModeLayout layout = new TextModeLayout(1, 2);
Container textContainer = new Container(layout, "PaddedContainer");
textContainer.add(layout.createConstraint().
widthPercentage(50), first);
textContainer.add(layout.createConstraint().
widthPercentage(50), last);
last.getField().setDoneListener(e ->
SignupForm
Binding means changes to the UI instantly change this field & visa versa. That's very convenient
TextModeLayout layout = new TextModeLayout(1, 2);
Container textContainer = new Container(layout, "PaddedContainer");
textContainer.add(layout.createConstraint().
widthPercentage(50), first);
textContainer.add(layout.createConstraint().
widthPercentage(50), last);
last.getField().setDoneListener(e ->
createBirthday(currentUser, uib).show());
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday(currentUser, uib).
show()));
return s;
}
public static SignupForm createBirthday(User currentUser, UiBinding uib) {
SignupForm s = new SignupForm("Birthday",
"Name",
getCurrentForm());
Label title = new Label("What's Your Birthday?", "SignupSubHeader");
Picker datePicker = new Picker();
datePicker.setType(PICKER_TYPE_DATE);
int twentyYears = 60000 * 60 * 24 * 365 * 20;
datePicker.setDate(
SignupForm
The createBirthday method now accepts the user and binding objects so we can fill them up with further details
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday(currentUser, uib).
show()));
return s;
}
public static SignupForm createBirthday(User currentUser, UiBinding uib) {
SignupForm s = new SignupForm("Birthday",
"Name",
getCurrentForm());
Label title = new Label("What's Your Birthday?", "SignupSubHeader");
Picker datePicker = new Picker();
datePicker.setType(PICKER_TYPE_DATE);
int twentyYears = 60000 * 60 * 24 * 365 * 20;
datePicker.setDate(
new Date(System.currentTimeMillis() - twentyYears));
uib.bind(currentUser.birthday, datePicker);
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender(currentUser, uib).show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
SignupForm
That's simple enough, the binding implicitly updates the user objects with changes from the UI. Next we can proceed to the changes in the birthday method obviously
the first change in the method is the signature which now accepts the user and binding
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday(currentUser, uib).
show()));
return s;
}
public static SignupForm createBirthday(User currentUser, UiBinding uib) {
SignupForm s = new SignupForm("Birthday",
"Name",
getCurrentForm());
Label title = new Label("What's Your Birthday?", "SignupSubHeader");
Picker datePicker = new Picker();
datePicker.setType(PICKER_TYPE_DATE);
int twentyYears = 60000 * 60 * 24 * 365 * 20;
datePicker.setDate(
new Date(System.currentTimeMillis() - twentyYears));
uib.bind(currentUser.birthday, datePicker);
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender(currentUser, uib).show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
SignupForm
Other than the method signature we added this line to bind the date picker to the birthday
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday(currentUser, uib).
show()));
return s;
}
public static SignupForm createBirthday(User currentUser, UiBinding uib) {
SignupForm s = new SignupForm("Birthday",
"Name",
getCurrentForm());
Label title = new Label("What's Your Birthday?", "SignupSubHeader");
Picker datePicker = new Picker();
datePicker.setType(PICKER_TYPE_DATE);
int twentyYears = 60000 * 60 * 24 * 365 * 20;
datePicker.setDate(
new Date(System.currentTimeMillis() - twentyYears));
uib.bind(currentUser.birthday, datePicker);
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender(currentUser, uib).show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
SignupForm
And we added the arguments to the gender method too
rb.setPressedIcon(selIcon);
rb.setUIID("GenderToggle");
return rb;
}
public static SignupForm createGender(User currentUser, UiBinding uib) {
SignupForm s = new SignupForm("Gender",
"Birthday",
getCurrentForm());
Label title = new Label("What's Your Gender?", "SignupSubHeader");
ButtonGroup bg = new ButtonGroup();
RadioButton female = createGenderButton(bg, "Female", "ue800");
RadioButton male = createGenderButton(bg, "Male", "ue801");
uib.bindGroup(currentUser.gender,
new String[]{"Male", "Female"}, male, female);
Container buttons = GridLayout.encloseIn(2, female, male);
buttons.setUIID("PaddedContainer");
s.content.addAll(title, buttons,
s.createNextButton(e -> createNumber(currentUser, uib).show()));
return s;
}
SignupForm
This leads us to the changes in the createGender() method. Since most of the changes are repetitive I'll skip the method signature and the signature of the followup
createNumber method. Suffice to say we pass the user & binding onward…

This is the binding code for the gender that automatically sets Male/Female for the gender attribute based on the radio button selection. It's a special case because these
are buttons so we need to provide the values that match each button.
new String[]{"Male", "Female"}, male, female);
Container buttons = GridLayout.encloseIn(2, female, male);
buttons.setUIID("PaddedContainer");
s.content.addAll(title, buttons,
s.createNextButton(e -> createNumber(currentUser, uib).show()));
return s;
}
public static SignupForm createNumber(User currentUser, UiBinding uib) {
return createMobileOrEmail(currentUser, currentUser.phone, uib,
"Mobile Number",
"What's Your Mobile Number?",
"Sign Up With Email Address",
TextArea.PHONENUMBER,
e -> createEmail(currentUser, uib).show());
}
private static SignupForm createMobileOrEmail(User currentUser,
Property userProp, UiBinding uib, String formTitle,
String subtitle, String signUpWith, int constraint,
ActionListener goToOther) {
SignupForm s =
new SignupForm(formTitle, getCurrentForm().getTitle(),
getCurrentForm());
SignupForm
The createNumber changes are a bit different because of the symbiotic relationship to the createEmail method. I'll list more of the code but I'll skip the createEmail
method as the changes there are obvious. 

The change itself is in the createMobileOrEmail method which is common to createNumber & createEmail
TextArea.PHONENUMBER,
e -> createEmail(currentUser, uib).show());
}
private static SignupForm createMobileOrEmail(User currentUser,
Property userProp, UiBinding uib, String formTitle,
String subtitle, String signUpWith, int constraint,
ActionListener goToOther) {
SignupForm s =
new SignupForm(formTitle, getCurrentForm().getTitle(),
getCurrentForm());
Label title = new Label(subtitle, "SignupSubHeader");
TextComponent textEntry = new TextComponent().
label(formTitle).
columns(20).
constraint(constraint);
uib.bind(userProp, textEntry);
Container textContainer = new Container(new TextModeLayout(1, 1),
"PaddedContainer");
textContainer.add(textEntry);
Button mobile = new Button(signUpWith, "BoldBlueLink");
mobile.addActionListener(goToOther);
SignupForm
This is the only change in this method. It's right under the declaration of textEntry but in effect it can be anywhere in the method. We bind the property to the text
component both of which are passed as arguments to this method.
TextArea.EMAILADDR,
e -> createNumber(currentUser, uib).show());
}
public static SignupForm createPassword(
User currentUser, UiBinding uib, boolean phone, String value) {
SignupForm s = new SignupForm("Password",
getCurrentForm().getTitle(),
getCurrentForm());
Label title = new Label("Choose a Password", "SignupSubHeader");
TextComponent password = new TextComponent().
label("Password").
columns(20);
uib.bind(currentUser.password, password);
Container textContainer = new Container(new TextModeLayout(1, 1),
"PaddedContainer");
textContainer.add(password);
s.content.addAll(title, textContainer,
s.createNextButton(e -> {
Dialog dlg = new Dialog("Signing Up...",
new BorderLayout(
BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE));
SignupForm
The final piece of the wizard is the createPassword method, which follows up with a code change that's pretty similar to everything we saw so far at least initially…

The binding call is pretty standard as we had up until now
SignupForm s = new SignupForm("Password",
getCurrentForm().getTitle(),
getCurrentForm());
Label title = new Label("Choose a Password", "SignupSubHeader");
TextComponent password = new TextComponent().
label("Password").
columns(20);
uib.bind(currentUser.password, password);
Container textContainer = new Container(new TextModeLayout(1, 1),
"PaddedContainer");
textContainer.add(password);
s.content.addAll(title, textContainer,
s.createNextButton(e -> {
Dialog dlg = new Dialog("Signing Up...",
new BorderLayout(
BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE));
dlg.add(CENTER, new InfiniteProgress());
dlg.showModeless();
ServerAPI.signup(currentUser, new Callback<User>() {
@Override
public void onSucess(User result) {
dlg.dispose();
createConfirmation(currentUser, phone, value).show();
SignupForm
We launch a progress dialog that runs while we wait for signup to complete
s.content.addAll(title, textContainer,
s.createNextButton(e -> {
Dialog dlg = new Dialog("Signing Up...",
new BorderLayout(
BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE));
dlg.add(CENTER, new InfiniteProgress());
dlg.showModeless();
ServerAPI.signup(currentUser, new Callback<User>() {
@Override
public void onSucess(User result) {
dlg.dispose();
createConfirmation(currentUser, phone, value).show();
}
@Override
public void onError(Object sender, Throwable err,
int errorCode, String errorMessage) {
dlg.dispose();
ToastBar.showErrorMessage(
"Error in server connection");
}
});
}));
return s;
}
SignupForm
If signup was successful we go to the confirmation UI and wait for that

That effectively created a user on the server and triggered an email or SMS to us. We can now check the confirmation value to see if the user is indeed valid.
"Enter the code in the message sent to " + value,
"CenterLabel");
}
TextComponent confirm = new TextComponent().
label("Confirmation Code").
columns(20).
constraint(TextArea.NUMERIC);
Container textContainer = new Container(new TextModeLayout(1, 1),
"PaddedContainer");
textContainer.add(confirm);
Button done = s.createNextButton(e -> {
Dialog d = new InfiniteProgress().showInifiniteBlocking();
if(ServerAPI.verifyUser(confirm.getText(), !phone)) {
UIController.showMainUI();
} else {
d.dispose();
ToastBar.showErrorMessage("Verification code error!");
}
});
done.setText("Confirm");
s.content.addAll(title, line, textContainer, done);
return s;
}
SignupForm
We do that by adding this code to the createConfirmation method. If verification succeeded we show the main UI…
"Enter the code in the message sent to " + value,
"CenterLabel");
}
TextComponent confirm = new TextComponent().
label("Confirmation Code").
columns(20).
constraint(TextArea.NUMERIC);
Container textContainer = new Container(new TextModeLayout(1, 1),
"PaddedContainer");
textContainer.add(confirm);
Button done = s.createNextButton(e -> {
Dialog d = new InfiniteProgress().showInifiniteBlocking();
if(ServerAPI.verifyUser(confirm.getText(), !phone)) {
UIController.showMainUI();
} else {
d.dispose();
ToastBar.showErrorMessage("Verification code error!");
}
});
done.setText("Confirm");
s.content.addAll(title, line, textContainer, done);
return s;
}
SignupForm
Otherwise we show an error message and remain in the current Form.
public static void showSplashScreen() {
Form splash = new Form(new BorderLayout(
BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE));
splash.setUIID("SplashForm");
Label logo = new Label("uf308", "IconFont");
logo.setName("Logo");
splash.add(CENTER, logo);
splash.setTransitionOutAnimator(
MorphTransition.
create(1200).
morph("Logo"));
final Motion anim = Motion.createLinearMotion(0, 127, 1000);
anim.start();
UITimer.timer(20, true, splash, () -> {
if(anim.isFinished()) {
if(!ServerAPI.isLoggedIn()) {
showLoginForm();
} else {
showMainUI();
}
} else {
logo.getUnselectedStyle().setOpacity(anim.getValue() + 127);
logo.repaint();
}
});
splash.show();
UIController
We still have one more change to make to the UIController class. Up until now we always started with the LoginForm but we should only start there when we are logged
out. We can just change the call to showMainUI() to this. If we aren't logged in correctly we behave as before after the splash screen. However, if we are logged in we go
to the main UI…

With that a new User is in place and should allow us to login to the app!

More Related Content

Similar to Creating a Facebook Clone - Part XXVIII - Transcript.pdf

Creating an Uber Clone - Part XXXIX.pdf
Creating an Uber Clone - Part XXXIX.pdfCreating an Uber Clone - Part XXXIX.pdf
Creating an Uber Clone - Part XXXIX.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XLVI - Transcript.pdf
Creating a Facebook Clone - Part XLVI - Transcript.pdfCreating a Facebook Clone - Part XLVI - Transcript.pdf
Creating a Facebook Clone - Part XLVI - Transcript.pdfShaiAlmog1
 
Creating an Uber Clone - Part XIV - Transcript.pdf
Creating an Uber Clone - Part XIV - Transcript.pdfCreating an Uber Clone - Part XIV - Transcript.pdf
Creating an Uber Clone - Part XIV - Transcript.pdfShaiAlmog1
 
Creating a Facebook Clone - Part VIII - Transcript.pdf
Creating a Facebook Clone - Part VIII - Transcript.pdfCreating a Facebook Clone - Part VIII - Transcript.pdf
Creating a Facebook Clone - Part VIII - Transcript.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XLV - Transcript.pdf
Creating a Facebook Clone - Part XLV - Transcript.pdfCreating a Facebook Clone - Part XLV - Transcript.pdf
Creating a Facebook Clone - Part XLV - Transcript.pdfShaiAlmog1
 
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo Ali Parmaksiz
 
Creating a Whatsapp Clone - Part III - Transcript.pdf
Creating a Whatsapp Clone - Part III - Transcript.pdfCreating a Whatsapp Clone - Part III - Transcript.pdf
Creating a Whatsapp Clone - Part III - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XLVI.pdf
Creating a Facebook Clone - Part XLVI.pdfCreating a Facebook Clone - Part XLVI.pdf
Creating a Facebook Clone - Part XLVI.pdfShaiAlmog1
 
Android Testing
Android TestingAndroid Testing
Android TestingEvan Lin
 
Orsiso
OrsisoOrsiso
Orsisoe27
 
Creating a Facebook Clone - Part XLI - Transcript.pdf
Creating a Facebook Clone - Part XLI - Transcript.pdfCreating a Facebook Clone - Part XLI - Transcript.pdf
Creating a Facebook Clone - Part XLI - Transcript.pdfShaiAlmog1
 
Creating an Uber Clone - Part XX - Transcript.pdf
Creating an Uber Clone - Part XX - Transcript.pdfCreating an Uber Clone - Part XX - Transcript.pdf
Creating an Uber Clone - Part XX - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdfCreating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfShaiAlmog1
 
Wicket KT part 2
Wicket KT part 2Wicket KT part 2
Wicket KT part 2stuq
 
Struts 2 + Spring
Struts 2 + SpringStruts 2 + Spring
Struts 2 + SpringBryan Hsueh
 

Similar to Creating a Facebook Clone - Part XXVIII - Transcript.pdf (20)

Creating an Uber Clone - Part XXXIX.pdf
Creating an Uber Clone - Part XXXIX.pdfCreating an Uber Clone - Part XXXIX.pdf
Creating an Uber Clone - Part XXXIX.pdf
 
Creating a Facebook Clone - Part XLVI - Transcript.pdf
Creating a Facebook Clone - Part XLVI - Transcript.pdfCreating a Facebook Clone - Part XLVI - Transcript.pdf
Creating a Facebook Clone - Part XLVI - Transcript.pdf
 
Geb qa fest2017
Geb qa fest2017Geb qa fest2017
Geb qa fest2017
 
Creating an Uber Clone - Part XIV - Transcript.pdf
Creating an Uber Clone - Part XIV - Transcript.pdfCreating an Uber Clone - Part XIV - Transcript.pdf
Creating an Uber Clone - Part XIV - Transcript.pdf
 
Creating a Facebook Clone - Part VIII - Transcript.pdf
Creating a Facebook Clone - Part VIII - Transcript.pdfCreating a Facebook Clone - Part VIII - Transcript.pdf
Creating a Facebook Clone - Part VIII - Transcript.pdf
 
Week 12 code
Week 12 codeWeek 12 code
Week 12 code
 
Creating a Facebook Clone - Part XLV - Transcript.pdf
Creating a Facebook Clone - Part XLV - Transcript.pdfCreating a Facebook Clone - Part XLV - Transcript.pdf
Creating a Facebook Clone - Part XLV - Transcript.pdf
 
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo A GWT Application with MVP Pattern Deploying to CloudFoundry using  Spring Roo
A GWT Application with MVP Pattern Deploying to CloudFoundry using Spring Roo
 
Vaadin7
Vaadin7Vaadin7
Vaadin7
 
Creating a Whatsapp Clone - Part III - Transcript.pdf
Creating a Whatsapp Clone - Part III - Transcript.pdfCreating a Whatsapp Clone - Part III - Transcript.pdf
Creating a Whatsapp Clone - Part III - Transcript.pdf
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
 
Creating a Facebook Clone - Part XLVI.pdf
Creating a Facebook Clone - Part XLVI.pdfCreating a Facebook Clone - Part XLVI.pdf
Creating a Facebook Clone - Part XLVI.pdf
 
Android Testing
Android TestingAndroid Testing
Android Testing
 
Orsiso
OrsisoOrsiso
Orsiso
 
Creating a Facebook Clone - Part XLI - Transcript.pdf
Creating a Facebook Clone - Part XLI - Transcript.pdfCreating a Facebook Clone - Part XLI - Transcript.pdf
Creating a Facebook Clone - Part XLI - Transcript.pdf
 
Creating an Uber Clone - Part XX - Transcript.pdf
Creating an Uber Clone - Part XX - Transcript.pdfCreating an Uber Clone - Part XX - Transcript.pdf
Creating an Uber Clone - Part XX - Transcript.pdf
 
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdfCreating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
 
Wicket KT part 2
Wicket KT part 2Wicket KT part 2
Wicket KT part 2
 
Struts 2 + Spring
Struts 2 + SpringStruts 2 + Spring
Struts 2 + Spring
 

More from ShaiAlmog1

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...ShaiAlmog1
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfShaiAlmog1
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfShaiAlmog1
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfShaiAlmog1
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfShaiAlmog1
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfShaiAlmog1
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfShaiAlmog1
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfShaiAlmog1
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfShaiAlmog1
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfCreating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdfCreating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdfShaiAlmog1
 

More from ShaiAlmog1 (20)

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
 
Creating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfCreating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdf
 
Creating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdfCreating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdf
 

Recently uploaded

New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfngoud9212
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 

Recently uploaded (20)

New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdf
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 

Creating a Facebook Clone - Part XXVIII - Transcript.pdf

  • 1. Creating a Facebook Clone - Part XXVIII The sensible place to start is with the login & signup processes and the way they tie to the server.
  • 2. Container logoContainer = BorderLayout.centerAbsolute(logo); logoContainer.setUIID("LoginTitle"); signUp.addActionListener(e -> UIController.showSignup()); login.addActionListener(e -> { User u = new User().password.set(password.getText()); if(user.getText().contains("@")) { u.email.set(user.getText()); } else { u.phone.set(user.getText()); } Dialog d = new InfiniteProgress().showInifiniteBlocking(); ServerAPI.login(u, new Callback<User>() { @Override public void onSucess(User value) { d.dispose(); UIController.showMainUI(); } @Override public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { d.dispose(); ToastBar.showErrorMessage("Login Failed"); } LoginForm The login change is trivial, we need to replace the action listener of the login button with this new one
  • 3. Container logoContainer = BorderLayout.centerAbsolute(logo); logoContainer.setUIID("LoginTitle"); signUp.addActionListener(e -> UIController.showSignup()); login.addActionListener(e -> { User u = new User().password.set(password.getText()); if(user.getText().contains("@")) { u.email.set(user.getText()); } else { u.phone.set(user.getText()); } Dialog d = new InfiniteProgress().showInifiniteBlocking(); ServerAPI.login(u, new Callback<User>() { @Override public void onSucess(User value) { d.dispose(); UIController.showMainUI(); } @Override public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { d.dispose(); ToastBar.showErrorMessage("Login Failed"); } LoginForm We use the User object as a data transfer object, we set the password and phone/email to send them to the server
  • 4. Container logoContainer = BorderLayout.centerAbsolute(logo); logoContainer.setUIID("LoginTitle"); signUp.addActionListener(e -> UIController.showSignup()); login.addActionListener(e -> { User u = new User().password.set(password.getText()); if(user.getText().contains("@")) { u.email.set(user.getText()); } else { u.phone.set(user.getText()); } Dialog d = new InfiniteProgress().showInifiniteBlocking(); ServerAPI.login(u, new Callback<User>() { @Override public void onSucess(User value) { d.dispose(); UIController.showMainUI(); } @Override public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { d.dispose(); ToastBar.showErrorMessage("Login Failed"); } LoginForm The infinite progress UI is a bit of a shortcut but for a feature like login it makes some sense as we can't avoid a delay
  • 5. login.addActionListener(e -> { User u = new User().password.set(password.getText()); if(user.getText().contains("@")) { u.email.set(user.getText()); } else { u.phone.set(user.getText()); } Dialog d = new InfiniteProgress().showInifiniteBlocking(); ServerAPI.login(u, new Callback<User>() { @Override public void onSucess(User value) { d.dispose(); UIController.showMainUI(); } @Override public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { d.dispose(); ToastBar.showErrorMessage("Login Failed"); } }); }); add(NORTH, logoContainer); LoginForm A successful login shows the main UI whereas an error just shows the error message. Both dispose the infinite progress dialog That's pretty simple and should work right away if we had a User object in place... To add a new user we need to overhaul the signup form.
  • 6. public class SignupForm extends Form { Container content = new Container(BoxLayout.y(), "PaddedContainer"); Container south = new Container(BoxLayout.y()); protected SignupForm(String title, String backLabel, Form previous) { super(title, new BorderLayout()); setUIID("SignupForm"); content.setScrollableY(true); add(CENTER, content); getToolbar().setBackCommand(backLabel, Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW, e -> previous.showBack()); getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape"); Button problem = new Button("Report a Problem", "BlueLink"); south.add(problem); problem.addActionListener(e -> sendMessage("Problem with Facebook Clone", new Message("Details..."), "mark@facebook.com")); add(SOUTH, south); SignupForm As you may recall the SignupForm has a series of methods to create the wizard flow UI. This series of methods should generate a User object that we can use for signup
  • 7. next.addActionListener(al); return next; } public static SignupForm createTerms() { SignupForm s = new SignupForm("Create Account", "Sign In", getCurrentForm()); Label title = new Label("Terms & Conditions", "SignupSubHeader"); RichTextView rt = new RichTextView( "By signing up you agree to our " + "<a href="terms">Facebook Terms</a> and that you have " + "read our <a href="data-policy">Data Policy</a>, including " + "our <a href="cookie-use">Cookie Use</a>."); rt.setAlignment(CENTER); rt.setUIID("PaddedContainer"); Button next = s.createNextButton(e -> createName().show()); next.setText("I Agree"); rt.addLinkListener(e -> { String link = (String) e.getSource(); execute("https://www.codenameone.com/"); }); s.content.addAll(title, rt, next); return s; } SignupForm The first in the series is the createTerms() method, since that method doesn't include any data there is no need for a User object there
  • 8. s.content.addAll(title, rt, next); return s; } public static SignupForm createName() { SignupForm s = new SignupForm("Name", "Terms", getCurrentForm()); Label title = new Label("What's Your Name?", "SignupSubHeader"); TextComponent first = new TextComponent(). label("First Name").columns(12); TextComponent last = new TextComponent(). label("Last Name").columns(12); User currentUser = new User(); UiBinding uib = new UiBinding(); uib.bind(currentUser.firstName, first); uib.bind(currentUser.familyName, last); TextModeLayout layout = new TextModeLayout(1, 2); Container textContainer = new Container(layout, "PaddedContainer"); textContainer.add(layout.createConstraint(). widthPercentage(50), first); textContainer.add(layout.createConstraint(). widthPercentage(50), last); last.getField().setDoneListener(e -> SignupForm The second method is createName() and there we already have some work
  • 9. s.content.addAll(title, rt, next); return s; } public static SignupForm createName() { SignupForm s = new SignupForm("Name", "Terms", getCurrentForm()); Label title = new Label("What's Your Name?", "SignupSubHeader"); TextComponent first = new TextComponent(). label("First Name").columns(12); TextComponent last = new TextComponent(). label("Last Name").columns(12); User currentUser = new User(); UiBinding uib = new UiBinding(); uib.bind(currentUser.firstName, first); uib.bind(currentUser.familyName, last); TextModeLayout layout = new TextModeLayout(1, 2); Container textContainer = new Container(layout, "PaddedContainer"); textContainer.add(layout.createConstraint(). widthPercentage(50), first); textContainer.add(layout.createConstraint(). widthPercentage(50), last); last.getField().setDoneListener(e -> SignupForm Since this is the first stage in the wizard we create the User & binding instances
  • 10. s.content.addAll(title, rt, next); return s; } public static SignupForm createName() { SignupForm s = new SignupForm("Name", "Terms", getCurrentForm()); Label title = new Label("What's Your Name?", "SignupSubHeader"); TextComponent first = new TextComponent(). label("First Name").columns(12); TextComponent last = new TextComponent(). label("Last Name").columns(12); User currentUser = new User(); UiBinding uib = new UiBinding(); uib.bind(currentUser.firstName, first); uib.bind(currentUser.familyName, last); TextModeLayout layout = new TextModeLayout(1, 2); Container textContainer = new Container(layout, "PaddedContainer"); textContainer.add(layout.createConstraint(). widthPercentage(50), first); textContainer.add(layout.createConstraint(). widthPercentage(50), last); last.getField().setDoneListener(e -> SignupForm Binding means changes to the UI instantly change this field & visa versa. That's very convenient
  • 11. TextModeLayout layout = new TextModeLayout(1, 2); Container textContainer = new Container(layout, "PaddedContainer"); textContainer.add(layout.createConstraint(). widthPercentage(50), first); textContainer.add(layout.createConstraint(). widthPercentage(50), last); last.getField().setDoneListener(e -> createBirthday(currentUser, uib).show()); s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday(currentUser, uib). show())); return s; } public static SignupForm createBirthday(User currentUser, UiBinding uib) { SignupForm s = new SignupForm("Birthday", "Name", getCurrentForm()); Label title = new Label("What's Your Birthday?", "SignupSubHeader"); Picker datePicker = new Picker(); datePicker.setType(PICKER_TYPE_DATE); int twentyYears = 60000 * 60 * 24 * 365 * 20; datePicker.setDate( SignupForm The createBirthday method now accepts the user and binding objects so we can fill them up with further details
  • 12. s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday(currentUser, uib). show())); return s; } public static SignupForm createBirthday(User currentUser, UiBinding uib) { SignupForm s = new SignupForm("Birthday", "Name", getCurrentForm()); Label title = new Label("What's Your Birthday?", "SignupSubHeader"); Picker datePicker = new Picker(); datePicker.setType(PICKER_TYPE_DATE); int twentyYears = 60000 * 60 * 24 * 365 * 20; datePicker.setDate( new Date(System.currentTimeMillis() - twentyYears)); uib.bind(currentUser.birthday, datePicker); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender(currentUser, uib).show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { SignupForm That's simple enough, the binding implicitly updates the user objects with changes from the UI. Next we can proceed to the changes in the birthday method obviously the first change in the method is the signature which now accepts the user and binding
  • 13. s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday(currentUser, uib). show())); return s; } public static SignupForm createBirthday(User currentUser, UiBinding uib) { SignupForm s = new SignupForm("Birthday", "Name", getCurrentForm()); Label title = new Label("What's Your Birthday?", "SignupSubHeader"); Picker datePicker = new Picker(); datePicker.setType(PICKER_TYPE_DATE); int twentyYears = 60000 * 60 * 24 * 365 * 20; datePicker.setDate( new Date(System.currentTimeMillis() - twentyYears)); uib.bind(currentUser.birthday, datePicker); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender(currentUser, uib).show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { SignupForm Other than the method signature we added this line to bind the date picker to the birthday
  • 14. s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday(currentUser, uib). show())); return s; } public static SignupForm createBirthday(User currentUser, UiBinding uib) { SignupForm s = new SignupForm("Birthday", "Name", getCurrentForm()); Label title = new Label("What's Your Birthday?", "SignupSubHeader"); Picker datePicker = new Picker(); datePicker.setType(PICKER_TYPE_DATE); int twentyYears = 60000 * 60 * 24 * 365 * 20; datePicker.setDate( new Date(System.currentTimeMillis() - twentyYears)); uib.bind(currentUser.birthday, datePicker); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender(currentUser, uib).show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { SignupForm And we added the arguments to the gender method too
  • 15. rb.setPressedIcon(selIcon); rb.setUIID("GenderToggle"); return rb; } public static SignupForm createGender(User currentUser, UiBinding uib) { SignupForm s = new SignupForm("Gender", "Birthday", getCurrentForm()); Label title = new Label("What's Your Gender?", "SignupSubHeader"); ButtonGroup bg = new ButtonGroup(); RadioButton female = createGenderButton(bg, "Female", "ue800"); RadioButton male = createGenderButton(bg, "Male", "ue801"); uib.bindGroup(currentUser.gender, new String[]{"Male", "Female"}, male, female); Container buttons = GridLayout.encloseIn(2, female, male); buttons.setUIID("PaddedContainer"); s.content.addAll(title, buttons, s.createNextButton(e -> createNumber(currentUser, uib).show())); return s; } SignupForm This leads us to the changes in the createGender() method. Since most of the changes are repetitive I'll skip the method signature and the signature of the followup createNumber method. Suffice to say we pass the user & binding onward…
 This is the binding code for the gender that automatically sets Male/Female for the gender attribute based on the radio button selection. It's a special case because these are buttons so we need to provide the values that match each button.
  • 16. new String[]{"Male", "Female"}, male, female); Container buttons = GridLayout.encloseIn(2, female, male); buttons.setUIID("PaddedContainer"); s.content.addAll(title, buttons, s.createNextButton(e -> createNumber(currentUser, uib).show())); return s; } public static SignupForm createNumber(User currentUser, UiBinding uib) { return createMobileOrEmail(currentUser, currentUser.phone, uib, "Mobile Number", "What's Your Mobile Number?", "Sign Up With Email Address", TextArea.PHONENUMBER, e -> createEmail(currentUser, uib).show()); } private static SignupForm createMobileOrEmail(User currentUser, Property userProp, UiBinding uib, String formTitle, String subtitle, String signUpWith, int constraint, ActionListener goToOther) { SignupForm s = new SignupForm(formTitle, getCurrentForm().getTitle(), getCurrentForm()); SignupForm The createNumber changes are a bit different because of the symbiotic relationship to the createEmail method. I'll list more of the code but I'll skip the createEmail method as the changes there are obvious. The change itself is in the createMobileOrEmail method which is common to createNumber & createEmail
  • 17. TextArea.PHONENUMBER, e -> createEmail(currentUser, uib).show()); } private static SignupForm createMobileOrEmail(User currentUser, Property userProp, UiBinding uib, String formTitle, String subtitle, String signUpWith, int constraint, ActionListener goToOther) { SignupForm s = new SignupForm(formTitle, getCurrentForm().getTitle(), getCurrentForm()); Label title = new Label(subtitle, "SignupSubHeader"); TextComponent textEntry = new TextComponent(). label(formTitle). columns(20). constraint(constraint); uib.bind(userProp, textEntry); Container textContainer = new Container(new TextModeLayout(1, 1), "PaddedContainer"); textContainer.add(textEntry); Button mobile = new Button(signUpWith, "BoldBlueLink"); mobile.addActionListener(goToOther); SignupForm This is the only change in this method. It's right under the declaration of textEntry but in effect it can be anywhere in the method. We bind the property to the text component both of which are passed as arguments to this method.
  • 18. TextArea.EMAILADDR, e -> createNumber(currentUser, uib).show()); } public static SignupForm createPassword( User currentUser, UiBinding uib, boolean phone, String value) { SignupForm s = new SignupForm("Password", getCurrentForm().getTitle(), getCurrentForm()); Label title = new Label("Choose a Password", "SignupSubHeader"); TextComponent password = new TextComponent(). label("Password"). columns(20); uib.bind(currentUser.password, password); Container textContainer = new Container(new TextModeLayout(1, 1), "PaddedContainer"); textContainer.add(password); s.content.addAll(title, textContainer, s.createNextButton(e -> { Dialog dlg = new Dialog("Signing Up...", new BorderLayout( BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE)); SignupForm The final piece of the wizard is the createPassword method, which follows up with a code change that's pretty similar to everything we saw so far at least initially… The binding call is pretty standard as we had up until now
  • 19. SignupForm s = new SignupForm("Password", getCurrentForm().getTitle(), getCurrentForm()); Label title = new Label("Choose a Password", "SignupSubHeader"); TextComponent password = new TextComponent(). label("Password"). columns(20); uib.bind(currentUser.password, password); Container textContainer = new Container(new TextModeLayout(1, 1), "PaddedContainer"); textContainer.add(password); s.content.addAll(title, textContainer, s.createNextButton(e -> { Dialog dlg = new Dialog("Signing Up...", new BorderLayout( BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE)); dlg.add(CENTER, new InfiniteProgress()); dlg.showModeless(); ServerAPI.signup(currentUser, new Callback<User>() { @Override public void onSucess(User result) { dlg.dispose(); createConfirmation(currentUser, phone, value).show(); SignupForm We launch a progress dialog that runs while we wait for signup to complete
  • 20. s.content.addAll(title, textContainer, s.createNextButton(e -> { Dialog dlg = new Dialog("Signing Up...", new BorderLayout( BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE)); dlg.add(CENTER, new InfiniteProgress()); dlg.showModeless(); ServerAPI.signup(currentUser, new Callback<User>() { @Override public void onSucess(User result) { dlg.dispose(); createConfirmation(currentUser, phone, value).show(); } @Override public void onError(Object sender, Throwable err, int errorCode, String errorMessage) { dlg.dispose(); ToastBar.showErrorMessage( "Error in server connection"); } }); })); return s; } SignupForm If signup was successful we go to the confirmation UI and wait for that That effectively created a user on the server and triggered an email or SMS to us. We can now check the confirmation value to see if the user is indeed valid.
  • 21. "Enter the code in the message sent to " + value, "CenterLabel"); } TextComponent confirm = new TextComponent(). label("Confirmation Code"). columns(20). constraint(TextArea.NUMERIC); Container textContainer = new Container(new TextModeLayout(1, 1), "PaddedContainer"); textContainer.add(confirm); Button done = s.createNextButton(e -> { Dialog d = new InfiniteProgress().showInifiniteBlocking(); if(ServerAPI.verifyUser(confirm.getText(), !phone)) { UIController.showMainUI(); } else { d.dispose(); ToastBar.showErrorMessage("Verification code error!"); } }); done.setText("Confirm"); s.content.addAll(title, line, textContainer, done); return s; } SignupForm We do that by adding this code to the createConfirmation method. If verification succeeded we show the main UI…
  • 22. "Enter the code in the message sent to " + value, "CenterLabel"); } TextComponent confirm = new TextComponent(). label("Confirmation Code"). columns(20). constraint(TextArea.NUMERIC); Container textContainer = new Container(new TextModeLayout(1, 1), "PaddedContainer"); textContainer.add(confirm); Button done = s.createNextButton(e -> { Dialog d = new InfiniteProgress().showInifiniteBlocking(); if(ServerAPI.verifyUser(confirm.getText(), !phone)) { UIController.showMainUI(); } else { d.dispose(); ToastBar.showErrorMessage("Verification code error!"); } }); done.setText("Confirm"); s.content.addAll(title, line, textContainer, done); return s; } SignupForm Otherwise we show an error message and remain in the current Form.
  • 23. public static void showSplashScreen() { Form splash = new Form(new BorderLayout( BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE)); splash.setUIID("SplashForm"); Label logo = new Label("uf308", "IconFont"); logo.setName("Logo"); splash.add(CENTER, logo); splash.setTransitionOutAnimator( MorphTransition. create(1200). morph("Logo")); final Motion anim = Motion.createLinearMotion(0, 127, 1000); anim.start(); UITimer.timer(20, true, splash, () -> { if(anim.isFinished()) { if(!ServerAPI.isLoggedIn()) { showLoginForm(); } else { showMainUI(); } } else { logo.getUnselectedStyle().setOpacity(anim.getValue() + 127); logo.repaint(); } }); splash.show(); UIController We still have one more change to make to the UIController class. Up until now we always started with the LoginForm but we should only start there when we are logged out. We can just change the call to showMainUI() to this. If we aren't logged in correctly we behave as before after the splash screen. However, if we are logged in we go to the main UI… With that a new User is in place and should allow us to login to the app!