Saturday, November 29, 2025

How Learning Something “Different” Might Help You Unblock the Stuff Holding You Back

I remember the moment Apple introduced SwiftUI and encouraged developers to transition to it—the shift felt overwhelming. The declarative mindset, automatic rendering cycle, and data-driven updates didn’t align with the imperative habits I had built for years. Everything felt unfamiliar. So instead of forcing it, I switched to Flutter for years—mainly because Dart offered a familiar, strongly typed structure. After building a few apps there, I returned to SwiftUI and found it dramatically easier to understand. What once felt impossible suddenly felt natural. This experience reflects a common learning pattern that can help developers adapt to new paradigms.

1. A Fresh Mental Model

SwiftUI and UIKit operate on fundamentally different principles. UIKit requires you to manually manage view states, lifecycle events, and layout sequences. SwiftUI expects you to describe what the UI should be, not how to update it. Trying to learn SwiftUI through a UIKit lens often creates internal conflict because every instinct you have points in the opposite direction. Flutter gave me a clean slate—a declarative world without UIKit baggage. Once I learned declarative concepts elsewhere, returning to SwiftUI felt like applying familiar principles with different syntax.

2. Reduced Cognitive Bias

When you’re deeply experienced in one framework, your expertise can actually become a barrier. This is known as cognitive fixation: your mind keeps trying to solve new problems using old patterns. The more senior you are in the old paradigm, the harder the new one feels. Moving to Flutter temporarily removed that bias. I wasn’t comparing it to UIKit on every line of code. I wasn’t trying to map old lifecycle calls to new ones. Flutter became a low-resistance environment for understanding declarative UI without the pressure of unlearning years of habits.

3. Pattern Recognition Across Frameworks

Flutter’s widget tree, reactive rebuilds, and state-driven UI updates share strong similarities with SwiftUI. After internalizing these concepts once, I could recognize their equivalents in SwiftUI immediately. Rebuilding views when state changes felt normal. Composing UI from small, reusable pieces made sense. Even though the syntax was different, the underlying patterns aligned. Learning these concepts in a different ecosystem helped me see SwiftUI as another dialect rather than a completely foreign language.

4. The Spacing Effect

Spacing is a well-established learning principle: stepping away from something difficult allows your brain to reorganize information, form new abstractions, and reduce frustration. When you return later, the same content often feels more approachable. By taking a break from SwiftUI and focusing on Flutter, my mind naturally reset its assumptions. The time away created space for insights to form subconsciously. That’s why returning to SwiftUI felt like clarity instead of confusion.

Key Takeaway

When a technology feels alien or mentally exhausting, learning a similar—but separate—one can unlock understanding much faster. Sometimes the best way to break through a mental barrier is to escape the old frame of reference entirely. Build a new mental model elsewhere, then come back with fresh eyes. This approach isn’t limited to SwiftUI; it applies to backend frameworks, languages, paradigms, and even non-technical skills. Progress often comes not from pushing harder, but from shifting perspective.

Sunday, July 30, 2023

The road is still long. 😀

 


I had a good time chit chat at the weekend with a friend who was also a developer. He told me that he had a feeling like if you were not constantly studying in software development, you were falling out of software development.


So, he got burned out, mental illness, experience low motivation. Eventually, he changed the career.

Sometimes it feels like that. Sometimes. A software developer's job is stressful and can affect their mental health. We shouldn’t be too hard on ourselves. Especially, those that want to have a life outside of coding. I highly recommend it. Does wonders for your mental health. I see people on Twitter who seemed to have no life. It’s no good to do a bunch of coding then go home and do a few hours more. Unless you are studying for a cert, of course. Get some hobbies. Don’t forget you have a family or SO, if that’s the case.

Coding is not a lifestyle; Coder is just a normal occupation like the others - no more noble, no more superiority; it’s paycheck, a future. Don’t let it define you anymore than those that separated or retired from the military should let their service completely define them. That will lead to mental health issues. I’ve heard of a few situations.

Wednesday, July 19, 2023

System Design 101 - CAP Theorem

CAP Theorem - When you can not desire everything at once

This theorem states that any distributed system can only provide two of the following three guarantees simultaneously:
  • Consistency: all nodes in a distributed system see the same data at the same time
  • Availability: every request receives a response, without guarantee that it is up-to-date (RUN 24/7 - no downtime)
  • Partition tolerance: system continues to function even when network partitions occur. (Machines are in different network)

 

Suppose we have to design a simple system of 2 ATMs that link together. When the user withdraws from ATM1, the amount of money must update to ATM2 as well.

We cannot design a system that concludes CAP because, to have C (consistency), data must be updated at once between ATM1 and ATM2. But if the link between ATM1 and ATM2 is broken, when a user withdraws on ATM1, ATM2 will be out of date, and then C(consistency) is violated. To solve it, we have to stop ATM1 and ATM2 operations to make sure that all is available to update the data; this violates A (Availability) of the system.

