The first Week focussed on adding enhancements for the mobile_app.. The first one being adding localizations to the app. Just an overview, the localizations logic lives in lib/locale/locales.dart and generated arb and messages in lib/l10n/
AppLocalizations are handled the InheritedWidget way, hence have an of method which returns Localizations.of<AppLocalizations>(context, AppLocalizations). flutter’s Localization defines the Locale for its child and the localized resources that the child depends on. Localized resources are loaded by the AppLocalizationDelegate which is just a collection of localized resources. The most important of the methods of the delegate being the load method, which is responsible for returning localized messages.
class AppLocalizations {
static Future<AppLocalizations> load(Locale locale) {
final name =
locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((bool _) {
Intl.defaultLocale = localeName;
return AppLocalizations();
});
}
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
String get title {
return Intl.message(
'CircuitVerse',
name: 'title',
desc: 'Title for CircuitVerse Mobile',
);
}
}
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en'].contains(locale.languageCode);
@override
Future<AppLocalizations> load(Locale locale) => AppLocalizations.load(locale);
@override
bool shouldReload(AppLocalizationsDelegate old) => false;
}
# generate arb resources for the getters defined AppLocalizations
flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/locale/locales.dart
# generate bunch of dart files that contains switching logic thru the above generated arb files
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/l10n/intl_en.arb lib/l10n/intl_messages.arb lib/locale/locales.dart
The localizations delegates are registered in the MaterialApp's localizationsDelegates.
return MaterialApp(
...
localizationsDelegates: [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
// For RTL Support
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
Locale('en', ''),
],
...
)
And there we go, AppLocalizations.of(context).title gives you the localized title in onGenerateTitle.
The next thing was adding pedantic as analysis_options.yaml for improved code quality, and Dart static analysis.
The one thing i am proud of using this package is not that it is used in Google internally but having a better understanding of the new, const & final variables. The gist of which is the following :
const is better than final as *const* EdgeInsets.all(8) doesn’t clutter up the memory and these small things add up, you must agree..
Most of the dart constructors are const, now you know why..
The second Week focussed on perfecting the API and adding some enhancements.. Some of the notable one’s being adding send_reset_password_instructions & GET public_key.pem to decode the data encoded in the token.
# POST api/v1/password/forgot
def forgot_password
@user = User.find_by!(email: params[:email])
# Devise is amazing :P
@user.send_reset_password_instructions
render json: { message: "password reset instructions sent to #{@user.email}" }
end
# GET /public_key.pem
def public_key
public_key = File.open(Rails.root.join("config", "public.pem"), "r:UTF-8")
send_file public_key
end
For the Group’s API #1462 added conter_cache to cache group_member_count in Groups to avoid N+1 queries.
First things first, counter_cache: true in group_member.rb.
class GroupMember < ApplicationRecord
...
belongs_to :group, counter_cache: true
end
Add a column in groups_table that would works as a counter for number of group_members.
def change
add_column :groups, :group_members_count, :integer
end
Resetting counters for already existing records.
def change
Group.all.each do |group|
Group.reset_counters(group.id, :group_members)
end
end
Now, group.group_members.count -> group.group_members.size, this is not much change, but hey check the logs, you’ll realize :P
Just another optimization, thanks @tachyons
# BEFORE -> O(N)
project = assignment.projects.find { |p| p.author_id == params[:current_user].id }
# AFTER -> O(1)
project = assignment.projects.find_by(author_id: params[:current_user].id)
#1473, #1477, #1482 were merged with some minor tweaks.. Yay!! The API docs would now live in CircuitVerse itself, updated the docs in view of the final API, for more details refer #1512.
This wraps it up for the first evaluation :fingers_crossed:
Written on June 18th, 2020 by Nitish AggarwalSee Ya Next Week