├── lib
├── utils
│ ├── services
│ │ └── services.dart
│ ├── ext
│ │ ├── ext.dart
│ │ ├── double.dart
│ │ └── context.dart
│ ├── helper
│ │ ├── helper.dart
│ │ ├── common.dart
│ │ └── constant.dart
│ └── utils.dart
├── core
│ ├── core.dart
│ └── localization
│ │ ├── localization.dart
│ │ ├── l10n.dart
│ │ ├── intl_en.arb
│ │ └── intl_id.arb
├── data
│ ├── data.dart
│ └── datasources
│ │ ├── datasources.dart
│ │ └── local
│ │ ├── local.dart
│ │ ├── data_helper.dart
│ │ ├── pref_manager.dart
│ │ └── portfolio_response.dart
├── presentation
│ ├── pages
│ │ ├── pages.dart
│ │ ├── main
│ │ │ ├── home
│ │ │ │ ├── home.dart
│ │ │ │ ├── home_title.dart
│ │ │ │ ├── home_description.dart
│ │ │ │ └── home_section.dart
│ │ │ ├── services
│ │ │ │ ├── services.dart
│ │ │ │ ├── services_title.dart
│ │ │ │ ├── services_section.dart
│ │ │ │ └── services_description.dart
│ │ │ ├── portfolio
│ │ │ │ ├── portfolio.dart
│ │ │ │ ├── portfolio_title.dart
│ │ │ │ └── portfolio_section.dart
│ │ │ ├── profile
│ │ │ │ ├── profile.dart
│ │ │ │ ├── profile_title.dart
│ │ │ │ ├── profile_button.dart
│ │ │ │ ├── profile_section.dart
│ │ │ │ └── profile_description.dart
│ │ │ ├── main.dart
│ │ │ ├── main_cubit.dart
│ │ │ ├── footer_copy_right.dart
│ │ │ ├── main_menu.dart
│ │ │ ├── main_popup_menu.dart
│ │ │ ├── footer.dart
│ │ │ ├── main_page.dart
│ │ │ └── main_drawer.dart
│ │ └── app_route.dart
│ ├── presentation.dart
│ ├── resources
│ │ ├── resources.dart
│ │ ├── images.dart
│ │ ├── dimens.dart
│ │ ├── palette.dart
│ │ └── styles.dart
│ └── widgets
│ │ ├── spacer_h.dart
│ │ ├── spacer_v.dart
│ │ ├── widgets.dart
│ │ ├── indicator_slider.dart
│ │ ├── circle_image.dart
│ │ ├── image_network.dart
│ │ ├── parent.dart
│ │ ├── animated_mouse.dart
│ │ ├── animated_box_slider.dart
│ │ ├── scroll_indicator.dart
│ │ ├── animated_widget_slider.dart
│ │ ├── responsive.dart
│ │ ├── animated_widget_shape.dart
│ │ ├── animated_text_strikethrough.dart
│ │ ├── animated_text_box.dart
│ │ └── animated_button.dart
├── di
│ └── di.dart
└── main.dart
├── web
├── fav
│ ├── favicon.ico
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── mstile-150x150.png
│ ├── apple-touch-icon.png
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── browserconfig.xml
│ ├── site.webmanifest
│ └── safari-pinned-tab.svg
├── manifest.json
└── index.html
├── assets
├── fonts
│ ├── Circe.otf
│ └── visuelt
│ │ ├── VisueltPro-Black.ttf
│ │ ├── VisueltPro-Bold.ttf
│ │ ├── VisueltPro-Italic.ttf
│ │ ├── VisueltPro-Light.ttf
│ │ ├── VisueltPro-Medium.ttf
│ │ ├── VisueltPro-Thin.ttf
│ │ ├── VisueltPro-Regular.ttf
│ │ ├── VisueltPro-BlackItalic.ttf
│ │ ├── VisueltPro-BoldItalic.ttf
│ │ ├── VisueltPro-ExtraLight.ttf
│ │ ├── VisueltPro-LightItalic.ttf
│ │ ├── VisueltPro-ThinItalic.ttf
│ │ ├── VisueltPro-MediumItalic.ttf
│ │ └── VisueltPro-ExtraLightItalic.ttf
├── images
│ ├── ic_avatar.png
│ ├── ic_launcher.jpg
│ ├── ic_profile.jpg
│ ├── ic_playstore.png
│ ├── ic_launcher_staging.jpg
│ ├── portfolio
│ │ ├── oifyoo
│ │ │ ├── image_1.png
│ │ │ ├── image_2.png
│ │ │ ├── image_3.png
│ │ │ ├── image_4.png
│ │ │ └── image_5.png
│ │ ├── brupedia
│ │ │ ├── image_1.png
│ │ │ ├── image_2.png
│ │ │ └── image_3.png
│ │ ├── eabsensi
│ │ │ ├── image_1.png
│ │ │ ├── image_2.png
│ │ │ ├── image_3.png
│ │ │ └── image_4.png
│ │ ├── myananda
│ │ │ ├── image_1.png
│ │ │ ├── image_2.png
│ │ │ ├── image_3.png
│ │ │ ├── image_4.png
│ │ │ └── image_5.png
│ │ ├── wautils
│ │ │ ├── image_1.png
│ │ │ ├── image_2.png
│ │ │ ├── image_3.png
│ │ │ └── image_4.png
│ │ ├── pataparking
│ │ │ ├── image_1.png
│ │ │ ├── image_2.png
│ │ │ └── image_3.png
│ │ └── patapaowners
│ │ │ ├── image_1.png
│ │ │ ├── image_2.png
│ │ │ └── image_3.png
│ ├── ic_facebook.svg
│ ├── ic_youtube.svg
│ ├── ic_upwork.svg
│ ├── ic_linkedin.svg
│ ├── ic_menu.svg
│ ├── ic_close.svg
│ ├── ic_github.svg
│ ├── ic_tiktok.svg
│ ├── ic_logo.svg
│ ├── ic_settings.svg
│ └── ic_instagram.svg
└── static_api
│ ├── portfolio_en.json
│ └── portfolio_id.json
├── analysis_options.yaml
├── l10n.yaml
├── .gitignore
└── pubspec.yaml
/lib/utils/services/services.dart:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/core/core.dart:
--------------------------------------------------------------------------------
1 | export 'localization/localization.dart';
2 |
--------------------------------------------------------------------------------
/lib/data/data.dart:
--------------------------------------------------------------------------------
1 | export 'datasources/datasources.dart';
2 |
--------------------------------------------------------------------------------
/lib/data/datasources/datasources.dart:
--------------------------------------------------------------------------------
1 | export 'local/local.dart';
2 |
--------------------------------------------------------------------------------
/lib/utils/ext/ext.dart:
--------------------------------------------------------------------------------
1 | export 'context.dart';
2 | export 'double.dart';
3 |
--------------------------------------------------------------------------------
/lib/utils/helper/helper.dart:
--------------------------------------------------------------------------------
1 | export 'common.dart';
2 | export 'constant.dart';
3 |
--------------------------------------------------------------------------------
/lib/presentation/pages/pages.dart:
--------------------------------------------------------------------------------
1 | export 'app_route.dart';
2 | export 'main/main.dart';
3 |
--------------------------------------------------------------------------------
/lib/core/localization/localization.dart:
--------------------------------------------------------------------------------
1 | export 'generated/strings.dart';
2 | export 'l10n.dart';
3 |
--------------------------------------------------------------------------------
/web/fav/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/web/fav/favicon.ico
--------------------------------------------------------------------------------
/assets/fonts/Circe.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/Circe.otf
--------------------------------------------------------------------------------
/lib/utils/utils.dart:
--------------------------------------------------------------------------------
1 | export 'ext/ext.dart';
2 | export 'helper/helper.dart';
3 | export 'services/services.dart';
4 |
--------------------------------------------------------------------------------
/assets/images/ic_avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/ic_avatar.png
--------------------------------------------------------------------------------
/web/fav/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/web/fav/favicon-16x16.png
--------------------------------------------------------------------------------
/web/fav/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/web/fav/favicon-32x32.png
--------------------------------------------------------------------------------
/web/fav/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/web/fav/mstile-150x150.png
--------------------------------------------------------------------------------
/assets/images/ic_launcher.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/ic_launcher.jpg
--------------------------------------------------------------------------------
/assets/images/ic_profile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/ic_profile.jpg
--------------------------------------------------------------------------------
/web/fav/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/web/fav/apple-touch-icon.png
--------------------------------------------------------------------------------
/assets/images/ic_playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/ic_playstore.png
--------------------------------------------------------------------------------
/lib/utils/ext/double.dart:
--------------------------------------------------------------------------------
1 | extension DoubleExtension on double {
2 | bool isVisible() {
3 | return this > 80;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/lib/data/datasources/local/local.dart:
--------------------------------------------------------------------------------
1 | export 'data_helper.dart';
2 | export 'portfolio_response.dart';
3 | export 'pref_manager.dart';
4 |
--------------------------------------------------------------------------------
/web/fav/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/web/fav/android-chrome-192x192.png
--------------------------------------------------------------------------------
/web/fav/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/web/fav/android-chrome-512x512.png
--------------------------------------------------------------------------------
/assets/images/ic_launcher_staging.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/ic_launcher_staging.jpg
--------------------------------------------------------------------------------
/lib/presentation/pages/main/home/home.dart:
--------------------------------------------------------------------------------
1 | export 'home_description.dart';
2 | export 'home_section.dart';
3 | export 'home_title.dart';
4 |
--------------------------------------------------------------------------------
/lib/presentation/presentation.dart:
--------------------------------------------------------------------------------
1 | export 'pages/pages.dart';
2 | export 'resources/resources.dart';
3 | export 'widgets/widgets.dart';
4 |
--------------------------------------------------------------------------------
/lib/presentation/resources/resources.dart:
--------------------------------------------------------------------------------
1 | export 'dimens.dart';
2 | export 'images.dart';
3 | export 'palette.dart';
4 | export 'styles.dart';
5 |
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-Black.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-Bold.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-Italic.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-Light.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-Medium.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-Thin.ttf
--------------------------------------------------------------------------------
/assets/images/portfolio/oifyoo/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/oifyoo/image_1.png
--------------------------------------------------------------------------------
/assets/images/portfolio/oifyoo/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/oifyoo/image_2.png
--------------------------------------------------------------------------------
/assets/images/portfolio/oifyoo/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/oifyoo/image_3.png
--------------------------------------------------------------------------------
/assets/images/portfolio/oifyoo/image_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/oifyoo/image_4.png
--------------------------------------------------------------------------------
/assets/images/portfolio/oifyoo/image_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/oifyoo/image_5.png
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-Regular.ttf
--------------------------------------------------------------------------------
/assets/images/portfolio/brupedia/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/brupedia/image_1.png
--------------------------------------------------------------------------------
/assets/images/portfolio/brupedia/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/brupedia/image_2.png
--------------------------------------------------------------------------------
/assets/images/portfolio/brupedia/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/brupedia/image_3.png
--------------------------------------------------------------------------------
/assets/images/portfolio/eabsensi/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/eabsensi/image_1.png
--------------------------------------------------------------------------------
/assets/images/portfolio/eabsensi/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/eabsensi/image_2.png
--------------------------------------------------------------------------------
/assets/images/portfolio/eabsensi/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/eabsensi/image_3.png
--------------------------------------------------------------------------------
/assets/images/portfolio/eabsensi/image_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/eabsensi/image_4.png
--------------------------------------------------------------------------------
/assets/images/portfolio/myananda/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/myananda/image_1.png
--------------------------------------------------------------------------------
/assets/images/portfolio/myananda/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/myananda/image_2.png
--------------------------------------------------------------------------------
/assets/images/portfolio/myananda/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/myananda/image_3.png
--------------------------------------------------------------------------------
/assets/images/portfolio/myananda/image_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/myananda/image_4.png
--------------------------------------------------------------------------------
/assets/images/portfolio/myananda/image_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/myananda/image_5.png
--------------------------------------------------------------------------------
/assets/images/portfolio/wautils/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/wautils/image_1.png
--------------------------------------------------------------------------------
/assets/images/portfolio/wautils/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/wautils/image_2.png
--------------------------------------------------------------------------------
/assets/images/portfolio/wautils/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/wautils/image_3.png
--------------------------------------------------------------------------------
/assets/images/portfolio/wautils/image_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/wautils/image_4.png
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:lint/analysis_options.yaml
2 | linter:
3 | rules:
4 | sort_pub_dependencies: false
5 | avoid_dynamic_calls: false
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-BlackItalic.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-BoldItalic.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-ExtraLight.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-LightItalic.ttf
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-ThinItalic.ttf
--------------------------------------------------------------------------------
/assets/images/portfolio/pataparking/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/pataparking/image_1.png
--------------------------------------------------------------------------------
/assets/images/portfolio/pataparking/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/pataparking/image_2.png
--------------------------------------------------------------------------------
/assets/images/portfolio/pataparking/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/pataparking/image_3.png
--------------------------------------------------------------------------------
/lib/presentation/pages/main/services/services.dart:
--------------------------------------------------------------------------------
1 | export 'services_description.dart';
2 | export 'services_section.dart';
3 | export 'services_title.dart';
4 |
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-MediumItalic.ttf
--------------------------------------------------------------------------------
/assets/images/portfolio/patapaowners/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/patapaowners/image_1.png
--------------------------------------------------------------------------------
/assets/images/portfolio/patapaowners/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/patapaowners/image_2.png
--------------------------------------------------------------------------------
/assets/images/portfolio/patapaowners/image_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/images/portfolio/patapaowners/image_3.png
--------------------------------------------------------------------------------
/lib/presentation/pages/main/portfolio/portfolio.dart:
--------------------------------------------------------------------------------
1 | export 'portfolio_description.dart';
2 | export 'portfolio_section.dart';
3 | export 'portfolio_title.dart';
4 |
--------------------------------------------------------------------------------
/assets/fonts/visuelt/VisueltPro-ExtraLightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazycatlabs/flutter-web-portfolio/HEAD/assets/fonts/visuelt/VisueltPro-ExtraLightItalic.ttf
--------------------------------------------------------------------------------
/lib/presentation/pages/main/profile/profile.dart:
--------------------------------------------------------------------------------
1 | export 'profile_button.dart';
2 | export 'profile_description.dart';
3 | export 'profile_section.dart';
4 | export 'profile_title.dart';
5 |
--------------------------------------------------------------------------------
/l10n.yaml:
--------------------------------------------------------------------------------
1 | arb-dir: lib/core/localization
2 | output-dir: lib/core/localization/generated
3 | template-arb-file: intl_en.arb
4 | output-localization-file: strings.dart
5 | output-class: Strings
6 | synthetic-package: false
--------------------------------------------------------------------------------
/web/fav/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #da532c
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/lib/core/localization/l10n.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class L10n {
4 | L10n._();
5 |
6 | static final all = [
7 | const Locale('en'),
8 | const Locale('id'),
9 | ];
10 |
11 | static String getFlag(String code) {
12 | switch (code) {
13 | case 'id':
14 | return 'Bahasa';
15 | case 'en':
16 | default:
17 | return 'English';
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/spacer_h.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 |
4 | class SpacerH extends StatelessWidget {
5 | const SpacerH({super.key, this.value});
6 |
7 | final double? value;
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return Container(
12 | width: value ?? Dimens.space8,
13 | );
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/spacer_v.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 |
4 | class SpacerV extends StatelessWidget {
5 | const SpacerV({super.key, this.value});
6 |
7 | final double? value;
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return SizedBox(
12 | height: value ?? Dimens.space8,
13 | );
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/main.dart:
--------------------------------------------------------------------------------
1 | export 'footer.dart';
2 | export 'footer_copy_right.dart';
3 | export 'home/home.dart';
4 | export 'main_cubit.dart';
5 | export 'main_drawer.dart';
6 | export 'main_menu.dart';
7 | export 'main_page.dart';
8 | export 'main_popup_menu.dart';
9 | export 'portfolio/portfolio.dart';
10 | export 'profile/profile.dart';
11 | export 'profile/profile_button.dart';
12 | export 'services/services.dart';
13 |
--------------------------------------------------------------------------------
/web/fav/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#ffffff",
17 | "background_color": "#ffffff",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/widgets.dart:
--------------------------------------------------------------------------------
1 | export 'animated_box_slider.dart';
2 | export 'animated_button.dart';
3 | export 'animated_mouse.dart';
4 | export 'animated_text_box.dart';
5 | export 'animated_text_strikethrough.dart';
6 | export 'animated_widget_shape.dart';
7 | export 'animated_widget_slider.dart';
8 | export 'circle_image.dart';
9 | export 'image_network.dart';
10 | export 'indicator_slider.dart';
11 | export 'parent.dart';
12 | export 'responsive.dart';
13 | export 'scroll_indicator.dart';
14 | export 'spacer_h.dart';
15 | export 'spacer_v.dart';
16 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "start_url": "/",
3 | "orientation": "portrait-primary",
4 | "prefer_related_applications": false,
5 | "name": "lazycatlabs",
6 | "short_name": "lazycatlabs",
7 | "icons": [
8 | {
9 | "src": "fav/android-chrome-192x192.png",
10 | "sizes": "192x192",
11 | "type": "image/png"
12 | },
13 | {
14 | "src": "fav/android-chrome-512x512.png",
15 | "sizes": "512x512",
16 | "type": "image/png"
17 | }
18 | ],
19 | "theme_color": "#ffffff",
20 | "background_color": "#ffffff",
21 | "display": "standalone"
22 | }
23 |
--------------------------------------------------------------------------------
/assets/images/ic_facebook.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/main_cubit.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_bloc/flutter_bloc.dart';
2 | import 'package:lazycatlabs/data/datasources/datasources.dart';
3 | import 'package:lazycatlabs/di/di.dart';
4 |
5 | class MainCubit extends Cubit {
6 | MainCubit() : super(DataHelper(type: "en"));
7 |
8 | void updateTheme(ActiveTheme activeTheme) {
9 | sl().theme = activeTheme.name;
10 | emit(DataHelper(activeTheme: activeTheme, type: sl().locale));
11 | }
12 |
13 | void updateLanguage(String type) {
14 | /// Update locale code
15 | sl().locale = type;
16 | emit(DataHelper(type: type, activeTheme: getActiveTheme()));
17 | }
18 |
19 | ActiveTheme getActiveTheme() {
20 | return ActiveTheme.values
21 | .firstWhere((element) => element.name == sl().theme);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/assets/images/ic_youtube.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 | lib/core/localization/generated
34 |
35 | # Web related
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Exceptions to above rules.
44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
45 |
46 | .metadata
47 | pubspec.lock
48 |
--------------------------------------------------------------------------------
/lib/presentation/pages/app_route.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:go_router/go_router.dart';
4 | import 'package:lazycatlabs/presentation/pages/pages.dart';
5 |
6 | enum Routes {
7 | root("/"),
8 | ;
9 |
10 | const Routes(this.path);
11 |
12 | final String path;
13 | }
14 |
15 | class AppRoute {
16 | static late BuildContext context;
17 |
18 | AppRoute.setStream(BuildContext ctx) {
19 | context = ctx;
20 | }
21 |
22 | static final GoRouter router = GoRouter(
23 | routes: [
24 | GoRoute(
25 | path: Routes.root.path,
26 | name: Routes.root.name,
27 | builder: (_, state) {
28 | return MainPage(
29 | key: state.pageKey,
30 | );
31 | },
32 | ),
33 | ],
34 | initialLocation: Routes.root.path,
35 | routerNeglect: true,
36 | debugLogDiagnostics: kDebugMode,
37 | );
38 | }
39 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/indicator_slider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 |
4 | // ignore: must_be_immutable
5 | class IndicatorSlider extends StatelessWidget {
6 | final bool isActive;
7 | Color? activeColour;
8 | Color? inActiveColour;
9 |
10 | IndicatorSlider({
11 | super.key,
12 | required this.isActive,
13 | this.activeColour,
14 | this.inActiveColour,
15 | });
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | return AnimatedContainer(
20 | duration: const Duration(milliseconds: 500),
21 | margin: EdgeInsets.all(Dimens.space2),
22 | width: isActive ? Dimens.space10 : Dimens.space8,
23 | height: isActive ? Dimens.space10 : Dimens.space8,
24 | decoration: BoxDecoration(
25 | color: isActive
26 | ? activeColour ?? Palette.offWhite
27 | : inActiveColour ?? Palette.offWhite.withOpacity(0.4),
28 | shape: BoxShape.circle,
29 | ),
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/di/di.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:get_it/get_it.dart';
3 | import 'package:lazycatlabs/data/datasources/datasources.dart';
4 | import 'package:lazycatlabs/presentation/pages/pages.dart';
5 | import 'package:shared_preferences/shared_preferences.dart';
6 |
7 | GetIt sl = GetIt.instance;
8 |
9 | Future serviceLocator({bool isUnitTest = false}) async {
10 | /// For unit testing only
11 | if (isUnitTest) {
12 | WidgetsFlutterBinding.ensureInitialized();
13 | sl.reset();
14 | // ignore: invalid_use_of_visible_for_testing_member
15 | SharedPreferences.setMockInitialValues({});
16 | await SharedPreferences.getInstance().then((value) {
17 | initPrefManager(value);
18 | });
19 | cubit();
20 | } else {
21 | cubit();
22 | }
23 | }
24 |
25 | // Register prefManager
26 | void initPrefManager(SharedPreferences initPrefManager) {
27 | sl.registerLazySingleton(() => PrefManager(initPrefManager));
28 | }
29 |
30 | void cubit() {
31 | sl.registerFactory(() => MainCubit());
32 | }
33 |
--------------------------------------------------------------------------------
/assets/images/ic_upwork.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/images/ic_linkedin.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/lib/presentation/resources/images.dart:
--------------------------------------------------------------------------------
1 | class Images {
2 | Images._();
3 |
4 | static String icAvatar = "assets/images/ic_avatar.png";
5 | static String icLogo = "assets/images/ic_logo.svg";
6 | static String icLogoText = "assets/images/ic_logo_text.svg";
7 | static String icLogoTextOneline = "assets/images/ic_logo_text_oneline.svg";
8 | static String icMenu = "assets/images/ic_menu.svg";
9 | static String icSettings = "assets/images/ic_settings.svg";
10 | static String icProfile = "assets/images/ic_profile.jpg";
11 | static String icLinkedIn = "assets/images/ic_linkedin.svg";
12 | static String icUpwork = "assets/images/ic_upwork.svg";
13 | static String icGithub = "assets/images/ic_github.svg";
14 | static String icFacebook = "assets/images/ic_facebook.svg";
15 | static String icInstagram = "assets/images/ic_instagram.svg";
16 | static String icTiktok = "assets/images/ic_tiktok.svg";
17 | static String icYoutube = "assets/images/ic_youtube.svg";
18 | static String icPlaystore = "assets/images/ic_playstore.png";
19 | static String icClose = "assets/images/ic_close.svg";
20 | }
21 |
--------------------------------------------------------------------------------
/assets/images/ic_menu.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/lib/utils/helper/common.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 | import 'package:logger/logger.dart';
4 |
5 | final log = Logger(
6 | printer: PrettyPrinter(
7 | methodCount: 1,
8 | lineLength: 110,
9 | ),
10 | );
11 |
12 | Size textSize({
13 | required String text,
14 | required TextStyle? style,
15 | int maxLines = 1,
16 | double maxWidth = double.infinity,
17 | }) {
18 | final TextPainter textPainter = TextPainter(
19 | text: TextSpan(text: text, style: style),
20 | maxLines: maxLines,
21 | textDirection: TextDirection.ltr,
22 | )..layout(maxWidth: maxWidth);
23 | return textPainter.size;
24 | }
25 |
26 | double responsiveSize(
27 | BuildContext context,
28 | double mobile,
29 | double desktop, {
30 | double? tablet,
31 | }) {
32 | if (Responsive.isDesktop(context)) {
33 | return desktop;
34 | } else if (Responsive.isTablet(context)) {
35 | return tablet ?? mobile;
36 | } else {
37 | return mobile;
38 | }
39 | }
40 |
41 | const durationShort = Duration(milliseconds: 400);
42 | const durationLong = Duration(milliseconds: 1500);
43 |
--------------------------------------------------------------------------------
/lib/data/datasources/local/data_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/data/datasources/local/pref_manager.dart';
3 |
4 | class DataHelper {
5 | final String? title;
6 | final String? desc;
7 | bool isSelected;
8 | final String? iconPath;
9 | final IconData? icon;
10 | final String? url;
11 | final String? type;
12 | final int? id;
13 | final ActiveTheme activeTheme;
14 | final AnimationController? animationController;
15 | Animation? animation;
16 | ColorTween? colorTween;
17 | VoidCallback? onPressed;
18 | Color? iconColor;
19 | bool onHover;
20 |
21 | DataHelper({
22 | this.title,
23 | this.desc,
24 | this.isSelected = false,
25 | this.iconPath,
26 | this.icon,
27 | this.url,
28 | this.type,
29 | this.id,
30 | this.activeTheme = ActiveTheme.system,
31 | this.animationController,
32 | this.animation,
33 | this.colorTween,
34 | this.onPressed,
35 | this.iconColor,
36 | this.onHover = false,
37 | }) {
38 | if (animationController != null && colorTween != null) {
39 | animation = colorTween!.animate(animationController!);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/assets/images/ic_close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/assets/images/ic_github.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/circle_image.dart:
--------------------------------------------------------------------------------
1 | import 'package:cached_network_image/cached_network_image.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:lazycatlabs/presentation/presentation.dart';
4 |
5 | ///*********************************************
6 | /// Created by ukietux on 03/11/20 with ♥
7 | /// (>’_’)> email : ukie.tux@gmail.com
8 | /// github : https://www.github.com/Lzyct <(’_’<)
9 | ///*********************************************
10 | /// © 2020 | All Right Reserved
11 | class CircleImage extends StatelessWidget {
12 | final String url;
13 | final double? size;
14 |
15 | const CircleImage({super.key, required this.url, this.size});
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | /// TODO Need to change with Fix on error image url
20 | return ClipRRect(
21 | borderRadius: BorderRadius.circular(360),
22 |
23 | /// 360 degree circle
24 | child: CachedNetworkImage(
25 | fit: BoxFit.cover,
26 | width: size,
27 | height: size,
28 | fadeInDuration: const Duration(milliseconds: 300),
29 | imageUrl: url,
30 | placeholder: (context, url) => SizedBox(
31 | width: Dimens.space46,
32 | height: Dimens.space46,
33 | child: const CupertinoActivityIndicator(),
34 | ),
35 | // errorWidget: (context, url, error) =>
36 | // new SvgPicture.asset(Images.icEmpty),
37 | ),
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/assets/images/ic_tiktok.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/image_network.dart:
--------------------------------------------------------------------------------
1 | import 'package:cached_network_image/cached_network_image.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:lazycatlabs/presentation/presentation.dart';
4 |
5 | ///*********************************************
6 | /// my-ananda-hospital |
7 | /// image_network.dart
8 | /// --------------------------------------------
9 | /// Created by Mudassir 🧑🏻💻 @ >codelogs_
10 | /// on 📅 08/06/21 🕰 10:10 with ❤️
11 | /// email : hey.mudassir@gmail.com
12 | /// github : https://www.github.com/Lzyct
13 | ///*********************************************
14 | /// © 2021 | All Right Reserved
15 | class ImageNetwork extends StatelessWidget {
16 | final String imageUrl;
17 | final double? width;
18 | final double? height;
19 |
20 | const ImageNetwork({
21 | super.key,
22 | required this.imageUrl,
23 | this.width,
24 | this.height,
25 | });
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | return CachedNetworkImage(
30 | fit: BoxFit.cover,
31 | width: width,
32 | height: height,
33 | fadeInDuration: const Duration(milliseconds: 300),
34 | imageUrl: imageUrl,
35 | placeholder: (context, url) => SizedBox(
36 | width: Dimens.space46,
37 | height: Dimens.space46,
38 | child: const CupertinoActivityIndicator(),
39 | ),
40 | // errorWidget: (context, url, error) =>
41 | // new SvgPicture.asset(Images.icEmpty),
42 | );
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/footer_copy_right.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/core/core.dart';
3 | import 'package:lazycatlabs/presentation/presentation.dart';
4 | import 'package:lazycatlabs/utils/utils.dart';
5 |
6 | class FooterCopyRight extends StatelessWidget {
7 | const FooterCopyRight({super.key, required this.context});
8 |
9 | final BuildContext context;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Container(
14 | color: Theme.of(context).scaffoldBackgroundColor,
15 | width: double.maxFinite,
16 | padding: EdgeInsets.symmetric(vertical: Dimens.space16),
17 | child: Column(
18 | children: [
19 | Text(
20 | "\u00a9 ${DateTime.now().year} ${Constants.get.appName}",
21 | style: Theme.of(context).textTheme.bodyText2,
22 | ),
23 | Row(
24 | mainAxisSize: MainAxisSize.min,
25 | mainAxisAlignment: MainAxisAlignment.center,
26 | children: [
27 | Text(
28 | "${Strings.of(context)!.createdWith} ",
29 | style: Theme.of(context).textTheme.bodyText2,
30 | ),
31 | const Icon(Icons.favorite, color: Palette.red),
32 | Text(
33 | " ${Strings.of(context)!.and} ",
34 | style: Theme.of(context).textTheme.bodyText2,
35 | ),
36 | const FlutterLogo(),
37 | ],
38 | ),
39 | ],
40 | ),
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/core/localization/intl_en.arb:
--------------------------------------------------------------------------------
1 | {
2 | "chooseTheme": "Choose Theme",
3 | "chooseLanguage": "Choose Language",
4 | "underDevelopmentTitle": "This site is under development",
5 | "underDevelopmentDesc": "Until him complete the codes",
6 | "createdWith": "Created with",
7 | "and": "and",
8 | "sendEmail": "Send Email",
9 | "home": "Home",
10 | "profile": "Profile",
11 | "portfolio": "Portfolio",
12 | "services": "Services",
13 | "themeLight": "Theme Light",
14 | "themeDark": "Theme Dark",
15 | "themeSystem": "Theme System",
16 | "appDesc": "Lazycat Labs is a place to share about new tech and programming with a lazy way.",
17 | "blog": "Blog",
18 | "hello": "Hello",
19 | "profileTitle": "My name is Mudassir.",
20 | "profileDesc": " Currently working on ikhlas.com as Software Engineer II. I am specialized in Mobile Application Development with more than 5 years experience. Writing code for Android Native and Hybrid with Flutter Framework then implement mobile apps guidelines and realize UI/UX quality is one of the most important things in mobile apps development. That's why, I always try to deliver pixel perfect layouts tested on various devices.",
21 | "downloadCV": "Download CV",
22 | "buildTitle": "Build",
23 | "buildDesc": "Help you tou build an application\nfrom scratch with high quality code.",
24 | "fixTitle": "Fix",
25 | "fixDesc": "Fix bugs in your application\nand also improve the performance.",
26 | "continueTitle": "Continue",
27 | "continueDesc": "Continue your existing application project\nand improve the Application quality.",
28 | "portfolioDesc": "Latest project",
29 | "tags": "Tags:",
30 | "support": "Support Me",
31 | "socialMedia": "Follow Me",
32 | "seeMyBlog": "See my blog"
33 | }
--------------------------------------------------------------------------------
/lib/utils/helper/constant.dart:
--------------------------------------------------------------------------------
1 | class Constants {
2 | Constants._();
3 |
4 | static Constants get = Constants._();
5 |
6 | String appName = "Lazycat Labs";
7 | String english = "English";
8 | String bahasa = "Bahasa";
9 | String fontFamily = "VisueltPro";
10 |
11 | String imagePlaceHolder =
12 | "https://cdn.dribbble.com/users/5478575/screenshots/12108011/media/17e913f849a16ea1f349b73afa04bbf9.jpg?compress=1&resize=400x300";
13 | String linkedInUrl = "https://www.linkedin.com/in/mudassir-321462139/";
14 | String upworkUrl = "https://www.upwork.com/freelancers/~01913209d41be922f1";
15 | String githubSponsorUrl = "https://github.com/sponsors/Lzyct";
16 | String githubUrl = "https://github.com/Lzyct";
17 |
18 | String playStore = "Play Store";
19 | String appStore = "App Store";
20 |
21 | String github = "GitHub";
22 | String linkedIn = "LinkedIn";
23 | String upwork = "Upwork";
24 |
25 | String githubSponsor = "GitHub Sponsor";
26 | String kofi = "Ko-Fi";
27 | String kofiUrl = "ko-fi.com/lzyct";
28 | String buymecoffee = "Buy me a coffee";
29 | String buymecoffeeUrl = "https://www.buymeacoffee.com/Lzyct";
30 | String saweria = "Saweria";
31 | String saweriaUrl = "https://saweria.co/Lzyct";
32 |
33 | String youtubeUrl =
34 | "https://www.youtube.com/channel/UCzXKJlJHPIsQKhvuzHQ7ImA";
35 | String instagramUrl = "https://www.instagram.com/lazycatlabs/";
36 | String facebookUrl = "https://www.facebook.com/lazycatlabs/";
37 | String tiktokUrl = "https://www.tiktok.com/@lazycatlabs";
38 | String githubCommunityUrl = "https://github.com/lazycatlabs";
39 | String blogUrl = "https://blog.lazycatlabs.com";
40 |
41 | String playStoreUrl =
42 | "https://play.google.com/store/apps/dev?id=6313853259913767184";
43 | }
44 |
--------------------------------------------------------------------------------
/lib/core/localization/intl_id.arb:
--------------------------------------------------------------------------------
1 | {
2 | "chooseTheme": "Pilih Tema",
3 | "chooseLanguage": "Pilih Bahasa",
4 | "underDevelopmentTitle": "Situs ini dalam tahap pengembangan",
5 | "underDevelopmentDesc": "Sampai dia menyelesaikan code nya",
6 | "createdWith": "Dibuat menggunakan",
7 | "and": "dan",
8 | "sendEmail": "Kirim Email",
9 | "home": "Beranda",
10 | "profile": "Profil",
11 | "portfolio": "Portofolio",
12 | "services": "Layanan",
13 | "themeLight": "Tema Terang",
14 | "themeDark": "Tema Gelap",
15 | "themeSystem": "Tema Sistem",
16 | "appDesc": "Lazycat Labs adalah tempat untuk berbagi hal mengenai teknologi yang terbaru dan pemrograman dengan santai.",
17 | "blog": "Blog",
18 | "hello": "Halo",
19 | "profileTitle": "Nama saya Mudassir.",
20 | "profileDesc": " Saat ini saya bekerja di ikhlas.com sebagai Software Engineer II. Saya fokus dalam pengembangan aplikasi seluler dengan pengalaman lebih dari 5 tahun. Menulis kode untuk Android native maupun menggunakan Flutter, kemudian menerapkan pedoman dalam membuat aplikasi mobile dan membuat UI/UX berkualitas adalah salah satu hal terpenting dalam pengembangan aplikasi mobile. Itulah sebabnya, saya selalu mencoba mengimplementasikan tata letak piksel yang sempurna yang diuji pada berbagai perangkat.",
21 | "downloadCV": "Unduh CV",
22 | "buildTitle": "Membangun",
23 | "buildDesc": "Membantu Anda membangun aplikasi\ndari awal dengan kualitas kode yang baik.",
24 | "fixTitle": "Memperbaiki",
25 | "fixDesc": "Mencari dan memperbaiki masalah pada \naplikasi Anda dan juga meningkatkan performanya.",
26 | "continueTitle": "Melanjutkan",
27 | "continueDesc": "Melanjutkan project aplikasi Anda\ndan meningkatkan kualiatasnya.",
28 | "portfolioDesc": "Project terbaru",
29 | "tags": "Tag:",
30 | "support": "Dukung Saya",
31 | "socialMedia": "Ikuti Saya",
32 | "seeMyBlog": "Lihat blog saya"
33 | }
34 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/parent.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | ///*********************************************
4 | /// Created by ukietux on 24/08/20 with ♥
5 | /// (>’_’)> email : ukie.tux@gmail.com
6 | /// github : https://www.github.com/Lzyct <(’_’<)
7 | ///*********************************************
8 | /// © 2020 | All Right Reserved
9 | class Parent extends StatefulWidget {
10 | final Widget? child;
11 | final PreferredSizeWidget? appBar;
12 | final bool avoidBottomInset;
13 | final Widget? floatingButton;
14 | final Widget? bottomNavigation;
15 | final Widget? drawer;
16 | final Widget? endDrawer;
17 | final Color? backgroundColor;
18 | final Key? scaffoldKey;
19 | final bool extendBodyBehindAppBar;
20 |
21 | const Parent({
22 | super.key,
23 | this.child,
24 | this.appBar,
25 | this.avoidBottomInset = true,
26 | this.floatingButton,
27 | this.backgroundColor,
28 | this.bottomNavigation,
29 | this.drawer,
30 | this.scaffoldKey,
31 | this.endDrawer,
32 | this.extendBodyBehindAppBar = false,
33 | });
34 |
35 | @override
36 | _ParentState createState() => _ParentState();
37 | }
38 |
39 | class _ParentState extends State {
40 | @override
41 | Widget build(BuildContext context) {
42 | return GestureDetector(
43 | onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
44 | child: Scaffold(
45 | key: widget.scaffoldKey,
46 | backgroundColor: widget.backgroundColor,
47 | resizeToAvoidBottomInset: widget.avoidBottomInset,
48 | extendBodyBehindAppBar: widget.extendBodyBehindAppBar,
49 | appBar: widget.appBar,
50 | body: widget.child,
51 | drawer: widget.drawer,
52 | endDrawer: widget.endDrawer,
53 | floatingActionButton: widget.floatingButton,
54 | bottomNavigationBar: widget.bottomNavigation,
55 | ),
56 | );
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/home/home_title.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 | import 'package:lazycatlabs/utils/utils.dart';
4 |
5 | class HomeTitle extends StatelessWidget {
6 | const HomeTitle({super.key, required this.animationController});
7 |
8 | final AnimationController animationController;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return AnimatedWidgetShape(
13 | animationController: animationController,
14 | width: responsiveSize(
15 | context,
16 | Dimens.space130 + Dimens.space12,
17 | Dimens.space200 + Dimens.space12,
18 | tablet: Dimens.space150 + Dimens.space12,
19 | ),
20 | height: responsiveSize(
21 | context,
22 | Dimens.space130 + Dimens.space12,
23 | Dimens.space200 + Dimens.space12,
24 | tablet: Dimens.space150 + Dimens.space12,
25 | ),
26 | boxShape: BoxShape.circle,
27 | child: Stack(
28 | children: [
29 | CircleAvatar(
30 | radius: Dimens.space24,
31 | backgroundColor: Theme.of(context).cardColor,
32 | ),
33 | CircleAvatar(
34 | radius: responsiveSize(
35 | context,
36 | Dimens.space64,
37 | Dimens.space150,
38 | tablet: Dimens.space72,
39 | ) +
40 | Dimens.space12,
41 | backgroundColor: Theme.of(context).cardColor,
42 | child: CircleAvatar(
43 | backgroundImage: AssetImage(Images.icAvatar),
44 | radius: responsiveSize(
45 | context,
46 | Dimens.space58,
47 | Dimens.space92,
48 | tablet: Dimens.space72,
49 | ),
50 | ),
51 | ),
52 | ],
53 | ),
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/profile/profile_title.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 | import 'package:lazycatlabs/utils/utils.dart';
4 |
5 | class ProfileTitle extends StatelessWidget {
6 | const ProfileTitle({super.key, required this.animationController});
7 |
8 | final AnimationController animationController;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return AnimatedWidgetShape(
13 | animationController: animationController,
14 | width: responsiveSize(
15 | context,
16 | Dimens.space130 + Dimens.space12,
17 | Dimens.space200 + Dimens.space12,
18 | tablet: Dimens.space150 + Dimens.space12,
19 | ),
20 | height: responsiveSize(
21 | context,
22 | Dimens.space130 + Dimens.space12,
23 | Dimens.space200 + Dimens.space12,
24 | tablet: Dimens.space150 + Dimens.space12,
25 | ),
26 | boxShape: BoxShape.circle,
27 | child: Stack(
28 | children: [
29 | CircleAvatar(
30 | radius: Dimens.space24,
31 | backgroundColor: Theme.of(context).cardColor,
32 | ),
33 | CircleAvatar(
34 | radius: responsiveSize(
35 | context,
36 | Dimens.space64,
37 | Dimens.space150,
38 | tablet: Dimens.space72,
39 | ) +
40 | Dimens.space12,
41 | backgroundColor: Theme.of(context).cardColor,
42 | child: CircleAvatar(
43 | backgroundImage: AssetImage(Images.icProfile),
44 | radius: responsiveSize(
45 | context,
46 | Dimens.space58,
47 | Dimens.space92,
48 | tablet: Dimens.space72,
49 | ),
50 | ),
51 | ),
52 | ],
53 | ),
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/services/services_title.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/core/core.dart';
3 | import 'package:lazycatlabs/presentation/presentation.dart';
4 | import 'package:lazycatlabs/utils/utils.dart';
5 |
6 | class ServicesTitle extends StatelessWidget {
7 | const ServicesTitle({super.key, required this.animationController});
8 |
9 | final AnimationController animationController;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return AnimatedWidgetShape(
14 | animationController: animationController,
15 | width: responsiveSize(
16 | context,
17 | context.widthInPercent(44),
18 | context.widthInPercent(28),
19 | tablet: Dimens.space220,
20 | ),
21 | height: responsiveSize(
22 | context,
23 | Dimens.space100,
24 | Dimens.space200,
25 | tablet: Dimens.space120,
26 | ),
27 | child: Stack(
28 | alignment: Alignment.center,
29 | children: [
30 | Positioned(
31 | right: 0,
32 | child: Icon(
33 | Icons.circle,
34 | color: Theme.of(context).cardColor,
35 | size: responsiveSize(context, Dimens.space72, Dimens.space150),
36 | ),
37 | ),
38 | Positioned(
39 | left: 0,
40 | bottom: responsiveSize(
41 | context,
42 | Dimens.space30,
43 | Dimens.space48,
44 | ),
45 | child: Text(
46 | Strings.of(context)!.services,
47 | style: Theme.of(context).textTheme.headline1?.copyWith(
48 | fontSize: responsiveSize(
49 | context,
50 | Dimens.space36,
51 | Dimens.h1,
52 | tablet: Dimens.h3,
53 | ),
54 | ),
55 | ),
56 | ),
57 | ],
58 | ),
59 | );
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/animated_mouse.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 |
4 | class AnimatedMouse extends StatefulWidget {
5 | const AnimatedMouse({super.key});
6 |
7 | @override
8 | State createState() => _AnimatedMouseState();
9 | }
10 |
11 | class _AnimatedMouseState extends State
12 | with SingleTickerProviderStateMixin {
13 | late final AnimationController _animationController = AnimationController(
14 | duration: const Duration(milliseconds: 800),
15 | vsync: this,
16 | )..repeat(reverse: true);
17 |
18 | late final Animation _animatedAlign =
19 | Tween(begin: Alignment.topCenter, end: const Alignment(0, 0.45))
20 | .animate(_animationController);
21 |
22 | @override
23 | void dispose() {
24 | super.dispose();
25 | _animationController.dispose();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return AnimatedBuilder(
31 | animation: _animationController,
32 | builder: (context, _) {
33 | return AnimatedContainer(
34 | duration: const Duration(milliseconds: 300),
35 | width: Dimens.space30,
36 | height: Dimens.space36 * 1.3,
37 | alignment: _animatedAlign.value,
38 | decoration: BoxDecoration(
39 | borderRadius: BorderRadius.circular(Dimens.space30),
40 | border: Border.all(
41 | color: Palette.hint,
42 | width: Dimens.space3,
43 | ),
44 | ),
45 | child: AnimatedOpacity(
46 | duration: const Duration(milliseconds: 300),
47 | opacity:
48 | _animationController.status == AnimationStatus.forward ? 1 : 0,
49 | child: Container(
50 | width: Dimens.space4,
51 | height: Dimens.space12,
52 | decoration: BoxDecoration(
53 | color: Palette.hint,
54 | borderRadius: BorderRadius.circular(Dimens.space8),
55 | ),
56 | ),
57 | ),
58 | );
59 | },
60 | );
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | Lazycat Labs
32 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/lib/presentation/resources/dimens.dart:
--------------------------------------------------------------------------------
1 | class Dimens {
2 | Dimens._();
3 |
4 | static double h1 = 96;
5 | static double h2 = 60;
6 | static double h3 = 48;
7 | static double h4 = 34;
8 | static double h5 = 24;
9 | static double h6 = 20;
10 | static double body1 = 16;
11 | static double body2 = 14;
12 | static double subtitle1 = 16;
13 | static double subtitle2 = 14;
14 | static double button = 14;
15 | static double caption = 12;
16 | static double overline = 10;
17 |
18 | static double zero = 0;
19 | static double space1 = 1;
20 | static double space2 = 2;
21 | static double space3 = 3;
22 | static double space4 = 4;
23 | static double space6 = 6;
24 | static double space8 = 8;
25 | static double space10 = 10;
26 | static double space12 = 12;
27 | static double space16 = 16;
28 | static double space17 = 17;
29 | static double space18 = 18;
30 | static double space20 = 20;
31 | static double space24 = 24;
32 | static double space30 = 30;
33 | static double space36 = 36;
34 | static double space42 = 42;
35 | static double space46 = 46;
36 | static double space48 = 48;
37 | static double space50 = 50;
38 | static double space58 = 58;
39 | static double space64 = 64;
40 | static double space72 = 72;
41 | static double space92 = 92;
42 | static double space100 = 100;
43 | static double space120 = 120;
44 | static double space130 = 130;
45 | static double space150 = 150;
46 | static double space180 = 180;
47 | static double space200 = 200;
48 | static double space220 = 220;
49 | static double space250 = 250;
50 | static double space280 = 280;
51 | static double space300 = 300;
52 | static double space400 = 400;
53 |
54 | static double selectedIndicatorW = 43;
55 | static double selectedIndicatorSmallW = 28;
56 | static double heightAppbarHome = 65;
57 | static double tab = 38;
58 | static double menu = 200;
59 | static double iconDropdown = 50;
60 | static double menuContainer = 350;
61 | static double carousel = 167;
62 |
63 | static double header = 160;
64 | static double minLabel = 116;
65 | static double bottomBar = 80;
66 | static double buttonH = 50;
67 | static double buttonWidth = 110;
68 |
69 | static const double cornerRadius = 15;
70 | static const double cornerButton = 80;
71 | static const double widthToast = 250;
72 | }
73 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/home/home_description.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/core/core.dart';
3 | import 'package:lazycatlabs/presentation/presentation.dart';
4 | import 'package:lazycatlabs/utils/utils.dart';
5 | import 'package:url_launcher/url_launcher_string.dart';
6 |
7 | class HomeDescription extends StatelessWidget {
8 | const HomeDescription({
9 | super.key,
10 | required this.animationController,
11 | });
12 |
13 | final AnimationController animationController;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Padding(
18 | padding: EdgeInsets.all(Dimens.space24),
19 | child: Column(
20 | crossAxisAlignment: CrossAxisAlignment.start,
21 | mainAxisSize: MainAxisSize.min,
22 | children: [
23 | AnimatedTextBox(
24 | animationController: animationController,
25 | text: "${Constants.get.appName}.",
26 | maxLines: 3,
27 | textStyle: Theme.of(context).textTheme.headline1!.copyWith(
28 | fontSize: responsiveSize(
29 | context,
30 | Dimens.space36,
31 | Dimens.h1,
32 | tablet: Dimens.h2,
33 | ),
34 | ),
35 | ),
36 | AnimatedTextBox(
37 | animationController: animationController,
38 | text: Strings.of(context)!.appDesc,
39 | heightFactor: responsiveSize(context, 2, 1),
40 | maxLines: responsiveSize(context, 2, 1).toInt(),
41 | textStyle: Theme.of(context).textTheme.bodyText1!.copyWith(
42 | fontSize: responsiveSize(
43 | context,
44 | Dimens.body2,
45 | Dimens.space17,
46 | ),
47 | ),
48 | ),
49 | SpacerV(value: Dimens.space24),
50 | AnimatedWidgetShape(
51 | animationController: animationController,
52 | width: Dimens.space150,
53 | height: Dimens.buttonH,
54 | child: Button(
55 | targetWidth: Dimens.space150,
56 | title: Strings.of(context)!.seeMyBlog,
57 | onPressed: () {
58 | launchUrlString(Constants.get.blogUrl);
59 | },
60 | ),
61 | ),
62 | ],
63 | ),
64 | );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/data/datasources/local/pref_manager.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:shared_preferences/shared_preferences.dart';
4 |
5 | enum ActiveTheme {
6 | light(
7 | ThemeMode.light,
8 | Icons.wb_sunny,
9 | ),
10 | dark(ThemeMode.dark, Icons.brightness_2),
11 | system(ThemeMode.system, Icons.brightness_auto_rounded);
12 |
13 | final ThemeMode mode;
14 | final IconData icon;
15 |
16 | const ActiveTheme(this.mode, this.icon);
17 | }
18 |
19 | class PrefManager {
20 | String kIsLogin = "isLogin";
21 | String kToken = "token";
22 | String kText = "text";
23 | String kColor = "color";
24 | String kIcon = "icon";
25 | String kUser = "user";
26 | String kFCM = "fcm";
27 | String kLanguage = "language";
28 | String kLocale = "locale";
29 | String kTheme = "theme";
30 |
31 | /// Light, Dark ,System
32 |
33 | SharedPreferences preferences;
34 |
35 | PrefManager(this.preferences);
36 |
37 | //for Bloc.Bloc.login
38 | set isLogin(bool value) => preferences.setBool(kIsLogin, value);
39 |
40 | bool get isLogin => preferences.getBool(kIsLogin) ?? false;
41 |
42 | set token(String? value) => preferences.setString(kToken, value ?? "");
43 |
44 | String? get token => preferences.getString(kToken);
45 |
46 | set fcmToken(String? value) => preferences.setString(kFCM, value ?? "");
47 |
48 | String? get fcmToken => preferences.getString(kFCM);
49 |
50 | set user(String? value) => preferences.setString(kUser, value ?? "");
51 |
52 | String? get user => preferences.getString(kUser);
53 |
54 | set text(String? value) => preferences.setString(kText, value ?? "");
55 |
56 | String get text => preferences.getString(kText) ?? "";
57 |
58 | set color(String? value) => preferences.setString(kColor, value ?? "");
59 |
60 | String? get color => preferences.getString(kColor);
61 |
62 | set icon(String? value) => preferences.setString(kIcon, value ?? "");
63 |
64 | String? get icon => preferences.getString(kIcon);
65 |
66 | /// Default locale set to English
67 | set locale(String? value) => preferences.setString(kLocale, value ?? "en");
68 |
69 | String get locale => preferences.getString(kLocale) ?? "en";
70 |
71 | /// Default locale set to English
72 | set theme(String? value) =>
73 | preferences.setString(kTheme, value ?? describeEnum(ActiveTheme.system));
74 |
75 | String get theme =>
76 | preferences.getString(kTheme) ?? describeEnum(ActiveTheme.system);
77 |
78 | void logout() => preferences.clear();
79 | }
80 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/portfolio/portfolio_title.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/core/core.dart';
3 | import 'package:lazycatlabs/presentation/presentation.dart';
4 | import 'package:lazycatlabs/utils/utils.dart';
5 |
6 | class PortfolioTitle extends StatelessWidget {
7 | const PortfolioTitle({super.key, required this.animationController});
8 |
9 | final AnimationController animationController;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return AnimatedWidgetShape(
14 | animationController: animationController,
15 | width: responsiveSize(
16 | context,
17 | context.widthInPercent(45),
18 | context.widthInPercent(32),
19 | tablet: Dimens.space250,
20 | ),
21 | height: responsiveSize(
22 | context,
23 | Dimens.space100,
24 | Dimens.space200,
25 | tablet: Dimens.space120,
26 | ),
27 | child: Stack(
28 | alignment: Alignment.center,
29 | children: [
30 | Positioned(
31 | right: 0,
32 | child: Icon(
33 | Icons.circle,
34 | color: Theme.of(context).cardColor,
35 | size: responsiveSize(context, Dimens.space72, Dimens.space150),
36 | ),
37 | ),
38 | Positioned(
39 | left: 0,
40 | bottom: responsiveSize(
41 | context,
42 | Dimens.space20,
43 | Dimens.space30,
44 | ),
45 | child: Column(
46 | crossAxisAlignment: CrossAxisAlignment.end,
47 | children: [
48 | Text(
49 | Strings.of(context)!.portfolio,
50 | style: Theme.of(context).textTheme.headline1?.copyWith(
51 | fontSize: responsiveSize(
52 | context,
53 | Dimens.space36,
54 | Dimens.h1,
55 | tablet: Dimens.h3,
56 | ),
57 | ),
58 | ),
59 | Text(
60 | Strings.of(context)!.portfolioDesc,
61 | style: Theme.of(context).textTheme.headline6?.copyWith(
62 | fontSize:
63 | responsiveSize(context, Dimens.body1, Dimens.h6),
64 | ),
65 | )
66 | ],
67 | ),
68 | ),
69 | ],
70 | ),
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/lib/data/datasources/local/portfolio_response.dart:
--------------------------------------------------------------------------------
1 | class PortfolioResponse {
2 | PortfolioResponse({
3 | this.data,
4 | });
5 |
6 | PortfolioResponse.fromJson(dynamic json) {
7 | if (json['data'] != null) {
8 | data = [];
9 | json['data'].forEach((v) {
10 | data?.add(Data.fromJson(v));
11 | });
12 | }
13 | }
14 |
15 | List? data;
16 |
17 | PortfolioResponse copyWith({
18 | List? data,
19 | }) =>
20 | PortfolioResponse(
21 | data: data ?? this.data,
22 | );
23 |
24 | Map toJson() {
25 | final map = {};
26 | if (data != null) {
27 | map['data'] = data?.map((v) => v.toJson()).toList();
28 | }
29 | return map;
30 | }
31 | }
32 |
33 | class Data {
34 | Data({
35 | this.title,
36 | this.descriptions,
37 | this.images,
38 | this.playStore,
39 | this.appStore,
40 | this.tag,
41 | this.onClick = false,
42 | this.onHover = false,
43 | this.activeIndex = 0,
44 | });
45 |
46 | Data.fromJson(dynamic json) {
47 | title = json['title'] as String?;
48 | descriptions = json['descriptions'] as String?;
49 | images = json['images'] != null
50 | ? json['images'].cast() as List?
51 | : [];
52 | playStore = json['playStore'] as String?;
53 | appStore = json['appStore'] as String?;
54 | tag =
55 | json['tag'] != null ? json['tag'].cast() as List? : [];
56 | }
57 |
58 | String? title;
59 | String? descriptions;
60 | List? images;
61 | String? playStore;
62 | String? appStore;
63 | List? tag;
64 | bool onHover = false;
65 | bool onClick = false;
66 | int activeIndex = 0;
67 |
68 | Data copyWith({
69 | String? title,
70 | String? descriptions,
71 | List? images,
72 | String? playStore,
73 | String? appStore,
74 | List? tag,
75 | }) =>
76 | Data(
77 | title: title ?? this.title,
78 | descriptions: descriptions ?? this.descriptions,
79 | images: images ?? this.images,
80 | playStore: playStore ?? this.playStore,
81 | appStore: appStore ?? this.appStore,
82 | tag: tag ?? this.tag,
83 | );
84 |
85 | Map toJson() {
86 | final map = {};
87 | map['title'] = title;
88 | map['descriptions'] = descriptions;
89 | map['images'] = images;
90 | map['playStore'] = playStore;
91 | map['appStore'] = appStore;
92 | map['tag'] = tag;
93 | return map;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/profile/profile_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/data/data.dart';
3 | import 'package:lazycatlabs/presentation/presentation.dart';
4 | import 'package:lazycatlabs/utils/utils.dart';
5 | import 'package:url_launcher/url_launcher_string.dart';
6 |
7 | class ProfileButton extends StatelessWidget {
8 | const ProfileButton({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | final List buttons = [
13 | DataHelper(
14 | title: Constants.get.linkedIn,
15 | iconPath: Images.icLinkedIn,
16 | iconColor: Palette.linkedIn,
17 | url: Constants.get.linkedInUrl,
18 | ),
19 | DataHelper(
20 | title: Constants.get.upwork,
21 | iconPath: Images.icUpwork,
22 | url: Constants.get.upworkUrl,
23 | ),
24 | DataHelper(
25 | title: Constants.get.github,
26 | iconPath: Images.icGithub,
27 | iconColor: Theme.of(context).textTheme.bodyText1?.color,
28 | url: Constants.get.githubUrl,
29 | ),
30 | ];
31 |
32 | return Wrap(
33 | runSpacing: Dimens.space16,
34 | spacing: Dimens.space16,
35 | children: buttons
36 | .asMap()
37 | .entries
38 | .map(
39 | (element) => Wrap(
40 | children: [
41 | AnimatedTextStrikethrough(
42 | text: element.value.title ?? "",
43 | textStyle: Theme.of(context)
44 | .textTheme
45 | .bodyText1!
46 | .copyWith(decoration: TextDecoration.underline),
47 | textStyleHover: Theme.of(context)
48 | .textTheme
49 | .bodyText1!
50 | .copyWith(fontWeight: FontWeight.w500),
51 | duration: const Duration(milliseconds: 400),
52 | onTap: () {
53 | launchUrlString(element.value.url!);
54 | },
55 | ),
56 | if (element.key < buttons.length - 1) ...{
57 | SpacerH(value: Dimens.space16),
58 | Text(
59 | "/",
60 | style: Theme.of(context)
61 | .textTheme
62 | .bodyText1
63 | ?.copyWith(fontWeight: FontWeight.normal),
64 | ),
65 | }
66 | ],
67 | ),
68 | )
69 | .toList(),
70 | );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/animated_box_slider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | const double _hiddenFactor = 3;
4 |
5 | class AnimatedBoxSlider extends AnimatedWidget {
6 | const AnimatedBoxSlider({
7 | super.key,
8 | required this.controller,
9 | required this.width,
10 | required this.height,
11 | this.visibleBoxAnimation,
12 | this.invisibleBoxAnimation,
13 | this.visibleBoxCurve = Curves.fastOutSlowIn,
14 | this.invisibleBoxCurve = Curves.fastOutSlowIn,
15 | }) : super(listenable: controller);
16 |
17 | final AnimationController controller;
18 | final double width;
19 | final double height;
20 | final Curve visibleBoxCurve;
21 | final Curve invisibleBoxCurve;
22 | final Animation? visibleBoxAnimation;
23 | final Animation? invisibleBoxAnimation;
24 |
25 | Animation get _visibleAnimation =>
26 | visibleBoxAnimation ??
27 | Tween(begin: 0, end: width - (_hiddenFactor * 2)).animate(
28 | CurvedAnimation(
29 | parent: controller,
30 | curve: Interval(0, 0.5, curve: visibleBoxCurve),
31 | ),
32 | );
33 |
34 | Animation get _invisibleAnimation =>
35 | Tween(begin: 0, end: width).animate(
36 | CurvedAnimation(
37 | parent: controller,
38 | curve: Interval(0.5, 1.0, curve: invisibleBoxCurve),
39 | ),
40 | );
41 |
42 | @override
43 | Widget build(BuildContext context) {
44 | return SizedBox(
45 | width: width,
46 | height: height,
47 | child: Stack(
48 | children: [
49 | Positioned(
50 | top: _hiddenFactor,
51 | left: _hiddenFactor,
52 | child: Container(
53 | width: (_visibleAnimation.value > (_hiddenFactor * 2))
54 | ? _visibleAnimation.value - (_hiddenFactor * 2)
55 | : _visibleAnimation.value,
56 | height: height - (_hiddenFactor * 2),
57 | color: controller.isCompleted
58 | ? Colors.transparent
59 | : Theme.of(context).textTheme.bodyText1?.color,
60 | ),
61 | ),
62 | Positioned(
63 | top: 0,
64 | child: Container(
65 | width: controller.isCompleted ? 0 : _invisibleAnimation.value,
66 | height: controller.isCompleted ? 0 : height,
67 | color: controller.isCompleted
68 | ? Colors.transparent
69 | : Theme.of(context).scaffoldBackgroundColor,
70 | ),
71 | ),
72 | ],
73 | ),
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/main_menu.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/data/datasources/datasources.dart';
3 | import 'package:lazycatlabs/presentation/presentation.dart';
4 | import 'package:lazycatlabs/utils/utils.dart';
5 |
6 | class MainMenu extends StatefulWidget {
7 | const MainMenu({
8 | super.key,
9 | required this.listMenu,
10 | required this.scrollController,
11 | required this.duration,
12 | });
13 |
14 | final List listMenu;
15 | final ScrollController scrollController;
16 | final int duration;
17 |
18 | @override
19 | State createState() => _MainMenuState();
20 | }
21 |
22 | class _MainMenuState extends State {
23 | @override
24 | Widget build(BuildContext context) {
25 | return Row(
26 | mainAxisAlignment: MainAxisAlignment.end,
27 | children: widget.listMenu.asMap().entries.map((e) {
28 | return Padding(
29 | padding: EdgeInsets.symmetric(horizontal: Dimens.space10),
30 | child: Row(
31 | children: [
32 | AnimatedOpacity(
33 | opacity: e.value.isSelected ? 1 : 0,
34 | duration: Duration(milliseconds: widget.duration),
35 | child: Row(
36 | children: [
37 | CircleAvatar(
38 | backgroundColor: Palette.primary,
39 | radius: Dimens.space2,
40 | ),
41 | SpacerH(value: Dimens.space2),
42 | ],
43 | ),
44 | ),
45 | AnimatedTextStrikethrough(
46 | text: e.value.title ?? "",
47 | textStyle: Theme.of(context).textTheme.bodyText1!,
48 | textStyleHover: Theme.of(context)
49 | .textTheme
50 | .bodyText1!
51 | .copyWith(fontWeight: FontWeight.w500),
52 | duration: Duration(milliseconds: widget.duration),
53 | onTap: () {
54 | setState(() {
55 | for (final item in widget.listMenu) {
56 | item.isSelected = false;
57 | }
58 | e.value.isSelected = true;
59 |
60 | widget.scrollController.animateTo(
61 | e.key * (context.heightInPercent(100)),
62 | duration: Duration(milliseconds: widget.duration),
63 | curve: Curves.linear,
64 | );
65 | });
66 | },
67 | )
68 | ],
69 | ),
70 | );
71 | }).toList(),
72 | );
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/scroll_indicator.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ScrollIndicator extends StatefulWidget {
4 | final ScrollController scrollController;
5 | final PageController pageController;
6 | final double width;
7 | final double height;
8 | final double indicatorWidth;
9 | final Decoration decoration;
10 | final Decoration indicatorDecoration;
11 | final AlignmentGeometry alignment;
12 |
13 | const ScrollIndicator({
14 | required this.scrollController,
15 | required this.pageController,
16 | this.width = 100,
17 | this.height = 10,
18 | this.indicatorWidth = 20,
19 | this.decoration = const BoxDecoration(color: Colors.black26),
20 | this.indicatorDecoration = const BoxDecoration(color: Colors.black),
21 | this.alignment = Alignment.center,
22 | });
23 |
24 | @override
25 | _ScrollIndicatorState createState() => _ScrollIndicatorState();
26 | }
27 |
28 | class _ScrollIndicatorState extends State {
29 | double currentPixels = 0.0;
30 | double mainContainer = 0.0;
31 | double move = 0.0;
32 |
33 | @override
34 | void initState() {
35 | widget.scrollController.addListener(() {
36 | _scrollListener();
37 | });
38 | widget.pageController.addListener(() {
39 | _pageListener();
40 | });
41 | super.initState();
42 | }
43 |
44 | void _scrollListener() {
45 | setState(() {
46 | currentPixels = widget.scrollController.position.pixels;
47 | mainContainer =
48 | widget.scrollController.position.maxScrollExtent / widget.width;
49 | move = currentPixels / mainContainer;
50 | });
51 | }
52 |
53 | void _pageListener() {
54 | setState(() {
55 | currentPixels = widget.pageController.position.pixels;
56 | mainContainer =
57 | widget.pageController.position.maxScrollExtent / widget.width;
58 | move = currentPixels / mainContainer;
59 | });
60 | }
61 |
62 | @override
63 | Widget build(BuildContext context) {
64 | return Align(
65 | alignment: widget.alignment,
66 | child: Container(
67 | height: widget.height,
68 | width: widget.width + widget.indicatorWidth,
69 | decoration: widget.decoration,
70 | child: Stack(
71 | fit: StackFit.expand,
72 | children: [
73 | AnimatedPositioned(
74 | duration: const Duration(milliseconds: 300),
75 | left: move,
76 | child: Container(
77 | height: widget.height,
78 | width: widget.indicatorWidth,
79 | decoration: widget.indicatorDecoration,
80 | ),
81 | ),
82 | ],
83 | ),
84 | ),
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/lib/presentation/resources/palette.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | // 100% — FF ## 50% — 80
4 | // 99% — FC ## 49% — 7D
5 | // 98% — FA ## 48% — 7A
6 | // 97% — F7 ## 47% — 78
7 | // 96% — F5 ## 46% — 75
8 | // 95% — F2 ## 45% — 73
9 | // 94% — F0 ## 44% — 70
10 | // 93% — ED ## 43% — 6E
11 | // 92% — EB ## 42% — 6B
12 | // 91% — E8 ## 41% — 69
13 | // 90% — E6 ## 40% — 66
14 | // 89% — E3 ## 39% — 63
15 | // 88% — E0 ## 38% — 61
16 | // 87% — DE ## 37% — 5E
17 | // 86% — DB ## 36% — 5C
18 | // 85% — D9 ## 35% — 59
19 | // 84% — D6 ## 34% — 57
20 | // 83% — D4 ## 33% — 54
21 | // 82% — D1 ## 32% — 52
22 | // 81% — CF ## 31% — 4F
23 | // 80% — CC ## 30% — 4D
24 | // 79% — C9 ## 29% — 4A
25 | // 78% — C7 ## 28% — 47
26 | // 77% — C4 ## 27% — 45
27 | // 76% — C2 ## 26% — 42
28 | // 75% — BF ## 25% — 40
29 | // 74% — BD ## 24% — 3D
30 | // 73% — BA ## 23% — 3B
31 | // 72% — B8 ## 22% — 38
32 | // 71% — B5 ## 21% — 36
33 | // 70% — B3 ## 20% — 33
34 | // 69% — B0 ## 19% — 30
35 | // 68% — AD ## 18% — 2E
36 | // 67% — AB ## 17% — 2B
37 | // 66% — A8 ## 16% — 29
38 | // 65% — A6 ## 15% — 26
39 | // 64% — A3 ## 14% — 24
40 | // 63% — A1 ## 13% — 21
41 | // 62% — 9E ## 12% — 1F
42 | // 61% — 9C ## 11% — 1C
43 | // 60% — 99 ## 10% — 1A
44 | // 59% — 96 ## 9% — 17
45 | // 58% — 94 ## 8% — 14
46 | // 57% — 91 ## 7% — 12
47 | // 56% — 8F ## 6% — 0F
48 | // 55% — 8C ## 5% — 0D
49 | // 54% — 8A ## 4% — 0A
50 | // 53% — 87 ## 3% — 08
51 | // 52% — 85 ## 2% — 05
52 | // 51% — 82 ## 1% — 03
53 |
54 | class Palette {
55 | Palette._();
56 |
57 | static const Color primary = Color(0xffE18925);
58 | static const Color primaryLight = Color(0xffF7B553);
59 | static const Color darkBackground = Color(0xff18191A);
60 | static const Color darkCard = Color(0xff242526);
61 | static const Color accent = primary;
62 | static const Color white = Color(0xffffffff);
63 | static const Color offWhite = Color(0xfff3f3f3);
64 | static const Color background = white;
65 | static const Color text = Color(0xff303030);
66 | static const Color textAlt = Color(0xff3D3D3D);
67 | static const Color hint = Color(0xff7E7E7E);
68 | static const Color disable = Color(0xffC4C4C4);
69 | static const Color red = Color(0xffED6464);
70 | static const Color divider = Color(0xffE0E0E0);
71 | static const Color yellow = Color(0xffF7BD00);
72 | static const Color green = Color(0xff27AE60);
73 | static const Color black10 = Color(0x1A000000);
74 | static const Color black15 = Color(0x26000000);
75 | static const Color black20 = Color(0x33000000);
76 | static const Color black25 = Color(0x40000000);
77 | static const Color black = Color(0xFF000000);
78 | static const Color linkedIn = Color(0xFF0e76a8);
79 | static const Color facebook = Color(0xff3b5998);
80 | static const Color youtube = Color(0xffc4302b);
81 | }
82 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/animated_widget_slider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | const double _hiddenFactor = 2;
4 |
5 | class AnimatedWidgetSlider extends AnimatedWidget {
6 | const AnimatedWidgetSlider({
7 | super.key,
8 | required this.controller,
9 | required this.width,
10 | required this.height,
11 | this.visibleBoxAnimation,
12 | this.invisibleBoxAnimation,
13 | this.visibleBoxCurve = Curves.fastOutSlowIn,
14 | this.invisibleBoxCurve = Curves.fastOutSlowIn,
15 | this.boxShape = BoxShape.rectangle,
16 | }) : super(listenable: controller);
17 |
18 | final AnimationController controller;
19 | final double width;
20 | final double height;
21 | final Curve visibleBoxCurve;
22 | final Curve invisibleBoxCurve;
23 | final Animation? visibleBoxAnimation;
24 | final Animation? invisibleBoxAnimation;
25 | final BoxShape boxShape;
26 |
27 | Animation get _visibleAnimation =>
28 | visibleBoxAnimation ??
29 | Tween(begin: 0, end: width - (_hiddenFactor * 2)).animate(
30 | CurvedAnimation(
31 | parent: controller,
32 | curve: Interval(0, 0.5, curve: visibleBoxCurve),
33 | ),
34 | );
35 |
36 | Animation get _invisibleAnimation =>
37 | Tween(begin: 0, end: width).animate(
38 | CurvedAnimation(
39 | parent: controller,
40 | curve: Interval(0.5, 1.0, curve: invisibleBoxCurve),
41 | ),
42 | );
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | return SizedBox(
47 | width: width,
48 | height: height,
49 | child: Stack(
50 | children: [
51 | Positioned(
52 | top: _hiddenFactor,
53 | left: _hiddenFactor,
54 | child: Container(
55 | width: (_visibleAnimation.value > (_hiddenFactor * 2))
56 | ? _visibleAnimation.value - (_hiddenFactor * 2)
57 | : _visibleAnimation.value,
58 | height: height - (_hiddenFactor * 2),
59 | decoration: BoxDecoration(
60 | shape: boxShape,
61 | color: controller.isCompleted
62 | ? Colors.transparent
63 | : Theme.of(context).textTheme.bodyText1?.color,
64 | ),
65 | ),
66 | ),
67 | Positioned(
68 | top: 0,
69 | child: Container(
70 | width: _invisibleAnimation.value,
71 | height: height,
72 | decoration: BoxDecoration(
73 | shape: boxShape,
74 | color: controller.isCompleted
75 | ? Colors.transparent
76 | : Theme.of(context).scaffoldBackgroundColor,
77 | ),
78 | ),
79 | ),
80 | ],
81 | ),
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/assets/images/ic_logo.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/profile/profile_section.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 | import 'package:lazycatlabs/utils/utils.dart';
4 | import 'package:visibility_detector/visibility_detector.dart';
5 |
6 | class ProfileSection extends StatefulWidget {
7 | const ProfileSection({
8 | super.key,
9 | required this.isVisible,
10 | });
11 |
12 | final Function(bool) isVisible;
13 |
14 | @override
15 | State createState() => _ProfileSectionState();
16 | }
17 |
18 | class _ProfileSectionState extends State
19 | with TickerProviderStateMixin {
20 | bool? _temp;
21 | bool _isVisible = true;
22 | bool _isFirst = true;
23 | final int _visibilityPercent = 50;
24 |
25 | late final AnimationController _animationController = AnimationController(
26 | vsync: this,
27 | duration: durationLong,
28 | );
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | return SliverToBoxAdapter(
33 | child: VisibilityDetector(
34 | key: const Key("profile"),
35 | onVisibilityChanged: (VisibilityInfo info) {
36 | final visiblePercentage = info.visibleFraction * 100;
37 |
38 | if (_temp == null) {
39 | _temp = visiblePercentage > _visibilityPercent;
40 | widget.isVisible(_temp ?? true);
41 | setState(() {
42 | _isVisible = _temp ?? true;
43 | });
44 | } else {
45 | if (_temp != visiblePercentage.isVisible()) {
46 | _temp = visiblePercentage > _visibilityPercent;
47 | widget.isVisible(_temp ?? true);
48 | setState(() {
49 | _isVisible = _temp ?? true;
50 | });
51 | }
52 | }
53 |
54 | if (_isVisible && _isFirst) {
55 | _animationController.forward();
56 | _isFirst = false;
57 | }
58 | },
59 | child: ConstrainedBox(
60 | constraints: BoxConstraints(
61 | minWidth: context.widthInPercent(100),
62 | minHeight: context.heightInPercent(100),
63 | ),
64 | child: Column(
65 | mainAxisAlignment: MainAxisAlignment.center,
66 | crossAxisAlignment: CrossAxisAlignment.start,
67 | mainAxisSize: MainAxisSize.min,
68 | children: [
69 | Center(
70 | child: ProfileTitle(animationController: _animationController),
71 | ),
72 | SpacerV(
73 | value: responsiveSize(
74 | context,
75 | Dimens.space16,
76 | Dimens.space50,
77 | tablet: Dimens.space30,
78 | ),
79 | ),
80 | ProfileDescription(animationController: _animationController),
81 | SpacerV(value: Dimens.space100),
82 | ],
83 | ),
84 | ),
85 | ),
86 | );
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/portfolio/portfolio_section.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 | import 'package:lazycatlabs/utils/utils.dart';
4 | import 'package:visibility_detector/visibility_detector.dart';
5 |
6 | class PortfolioSection extends StatefulWidget {
7 | const PortfolioSection({
8 | super.key,
9 | required this.isVisible,
10 | });
11 |
12 | final Function(bool) isVisible;
13 |
14 | @override
15 | State createState() => _PortfolioSectionState();
16 | }
17 |
18 | class _PortfolioSectionState extends State
19 | with TickerProviderStateMixin {
20 | bool? _temp;
21 | bool _isVisible = true;
22 | bool _isFirst = true;
23 | final int _visibilityPercent = 50;
24 | late final AnimationController _animationController = AnimationController(
25 | vsync: this,
26 | duration: durationLong,
27 | );
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return SliverToBoxAdapter(
32 | child: VisibilityDetector(
33 | key: const Key("portfolio"),
34 | onVisibilityChanged: (VisibilityInfo info) {
35 | final visiblePercentage = info.visibleFraction * 100;
36 |
37 | if (_temp == null) {
38 | _temp = visiblePercentage > _visibilityPercent;
39 | widget.isVisible(_temp ?? true);
40 | setState(() {
41 | _isVisible = _temp ?? true;
42 | });
43 | } else {
44 | if (_temp != visiblePercentage > _visibilityPercent) {
45 | _temp = visiblePercentage > _visibilityPercent;
46 | widget.isVisible(_temp ?? true);
47 | setState(() {
48 | _isVisible = _temp ?? true;
49 | });
50 | }
51 | }
52 |
53 | if (_isVisible && _isFirst) {
54 | _animationController.forward();
55 | _isFirst = false;
56 | }
57 | // log.d('Widget ${info.key} is $visiblePercentage% visible');
58 | },
59 | child: ConstrainedBox(
60 | constraints: BoxConstraints(
61 | minWidth: context.widthInPercent(100),
62 | minHeight: context.heightInPercent(100),
63 | ),
64 | child: Column(
65 | mainAxisAlignment: MainAxisAlignment.center,
66 | crossAxisAlignment: CrossAxisAlignment.start,
67 | mainAxisSize: MainAxisSize.min,
68 | children: [
69 | Center(
70 | child:
71 | PortfolioTitle(animationController: _animationController),
72 | ),
73 | SpacerV(
74 | value: responsiveSize(context, Dimens.space2, Dimens.space8),
75 | ),
76 | PortfolioDescription(
77 | animationController: _animationController,
78 | ),
79 | SpacerV(value: Dimens.space100),
80 | ],
81 | ),
82 | ),
83 | ),
84 | );
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/responsive.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../utils/utils.dart';
4 |
5 | enum DisplayType {
6 | desktop,
7 | tablet,
8 | mobile,
9 | }
10 |
11 | class Responsive extends StatelessWidget {
12 | const Responsive({
13 | super.key,
14 | required this.builder,
15 | });
16 |
17 | final Widget Function(
18 | BuildContext context,
19 | BoxConstraints constraints,
20 | ) builder;
21 |
22 | static DisplayType displayTypeOf(BuildContext context) {
23 | final width = MediaQuery.of(context).size.width;
24 | if (width >= const RefinedBreakpoints().desktopNormal) {
25 | return DisplayType.desktop;
26 | } else if (width >= const RefinedBreakpoints().tabletNormal) {
27 | return DisplayType.tablet;
28 | } else {
29 | return DisplayType.mobile;
30 | }
31 | }
32 |
33 | /// Returns a boolean if we are in a display of [DisplayType.desktop]. Used to
34 | /// build adaptive and responsive layouts.
35 | static bool isDesktop(BuildContext context) {
36 | return displayTypeOf(context) == DisplayType.desktop;
37 | }
38 |
39 | /// Returns a boolean if we are in a display of [DisplayType.mobile]. Used to
40 | /// build adaptive and responsive layouts.
41 | static bool isMobile(BuildContext context) {
42 | return displayTypeOf(context) == DisplayType.mobile;
43 | }
44 |
45 | static bool isTablet(BuildContext context) {
46 | return displayTypeOf(context) == DisplayType.tablet;
47 | }
48 |
49 | @override
50 | Widget build(BuildContext context) {
51 | log.d("Display type ${displayTypeOf(context)}");
52 | return LayoutBuilder(
53 | builder: (context, constraints) {
54 | return builder(context, constraints);
55 | },
56 | );
57 | }
58 | }
59 |
60 | class RefinedBreakpoints {
61 | final double mobileSmall;
62 | final double mobileNormal;
63 | final double mobileLarge;
64 | final double mobileExtraLarge;
65 |
66 | final double tabletSmall;
67 | final double tabletNormal;
68 | final double tabletLarge;
69 | final double tabletExtraLarge;
70 |
71 | final double desktopSmall;
72 | final double desktopNormal;
73 | final double desktopLarge;
74 | final double desktopExtraLarge;
75 |
76 | const RefinedBreakpoints({
77 | this.mobileSmall = 320,
78 | this.mobileNormal = 375,
79 | this.mobileLarge = 414,
80 | this.mobileExtraLarge = 480,
81 | this.tabletSmall = 600,
82 | this.tabletNormal = 768,
83 | this.tabletLarge = 850,
84 | this.tabletExtraLarge = 900,
85 | this.desktopSmall = 950,
86 | this.desktopNormal = 1366,
87 | this.desktopLarge = 3840,
88 | this.desktopExtraLarge = 4096,
89 | });
90 |
91 | @override
92 | String toString() {
93 | return "Desktop: Small - $desktopSmall Normal - $desktopNormal Large - $desktopLarge ExtraLarge - $desktopExtraLarge\nTablet: Small - $tabletSmall Normal - $tabletNormal Large - $tabletLarge ExtraLarge - $tabletExtraLarge\nMobile: Small - $mobileSmall Normal - $mobileNormal Large - $mobileLarge ExtraLarge - $mobileExtraLarge";
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/gestures.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/services.dart';
6 | import 'package:flutter_bloc/flutter_bloc.dart';
7 | import 'package:flutter_localizations/flutter_localizations.dart';
8 | import 'package:flutter_web_plugins/flutter_web_plugins.dart';
9 | import 'package:lazycatlabs/core/core.dart';
10 | import 'package:lazycatlabs/data/data.dart';
11 | import 'package:lazycatlabs/di/di.dart';
12 | import 'package:lazycatlabs/presentation/presentation.dart';
13 | import 'package:lazycatlabs/utils/utils.dart';
14 | import 'package:shared_preferences/shared_preferences.dart';
15 |
16 | Future main() async {
17 | /// Register Service locator
18 |
19 | WidgetsFlutterBinding.ensureInitialized();
20 | await serviceLocator();
21 |
22 | runZonedGuarded(
23 | /// Lock device orientation to portrait
24 | () => SystemChrome.setPreferredOrientations(
25 | [
26 | DeviceOrientation.portraitUp,
27 | DeviceOrientation.portraitDown,
28 | ],
29 | ).then((_) async {
30 | /// Load SharedPref before load My App Widget
31 | SharedPreferences.getInstance().then((value) {
32 | initPrefManager(value);
33 | setUrlStrategy(PathUrlStrategy());
34 | runApp(LzyctApp());
35 | });
36 | }),
37 | (error, stackTrace) async {},
38 | );
39 | }
40 |
41 | class LzyctApp extends StatelessWidget {
42 | @override
43 | Widget build(BuildContext context) {
44 | return BlocProvider(
45 | create: (_) => sl(),
46 | child: BlocBuilder(
47 | builder: (context, data) {
48 | /// Pass context to appRoute
49 | AppRoute.setStream(context);
50 |
51 | return MaterialApp.router(
52 | routeInformationProvider: AppRoute.router.routeInformationProvider,
53 | routeInformationParser: AppRoute.router.routeInformationParser,
54 | routerDelegate: AppRoute.router.routerDelegate,
55 | scrollBehavior: const MaterialScrollBehavior().copyWith(
56 | dragDevices: {
57 | PointerDeviceKind.mouse,
58 | PointerDeviceKind.touch,
59 | PointerDeviceKind.stylus,
60 | PointerDeviceKind.unknown
61 | },
62 | ),
63 | localizationsDelegates: const [
64 | Strings.delegate,
65 | GlobalMaterialLocalizations.delegate,
66 | GlobalWidgetsLocalizations.delegate,
67 | GlobalCupertinoLocalizations.delegate,
68 | ],
69 | debugShowCheckedModeBanner: false,
70 | builder: (BuildContext context, Widget? child) {
71 | final MediaQueryData data = MediaQuery.of(context);
72 |
73 | return MediaQuery(
74 | data: data.copyWith(alwaysUse24HourFormat: true),
75 | child: child!,
76 | );
77 | },
78 | title: Constants.get.appName,
79 | theme: themeLight(context),
80 | darkTheme: themeDark(context),
81 | locale: Locale(data.type ?? "en"),
82 | supportedLocales: L10n.all,
83 | useInheritedMediaQuery: true,
84 | themeMode: data.activeTheme.mode,
85 |
86 | /// Check if theme is light or dark first
87 | );
88 | },
89 | ),
90 | );
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/animated_widget_shape.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 |
4 | class AnimatedWidgetShape extends StatefulWidget {
5 | const AnimatedWidgetShape({
6 | super.key,
7 | required this.child,
8 | required this.animationController,
9 | required this.width,
10 | required this.height,
11 | this.visibleAnimationCurve = Curves.fastOutSlowIn,
12 | this.invisibleAnimationCurve = Curves.fastOutSlowIn,
13 | this.slideAnimationCurve = Curves.fastOutSlowIn,
14 | this.visibleBoxAnimation,
15 | this.invisibleBoxAnimation,
16 | this.position,
17 | this.boxShape = BoxShape.rectangle,
18 | });
19 |
20 | final Widget child;
21 | final AnimationController animationController;
22 | final Animation? visibleBoxAnimation;
23 | final Animation? invisibleBoxAnimation;
24 | final Animation? position;
25 | final Curve visibleAnimationCurve;
26 | final Curve invisibleAnimationCurve;
27 | final Curve slideAnimationCurve;
28 | final double width;
29 | final double height;
30 | final BoxShape boxShape;
31 |
32 | @override
33 | State createState() => _AnimatedWidgetShapeState();
34 | }
35 |
36 | class _AnimatedWidgetShapeState extends State
37 | with SingleTickerProviderStateMixin {
38 | late Animation visibleAnimation = widget.visibleBoxAnimation ??
39 | Tween(begin: 0, end: widget.width).animate(
40 | CurvedAnimation(
41 | parent: widget.animationController,
42 | curve: Interval(
43 | 0,
44 | 0.35,
45 | curve: widget.visibleAnimationCurve,
46 | ),
47 | ),
48 | );
49 |
50 | late Animation invisibleAnimation =
51 | invisibleAnimation = widget.invisibleBoxAnimation ??
52 | Tween(begin: 0, end: widget.width).animate(
53 | CurvedAnimation(
54 | parent: widget.animationController,
55 | curve: Interval(
56 | 0.35,
57 | 0.7,
58 | curve: widget.invisibleAnimationCurve,
59 | ),
60 | ),
61 | );
62 |
63 | late final Animation _textPositionAnimation = RelativeRectTween(
64 | begin: RelativeRect.fromSize(
65 | Rect.fromLTWH(0, widget.height, widget.width, widget.height),
66 | Size(widget.width, widget.height),
67 | ),
68 | end: RelativeRect.fromSize(
69 | Rect.fromLTWH(0, 0, widget.width, widget.height),
70 | Size(widget.width, widget.height),
71 | ),
72 | ).animate(
73 | CurvedAnimation(
74 | parent: widget.animationController,
75 | curve: Interval(0.6, 1.0, curve: widget.invisibleAnimationCurve),
76 | ),
77 | );
78 |
79 | @override
80 | Widget build(BuildContext context) {
81 | return SizedBox(
82 | height: widget.height,
83 | child: Stack(
84 | children: [
85 | AnimatedWidgetSlider(
86 | controller: widget.animationController,
87 | width: widget.width,
88 | height: widget.height,
89 | visibleBoxAnimation: visibleAnimation,
90 | invisibleBoxAnimation: invisibleAnimation,
91 | boxShape: widget.boxShape,
92 | ),
93 | PositionedTransition(
94 | rect: _textPositionAnimation,
95 | child: widget.child,
96 | ),
97 | ],
98 | ),
99 | );
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/assets/images/ic_settings.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/assets/images/ic_instagram.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/services/services_section.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/core/core.dart';
3 | import 'package:lazycatlabs/data/data.dart';
4 | import 'package:lazycatlabs/presentation/presentation.dart';
5 | import 'package:lazycatlabs/utils/utils.dart';
6 | import 'package:visibility_detector/visibility_detector.dart';
7 |
8 | class ServicesSection extends StatefulWidget {
9 | const ServicesSection({
10 | super.key,
11 | required this.isVisible,
12 | });
13 |
14 | final Function(bool) isVisible;
15 |
16 | @override
17 | State createState() => _ServicesSectionState();
18 | }
19 |
20 | class _ServicesSectionState extends State
21 | with TickerProviderStateMixin {
22 | bool? _temp;
23 | bool _isVisible = true;
24 | bool _isFirst = true;
25 | final int _visibilityPercent = 50;
26 |
27 | List _listServices = [];
28 | late final AnimationController _animationController = AnimationController(
29 | vsync: this,
30 | duration: durationLong,
31 | );
32 |
33 | @override
34 | void didChangeDependencies() {
35 | super.didChangeDependencies();
36 | _listServices = [
37 | DataHelper(
38 | title: Strings.of(context)!.buildTitle,
39 | desc: Strings.of(context)!.buildDesc,
40 | icon: Icons.build_circle,
41 | ),
42 | DataHelper(
43 | title: Strings.of(context)!.fixTitle,
44 | desc: Strings.of(context)!.fixDesc,
45 | icon: Icons.bug_report_rounded,
46 | ),
47 | DataHelper(
48 | title: Strings.of(context)!.continueTitle,
49 | desc: Strings.of(context)!.continueDesc,
50 | icon: Icons.next_plan,
51 | ),
52 | ];
53 | }
54 |
55 | @override
56 | Widget build(BuildContext context) {
57 | return SliverToBoxAdapter(
58 | child: VisibilityDetector(
59 | key: const Key("services"),
60 | onVisibilityChanged: (VisibilityInfo info) {
61 | final visiblePercentage = info.visibleFraction * 100;
62 |
63 | if (_temp == null) {
64 | _temp = visiblePercentage > _visibilityPercent;
65 | widget.isVisible(_temp ?? true);
66 | setState(() {
67 | _isVisible = _temp ?? true;
68 | });
69 | } else {
70 | if (_temp != visiblePercentage > _visibilityPercent) {
71 | _temp = visiblePercentage > _visibilityPercent;
72 | widget.isVisible(_temp ?? true);
73 | setState(() {
74 | _isVisible = _temp ?? true;
75 | });
76 | }
77 | }
78 |
79 | if (_isVisible && _isFirst) {
80 | _animationController.forward();
81 | _isFirst = false;
82 | }
83 | // log.d('Widget ${info.key} is $visiblePercentage% visible');
84 | },
85 | child: ConstrainedBox(
86 | constraints: BoxConstraints(
87 | minWidth: context.widthInPercent(100),
88 | minHeight: context.heightInPercent(100),
89 | ),
90 | child: Column(
91 | mainAxisAlignment: MainAxisAlignment.center,
92 | crossAxisAlignment: CrossAxisAlignment.start,
93 | mainAxisSize: MainAxisSize.min,
94 | children: [
95 | Center(
96 | child: ServicesTitle(animationController: _animationController),
97 | ),
98 | SpacerV(
99 | value: responsiveSize(context, Dimens.space8, Dimens.space50),
100 | ),
101 | ServicesDescription(
102 | animationController: _animationController,
103 | listServices: _listServices,
104 | ),
105 | SpacerV(value: Dimens.space100),
106 | ],
107 | ),
108 | ),
109 | ),
110 | );
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/animated_text_strikethrough.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/utils/helper/common.dart';
3 |
4 | class AnimatedTextStrikethrough extends StatefulWidget {
5 | const AnimatedTextStrikethrough({
6 | super.key,
7 | required this.text,
8 | required this.textStyle,
9 | required this.textStyleHover,
10 | required this.duration,
11 | this.thickness = 2,
12 | required this.onTap,
13 | });
14 |
15 | final String text;
16 | final TextStyle textStyle;
17 | final TextStyle textStyleHover;
18 | final Duration duration;
19 | final VoidCallback onTap;
20 | final double thickness;
21 |
22 | @override
23 | State createState() =>
24 | _AnimatedTextStrikethroughState();
25 | }
26 |
27 | class _AnimatedTextStrikethroughState extends State
28 | with TickerProviderStateMixin {
29 | late final AnimationController _forwardController =
30 | AnimationController(vsync: this, duration: widget.duration)
31 | ..addListener(() {
32 | setState(() {});
33 | });
34 |
35 | late final AnimationController _backwardController =
36 | AnimationController(vsync: this, duration: widget.duration)
37 | ..addListener(() {
38 | setState(() {});
39 | })
40 | ..addStatusListener((status) {
41 | if (status == AnimationStatus.completed) {
42 | _backwardController.reset();
43 | _forwardController.reset();
44 | }
45 | });
46 |
47 | late final double _textWidth =
48 | textSize(text: widget.text, style: widget.textStyle).width;
49 | late final double _textHeight =
50 | textSize(text: widget.text, style: widget.textStyle).height;
51 |
52 | late final Animation _forwardAnimation =
53 | Tween(begin: 0, end: _textWidth).animate(
54 | CurvedAnimation(parent: _forwardController, curve: Curves.fastOutSlowIn),
55 | );
56 | late final Animation _backwardAnimation =
57 | Tween(begin: 0, end: _textWidth).animate(
58 | CurvedAnimation(parent: _backwardController, curve: Curves.fastOutSlowIn),
59 | );
60 |
61 | bool _isHover = false;
62 |
63 | @override
64 | void dispose() {
65 | _forwardController.dispose();
66 | _backwardController.dispose();
67 | super.dispose();
68 | }
69 |
70 | @override
71 | Widget build(BuildContext context) {
72 | return InkWell(
73 | onTap: widget.onTap.call,
74 | hoverColor: Colors.transparent,
75 | child: MouseRegion(
76 | onEnter: (_) => _onHover(true),
77 | onExit: (_) => _onHover(false),
78 | child: Stack(
79 | children: [
80 | Positioned(
81 | top: (_textHeight / 2) - widget.thickness,
82 | child: Container(
83 | height: widget.thickness,
84 | color: Theme.of(context).textTheme.bodyText1?.color,
85 | width: _forwardAnimation.value,
86 | ),
87 | ),
88 | Positioned(
89 | top: (_textHeight / 2) - widget.thickness,
90 | child: Container(
91 | height: widget.thickness,
92 | color: Theme.of(context).scaffoldBackgroundColor,
93 | width: _backwardAnimation.value,
94 | ),
95 | ),
96 | Text(
97 | widget.text,
98 | style: _isHover ? widget.textStyleHover : widget.textStyle,
99 | ),
100 | ],
101 | ),
102 | ),
103 | );
104 | }
105 |
106 | void _onHover(bool hovering) {
107 | if (hovering) {
108 | setState(() {
109 | _forwardController.forward();
110 | _isHover = hovering;
111 | });
112 | } else {
113 | setState(() {
114 | _backwardController.forward();
115 | _isHover = hovering;
116 | });
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: lazycatlabs
2 | description: Lazycat Labs is a place to share about new tech and programming with a lazy way.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: ">=2.17.1 <3.0.0"
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 | flutter_localizations:
27 | sdk: flutter
28 | flutter_web_plugins:
29 | sdk: flutter
30 |
31 | # Use as default SVG image loader, prefer use SVG as image asset
32 | flutter_svg: ^1.1.6
33 |
34 | # Use as sharedPreferences to save local data
35 | shared_preferences: ^2.0.15
36 |
37 | # Use for Dependencies Injection
38 | get_it: ^7.2.0
39 |
40 | # Use for State Management with BLoC pattern
41 | flutter_bloc: ^8.1.1
42 | equatable: ^2.0.5
43 |
44 | # Use for Time/Date Format
45 | intl: ^0.17.0
46 |
47 | # Use as path reader for Android and iOS
48 | path_provider: ^2.0.11
49 |
50 | # Use for request permission
51 | cached_network_image: ^3.2.2
52 |
53 | # logger
54 | logger: ^1.1.0
55 |
56 | # router
57 | go_router: ^5.1.1
58 |
59 | url_launcher: ^6.1.6
60 | visibility_detector: ^0.3.3
61 |
62 | google_fonts: ^3.0.1
63 |
64 | dev_dependencies:
65 | flutter_test:
66 | sdk: flutter
67 | flutter_launcher_icons: ^0.10.0
68 | lint: ^1.10.0
69 |
70 |
71 | # For information on the generic Dart part of this file, see the
72 | # following page: https://dart.dev/tools/pub/pubspec
73 |
74 | # The following section is specific to Flutter.
75 | flutter:
76 | # The following line ensures that the Material Icons font is
77 | # included with your application, so that you can use the icons in
78 | # the material Icons class.
79 | uses-material-design: true
80 |
81 | # To add assets to your application, add an assets section, like this:
82 | assets:
83 | - assets/images/
84 | - assets/images/portfolio/oifyoo/
85 | - assets/images/portfolio/eabsensi/
86 | - assets/images/portfolio/brupedia/
87 | - assets/images/portfolio/myananda/
88 | - assets/images/portfolio/patapaowners/
89 | - assets/images/portfolio/pataparking/
90 | - assets/images/portfolio/wautils/
91 | - assets/static_api/
92 |
93 | fonts:
94 | - family: VisueltPro
95 | fonts:
96 | - asset: assets/fonts/visuelt/VisueltPro-Thin.ttf
97 | weight: 100
98 | - asset: assets/fonts/visuelt/VisueltPro-ExtraLight.ttf
99 | weight: 200
100 | - asset: assets/fonts/visuelt/VisueltPro-Light.ttf
101 | weight: 300
102 | - asset: assets/fonts/visuelt/VisueltPro-Regular.ttf
103 | weight: 400
104 | - asset: assets/fonts/visuelt/VisueltPro-Medium.ttf
105 | weight: 500
106 | - asset: assets/fonts/visuelt/VisueltPro-Black.ttf
107 | weight: 700
108 | - asset: assets/fonts/visuelt/VisueltPro-Bold.ttf
109 | weight: 800
110 | #
111 | # For details regarding fonts from package dependencies,
112 | # see https://flutter.dev/custom-fonts/#from-packages
113 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/animated_text_box.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 | import 'package:lazycatlabs/utils/helper/common.dart';
4 |
5 | class AnimatedTextBox extends StatefulWidget {
6 | const AnimatedTextBox({
7 | super.key,
8 | required this.text,
9 | required this.textStyle,
10 | required this.animationController,
11 | this.maxLines = 1,
12 | this.widthFactor = 1,
13 | this.heightFactor = 1,
14 | this.width = double.infinity,
15 | this.visibleAnimationCurve = Curves.fastOutSlowIn,
16 | this.invisibleAnimationCurve = Curves.fastOutSlowIn,
17 | this.slideAnimationCurve = Curves.fastOutSlowIn,
18 | this.visibleBoxAnimation,
19 | this.invisibleBoxAnimation,
20 | this.position,
21 | this.textAlign,
22 | });
23 |
24 | final String text;
25 | final TextStyle textStyle;
26 | final AnimationController animationController;
27 | final Animation? visibleBoxAnimation;
28 | final Animation? invisibleBoxAnimation;
29 | final Animation? position;
30 | final Curve visibleAnimationCurve;
31 | final Curve invisibleAnimationCurve;
32 | final Curve slideAnimationCurve;
33 | final double width;
34 | final int maxLines;
35 | final double heightFactor;
36 | final double widthFactor;
37 | final TextAlign? textAlign;
38 |
39 | @override
40 | State createState() => _AnimatedTextBoxState();
41 | }
42 |
43 | class _AnimatedTextBoxState extends State
44 | with SingleTickerProviderStateMixin {
45 | late final Size _size = textSize(
46 | text: widget.text,
47 | style: widget.textStyle,
48 | maxWidth: widget.width,
49 | maxLines: widget.maxLines,
50 | );
51 | late final double _textWidth = _size.width * widget.widthFactor;
52 |
53 | late final double _textHeight = _size.height * widget.heightFactor;
54 |
55 | late Animation visibleAnimation = widget.visibleBoxAnimation ??
56 | Tween(begin: 0, end: _textWidth).animate(
57 | CurvedAnimation(
58 | parent: widget.animationController,
59 | curve: Interval(
60 | 0,
61 | 0.35,
62 | curve: widget.visibleAnimationCurve,
63 | ),
64 | ),
65 | );
66 |
67 | late Animation invisibleAnimation =
68 | invisibleAnimation = widget.invisibleBoxAnimation ??
69 | Tween(begin: 0, end: _textWidth).animate(
70 | CurvedAnimation(
71 | parent: widget.animationController,
72 | curve: Interval(
73 | 0.35,
74 | 0.7,
75 | curve: widget.invisibleAnimationCurve,
76 | ),
77 | ),
78 | );
79 |
80 | late final Animation _textPositionAnimation = RelativeRectTween(
81 | begin: RelativeRect.fromSize(
82 | Rect.fromLTWH(0, _textHeight, _textWidth, _textHeight),
83 | Size(_textWidth, _textHeight),
84 | ),
85 | end: RelativeRect.fromSize(
86 | Rect.fromLTWH(0, 0, _textWidth, _textHeight),
87 | Size(_textWidth, _textHeight),
88 | ),
89 | ).animate(
90 | CurvedAnimation(
91 | parent: widget.animationController,
92 | curve: Interval(0.6, 1.0, curve: widget.invisibleAnimationCurve),
93 | ),
94 | );
95 |
96 | @override
97 | Widget build(BuildContext context) {
98 | return SizedBox(
99 | height: _textHeight,
100 | child: Stack(
101 | children: [
102 | AnimatedBoxSlider(
103 | controller: widget.animationController,
104 | width: _textWidth,
105 | height: _textHeight,
106 | visibleBoxAnimation: visibleAnimation,
107 | invisibleBoxAnimation: invisibleAnimation,
108 | ),
109 | PositionedTransition(
110 | rect: _textPositionAnimation,
111 | child: Text(
112 | widget.text,
113 | style: widget.textStyle,
114 | textAlign: widget.textAlign,
115 | ),
116 | ),
117 | ],
118 | ),
119 | );
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/lib/presentation/pages/main/profile/profile_description.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/core/core.dart';
3 | import 'package:lazycatlabs/data/datasources/datasources.dart';
4 | import 'package:lazycatlabs/di/di.dart';
5 | import 'package:lazycatlabs/presentation/presentation.dart';
6 | import 'package:lazycatlabs/utils/utils.dart';
7 |
8 | class ProfileDescription extends StatelessWidget {
9 | const ProfileDescription({super.key, required this.animationController});
10 |
11 | final AnimationController animationController;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return Padding(
16 | padding: EdgeInsets.symmetric(
17 | horizontal: responsiveSize(
18 | context,
19 | Dimens.space24,
20 | context.widthInPercent(15),
21 | tablet: context.widthInPercent(13),
22 | ),
23 | ),
24 | child: Stack(
25 | children: [
26 | Positioned(
27 | left: responsiveSize(
28 | context,
29 | Dimens.space50,
30 | Dimens.space120,
31 | tablet: Dimens.space72,
32 | ),
33 | top: responsiveSize(context, -10, -40, tablet: -20),
34 | child: Icon(
35 | Icons.format_quote,
36 | color: Theme.of(context).cardColor,
37 | size: responsiveSize(
38 | context,
39 | Dimens.space50,
40 | Dimens.space150,
41 | tablet: Dimens.space72,
42 | ),
43 | ),
44 | ),
45 | Column(
46 | crossAxisAlignment: CrossAxisAlignment.start,
47 | mainAxisSize: MainAxisSize.min,
48 | children: [
49 | AnimatedTextBox(
50 | text: Strings.of(context)!.hello,
51 | textStyle: Theme.of(context).textTheme.headline1!.copyWith(
52 | fontSize: responsiveSize(
53 | context,
54 | Dimens.space36,
55 | Dimens.h1,
56 | tablet: Dimens.h3,
57 | ),
58 | ),
59 | animationController: animationController,
60 | ),
61 | AnimatedWidgetShape(
62 | animationController: animationController,
63 | width: context.widthInPercent(100),
64 | height: responsiveSize(
65 | context,
66 | Dimens.space200,
67 | Dimens.space150,
68 | tablet: Dimens.space120,
69 | ),
70 | child: RichText(
71 | text: TextSpan(
72 | text: Strings.of(context)!.profileTitle,
73 | style: Theme.of(context).textTheme.bodyText1!.copyWith(
74 | fontSize: responsiveSize(
75 | context,
76 | Dimens.body1,
77 | Dimens.h6,
78 | ),
79 | fontWeight: FontWeight.w500,
80 | ),
81 | children: [
82 | TextSpan(
83 | text: Strings.of(context)!.profileDesc,
84 | style: Theme.of(context).textTheme.bodyText1!.copyWith(
85 | fontSize: responsiveSize(
86 | context,
87 | Dimens.body2,
88 | Dimens.space17,
89 | ),
90 | ),
91 | )
92 | ],
93 | ),
94 | textAlign: TextAlign.justify,
95 | ),
96 | ),
97 | if (sl().locale != "en")
98 | SpacerV(value: Dimens.space16),
99 | AnimatedWidgetShape(
100 | width: Dimens.space250,
101 | height: Dimens.space24,
102 | animationController: animationController,
103 | child: const ProfileButton(),
104 | ),
105 | ],
106 | ),
107 | ],
108 | ),
109 | );
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/lib/presentation/widgets/animated_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:lazycatlabs/presentation/presentation.dart';
3 |
4 | ///*********************************************
5 | /// Created by ukieTux on 23/04/2020 with ♥
6 | /// (>’_’)> email : ukie.tux@gmail.com
7 | /// github : https://www.github.com/Lzyct <(’_’<)
8 | ///*********************************************
9 | /// © 2020 | All Right Reserved
10 | class Button extends StatefulWidget {
11 | final String title;
12 | final VoidCallback onPressed;
13 | final double? startWidth;
14 | final double targetWidth;
15 | final double height;
16 | final Color? color;
17 | final Color? titleColor;
18 | final double? fontSize;
19 | final Color? splashColor;
20 | final Offset startOffset;
21 | final Offset targetOffset;
22 | final Widget? child;
23 | final Duration duration;
24 | final BorderRadiusGeometry startBorderRadius;
25 | final BorderRadiusGeometry? endBorderRadius;
26 |
27 | const Button({
28 | super.key,
29 | required this.title,
30 | required this.onPressed,
31 | this.titleColor,
32 | this.fontSize,
33 | this.splashColor,
34 | this.startOffset = Offset.zero,
35 | this.targetOffset = const Offset(0.1, 0),
36 | this.startWidth = 45,
37 | this.targetWidth = 150,
38 | this.height = 45,
39 | this.child,
40 | this.duration = const Duration(
41 | milliseconds: 300,
42 | ),
43 | this.startBorderRadius =
44 | const BorderRadius.all(Radius.circular(Dimens.cornerButton)),
45 | this.endBorderRadius,
46 | this.color,
47 | });
48 |
49 | @override
50 | State