Now, We engineers will have to trade off one element. In the case of the ATM, we have the following combinations:

  • CA: Not considering taking this case into account since in distributed systems, Partition tolerance is a must. Due to mis-synchronization, missing Partition tolerance in an ATM situation will cause Consistency to violate.
  • CP: Due to the constraint that Consistency is a must, Partition tolerance will make the system unavailable since it cannot guarantee consistency.
  • AP: Prefer Availability and Partition tolerance over Consistency. The ATMs always work, even when the connection between 2 ATMs is broken Partition tolerance. It's not consistent but can be solved later when 2 ATMs are connected again. So, this is the best solution.

Designing a system is not an easy task: vague, abstract, requires estimation, and requires thinking about something before it happens. In the real world, even after picking 2 elements out of 3, it's not always balance (50-50) between 2 factors. Sometimes, we have to trade off making one factor more important than the other to reduce complexity. Example: There is no 100% availability, and Partition tolerance may take time to become active and make synchonization.


#systemdesign101

Friday, June 16, 2023

Boost performance and security with modern networking

Hey there, fellow developers! I had a chance to participate in a session of “Boost performance and security with modern networking” in the Apple WWDC. Here is the quick summary I think I should share: 



Do you want to make your app faster, safer and smarter so that it can deliver more value to the client business? Of course, you do! That's why you need to know about the latest and greatest networking technologies that can boost your app's performance and security. In this post, I'll give you a quick overview of some of the most important networking protocols that you should be using in your app: IPv6, HTTP/2, TLS 1.3 and Encrypted DNS. Let's dive in! 

1. Using IPv6. 
IPv6 has a number of benefit that you should consider:
- Larger Address Space: 3.4 x 10^38 unique IP addresses on v6 vs 4.3b on v4  
- Improved Security: IPv6 comes with built-in security features including IPsec, which offers data integrity, authentication, and encryption for internet traffic.
- Simplified Header Format: compared to IPv4, IPv6 features a simpler and more effective header structure, which lowers processing costs and boosts the speed of the internet connection
- Prioritize: IPv6 offers stronger support for QoS features, allowing internet service providers to priorities traffic and guarantee that essential applications, like voice and video, receive the required bandwidth and low latency
- Improved Support for Mobile Devices: smartphones and tablets could gain a lot of benefits from IPv6 with quicker and more efficient in term of connection


2. Upgrade to HTTP/2
HTTP/2 attempts to solve many of the shortcomings and inflexibilities of HTTP/1.1
- Multiplexing and concurrency: many requests can be sent and getting responses with just one connection
- Header compression: HTTP header size is drastically reduced
- Server push: The server can send resources the client has not yet requested
You can see how fast HTTP/2 much faster compared to HTTP/1 in here

2.1 Upgrade to HTTP/3
HTTP/3 will be the first major upgrade to the hypertext transfer protocol since HTTP/2 was approved in 2015. An important difference in HTTP/3 is that it runs on QUIC, a new transport protocol. QUIC is designed for mobile-heavy Internet usage in which people carry smartphones that constantly switch from one network to another as they move about their day. Some benefits
- Developing a workaround for the sluggish performance when a smartphone switches from WiFi to cellular data (such as when leaving the house or office)
- Decreasing the effects of packet loss
- Faster connection establishment: QUIC allows TLS version negotiation to happen at the same time as the cryptographic and transport handshakes
- Zero round-trip time (0-RTT): For servers they have already connected to, clients can skip the handshake requirement
- More comprehensive encryption: QUIC’s new approach to handshakes will provide encryption by default — a huge upgrade from HTTP/2 — and will help mitigate the risk of attacks. More info

3. Upgrade to TLS 1.3
TLS 1.3 is the latest version of the TLS protocol. TLS 1.3 dropped support for older, less secure cryptographic features, and it sped up TLS handshakes, among other improvements. So, it is considered to be better and safer than TLS 1.2. 
The benefits:
- Improved Performance and Efficiency: TLS 1.3 handshake is faster than TLS 1.2 due to one round trips instead of two.
- More Robust Security: 
-- Perfect Forward Secrecy - discard the encryption keys for every session (no more static like TLS 1.2)
-- Simple and Stronger Cipher Suites:

4. Encrypted DNS
Traditionally, DNS queries and replies are performed over plaintext. They are sent over the Internet without any kind of encryption or protection, even when you are accessing a secured website. This has a great impact on security and privacy, as these queries might be subject to surveillance, spoofing and tracking by malicious actors, advertisers, ISPs, and others. To prevent this and secure your connections, your server communication should support DNS over TLS (DoT) and DNS over HTTPS (DoH), two standards developed for encrypting plaintext DNS traffic. This prevents untrustworthy entities from interpreting and manipulating your queries.
#happycoding

Tuesday, February 14, 2023

Being laid off or jobless is that bad?

One question I started asking myself a few years ago is what are the purposes of my life in other words, what motivates me daily when I wake up in the morning?

