SlideShare a Scribd company logo
1 of 13
Download to read offline
Creating a Facebook Clone - Part XXIX
Mapping the newsfeed is pretty simple now that we have a functional ServerAPI.
return l;
}
public static String formatTimeAgo(long time) {
long current = System.currentTimeMillis() - time;
if(current < HOUR) {
long minutes = current / 60000;
if(minutes < 2) {
return "Just now";
}
return minutes + " minutes ago";
}
if(current < HOUR * 10) {
return (current / HOUR) + " hours ago";
}
return L10NManager.getInstance().
formatDateTimeShort(new Date(time));
}
public static Component[] toArray(List<Component> components) {
Component[] cmps = new Component[components.size()];
components.toArray(cmps);
return cmps;
}
}
UIUtils
First we need a new utility method for the UIUtils class. 

This is mostly boilerplate code… Notice that a lot of Java developers would just do something like components.toArray() but that's problematic as it requires reflection to
detect the generic type of the list and allocate an array of that specific type. Codename One doesn't support that as it would include runtime overhead.
public class NewsfeedContainer extends InfiniteContainer {
@Override
public Component[] fetchComponents(int index, int amount) {
ArrayList<Component> components = new ArrayList<>();
if(index == 0) {
components.add(createPostBar());
components.add(UIUtils.createSpace());
}
int page = index / amount;
if(index % amount > 0) {
page++;
}
List<Post> response = ServerAPI.newsfeed(page, amount);
if(response == null) {
if(index == 0) {
return UIUtils.toArray(components);
}
return null;
}
for(Post p : response) {
components.add(createNewsItem(p.user.get(), p));
NewsfeedContainer
Once this is out of the way the generic code in the NewsfeedContainer class is simpler
public class NewsfeedContainer extends InfiniteContainer {
@Override
public Component[] fetchComponents(int index, int amount) {
ArrayList<Component> components = new ArrayList<>();
if(index == 0) {
components.add(createPostBar());
components.add(UIUtils.createSpace());
}
int page = index / amount;
if(index % amount > 0) {
page++;
}
List<Post> response = ServerAPI.newsfeed(page, amount);
if(response == null) {
if(index == 0) {
return UIUtils.toArray(components);
}
return null;
}
for(Post p : response) {
components.add(createNewsItem(p.user.get(), p));
NewsfeedContainer
We no longer need the lastTime variable as the code works with standard paging now
public class NewsfeedContainer extends InfiniteContainer {
@Override
public Component[] fetchComponents(int index, int amount) {
ArrayList<Component> components = new ArrayList<>();
if(index == 0) {
components.add(createPostBar());
components.add(UIUtils.createSpace());
}
int page = index / amount;
if(index % amount > 0) {
page++;
}
List<Post> response = ServerAPI.newsfeed(page, amount);
if(response == null) {
if(index == 0) {
return UIUtils.toArray(components);
}
return null;
}
for(Post p : response) {
components.add(createNewsItem(p.user.get(), p));
NewsfeedContainer
This is a special case for the edge of the data where the number of entries is smaller than a full page size
public class NewsfeedContainer extends InfiniteContainer {
@Override
public Component[] fetchComponents(int index, int amount) {
ArrayList<Component> components = new ArrayList<>();
if(index == 0) {
components.add(createPostBar());
components.add(UIUtils.createSpace());
}
int page = index / amount;
if(index % amount > 0) {
page++;
}
List<Post> response = ServerAPI.newsfeed(page, amount);
if(response == null) {
if(index == 0) {
return UIUtils.toArray(components);
}
return null;
}
for(Post p : response) {
components.add(createNewsItem(p.user.get(), p));
NewsfeedContainer
We request the page data using a synchronous API call this specific API call uses invokeAndBlock internally and is thus safe on the EDT
if(index == 0) {
components.add(createPostBar());
components.add(UIUtils.createSpace());
}
int page = index / amount;
if(index % amount > 0) {
page++;
}
List<Post> response = ServerAPI.newsfeed(page, amount);
if(response == null) {
if(index == 0) {
return UIUtils.toArray(components);
}
return null;
}
for(Post p : response) {
components.add(createNewsItem(p.user.get(), p));
components.add(UIUtils.createHalfSpace());
}
return UIUtils.toArray(components);
}
private static Container createNewsTitle(User u, Post p) {
Button avatar = new Button("", u.getAvatar(6.5f), "CleanButton");
Button name = new Button(u.fullName(), "PostTitle");
NewsfeedContainer
We build components for the responses and then convert them to an array as required by the API. That's pretty simple and will automatically fetch additional data as we
scroll down in the UI.
public class NewPostForm extends Form {
private static final String[] POST_STYLES = {
"Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack",
"PostStyleRed", "PostStylePurple" };
private TextArea post = new TextArea(3, 80);
private String postStyleValue;
public NewPostForm() {
super("Create Post", new BorderLayout());
Form current = getCurrentForm();
getToolbar().setBackCommand("Cancel",
Toolbar.BackCommandPolicy.
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> post(current));
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
NewPostForm
So the big missing piece is actual content that fits into that feed. To do that we need to make some changes to the NewPostForm. First I extracted two of the local fields
into class level variables that I can use later
public class NewPostForm extends Form {
private static final String[] POST_STYLES = {
"Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack",
"PostStyleRed", "PostStylePurple" };
private TextArea post = new TextArea(3, 80);
private String postStyleValue;
public NewPostForm() {
super("Create Post", new BorderLayout());
Form current = getCurrentForm();
getToolbar().setBackCommand("Cancel",
Toolbar.BackCommandPolicy.
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> post(current));
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
NewPostForm
We can then change the event handling code to invoke the post method instead of the blank block we had before
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
add(NORTH, userSettings);
post.setUIID("Label");
post.setGrowByContent(false);
Container postStyles = createPostStyles(post);
add(CENTER, LayeredLayout.encloseIn(
BorderLayout.north(post), BorderLayout.south(postStyles)));
setEditOnShow(post);
}
private void post(Form previousForm) {
Dialog dlg = new InfiniteProgress().showInifiniteBlocking();
if(!ServerAPI.post(new Post().
content.set(post.getText()).
visibility.set("public").
styling.set(postStyleValue))) {
dlg.dispose();
ToastBar.showErrorMessage("Error posting to server");
return;
}
previousForm.showBack();
}
private Container createPostStyles(TextArea post) {
NewPostForm
After that all the logic is in the post method itself…
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
add(NORTH, userSettings);
post.setUIID("Label");
post.setGrowByContent(false);
Container postStyles = createPostStyles(post);
add(CENTER, LayeredLayout.encloseIn(
BorderLayout.north(post), BorderLayout.south(postStyles)));
setEditOnShow(post);
}
private void post(Form previousForm) {
Dialog dlg = new InfiniteProgress().showInifiniteBlocking();
if(!ServerAPI.post(new Post().
content.set(post.getText()).
visibility.set("public").
styling.set(postStyleValue))) {
dlg.dispose();
ToastBar.showErrorMessage("Error posting to server");
return;
}
previousForm.showBack();
}
private Container createPostStyles(TextArea post) {
NewPostForm
We create a Post object on the fly, right now all posts are public as I don't want to get into "friends only" UI etc.
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
add(NORTH, userSettings);
post.setUIID("Label");
post.setGrowByContent(false);
Container postStyles = createPostStyles(post);
add(CENTER, LayeredLayout.encloseIn(
BorderLayout.north(post), BorderLayout.south(postStyles)));
setEditOnShow(post);
}
private void post(Form previousForm) {
Dialog dlg = new InfiniteProgress().showInifiniteBlocking();
if(!ServerAPI.post(new Post().
content.set(post.getText()).
visibility.set("public").
styling.set(postStyleValue))) {
dlg.dispose();
ToastBar.showErrorMessage("Error posting to server");
return;
}
previousForm.showBack();
}
private Container createPostStyles(TextArea post) {
NewPostForm
If the post succeeded we can go back to the previousForm

Notice that you will need to refresh after adding a post right now, this is something we'll resolve when integrating push later

With that we can post and see the entries appear in the newsfeed...
public class FriendsContainer extends Container {
public FriendsContainer() {
super(BoxLayout.y());
setScrollableY(true);
init();
addPullToRefresh(() -> {
ServerAPI.refreshMe();
removeAll();
init();
revalidate();
});
}
private void init() {
int friendCount = ServerAPI.me().friendRequests.size();
EncodedImage placeholder = FontImage.createMaterial(
MATERIAL_PERSON, "Label", 18).toEncodedImage();
add(createTitle("FRIEND REQUESTS", friendCount));
if(friendCount == 0) {
Container padded = new Container(new BorderLayout(),
FriendsContainer
Because of the way login works our User object stored in ServerAPI.me() will include the friend requests and people we should know. This should work out of the box and
suggest friend requests whenever we login. One missing piece is refresh. Since we cache the user object we might have additional friends waiting.

We can implement that in the addPullToRefresh call within the FriendsContainer constructor.

That updates the User object and after that the UI is rebuilt with the new friends.

More Related Content

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

Gutenberg sous le capot, modules réutilisables
Gutenberg sous le capot, modules réutilisablesGutenberg sous le capot, modules réutilisables
Gutenberg sous le capot, modules réutilisablesRiad Benguella
 
Creating an Uber Clone - Part XXXX - Transcript.pdf
Creating an Uber Clone - Part XXXX - Transcript.pdfCreating an Uber Clone - Part XXXX - Transcript.pdf
Creating an Uber Clone - Part XXXX - Transcript.pdfShaiAlmog1
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
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
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to HooksSoluto
 
Creating a Facebook Clone - Part XVI.pdf
Creating a Facebook Clone - Part XVI.pdfCreating a Facebook Clone - Part XVI.pdf
Creating a Facebook Clone - Part XVI.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
 
Creating a Facebook Clone - Part XXXIV.pdf
Creating a Facebook Clone - Part XXXIV.pdfCreating a Facebook Clone - Part XXXIV.pdf
Creating a Facebook Clone - Part XXXIV.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XL - Transcript.pdf
Creating a Facebook Clone - Part XL - Transcript.pdfCreating a Facebook Clone - Part XL - Transcript.pdf
Creating a Facebook Clone - Part XL - Transcript.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XXXIII - Transcript.pdf
Creating a Facebook Clone - Part XXXIII - Transcript.pdfCreating a Facebook Clone - Part XXXIII - Transcript.pdf
Creating a Facebook Clone - Part XXXIII - Transcript.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XVI - Transcript.pdf
Creating a Facebook Clone - Part XVI - Transcript.pdfCreating a Facebook Clone - Part XVI - Transcript.pdf
Creating a Facebook Clone - Part XVI - Transcript.pdfShaiAlmog1
 
Initial UI Mockup - Part 3.pdf
Initial UI Mockup - Part 3.pdfInitial UI Mockup - Part 3.pdf
Initial UI Mockup - Part 3.pdfShaiAlmog1
 
Advanced Java - Practical File
Advanced Java - Practical FileAdvanced Java - Practical File
Advanced Java - Practical FileFahad Shaikh
 
Creating a Facebook Clone - Part VI - Transcript.pdf
Creating a Facebook Clone - Part VI - Transcript.pdfCreating a Facebook Clone - Part VI - Transcript.pdf
Creating a Facebook Clone - Part VI - Transcript.pdfShaiAlmog1
 
Wicket KT part 2
Wicket KT part 2Wicket KT part 2
Wicket KT part 2stuq
 
GWT Training - Session 3/3
GWT Training - Session 3/3GWT Training - Session 3/3
GWT Training - Session 3/3Faiz Bashir
 
Creating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdfCreating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdfShaiAlmog1
 
OOP program questions with answers
OOP program questions with answersOOP program questions with answers
OOP program questions with answersQuratulain Naqvi
 

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

Gutenberg sous le capot, modules réutilisables
Gutenberg sous le capot, modules réutilisablesGutenberg sous le capot, modules réutilisables
Gutenberg sous le capot, modules réutilisables
 
Creating an Uber Clone - Part XXXX - Transcript.pdf
Creating an Uber Clone - Part XXXX - Transcript.pdfCreating an Uber Clone - Part XXXX - Transcript.pdf
Creating an Uber Clone - Part XXXX - Transcript.pdf
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
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
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
 
Creating a Facebook Clone - Part XVI.pdf
Creating a Facebook Clone - Part XVI.pdfCreating a Facebook Clone - Part XVI.pdf
Creating a Facebook Clone - Part XVI.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
 
Creating a Facebook Clone - Part XXXIV.pdf
Creating a Facebook Clone - Part XXXIV.pdfCreating a Facebook Clone - Part XXXIV.pdf
Creating a Facebook Clone - Part XXXIV.pdf
 
Creating a Facebook Clone - Part XL - Transcript.pdf
Creating a Facebook Clone - Part XL - Transcript.pdfCreating a Facebook Clone - Part XL - Transcript.pdf
Creating a Facebook Clone - Part XL - Transcript.pdf
 
Creating a Facebook Clone - Part XXXIII - Transcript.pdf
Creating a Facebook Clone - Part XXXIII - Transcript.pdfCreating a Facebook Clone - Part XXXIII - Transcript.pdf
Creating a Facebook Clone - Part XXXIII - Transcript.pdf
 
Creating a Facebook Clone - Part XVI - Transcript.pdf
Creating a Facebook Clone - Part XVI - Transcript.pdfCreating a Facebook Clone - Part XVI - Transcript.pdf
Creating a Facebook Clone - Part XVI - Transcript.pdf
 
Initial UI Mockup - Part 3.pdf
Initial UI Mockup - Part 3.pdfInitial UI Mockup - Part 3.pdf
Initial UI Mockup - Part 3.pdf
 
Advanced Java - Practical File
Advanced Java - Practical FileAdvanced Java - Practical File
Advanced Java - Practical File
 
Creating a Facebook Clone - Part VI - Transcript.pdf
Creating a Facebook Clone - Part VI - Transcript.pdfCreating a Facebook Clone - Part VI - Transcript.pdf
Creating a Facebook Clone - Part VI - Transcript.pdf
 
Wicket KT part 2
Wicket KT part 2Wicket KT part 2
Wicket KT part 2
 
GWT Training - Session 3/3
GWT Training - Session 3/3GWT Training - Session 3/3
GWT Training - Session 3/3
 
Angular 2.0 - What to expect
Angular 2.0 - What to expectAngular 2.0 - What to expect
Angular 2.0 - What to expect
 
Creating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdfCreating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdf
 
To-Do App With Flutter: Step By Step Guide
To-Do App With Flutter: Step By Step GuideTo-Do App With Flutter: Step By Step Guide
To-Do App With Flutter: Step By Step Guide
 
OOP program questions with answers
OOP program questions with answersOOP program questions with answers
OOP program questions with answers
 

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 II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.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 IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.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
 

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 II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.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 IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.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
 

Recently uploaded

Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMKumar Satyam
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....rightmanforbloodline
 
Choreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software EngineeringChoreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software EngineeringWSO2
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Decarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceDecarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceIES VE
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightSafe Software
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformLess Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformWSO2
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Bhuvaneswari Subramani
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
How to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfHow to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfdanishmna97
 
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...caitlingebhard1
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseWSO2
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)Samir Dash
 

Recently uploaded (20)

Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
 
Choreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software EngineeringChoreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software Engineering
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Decarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational PerformanceDecarbonising Commercial Real Estate: The Role of Operational Performance
Decarbonising Commercial Real Estate: The Role of Operational Performance
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and Insight
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data PlatformLess Is More: Utilizing Ballerina to Architect a Cloud Data Platform
Less Is More: Utilizing Ballerina to Architect a Cloud Data Platform
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
How to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfHow to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cf
 
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...Stronger Together: Developing an Organizational Strategy for Accessible Desig...
Stronger Together: Developing an Organizational Strategy for Accessible Desig...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern Enterprise
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 

Creating a Facebook Clone - Part XXIX - Transcript.pdf

  • 1. Creating a Facebook Clone - Part XXIX Mapping the newsfeed is pretty simple now that we have a functional ServerAPI.
  • 2. return l; } public static String formatTimeAgo(long time) { long current = System.currentTimeMillis() - time; if(current < HOUR) { long minutes = current / 60000; if(minutes < 2) { return "Just now"; } return minutes + " minutes ago"; } if(current < HOUR * 10) { return (current / HOUR) + " hours ago"; } return L10NManager.getInstance(). formatDateTimeShort(new Date(time)); } public static Component[] toArray(List<Component> components) { Component[] cmps = new Component[components.size()]; components.toArray(cmps); return cmps; } } UIUtils First we need a new utility method for the UIUtils class. This is mostly boilerplate code… Notice that a lot of Java developers would just do something like components.toArray() but that's problematic as it requires reflection to detect the generic type of the list and allocate an array of that specific type. Codename One doesn't support that as it would include runtime overhead.
  • 3. public class NewsfeedContainer extends InfiniteContainer { @Override public Component[] fetchComponents(int index, int amount) { ArrayList<Component> components = new ArrayList<>(); if(index == 0) { components.add(createPostBar()); components.add(UIUtils.createSpace()); } int page = index / amount; if(index % amount > 0) { page++; } List<Post> response = ServerAPI.newsfeed(page, amount); if(response == null) { if(index == 0) { return UIUtils.toArray(components); } return null; } for(Post p : response) { components.add(createNewsItem(p.user.get(), p)); NewsfeedContainer Once this is out of the way the generic code in the NewsfeedContainer class is simpler
  • 4. public class NewsfeedContainer extends InfiniteContainer { @Override public Component[] fetchComponents(int index, int amount) { ArrayList<Component> components = new ArrayList<>(); if(index == 0) { components.add(createPostBar()); components.add(UIUtils.createSpace()); } int page = index / amount; if(index % amount > 0) { page++; } List<Post> response = ServerAPI.newsfeed(page, amount); if(response == null) { if(index == 0) { return UIUtils.toArray(components); } return null; } for(Post p : response) { components.add(createNewsItem(p.user.get(), p)); NewsfeedContainer We no longer need the lastTime variable as the code works with standard paging now
  • 5. public class NewsfeedContainer extends InfiniteContainer { @Override public Component[] fetchComponents(int index, int amount) { ArrayList<Component> components = new ArrayList<>(); if(index == 0) { components.add(createPostBar()); components.add(UIUtils.createSpace()); } int page = index / amount; if(index % amount > 0) { page++; } List<Post> response = ServerAPI.newsfeed(page, amount); if(response == null) { if(index == 0) { return UIUtils.toArray(components); } return null; } for(Post p : response) { components.add(createNewsItem(p.user.get(), p)); NewsfeedContainer This is a special case for the edge of the data where the number of entries is smaller than a full page size
  • 6. public class NewsfeedContainer extends InfiniteContainer { @Override public Component[] fetchComponents(int index, int amount) { ArrayList<Component> components = new ArrayList<>(); if(index == 0) { components.add(createPostBar()); components.add(UIUtils.createSpace()); } int page = index / amount; if(index % amount > 0) { page++; } List<Post> response = ServerAPI.newsfeed(page, amount); if(response == null) { if(index == 0) { return UIUtils.toArray(components); } return null; } for(Post p : response) { components.add(createNewsItem(p.user.get(), p)); NewsfeedContainer We request the page data using a synchronous API call this specific API call uses invokeAndBlock internally and is thus safe on the EDT
  • 7. if(index == 0) { components.add(createPostBar()); components.add(UIUtils.createSpace()); } int page = index / amount; if(index % amount > 0) { page++; } List<Post> response = ServerAPI.newsfeed(page, amount); if(response == null) { if(index == 0) { return UIUtils.toArray(components); } return null; } for(Post p : response) { components.add(createNewsItem(p.user.get(), p)); components.add(UIUtils.createHalfSpace()); } return UIUtils.toArray(components); } private static Container createNewsTitle(User u, Post p) { Button avatar = new Button("", u.getAvatar(6.5f), "CleanButton"); Button name = new Button(u.fullName(), "PostTitle"); NewsfeedContainer We build components for the responses and then convert them to an array as required by the API. That's pretty simple and will automatically fetch additional data as we scroll down in the UI.
  • 8. public class NewPostForm extends Form { private static final String[] POST_STYLES = { "Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack", "PostStyleRed", "PostStylePurple" }; private TextArea post = new TextArea(3, 80); private String postStyleValue; public NewPostForm() { super("Create Post", new BorderLayout()); Form current = getCurrentForm(); getToolbar().setBackCommand("Cancel", Toolbar.BackCommandPolicy. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> post(current)); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( NewPostForm So the big missing piece is actual content that fits into that feed. To do that we need to make some changes to the NewPostForm. First I extracted two of the local fields into class level variables that I can use later
  • 9. public class NewPostForm extends Form { private static final String[] POST_STYLES = { "Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack", "PostStyleRed", "PostStylePurple" }; private TextArea post = new TextArea(3, 80); private String postStyleValue; public NewPostForm() { super("Create Post", new BorderLayout()); Form current = getCurrentForm(); getToolbar().setBackCommand("Cancel", Toolbar.BackCommandPolicy. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> post(current)); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( NewPostForm We can then change the event handling code to invoke the post method instead of the blank block we had before
  • 10. BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); add(NORTH, userSettings); post.setUIID("Label"); post.setGrowByContent(false); Container postStyles = createPostStyles(post); add(CENTER, LayeredLayout.encloseIn( BorderLayout.north(post), BorderLayout.south(postStyles))); setEditOnShow(post); } private void post(Form previousForm) { Dialog dlg = new InfiniteProgress().showInifiniteBlocking(); if(!ServerAPI.post(new Post(). content.set(post.getText()). visibility.set("public"). styling.set(postStyleValue))) { dlg.dispose(); ToastBar.showErrorMessage("Error posting to server"); return; } previousForm.showBack(); } private Container createPostStyles(TextArea post) { NewPostForm After that all the logic is in the post method itself…
  • 11. BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); add(NORTH, userSettings); post.setUIID("Label"); post.setGrowByContent(false); Container postStyles = createPostStyles(post); add(CENTER, LayeredLayout.encloseIn( BorderLayout.north(post), BorderLayout.south(postStyles))); setEditOnShow(post); } private void post(Form previousForm) { Dialog dlg = new InfiniteProgress().showInifiniteBlocking(); if(!ServerAPI.post(new Post(). content.set(post.getText()). visibility.set("public"). styling.set(postStyleValue))) { dlg.dispose(); ToastBar.showErrorMessage("Error posting to server"); return; } previousForm.showBack(); } private Container createPostStyles(TextArea post) { NewPostForm We create a Post object on the fly, right now all posts are public as I don't want to get into "friends only" UI etc.
  • 12. BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); add(NORTH, userSettings); post.setUIID("Label"); post.setGrowByContent(false); Container postStyles = createPostStyles(post); add(CENTER, LayeredLayout.encloseIn( BorderLayout.north(post), BorderLayout.south(postStyles))); setEditOnShow(post); } private void post(Form previousForm) { Dialog dlg = new InfiniteProgress().showInifiniteBlocking(); if(!ServerAPI.post(new Post(). content.set(post.getText()). visibility.set("public"). styling.set(postStyleValue))) { dlg.dispose(); ToastBar.showErrorMessage("Error posting to server"); return; } previousForm.showBack(); } private Container createPostStyles(TextArea post) { NewPostForm If the post succeeded we can go back to the previousForm Notice that you will need to refresh after adding a post right now, this is something we'll resolve when integrating push later With that we can post and see the entries appear in the newsfeed...
  • 13. public class FriendsContainer extends Container { public FriendsContainer() { super(BoxLayout.y()); setScrollableY(true); init(); addPullToRefresh(() -> { ServerAPI.refreshMe(); removeAll(); init(); revalidate(); }); } private void init() { int friendCount = ServerAPI.me().friendRequests.size(); EncodedImage placeholder = FontImage.createMaterial( MATERIAL_PERSON, "Label", 18).toEncodedImage(); add(createTitle("FRIEND REQUESTS", friendCount)); if(friendCount == 0) { Container padded = new Container(new BorderLayout(), FriendsContainer Because of the way login works our User object stored in ServerAPI.me() will include the friend requests and people we should know. This should work out of the box and suggest friend requests whenever we login. One missing piece is refresh. Since we cache the user object we might have additional friends waiting. We can implement that in the addPullToRefresh call within the FriendsContainer constructor. That updates the User object and after that the UI is rebuilt with the new friends.