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