... and do you know that question kept unanswered during recent years. The reason is having a 9-to-5 job keep me busy, since I focus on working to deliver best possible outcomes to the company. It turns out that having a job to secure monthly pay check does not help me feel good even though it helps me cover my monthly expenses.

Until 2 months ago, I decided to move out of the comfort zone, and to come back to VN, and again the rush of having a pay-check job put me into that loop again until I finally moved out of it again. During last 2 weeks I am jobless, but I am so happy. I believe a lot of people will think it is crazy, but it actually is. After many years continuously working I didn't have time to think about this biggest question of my life, and find my life's goals.

Since being jobless, I don't need to care about company works, and I have more time to do these things:

- Read books. I've read so many books until now, and I started with some small books (less than 150 pages per book). I read 5 of them already.

- Watch dozens of videos about life's advices on YouTube.

- Enroll a course to find meaningful of life.

- Join some communities to get more motivations.

Fortunately, after few weeks I finally see the light at the end of the turnel, I somehow feel that I found the direction in my life. I don't mean goals are crazy but they show me how my life is going to be.

Will I open to work again? Definitely yes, but perhaps not right now :)

.

I believe in worse situations you can still find your ways to get out of it, and to be a better version of yourself. Thus, I would recommend anyone was laidoff or being jobless not to be frustrated, but be optimistic.

Remember you always have a choice, and having a choice is a powerful right.

Monday, February 13, 2023

Flutter 3.7: What’s New

2023 has just begun with a new exciting release for Flutter i.e version 3.7. As it continues to evolve, there is no doubt that Flutter will continue to be one of the widest used cross-platform development frameworks. 

Let’s take a quick look at the improvements that come along with the new version:

Improved Material 3 Support:

Photo by Kevin Chisholm on Medium

Migration of certain widgets has improved the Material3 experience. Some of these widgets include Badge, Bottombar, Menus, DropdownMenu, Snackbar and TabBar.

In order to use the new features you just need to turn on the useMaterial3 flag in the app’s ThemeData widget.

Menu Bars and Cascading Menus:

This release of Flutter introduces the ability to create menu bars and cascading context menus. For macOS, developers can use the PlatformMenuBar widget to create a menu bar that is rendered by macOS natively, instead of by Flutter. 

Additionally, for all platforms, developers can use the Material Design menu that provides cascading menu bars (MenuBar) or standalone cascading menus triggered by another user interface element (MenuAnchor). 

These menus are fully customizable, and the menu items can be custom widgets or use the new menu item widgets (MenuItemButton, SubmenuButton).

Impeller Preview:

A new Impeller rendering engine that is now available for preview on iOS on the stable channel. The performance of Impeller is believed to be comparable or better than the Skia renderer for most apps, and it implements all but a small number of rarely used corner cases.

iOS release validation:

The flutter build ipa command now includes a feature that checks and validates certain settings for iOS apps before submission to the App Store. 

This helps ensure that the app is ready for release by informing the developer of any changes that need to be made before submission. 

This new feature is a checklist of settings to update which helps developers to prepare the app for release.

DevTools Updates:

This new SDK includes several new tooling features and improvements for developers using Flutter. One of the major improvements is in the DevTools Memory debugging tool, which has undergone a complete overhaul and includes three new feature tabs: Profile, Trace, and Diff. These tabs support all the previously supported memory debugging features and add more for ease of debugging. 

The new features include the ability to analyze current memory allocation for the app by class and memory type, investigate the code paths that are allocating memory for a set of classes at runtime, and compare memory snapshots to understand memory management between two points in time.

Photo by Kevin Chisholm on Medium

Custom Context Menus:

The new context menu feature in Flutter allows developers to create custom context menus for different parts of their app, giving them more control over the user experience. This feature works by adding a new contextMenuBuilder parameter to existing widgets that already show a context menu by default, such as TextField.

Developers can return any widget they want from the contextMenuBuilder, including modifying the default platform-adaptive context menu. This feature can also be used outside of text selection, such as creating an Image widget that shows a Save button when right-clicked or long-pressed.

CupertinoListSection & CupertinoListTile widgets:

Cupertino has two new widgets, CupertinoListSection and CupertinoListTile, for showing a scrollable list of widgets in the iOS style. They are the Cupertino versions of ListView and ListTile in Material.

Scrolling Improvements:

This change will allow users to return null from the itemBuilder and indicate the end of the list, making it easier for them to work with scrolling widgets like ListView. 

Additionally, the new Scrollbars and DraggableScrollableSheet widgets will provide more control and customization options for scroll views, and the improved handling for text selection within scrolling contexts will make it easier to select text in scrolling views.

Internationalization Tools and Docs:

Internationalization support has been completely revamped.  The gen-l10n tool now supports:

  • Descriptive syntax errors.
  • Complex messages involving nested/multiple plurals, selects, and placeholders.

Text magnifier:

