Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/fonts/Vazir-Medium-FD.ttf
Binary file not shown.
12 changes: 12 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"home_title": "Smart Washing",
"home_sub_title":"Machine",
"mode":"Mode",
"minutes":"minutes",
"choose_water":"Choose water",
"tip_save":"Please save choice",
"current":"Current",
"standard":"Standard",
"gentle":"Gentle",
"fast":"Fast"
}
12 changes: 12 additions & 0 deletions lang/fa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"home_title": "ماشین لباسشویی",
"home_sub_title":"هوشمند",
"mode":"حالت",
"minutes":"دقیقه",
"choose_water":"انتخاب آب",
"tip_save":"لطفا انتخاب خود را ذخیره کنید",
"current":"فعلی",
"standard":"استاندارد",
"gentle":"آهسته",
"fast":"سریع"
}
67 changes: 67 additions & 0 deletions lib/core/lang/app_localizations.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class AppLocalizations {
final Locale locale;

AppLocalizations(this.locale);

// Helper method to keep the code in the widgets concise
// Localizations are accessed using an InheritedWidget "of" syntax
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}

// Static member to have a simple access to the delegate from the MaterialApp
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();

Map<String, String> _localizedStrings;

Future<bool> load() async {
// Load the language JSON file from the "lang" folder
String jsonString =
await rootBundle.loadString('lang/${locale.languageCode}.json');
Map<String, dynamic> jsonMap = json.decode(jsonString);

_localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});

return true;
}

// This method will be called from every widget which needs a localized text
String translate(String key) {
return _localizedStrings[key];
}
}

// LocalizationsDelegate is a factory for a set of localized resources
// In this case, the localized strings will be gotten in an AppLocalizations object
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
// This delegate instance will never change (it doesn't even have fields!)
// It can provide a constant constructor.
const _AppLocalizationsDelegate();

@override
bool isSupported(Locale locale) {
// Include all of your supported language codes here
return ['en', 'fa'].contains(locale.languageCode);
}

@override
Future<AppLocalizations> load(Locale locale) async {
// AppLocalizations class is where the JSON loading actually runs
AppLocalizations localizations = new AppLocalizations(locale);
await localizations.load();
return localizations;
}

@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
58 changes: 41 additions & 17 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_whirlpool/screens/main/main_screen.dart';
import 'package:flutter_whirlpool/view_models/dev_view_model.dart';
import 'package:flutter_whirlpool/view_models/language_view_model.dart';
import 'package:flutter_whirlpool/view_models/main_view_model.dart';
import 'package:flutter_whirlpool/view_models/service_locator.dart';
import 'package:flutter_whirlpool/view_models/timer_view_model.dart';
import 'package:provider/provider.dart';

import 'core/lang/app_localizations.dart';

void main() {
ServiceLocator.init();

Expand All @@ -18,22 +22,42 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => ServiceLocator.get<DevViewModel>()),
ChangeNotifierProvider(
create: (_) => ServiceLocator.get<MainViewModel>()),
ChangeNotifierProvider(
create: (_) => ServiceLocator.get<TimerViewModel>()),
],
child: MaterialApp(
title: 'Smart Washing Machine',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MainScreen(),
),
);
providers: [
ChangeNotifierProvider(
create: (_) => ServiceLocator.get<DevViewModel>()),
ChangeNotifierProvider(
create: (_) => ServiceLocator.get<MainViewModel>()),
ChangeNotifierProvider(
create: (_) => ServiceLocator.get<TimerViewModel>()),
ChangeNotifierProvider(
create: (_) => ServiceLocator.get<LanguageViewModel>()),
],
child: Consumer<LanguageViewModel>(
builder: (context, model, child) {
return MaterialApp(
locale: model.appLocal,
title: 'Smart Washing Machine',
// List all of the app's supported locales here
supportedLocales: [
Locale('en', 'US'),
Locale('fa', 'IR'),
],
// These delegates make sure that the localization data for the proper language is loaded
localizationsDelegates: [
// A class which loads the translations from JSON files
AppLocalizations.delegate,
// Built-in localization of basic text for Material widgets
GlobalMaterialLocalizations.delegate,
// Built-in localization for text direction LTR/RTL
GlobalWidgetsLocalizations.delegate,
],
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
fontFamily: model.isRTL ? "Vazir" : null),
home: MainScreen(),
);
},
));
}
}
34 changes: 21 additions & 13 deletions lib/screens/main/main_screen.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_whirlpool/core/lang/app_localizations.dart';
import 'package:flutter_whirlpool/models/mode_item_model.dart';
import 'package:flutter_whirlpool/screens/main/mode_tile.dart';
import 'package:flutter_whirlpool/screens/main/top_bar.dart';
Expand All @@ -8,18 +9,22 @@ import 'package:flutter_whirlpool/screens/water_drawer/water_drawer.dart';
import 'package:flutter_whirlpool/shared/colors.dart';
import 'package:flutter_whirlpool/shared/consts.dart';
import 'package:flutter_whirlpool/shared/widgets.dart';
import 'package:flutter_whirlpool/view_models/language_view_model.dart';
import 'package:flutter_whirlpool/view_models/main_view_model.dart';
import 'package:flutter_whirlpool/view_models/service_locator.dart';
import 'package:provider/provider.dart';