The magnifying glass that appears during text selection on Android and iOS now works in Flutter. This is enabled out of the box for all apps with text selection, but if you want to disable or customize it, see the magnifierConfiguration property.

Reduce animation lag on iOS devices:

Animation quality has greatly improved with the new version of Flutter, thanks to open source contributors.

Font asset hot reload:

Including new fonts to the pubspec.yaml file previously required the app to be rebuilt, unlike other assets which could be hot reloaded. This problem has been solved in Flutter 3.7.

Custom Shader Support Improvements:

Custom shaders can now be hot reloaded and the new Flutter SDK contains a shader compiler that is responsible to correctly compile the listed shader in pubspec.yaml to the relevant backend-specific format for the target platform.

toImageSync:

This release adds new methods, Picture.toImageSync and Scene.toImageSync, to dart:ui. These methods are similar to the asynchronous methods, Picture.toImage, and Scene.toImage, but they synchronously return a handle to an Image. 

The rasterization for the Image takes place in the background and the image is kept as GPU resident when a GPU context is available, which makes it faster to draw compared to images produced by toImage. 

These new toImageSync APIs are useful for quickly snapping off an expensive-to-rasterize picture for reuse across multiple frames, applying multi-pass filters to a picture, and applying custom shaders.

Support discontinuation for macOS 10.11-10.13:

Flutter has announced that it will no longer support macOS versions 10.11, 10.12, and 10.13. This decision was made after further analysis revealed that removing support for these versions would have limited additional impact, and would simplify the codebase.

 This means that apps built against stable Flutter SDKs with this release and onward will no longer work on these versions, and the minimum macOS version supported by Flutter increases to 10.14 Mojave.

Consequently the OpenGL backend has been removed from both the iOS and macOS embedders which has reduced the compressed size of the Flutter engine by about 100KB.

Memory Management

This release of Flutter includes several improvements to memory management that aim to reduce lag caused by garbage collection pauses, lower CPU utilization due to allocation velocity and background GC threads, and reduce the overall memory footprint. 

One example of this is expanding the existing practice of manually deallocating native resources that back certain dart:ui Dart objects. Benchmarks of the Flutter framework migrated to this API have shown that these improvements can reduce 90%-ile frame build times by up to more than 30%, resulting in smoother animations with less jank. 

Photo by Kevin Chisholm on Medium

Additionally, the Flutter engine no longer registers the size of GPU images with the Dart VM, which eliminates synchronous GC work while building frames when a widget creates GPU resident images. The Flutter Engine also does a better job of dynamically updating the Dart VM with information about Flutter application state. 

Finally, for add-to-app Flutter applications, the Flutter engine now informs the Dart VM when the Flutter view is no longer displayed, this causes the Dart VM to trigger a final major GC for the Isolate associated with the view which reduces Flutter's memory footprint when no Flutter views are visible.

Saturday, February 11, 2023

Common Mistakes That Junior Developers Should Avoid

A career as a developer in any sector is pretty challenging. The profession can appear even more daunting when you are a junior developer. The lack of formal training about real-world software development scenarios during college days leaves the developers to learn on their own. Hence, they make many novice mistakes that stick for a long time. Without proper guidance, the initial habits can slow down the junior developer’s career progression.

Everyone makes several of these beginner’s mistakes during the initial phases of their career. If you are passionate about making it big in your development sector, here is a list of the top ten common mistakes you need to be aware of as a junior developer.


Focusing on Code Instead of the Big Picture

It’s easy to get bogged down in the details when you’re starting out. But it’s important to remember that code is only a small part of the development process. Focusing on the big picture will help you understand the overall goal of your project and help you make better decisions. To come up with good solutions, you need to spend time thinking. You have to remember that the author of React did not come up with the idea for the framework in a day. You have to focus on your target and follow up on whatever you need to get to that target.

Not Knowing Their Self Worth

When developers are fresh out of their institutions or when they are out in the market looking for a job, they most likely have no idea about their worth. Depending on individuals, they either overestimate their capability or underestimate it. In either case, not knowing is not helpful to get the right start to their career.

Developers who overestimate their capabilities tend to have high expectations from their first job. They feel they are doing the company a favor. This mindset reflects in the interviews and, later, in their work.

Again, developers who underestimate their abilities tend to take the very first offer they get. They do not try to find out if they are paid as per the market standard. They also prefer not to ask what kind of work they will be offered or whether the work culture is flexible and a good fit for them.

It is not always easy to negotiate during your first job search. Circumstances can compel you to start earning as early as possible. If that is the case, surely you can latch on to the first software job you get. Once you start making money, you can further your career in your own time and money. You can also find out if a position is suitable for you by doing a bit of research on the internet. Learn about the company culture from the reviews provided by employees on various sites.

Not Reading Documentation

Junior developers rarely read documentation, or they only read it superficially. They often skip it and start working on a subject or solving their problem. But the fact is that documentation is an important source of information. And you need to read it in-depth if you want to be a successful developer.

Documentation can help you learn the syntax and usage of a language or library, as well as how to use a tool or library properly. It can also help you understand the API for a particular software system. So, be sure to read the documentation.

Not Asking Questions

A common mistake junior developers often make is they do not ask questions proactively. Some developers are shy in asking questions. Others might be hesitant because they think their query might be a silly on.

Whichever might be the reason, they need to overcome the hurdle to be successful in their career. They should ask questions every time they do not understand. People will be more than happy to explain when they are on the topic.

Sometimes, the question will not have a straightforward answer. People might give their opinion based on their knowledge. If you are not satisfied, you can ask someone else to confirm your understanding. The idea is to clear out any doubt as quickly and as confidently as possible.

Lacking of Practice

Junior developers often underestimate the importance of practice. It’s not enough to just learn the theory — you also need to practice what you have learned.

Practice makes a man perfect, and the more you practice, the better you will become at your work. Try to find opportunities to practice your skills, whether it’s through tutorials, exercises, or projects. No one is born as a great developer. They become one by working hard and practicing‌.

They should practice according to their field of work. If you are a software developer, work hard on your problem-solving skills, programming languages, and accuracy and attention to details. These sometimes may seem very easy for you, but if you want to develop these skills, then you have to practice them. Everything takes practice!

Conclusion

This list summarizes experiences shared by other developers over the year and my experience as well. As a unique individual, your experiences might vary from others. If you remain vigilant and stay away from these mistakes, you can achieve a great start as a developer. Hence, understand the mistakes and take action based on your situation. I am sure, armed with the above knowledge and perseverance, you can achieve the professional and personal goals you set for yourself.

Source

Thursday, February 9, 2023

Copy-On-Write In Swift

 Types in Swift fall into one of two categories

* Value Type: where each instance keeps a unique copy of its data, usually defined as a struct, enum, or tuple. 

* Reference types: each instances share a single copy of the data, and the type is usually defined as a class.

What is Copy On Write

Copy on write is a common computing technique that helps boost performance when copying structures. To give you an example, imagine an array with 1000 things inside it: if you copied that array into another variable, Swift would have to copy all 1000 elements even if the two arrays ended up being the same.

This problem is solved using copy on write: when you point two variables at the same array they both point to the same underlying data. Swift promises that structs like arrays and dictionaries are copied as values, like numbers, so having two variables point to the same data might seem to contradict that. The solution is simple but clever: if you modify the second variable, Swift takes a full copy at that point so that only the second variable is modified - the first isn't changed.

Warning: copy on write is a feature specifically added to Swift arrays and dictionaries; you don't get it for free in your own data types.

Implement Copy-on-Write for your custom value type

```

final class Ref<T> {

  var val : T

  init(_ v : T) {val = v}

}

struct Box<T> {

    var ref : Ref<T>

    init(_ x : T) { ref = Ref(x) }

    var value: T {

        get { return ref.val }

        set {

          if (!isUniquelyReferencedNonObjC(&ref)) {

            ref = Ref(newValue)

            return

          }

          ref.val = newValue

        }

    }

}

// This code was an example taken from the swift repo doc file OptimizationTips 

// Link: https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-copy-on-write-semantics-for-large-values

```

Summary

This subject isn’t simple but understanding it is pivotal for your advancement as an iOS designer. Copy-on-write is one of the foremost imperative dialect highlights of Swift and ought not to be underestimated.

Credit

* https://holyswift.app/copy-on-write-in-swift/

* https://viblo.asia/p/hieu-ve-copy-on-write-trong-swift-maGK7bkx5j2

Tuesday, August 30, 2022

Basic project planning

Recently, I had followed an online course and I found an interesting brief about how to plan a project. So I decide to put it here just in case someone needs it.

Project planning is one of the most critical stages of software development. It is an important part of commencing any new project. That's because it serves as a roadmap that shows the phases of the project, as well as their start and end dates, and dependencies. By the end of this reading, you should recognize the importance of project planning. 

1. Project performance and success rates

Project planning involves comprehensive mapping and organization of project goals, tasks, schedules and resources before anyone assigns project roles and the team starts implementing the plan. With proper planning in place, you can boost the project performance and success rates of a team.

2. Clear objectives

Having a clear idea of what needs to be achieved greatly increases the likelihood that you will do it. But, without a concise objective from the start, the project will be complicated. If the team isn't clear on what they are working on, it’s almost impossible to know when the project is completed. Proper planning helps the team focus on the most important things: the objectives and the end goal.

3. Resource allocation

Planning out a project will tell you how many team members you need to execute the project. The plan also allows project managers to monitor which resources have been allocated and thus avoid excessive allocation.

4. Communication

Planning helps communication. With good communication, every team member knows exactly what is required of them ahead of time. A well-written plan will help you communicate key details, making it seamless for you and your entire team to complete specific tasks. Listening to their input and ideas is also a great way to achieve buy-in and foster the commitment of every team member.