class MainScreen extends StatelessWidget {
static const margin = EdgeInsets.only(
left: GLOBAL_EDGE_MARGIN_VALUE,
static const margin = EdgeInsetsDirectional.only(
start: GLOBAL_EDGE_MARGIN_VALUE,
);

const MainScreen({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
bool _isRtl = ServiceLocator.get<LanguageViewModel>()?.isRTL ?? false;

return Container(
color: CustomColors.primaryColor,
child: Scaffold(
Expand All @@ -32,8 +37,10 @@ class MainScreen extends StatelessWidget {
),
drawer: ClipRRect(
borderRadius: BorderRadius.only(
topRight: Radius.circular(45),
bottomRight: Radius.circular(45),
topRight: _isRtl ? Radius.circular(0) : Radius.circular(45),
bottomRight: _isRtl ? Radius.circular(0) : Radius.circular(45),
bottomLeft: _isRtl ? Radius.circular(45) : Radius.circular(0),
topLeft: _isRtl ? Radius.circular(45) : Radius.circular(0),
),
child: Drawer(
child: WaterDrawer(),
Expand All @@ -44,10 +51,10 @@ class MainScreen extends StatelessWidget {
child: Container(
child: Stack(
children: [
Positioned(
right: 0,
PositionedDirectional(
end: 0,
child: Transform.translate(
offset: Offset(100, 120),
offset: Offset(_isRtl ? -100 : 100, 120),
child: WashingMachineCase(
width: 380,
height: 380,
Expand All @@ -61,9 +68,9 @@ class MainScreen extends StatelessWidget {
Padding(
padding: margin,
child: Text(
'Smart Washing',
AppLocalizations.of(context).translate("home_title"),
style: TextStyle(
fontSize: 28,
fontSize: _isRtl ? 22 : 28,
color: CustomColors.headerColor,
fontWeight: FontWeight.w800,
),
Expand All @@ -73,9 +80,10 @@ class MainScreen extends StatelessWidget {
Padding(
padding: margin,
child: Text(
'Machine',
AppLocalizations.of(context)
.translate("home_sub_title"),
style: TextStyle(
fontSize: 26,
fontSize: _isRtl ? 20 : 26,
color: CustomColors.headerColor,
fontWeight: FontWeight.w400,
),
Expand Down Expand Up @@ -262,7 +270,7 @@ class _ModesList extends StatelessWidget {
Padding(
padding: MainScreen.margin,
child: Text(
'Mode',
AppLocalizations.of(context).translate("mode"),
style: TextStyle(
fontSize: 23,
color: CustomColors.headerColor,
Expand All @@ -284,7 +292,7 @@ class _ModesList extends StatelessWidget {
return ModeTile(
pressed: viewModel?.selectedMode == item,
indicatorColor: item.color,
name: item.name,
name: AppLocalizations.of(context).translate(item.name),
minutes: item.minutes,
disabled: viewModel.modeStatus == ModeStatus.running,
onTap: () => viewModel.selectMode(item),
Expand Down
7 changes: 4 additions & 3 deletions lib/screens/main/mode_tile.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_whirlpool/core/lang/app_localizations.dart';
import 'package:flutter_whirlpool/shared/colors.dart';
import 'package:flutter_whirlpool/shared/consts.dart';
import 'package:flutter_whirlpool/shared/widgets.dart';
Expand Down Expand Up @@ -30,8 +31,8 @@ class ModeTile extends StatelessWidget {
onTap: this.onTap,
width: 120,
disabled: disabled,
margin: const EdgeInsets.only(
left: GLOBAL_EDGE_MARGIN_VALUE,
margin: const EdgeInsetsDirectional.only(
start: GLOBAL_EDGE_MARGIN_VALUE,
top: 10,
bottom: 10,
),
Expand Down Expand Up @@ -62,7 +63,7 @@ class ModeTile extends StatelessWidget {
height: 6,
),
Text(
'$minutes minutes',
'$minutes ${AppLocalizations.of(context).translate("minutes")}',
style: TextStyle(
fontSize: 13,
color: CustomColors.headerColor.withAlpha(120),
Expand Down
21 changes: 19 additions & 2 deletions lib/screens/main/top_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter_whirlpool/shared/colors.dart';
import 'package:flutter_whirlpool/shared/consts.dart';
import 'package:flutter_whirlpool/shared/widgets.dart';
import 'package:flutter_whirlpool/view_models/dev_view_model.dart';
import 'package:flutter_whirlpool/view_models/language_view_model.dart';
import 'package:provider/provider.dart';

class TopBar extends StatelessWidget {
Expand All @@ -13,10 +14,9 @@ class TopBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.fromLTRB(
margin: EdgeInsetsDirectional.fromSTEB(
GLOBAL_EDGE_MARGIN_VALUE, DRAWER_BUTTON_MARGIN_TOP, 18, 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Consumer<DevViewModel>(builder: (context, viewModel, _) {
Expand All @@ -31,6 +31,23 @@ class TopBar extends StatelessWidget {
},
);
}),
SizedBox(
width: 25,
),
Consumer<LanguageViewModel>(builder: (context, viewModel, _) {
return NeumorphicIconButton(
icon: Icon(
Icons.translate,
color: CustomColors.textColor,
),
onTap: () {
viewModel.appLocal = viewModel.appLocal;
},
);
}),
Expanded(
child: Container(),
),
TimerPanel()
],
),
Expand Down
Loading