5. Project-specific training

Project planning ensures team members have the required technical know-how to execute the assigned tasks and identifies talent pipelines to provide an adequate supply of trained talents throughout the lifecycle of the project.

And those are the basics of project planning!

Monday, August 29, 2022

JSON Visio - generates graph diagrams from JSON objects


JSON Visio is a tool that generates graph diagrams from JSON objects. These diagrams are much easier to navigate than the textual format and to make it even more convenient, the tool also allows you to search the nodes. Additionally, the generated diagrams can also be downloaded or clipboard as image.

Check it out: JSON Visio - Directly onto graphs

Sunday, July 24, 2022

How To Secure Flutter Application



1. Stay up-to-date

Getting your flutter sdk, plugin and packages up to date is the easiest and one the best ways to secure your apps. Google Flutter Team releases security fixes and patches for vulnerabilities found on the Flutter framework.


2. Secure your data

Do not use sharing settings or SQLite to store sensitive user data. This is because it is easy to open on any device. So you will be required to encrypt the stored data. For that, you can use flutter_secure_storage. This package uses Keystore for Android and Keychain for iOS


3.Jailbroken and rooted devices

Rooted Android device and jailbroken iOS device have more privileges compared to regular system. It can introduce malwares to the user's device and bypass the normal behavior of the device. There is package in Flutter that is flutter_jailbreak_detection. You can use this package to detect if your app is running on a jailbroken or rooted device. Use Root Beer on Android and DTT Jailbreak Detection on iOS.


4. Local Auth

To prevent unauthorized access we shall use the local_auth package to provide a gateway to get the access the app content as many times the user closes the app temporarily. This includes authentication with biometrics such as fingerprint or facial recognition.


5. Restrict network traffic

One way to restrict network traffic or connection to an unsecured endpoint is through explicity whitelisting your domain


6. Ceritificate pinning

You can also implement certificate pinning for your apps to restrict the secure connection the particular certificates. This ensures that the connection between your apps and your server is trusted and authentic



7. Obfuscate code

The compiled binaries and code of your apps can be reversed engineered. Some of the things that can be exposed include the strings, method and classes, and API keys. These data are either in their original form or in  plain text.

```

flutter build appbundle --obfuscate --split-debug-info=/<directory>

```

Getting Started with Flutter Bloc Pattern

 Bloc Pattern


1. Why Bloc

- Keep your code clarm organized, clean, and maintainable

- Compatible with flutter declarative programming


2. What's Bloc

- A design pattern created by Google to separate Logic from UI 

- There is many library to implement this design pattern. But IMO, you should use the flutter_bloc of Felix Angelo. It is a state management to easier your life

- For every action inside the application, there will be a relative state from it. For example, when the data is fetching, the app should be in a loading state displaying a loading animation on the screen


3. The Core Concepts

- Stream is the foundation of Bloc


3.1 Stream

- Stream is a sequence of async event. Each event is a data event or error event.

- When a stream has dispatched its event, it will also notify to all listener subscribed to it


3.2 Receive Stream

- async* means asynchronous generation function, it generates async data

- yield pushes the data (integer) through the Stream

- await keyword helps to wait for a process to finish before proceeding to the next step


```

Stream<int> dataStream() async* {

for (int i = 0; i<3; i++) {

await Future.delayed(Duration(seconds:3));

yield i;

}

}


Stream<int> stream = dataStream();


stream.listen((event) {

    print("RECEIVE data ${event.toString()}");

  });


```

- async* means asynchronous generation function, it generates async data

- yield pushes the data (integer) through the Stream

- await keyword helps to wait for a process to finish before proceeding to the next step


3.3 Cubit and Bloc


- Cubit is a minimal version of Bloc

- Cubit only emits a stream of states

- Bloc emits a stream of states and receive a stream of event


4. Flutter BLOC

4.1 BlocProvider

- A widget that creates and provides a Bloc to all of its children. A single instance of it can be provided to multi widgets within a tree hierarchy




4.2 Bloc Builder

- BlocBuilder is a widget that helps rebuild the UI based on some Bloc state 

changes

- Rebuild a large UI is a heavy cpu task to compute. That's why you need to wrap the exact part of the UI you want to rebuild inside BlocBuilder. For example, if a text is nested inside a column or a row, dont build entire the column/ row, rather to rebuild the text widge only by wrapping it inside the BlocBuilder

- If you dont provide exactly the cubit/ Bloc in Blocbuilder, it will search for the nearest parent bloc in the tree

5. Code Implementation


counter_app.dart

```

import 'package:flutter/material.dart';


import 'counter/counter.dart';


class CounterApp extends MaterialApp {

  const CounterApp({Key? key}) : super(key: key, home: const CounterPage());

}

```


counter_page.dart

```

import 'package:flutter/material.dart';

import 'package:flutter_bloc/flutter_bloc.dart';


import '../counter.dart';

import 'counter_view.dart';


class CounterPage extends StatelessWidget {

  const CounterPage({Key? key}) : super(key: key);


  @override

  Widget build(BuildContext context) {

    return BlocProvider(

      create: (_) => CounterCubit(),

      child: CounterView(),

    );

  }

}

```


counter_cubit.dart

```

import 'package:bloc/bloc.dart';


class CounterCubit extends Cubit<int> {

  CounterCubit() : super(0);


  /// Add 1 to the current state.

  void increment() => emit(state + 1);


  /// Subtract 1 from the current state.

  void decrement() => emit(state - 1);

}

```


counter_view.dart

```

import 'package:flutter/material.dart';

import 'package:flutter_bloc/flutter_bloc.dart';


import '../counter.dart';


class CounterView extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    final textTheme = Theme.of(context).textTheme;

    return Scaffold(

      appBar: AppBar(title: const Text('Counter')),

      body: Center(

        child: BlocBuilder<CounterCubit, int>(

          builder: (context, state) {

            return Text('$state', style: textTheme.headline2);

          },

        ),

      ),

      floatingActionButton: Column(

        mainAxisAlignment: MainAxisAlignment.end,

        crossAxisAlignment: CrossAxisAlignment.end,

        children: <Widget>[

          FloatingActionButton(

            key: const Key('counterView_increment_floatingActionButton'),

            child: const Icon(Icons.add),

            onPressed: () => context.read<CounterCubit>().increment(),

          ),

          const SizedBox(height: 8),

          FloatingActionButton(

            key: const Key('counterView_decrement_floatingActionButton'),

            child: const Icon(Icons.remove),

            onPressed: () => context.read<CounterCubit>().decrement(),

          ),

        ],

      ),

    );

  }

}

```

6. Summary

- Bloc is a good pattern to improve the code quality and help easier the state management in app

- Must familiar with stream and reactive programming

- Much of boilerplate code


Reference link:

- https://bloclibrary.dev/#/gettingstarted

Thursday, July 21, 2022

How to get your app rejection on App Store (and how to fix it)



App Content Is Inappropriate

  • Apps related to sensitive content, such as porn and gambling, are automatically rejected. They will also not approve content about terrorism, racism, violence, substance abuse. Generally, if your app offends people or encourages them to break the law, you will probably get a rejection approval
  • In this case, either you modify the content or not launch it into the Apple Store.


You Have No Privacy Policy

  • Apple requires the application to take the user privacy data seriously to comply the GDPR in Europe and various FTC rules in the US.
  • To avoid rejection, make sure that users have been aware of the Term Of Use, Privacy Policy.
  • It should explain how you use the specific data that you collect: how it’s stored, and whether or not you share it with other third-party entities.
  • Lastly, the user has full permission for his own data, even asking to remove it: making a function for request to remove data is a reasonable choice. 


Missing Sign in with Apple for third party sign up

  • Apps that exclusively use a third-party or social login service (such as Facebook Login, Google Sign-In, Sign in with Twitter, Sign In with LinkedIn, Login with Amazon, or WeChat Login) to set up or authenticate the user’s primary account with the app must also offer Sign in with Apple as an equivalent option


App Wants to Share Personal User Data

  • In general, users must have control over their data at all times. Users must notice how and why the application would like to use their data and privacy: photos, location, notification...
  • The key is being declaration right and enough permission will avoid you to be rejected in this section.


The App Is a Copy of Another App

  • Apps that are cloned from another app on the Apple Store will get rejection. You should come up with a unique app concept.
  • Another case is spamming, the same app but multiple variants. For example: same app feature and UI but different theme, data...


Hardware and Software Are Not Compatible

  • App can not only run on iPhone but also on iPad as well and vice versa


You’re Using Private API

  • Private APIs are the API used internally by Apple. They are undocumented or  don't officially documented by Apple. The APIs are not stable and can be changed anytime, so they're less guarantee
  • Make sure your code base and even the external libraries don't mess with these or wait for a brutal rejection.


Bugs and Crashes Occur During the Review Process

  • If any crash or significant bug or performance issue (ex: http 500, no network, lagging...) appears during the process, the app will be rejected immediately. Those who perform the review process are human and they test on the physical device (not on an  emulator).
  •  To avoid this, please take the QA step seriously.


Unusually Long Load Times

  • Apps that take long loading times may cause poor user experience, therefore, could be rejected. To prevent this kind of issue, simplify the user interface and optimize your code to make it run faster, compressing images and assets to reduce load times.
  • For apps that need to connect to a server, you only fetch required data and utilize the caching mechanism.
  • For cold startup, it's a good idea to add a splash screen


Placeholder Content Is Still in the App

  • A placeholder or dummy content is a sign of an uncompleted app. A not yet complete app violates the App Store rules, so the app will be rejected.
  • Inspecting every corner of your app ensures that you catch these simple mistakes before submission.


Broken Links in the App

  • Broken links in apps will also be rejected by Apple. For reviewers, it's a sign of poor performance application may affect to user. Thoroughly check all your app links before submit the app.


App Appears to Be Unfinished

  • Even if the app is complete, the mistake in app name (app beta, app dev, app demo...) or build version (0.x) may get your app violate the incomplete app case. The app to submit to stores are considered ready for distribution.
  • Be aware.


Incomplete or Inaccurate Metadata

  • This is about the meta data you put on the App Store Dashboard: app descriptions, screenshots, age ratings, payment options, and privacy information. The key is honest, sincere and transparent. Do not cheat.
  • Remember to upload screenshots for every screen size on the iPhone/ iPad. Do not use any other exotic template device (ex: Android) but an iPhone/iPad.
  • Do not mention any keywords about different platforms (ex: Android)


Low-Quality UI

  • Apple has provided a detailed description of how an app should be designed to comply with their platform (Human Interface Guidelines). 
  • A poor UI design that fails to meet standards may get rejected. 
  • Please make sure your app looks fantastic and consistent across all Apple devices.

Saturday, July 9, 2022

How to prevent wifi sleep after suspend for Ubuntu Linux

 1. Change power state of the wifi card to 3

```

$cat /etc/NetworkManager/conf.d/default-wifi-powersave-on.conf

[connection]

wifi.powersave = 3

# Slow sleep fix: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1670041

#wifi.powersave = 2

```

2. After saving the file run `sudo systemctl restart NetworkManager`

3. Make a reset bash script and name it `iwlwifi-reset`

```

#!/bin/sh


# NAME: /lib/systemd/system-sleep/iwlwifi-reset

# DESC: Resets Intel WiFi which can be flakey after a long suspend.

# DATE: Apr 1, 2017. Modified August 30, 2017.


MYNAME=$0


restart_wifi() {

    /usr/bin/logger $MYNAME 'restart_wifi BEGIN'

    /sbin/modprobe -v -r iwldvm # This removes iwlwifi too

    /sbin/modprobe -v iwlwifi   # This starts iwldvm too

#    systemctl restart NetworkManager.service

    /usr/bin/logger 'systemctl restart NetworkManager.service (SUPPRESSED)'

    /usr/bin/logger $MYNAME 'restart_wifi END'

}

/usr/bin/logger $MYNAME 'case=[' ${1}' ]'

case "${1}/${2}" in

    hibernate|suspend|pre*)

      ;;

    resume|thaw|post*)

      restart_wifi;;

esac

```

4. Copy the iwlwifi-reset script to systemd folder

```

sudo cp -r /path-to-iwlwifi/script /lib/systemd/system-sleep/

```

5. Set excute permission for the script

```

chmod a+x /lib/systemd/system-sleep/iwlwifi-reset

```

Sunday, July 3, 2022

Configure VPN L2TP/IPSec on Ubuntu for Ubuntu Linux


1. sudo apt-get install network-manager-l2tp

2. sudo apt-get install network-manager-l2tp-gnome

3. Settings > Network > Click on "+" > Then choose "Layer 2 Tunneling Protocol (L2TP)"

4. Input VPN name into "Name" textbox.

5. Input host name into "Gateway" textbox.

6. Input user name into "Username" textbox. 

7. Input password into "Username" textbox. 

8. Choose "IPSec Settings".

9. Tick "Enable IPsec tunnel to L2TP host" checkbox

10. Input shared secret into "Pre-shared key". textbox


Bonus:

sudo service xl2tpd stop

sudo systemctl disable xl2tpd

Tuesday, June 28, 2022

Install a custom font on Ubuntu Linux

Install a custom font

sudo mkdir /usr/share/fonts/myfonts && cd /usr/share/fonts/myfonts

sudo unzip -d . ~/Downloads/font.zip

sudo fc-cache -fv

fc-match FontName


Install Microsoft font

sudo apt install ttf-mscorefonts-installer

Font supported list:

  • Times New Roman
  • Arial Black
  • Arial
  • Comic Sans MS
  • Courier New
  • Impact
  • Verdana

Friday, June 17, 2022

Install wireguard on Ubuntu Linux 22.04 LTS

Installing the WireGuard Client

sudo apt update && sudo apt upgrade

sudo apt install openresolv

sudo apt install wireguard


Generating Private and Public Keys

wg genkey | tee private.key | wg pubkey > public.key

sudo nano /etc/wireguard/wg0.conf


In the file type:

[Interface]

PrivateKey = <contents-of-client-privatekey>

Address = 10.0.0.1/24

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

ListenPort = 51820

[Peer]

PublicKey = <contents-of-server-publickey>

AllowedIPs = 10.0.0.2/32


WireGuard Startup

sudo wg-quick up wg0


Check connection status

sudo wg show


Thursday, June 16, 2022

[Dev] Dart 2.17, now you can declare enums with members.

What else can you do with this?

- Define multiple properties

- Add named or positional arguments to the constructor (as long as it's a "const" constructor)

- Define custom methods and getters