├── .github └── workflows │ └── flutter_web.yaml ├── .gitignore ├── .metadata ├── .vscode └── launch.json ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── br │ │ │ │ └── com │ │ │ │ └── toshiossada │ │ │ │ └── homepage │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── experiences.json ├── experiences_enUs.json ├── images │ ├── awards │ │ ├── dart.png │ │ ├── flutter.png │ │ ├── gde.png │ │ └── mvp.png │ ├── favicon.png │ ├── flutterbrasil │ │ ├── dash.png │ │ └── flutter_br.png │ ├── icons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ └── logo.png │ ├── logo_toshi.png │ ├── meia_entrada.png │ └── toshi.png └── lang │ ├── en_US.json │ └── pt_BR.json ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── app │ └── modules │ │ └── home │ │ ├── data │ │ ├── datasource │ │ │ └── experience_datasource_impl.dart │ │ ├── mappers │ │ │ └── experience_mapper.dart │ │ └── repositories │ │ │ ├── datasources │ │ │ └── experience_datasource.dart │ │ │ ├── experience_repository_impl.dart │ │ │ └── models │ │ │ └── experience_model.dart │ │ ├── domain │ │ ├── entities │ │ │ └── experience_entity.dart │ │ ├── interfaces │ │ │ └── experience_repository.dart │ │ └── usecases │ │ │ └── get_experiences_usecase.dart │ │ ├── home_module.dart │ │ └── pages │ │ ├── about │ │ ├── about_page.dart │ │ └── widget │ │ │ ├── avatar_widget.dart │ │ │ ├── awards_widget.dart │ │ │ └── info_widget.dart │ │ ├── carrer │ │ ├── carrer_controller.dart │ │ ├── carrer_page.dart │ │ └── carrer_store.dart │ │ ├── contacts │ │ ├── contact_page.dart │ │ └── widgets │ │ │ └── contact_tile_widget.dart │ │ ├── dne │ │ ├── dne_module.dart │ │ └── pages │ │ │ ├── dne_page.dart │ │ │ └── widegets │ │ │ ├── app_bar_widget.dart │ │ │ ├── certificate.dart │ │ │ ├── detail_row_widget.dart │ │ │ ├── info_widget.dart │ │ │ ├── link_widget.dart │ │ │ └── valid_widget.dart │ │ ├── generator │ │ └── experiences_pages.dart │ │ ├── initial │ │ ├── initial_page.dart │ │ └── initial_page_controller.dart │ │ └── widgets │ │ ├── contact_widget.dart │ │ └── social_button_widget.dart ├── app_module.dart ├── app_store.dart ├── app_widget.dart ├── core_module.dart └── main.dart ├── pubspec.lock ├── pubspec.yaml ├── test └── widget_test.dart ├── web ├── favicon.ico ├── favicon.png ├── icons │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── android-icon-144x144.png │ ├── android-icon-192x192.png │ ├── android-icon-36x36.png │ ├── android-icon-48x48.png │ ├── android-icon-72x72.png │ ├── android-icon-96x96.png │ ├── apple-icon-114x114.png │ ├── apple-icon-120x120.png │ ├── apple-icon-144x144.png │ ├── apple-icon-152x152.png │ ├── apple-icon-180x180.png │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── apple-icon-precomposed.png │ ├── apple-icon.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── favicon.ico │ ├── manifest.json │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ └── ms-icon-70x70.png ├── index.html ├── logo.png ├── manifest.json └── style.css └── windows ├── .gitignore ├── CMakeLists.txt ├── flutter ├── CMakeLists.txt ├── generated_plugin_registrant.cc ├── generated_plugin_registrant.h └── generated_plugins.cmake └── runner ├── CMakeLists.txt ├── Runner.rc ├── flutter_window.cpp ├── flutter_window.h ├── main.cpp ├── resource.h ├── resources └── app_icon.ico ├── runner.exe.manifest ├── utils.cpp ├── utils.h ├── win32_window.cpp └── win32_window.h /.github/workflows/flutter_web.yaml: -------------------------------------------------------------------------------- 1 | name: Flutter Web 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | env: 11 | TESTE3: "21" 12 | CNAME: ${{ vars.CNAME }} 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v1 18 | 19 | - name: Setup Flutter 20 | uses: subosito/flutter-action@v1 21 | with: 22 | channel: "stable" 23 | 24 | - name: Install dependencies 25 | run: flutter pub get 26 | 27 | - name: Build Web 28 | run: flutter build web --release 29 | 30 | - name: Deploy 31 | run: | 32 | cd build/web 33 | echo '${{ env.CNAME }}' > CNAME 34 | git init 35 | git config --global user.email toshiossada@gmail.com 36 | git config --global user.name toshiossada 37 | git status 38 | git remote add origin https://${{secrets.token}}@github.com/toshiossada/toshiossada.github.io.git 39 | git checkout -b gh-pages 40 | git add --all 41 | git commit -m "update" 42 | git push origin gh-pages -f 43 | -------------------------------------------------------------------------------- /.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 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 18116933e77adc82f80866c928266a5b4f1ed645 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "name": "flutter_web_site", 10 | "request": "launch", 11 | "type": "dart" 12 | }, 13 | { 14 | "name": "flutter_web_site (profile mode)", 15 | "request": "launch", 16 | "type": "dart", 17 | "flutterMode": "profile" 18 | }, 19 | { 20 | "name": "flutter_web_site (release mode)", 21 | "request": "launch", 22 | "type": "dart", 23 | "flutterMode": "release" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # homepage 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | # flutter_web_site 18 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 30 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "br.com.toshiossada.homepage" 47 | minSdkVersion flutter.minSdkVersion 48 | targetSdkVersion 30 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/br/com/toshiossada/homepage/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package br.com.toshiossada.homepage 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | tasks.register("clean", Delete) { 28 | delete rootProject.layout.buildDirectory 29 | } 30 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /assets/experiences.json: -------------------------------------------------------------------------------- 1 | { 2 | "experiences": [ 3 | { 4 | "company": "FARMÁCIAS APP By GrupoSC", 5 | "start": "03/2024", 6 | "end": null, 7 | "role": "Líder Técnico Mobile ", 8 | "description": [ 9 | "Liderança da equipe de desenvolvimento no projeto de aplicativo da Farmácias APP, atuando na distribuição e definição de tarefas e prioridades de desenvolvimento, acompanhando o progresso da equipe e garantindo a entrega dos prazos acordados, realizando reuniões de alinhamento e planejamento junto a equipe e atuando na resolução de conflitos.", 10 | "Definição da visão técnica do aplicativo, garantindo escalabilidade e boas práticas, aplicando proatividade para antecipar desafios e propor melhorias contínuas.", 11 | "Desenvolvimento e implementação de novas funcionalidades para o projeto.", 12 | "Revisão de código e garantia da qualidade por meio de code reviews e testes.", 13 | "Atuação na linha de frente de tomada de decisões estratégicas para a evolução do aplicativo, aplicando pensamento crítico para avaliar soluções e direcionar o desenvolvimento de forma eficaz.", 14 | "Acompanhamento e suporte técnico à equipe, promovendo boas práticas de desenvolvimento." 15 | ] 16 | }, 17 | { 18 | "company": "GRANTER", 19 | "start": "06/2022", 20 | "end": "10/2024", 21 | "role": "Consultor Especialista Flutter", 22 | "description": [ 23 | "Desenvolvimento e arquitetura de aplicativos móveis multiplataforma de alto desempenho.", 24 | "Colaboração com stakeholders para traduzir requisitos de negócio em funcionalidades intuitivas e eficientes para o usuário.", 25 | "Implementação de código limpo, escalável, seguindo as melhores práticas de desenvolvimento.", 26 | "Integração de APIs e serviços externos para funcionalidades avançadas.", 27 | "Suporte contínuo e otimização do desempenho dos aplicativos.", 28 | "Mentoria e compartilhamento de conhecimento em Flutter, contribuindo para o crescimento da equipe." 29 | ] 30 | }, 31 | { 32 | "company": "BEES (via Avantti)", 33 | "start": "05/2022", 34 | "end": "02/2024", 35 | "role": "Líder Técnico Mobile", 36 | "description": [ 37 | "Curadoria de projetos e identificação de novas oportunidades alinhadas às necessidades dos clientes.", 38 | "Comunicação clara e objetiva sobre soluções técnicas e progresso dos projetos para stakeholders.", 39 | "Desenvolvimento de aplicativos multiplataforma e Design Systems para grandes empresas, como TADA e Zé Delivery.", 40 | "Implementação de Server Driven UI (SDUI) para proporcionar uma experiência de usuário mais dinâmica e personalizada.", 41 | "Projeto e implementação de um Design System reutilizável, garantindo consistência e agilidade no desenvolvimento.", 42 | "Colaboração com designers, engenheiros de back-end e gerentes de produto para otimizar processos e entregas.", 43 | "Mentoria e suporte a desenvolvedores juniores, promovendo a troca de conhecimento dentro da equipe, aplicando empatia para compreender desafios e facilitar o aprendizado." 44 | ] 45 | }, 46 | { 47 | "company": "CVC Corp (via ioasys)", 48 | "start": "04/2021", 49 | "end": "04/2022", 50 | "role": "Flutter Specialist", 51 | "description": [ 52 | "Desenvolvimento e manutenção de um aplicativo B2B e B2C completo utilizando Flutter, garantindo uma experiência eficiente e centrada no usuário.", 53 | "Mentoria e orientação de desenvolvedores juniores por meio de revisões de código, sessões de compartilhamento de conhecimento e suporte técnico, aplicando comunicação eficaz para transmitir ideias de forma clara e construtiva.", 54 | "Liderança na reformulação da arquitetura do aplicativo com princípios de arquitetura limpa, aumentando a manutenibilidade, escalabilidade e testabilidade do código.", 55 | "Otimização do desempenho do aplicativo e uso eficiente dos recursos, garantindo uma experiência fluida e responsiva." 56 | ] 57 | }, 58 | { 59 | "company": "MATERIALIZE", 60 | "start": "11/2020", 61 | "end": "12/2021", 62 | "role": "Especialista Flutter ", 63 | "description": [ 64 | "Desenvolvimento e implementação de aplicativos móveis multiplataforma de alta qualidade para diversos clientes.", 65 | "Tradução de requisitos do cliente em soluções eficientes e centradas na experiência do usuário.", 66 | "Forte experiência na construção de aplicativos Flutter com funcionamento otimizado para iOS e Android.", 67 | "Superação de desafios técnicos por meio da implementação de soluções eficazes e escaláveis, aplicando resiliência para lidar com obstáculos e aprimorar continuamente o desenvolvimento.", 68 | "Colaboração estreita com clientes e equipes multidisciplinares para garantir a entrega de produtos alinhados às necessidades do mercado, aplicando trabalho em equipe para integrar diferentes perspectivas e alcançar melhores resultados.", 69 | "Utilização de widgets e bibliotecas Flutter para criar aplicativos interativos e ricos em funcionalidades. " 70 | ] 71 | }, 72 | { 73 | "company": "IOB/AO3", 74 | "start": "07/2019", 75 | "end": "04/2021", 76 | "role": "Analista Desenvolvedor de Sistemas Sênior", 77 | "description": [ 78 | "Desenvolvimento e implementação de um sistema de auditoria eletrônica (SPED) para validação e certificação de arquivos digitais, otimizando processos e garantindo conformidade regulatória.", 79 | "Liderança no desenvolvimento de aplicativos móveis multiplataforma com IA do IBM Watson, proporcionando soluções inovadoras e melhorando a experiência do usuário.", 80 | "Expertise técnica em .NET 4.5, .NET Core, SQL Server, Angular, Flutter, JavaScript, CSS e HTML5, contribuindo para diversos projetos e superando desafios complexos.", 81 | "Mentoria e orientação de desenvolvedores juniores, promovendo um ambiente colaborativo e incentivando o compartilhamento de conhecimento." 82 | ] 83 | }, 84 | { 85 | "company": "FRIENDSBEE", 86 | "start": "03/2019", 87 | "end": "11/2020", 88 | "role": "Analista Desenvolvedor de Sistemas Sênior", 89 | "description": [ 90 | "Desenvolvimento e lançamento de um aplicativo de rede social para auxiliar usuários na resolução de desafios diários.", 91 | "Implementação full-stack utilizando angular 6 (front-end), .NET Core (back-end) e MySQL (banco de dados).", 92 | "Colaboração e acompanhamento de 100% das equipes multifuncionais para garantir alinhamento entre desenvolvimento, design e produto.", 93 | "Otimização do desempenho do aplicativo, garantindo escalabilidade e uma experiência de usuário aprimorada." 94 | ] 95 | }, 96 | { 97 | "company": "RAÍZEN", 98 | "start": "01/2018", 99 | "end": "07/2019", 100 | "role": "Analista Desenvolvedor de Sistemas Sênior", 101 | "description": [ 102 | "Garantia da confiabilidade e sustentabilidade de sistemas através da identificação e resolução de bugs.", 103 | "Manutenção e otimização de sistemas desenvolvidos em .NET (MVC, WebForms e Core), jQuery e SQL Server.", 104 | "Colaboração com equipes multifuncionais para resolução de problemas e implementação de melhorias.", 105 | "Desenvolvimento full-stack, atuando na análise, testes e prevenção de falhas para reduzir interrupções nos sistemas, aplicando resolução de problemas para identificar e corrigir erros de forma eficiente." 106 | ] 107 | }, 108 | { 109 | "company": "SAGE", 110 | "start": "12/2016", 111 | "end": "01/2018", 112 | "role": "Analista Desenvolvedor de Sistemas Pleno", 113 | "description": [ 114 | "Liderança no desenvolvimento e implementação do SPED, sistema de auditoria eletrônica para validação de arquivos contábeis e fiscais, garantindo conformidade regulatória e maior eficiência nos processos.", 115 | "Atualização e implementação de módulos fiscais e contábeis (ECF, eSocial, Reinf) para manter o sistema alinhado às regulamentações vigentes.", 116 | "Modernização da experiência do usuário, migrando aplicações de Silverlight para HTML5, utilizando Bootstrap, CSS3 e jQuery.", 117 | "Desenvolvimento e manutenção de sistemas complexos com .NET 4.5, SQL Server, JavaScript, CSS e HTML5.", 118 | "Colaboração com equipes multifuncionais para garantir a implementação eficiente do sistema de auditoria." 119 | ] 120 | }, 121 | { 122 | "company": "Ci&T", 123 | "start": "02/2012", 124 | "end": "12/2013", 125 | "role": "Engenheiro de Software Jr.)", 126 | "description": [ 127 | "Integração de aplicações legadas com SAP na DPaschoal, utilizando VB3, .NET, PL/SQL e SQL Server, facilitando a troca de dados e melhorando a eficiência do sistema.", 128 | "Desenvolvimento de melhorias no sistema de cotação de preços da Coca-Cola e no sistema de avaliação de funcionários da Makro, aplicando .NET e SQL Server.", 129 | "Adaptação a múltiplas linguagens de programação e bancos de dados, garantindo flexibilidade e eficiência no desenvolvimento de soluções.", 130 | "Contribuição ativa para o ambiente Scrum, participando de reuniões e colaborando com a equipe para otimizar entregas e processos." 131 | ] 132 | }, 133 | { 134 | "company": "Gerencial Informática", 135 | "start": "07/2011", 136 | "end": "01/2012", 137 | "role": "Desenvolvedor de Software", 138 | "description": [ 139 | "Desenvolvimento e manutenção de aplicações em Delphi 5 e 7.", 140 | "Utilização do banco de dados Firebird para armazenamento e recuperação de informações.", 141 | "Conhecimento básico em PHP, com interesse em aprendizado e aprimoramento contínuo." 142 | ] 143 | }, 144 | { 145 | "company": "PC TECH", 146 | "start": "01/2006", 147 | "end": "01/2008", 148 | "role": "Programador", 149 | "description": [ 150 | "Desenvolvimento e implementação de aplicações web utilizando PHP e MySQL.", 151 | "Criação e manutenção de sites e aplicações com Joomla! CMS, garantindo um gerenciamento de conteúdo eficiente.", 152 | "Participação em todas as etapas do ciclo de desenvolvimento, da análise de requisitos à implantação.", 153 | "Colaboração com designers, gerentes de projeto e desenvolvedores para o sucesso dos projetos.", 154 | "Desenvolvimento de fortes habilidades analíticas e de resolução de problemas." 155 | ] 156 | } 157 | ] 158 | } -------------------------------------------------------------------------------- /assets/experiences_enUs.json: -------------------------------------------------------------------------------- 1 | { 2 | "experiences": [ 3 | { 4 | "company": "FARMÁCIAS APP By GrupoSC", 5 | "end": null, 6 | "start": "03/2024", 7 | "role": "Technical Lead Mobile ", 8 | "description": [ 9 | "Led the development team for the Farmácias APP application project, distributing and defining tasks and development priorities, monitoring team progress, and ensuring delivery within agreed deadlines, conducting alignment and planning meetings with the team and resolving conflicts.", 10 | "Defined the technical vision for the application, ensuring scalability and best practices, proactively anticipating challenges and proposing continuous improvements.", 11 | "Developed and executed new features for the project.", 12 | "Conducted code reviews and ensured quality through code reviews and testing.", 13 | "Played a frontline role in strategic decision-making for application evolution, applying critical thinking to evaluate solutions and direct development effectively.", 14 | "Provided technical guidance and support to the team, promoting development best practices." 15 | ] 16 | }, 17 | { 18 | "company": "GRANTER", 19 | "end": "10/2024", 20 | "start": "06/2022", 21 | "role": "Consultant Flutter Specialist", 22 | "description": [ 23 | "Developed and architected high-performance, cross-platform mobile applications.", 24 | "Worked together with stakeholders to translate business requirements into user-friendly features.", 25 | "Applied clean, scalable code following best practices.", 26 | "Integrated APIs and external services for advanced functionality.", 27 | "Provided ongoing support and optimized app performance.", 28 | "Mentored and shared knowledge in Flutter with the team." 29 | ] 30 | }, 31 | { 32 | "company": "BEES (via Avantti)", 33 | "end": "02/2024", 34 | "start": "05/2022", 35 | "role": "Technical Lead Mobile", 36 | "description": [ 37 | "Curated projects and identified new opportunities aligned with client needs. ", 38 | "Communicated technical solutions and project progress clearly to stakeholders.", 39 | "Developed cross-platform applications and design systems for major companies like TADA and Zé Delivery.", 40 | "Implemented Server-Driven UI (SDUI) for a dynamic and personalized user experience.", 41 | "Designed and carried a reusable design system, ensuring consistency and development agility.", 42 | "Cooperated with designers, back-end engineers, and product managers to optimize processes and deliveries.", 43 | "Mentored and supported junior developers, promoting knowledge sharing within the team." 44 | ] 45 | }, 46 | { 47 | "company": "CVC Corp (via ioasys)", 48 | "start": "04/2021", 49 | "end": "04/2022", 50 | "role": "Flutter Specialist", 51 | "description": [ 52 | "Optimized application performance and resource utilization, ensuring a smooth and responsive experience.", 53 | "Led the redesign of the application's architecture using clean architecture principles, increasing maintainability, scalability, and testability.", 54 | "Mentored junior developers through code reviews, knowledge-sharing sessions, and technical support.", 55 | "Developed and maintained a comprehensive B2B and B2C application using Flutter, ensuring an efficient and user-centric experience.Key Tools: Flutter, Dart, Server Driven UI, Jira, AWS e Adobe XD" 56 | ] 57 | }, 58 | { 59 | "company": "MATERIALIZE", 60 | "start": "11/2020", 61 | "end": "12/2021", 62 | "role": "Flutter Specialist ", 63 | "description": [ 64 | "Developed and performed high-quality, cross-platform mobile applications for various clients.", 65 | "Translated client requirements into efficient, user-centric solutions.", 66 | "Built Flutter applications optimized for iOS and Android.", 67 | "Effected effective and scalable solutions to technical challenges.", 68 | "Effected with clients and multidisciplinary teams to deliver market-aligned products.", 69 | "Utilized Flutter widgets and libraries to create interactive, feature-rich applications. " 70 | ] 71 | }, 72 | { 73 | "company": "IOB/AO3", 74 | "start": "07/2019", 75 | "end": "04/2021", 76 | "role": "Senior Systems Analyst Developer", 77 | "description": [ 78 | "Developed and orchestrated an electronic audit system (SPED) for validating and certifying digital files, optimizing processes, and ensuring regulatory compliance.", 79 | "Led the development of cross-platform mobile applications with IBM Watson AI, providing innovative solutions and improving user experience.", 80 | "Applied technical expertise in .NET 4.5, .NET Core, SQL Server, Angular, Flutter, JavaScript, CSS, and HTML5 to various projects.", 81 | "Mentored junior developers, fostering a collaborative environment and encouraging knowledge sharing." 82 | ] 83 | }, 84 | { 85 | "company": "FRIENDSBEE", 86 | "start": "03/2019", 87 | "end": "11/2020", 88 | "role": "Senior Systems Analyst Develope", 89 | "description": [ 90 | "Developed and builded a social network application to help users solve daily challenges.", 91 | "Conducted full-stack development using Angular 6 (front-end), .NET Core (back-end), and MySQL (database).", 92 | "Collaboration and monitoring of 100% of multifunctional teams to ensure alignment between development, design and product.", 93 | "Optimized application performance, ensuring scalability and an enhanced user experience." 94 | ] 95 | }, 96 | { 97 | "company": "RAÍZEN", 98 | "start": "01/2018", 99 | "end": "07/2019", 100 | "role": "Senior Systems Analyst Developer", 101 | "description": [ 102 | "Ensured system reliability and sustainability by identifying and resolving bugs.", 103 | "Upheld and optimized systems developed in .NET (MVC, WebForms, and Core), jQuery, and SQL Server.", 104 | "Cooperated with cross-functional teams to resolve problems and implement improvements.", 105 | "Performed full-stack development, including analysis, testing, and failure prevention to reduce system interruptions." 106 | ] 107 | }, 108 | { 109 | "company": "SAGE", 110 | "start": "12/2016", 111 | "end": "01/2018", 112 | "role": "Systems Analyst Developer", 113 | "description": [ 114 | "Led the development and implementation of SPED, an electronic audit system for validating accounting and tax files, ensuring regulatory compliance and greater process efficiency.", 115 | "Updated and integrated fiscal and accounting modules (ECF, eSocial, Reinf) to keep the system aligned with current regulations.", 116 | "Modernized the user experience by migrating applications from Silverlight to HTML5 using Bootstrap, CSS3, and jQuery.", 117 | "Kept up complex systems with .NET 4.5, SQL Server, JavaScript, CSS, and HTML5.", 118 | "Partnered with cross-functional teams to ensure efficient implementation of the audit system." 119 | ] 120 | }, 121 | { 122 | "company": "Ci&T", 123 | "start": "02/2012", 124 | "end": "12/2013", 125 | "role": "Software Engineer Jr.", 126 | "description": [ 127 | "Integrated legacy applications with SAP at DPaschoal using VB3, .NET, PL/SQL, and SQL Server, facilitating data exchange and improving system efficiency.", 128 | "Developed improvements in Coca-Cola's price quote system and Makro's employee evaluation system using .NET and SQL Server.", 129 | "Adapted to multiple programming languages and databases, ensuring flexibility and efficiency in solution development.", 130 | "Contributed actively to the Scrum environment, participating in meetings and collaborating with the team to optimize deliveries and processes." 131 | ] 132 | }, 133 | { 134 | "company": "Gerencial Informática", 135 | "start": "07/2011", 136 | "end": "01/2012", 137 | "role": "Software Developer", 138 | "description": [ 139 | "Developed and preserved applications in Delphi 5 and 7.", 140 | "Used the Firebird database for information storage and retrieval.", 141 | "Gained basic knowledge in PHP, with an interest in continuous learning and improvement." 142 | ] 143 | }, 144 | { 145 | "company": "PC TECH", 146 | "start": "01/2006", 147 | "end": "01/2008", 148 | "role": "Programmer", 149 | "description": [ 150 | "Developed and Engineered web applications using PHP and MySQL.", 151 | "Created and serviced websites and applications with Joomla! CMS, ensuring efficient content management.", 152 | "Participated in all stages of the development cycle, from requirement analysis to deployment.", 153 | "Collaborated with designers, project managers, and developers for project success.", 154 | "Developed strong analytical and problem-solving skills." 155 | ] 156 | } 157 | ] 158 | } -------------------------------------------------------------------------------- /assets/images/awards/dart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/awards/dart.png -------------------------------------------------------------------------------- /assets/images/awards/flutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/awards/flutter.png -------------------------------------------------------------------------------- /assets/images/awards/gde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/awards/gde.png -------------------------------------------------------------------------------- /assets/images/awards/mvp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/awards/mvp.png -------------------------------------------------------------------------------- /assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/favicon.png -------------------------------------------------------------------------------- /assets/images/flutterbrasil/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/flutterbrasil/dash.png -------------------------------------------------------------------------------- /assets/images/flutterbrasil/flutter_br.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/flutterbrasil/flutter_br.png -------------------------------------------------------------------------------- /assets/images/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /assets/images/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /assets/images/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /assets/images/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/icons/favicon-16x16.png -------------------------------------------------------------------------------- /assets/images/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/icons/favicon-32x32.png -------------------------------------------------------------------------------- /assets/images/icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/icons/logo.png -------------------------------------------------------------------------------- /assets/images/logo_toshi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/logo_toshi.png -------------------------------------------------------------------------------- /assets/images/meia_entrada.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/meia_entrada.png -------------------------------------------------------------------------------- /assets/images/toshi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/assets/images/toshi.png -------------------------------------------------------------------------------- /assets/lang/en_US.json: -------------------------------------------------------------------------------- 1 | { 2 | "about": "About", 3 | "carrer": "Carrer", 4 | "contact": "Contact", 5 | "main_description": "A Microsoft Most Valuable Professional (MVP) and Google Developer Expert (GDE) in Flutter and Dart, with over 18 years of experience in software development. A postgraduate degree in Software Engineering complements a strong background in building high-quality mobile applications using Flutter. Expertise in team leadership, project management, and stakeholder communication, along with a passion for community building and knowledge sharing as demonstrated by founding Flutter Brasil.", 6 | "details": "Details", 7 | "get_in_touch": "Get in Touch", 8 | "change_language": "Change Language", 9 | "to": "to", 10 | "follow": "Follow", 11 | "phone": "Phone", 12 | "address": "Address", 13 | "current": "Current", 14 | "send_email": "Send Email", 15 | "experience": "Experience" 16 | } -------------------------------------------------------------------------------- /assets/lang/pt_BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "about": "Sobre", 3 | "carrer": "Carreira", 4 | "contact": "Contato", 5 | "main_description": "Profissional reconhecido pelo programa da Microsoft como Most Value Professional e do Google Developer Expert em Flutter e Dart, pós graduado em Engenharia de Software, com formação tecnológica em Jogos Digitais e técnica em Informática com mais de 18 anos de experiência na área, atuando em empresas nacionais e multinacionais de grande porte de tecnologia. Profissional com ampla experiência em desenvolvimento de aplicações mobile utilizando Flutter. Possui conhecimento em programação de software em diversas ferramentas da área. Vivência com gestão de equipes, condução de projeto com equipes multidisciplinares e troca com stakeholders. Como fundador da Flutter Brasil, encontra-se na linha de frente na organização de eventos e atividades, visando expandir e fortalecer a comunidade.", 6 | "details": "Detalhes", 7 | "change_language": "Trocar Idioma", 8 | "get_in_touch": "Entre em Contato", 9 | "to": "até", 10 | "follow": "Siga", 11 | "phone": "Telefone", 12 | "address": "Endereço", 13 | "send_email": "Enviar Email", 14 | "current": "Atual", 15 | "experience": "Expêriencia" 16 | } -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | homepage 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/app/modules/home/data/datasource/experience_datasource_impl.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:dio/dio.dart'; 4 | 5 | import '../repositories/datasources/experience_datasource.dart'; 6 | import '../repositories/models/experience_model.dart'; 7 | 8 | class ExperienceDatasourceImpl implements ExperienceDatasource { 9 | final String _assetPath = 10 | 'https://raw.githubusercontent.com/toshiossada/toshiossada/refs/heads/main/experiences.json'; 11 | final String _assetPathEnUs = 12 | 'https://raw.githubusercontent.com/toshiossada/toshiossada/refs/heads/main/experiences_enUs.json'; 13 | 14 | @override 15 | Future> getExperiences(bool isPtBr) async { 16 | final urlString = isPtBr ? _assetPath : _assetPathEnUs; 17 | final http = Dio(); 18 | try { 19 | final response = await http.get(urlString); 20 | 21 | if (response.statusCode == 200) { 22 | final jsonString = response.data; 23 | final decodedJson = jsonDecode(jsonString) as Map; 24 | 25 | if (decodedJson.containsKey('experiences') && 26 | decodedJson['experiences'] is List) { 27 | final List experienceListJson = 28 | decodedJson['experiences'] as List; 29 | 30 | final List experiences = 31 | experienceListJson.map((jsonItem) { 32 | if (jsonItem is Map) { 33 | return ExperienceModel.fromJson(jsonItem); 34 | } else { 35 | throw FormatException( 36 | "Invalid item type found in 'experiences' list: ${jsonItem.runtimeType}"); 37 | } 38 | }).toList(); 39 | 40 | return experiences; 41 | } else { 42 | throw FormatException( 43 | "Invalid JSON structure: 'experiences' key not found or is not a list in $urlString"); 44 | } 45 | } else { 46 | throw Exception( 47 | 'Failed to load experiences from $urlString. Status code: ${response.statusCode}'); 48 | } 49 | } catch (e) { 50 | throw Exception('Error fetching experiences from $urlString: $e'); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/app/modules/home/data/mappers/experience_mapper.dart: -------------------------------------------------------------------------------- 1 | import '../../domain/entities/experience_entity.dart'; 2 | import '../repositories/models/experience_model.dart'; 3 | 4 | class ExperienceMapper { 5 | ExperienceEntity toEntity(ExperienceModel model) { 6 | return ExperienceEntity( 7 | company: model.company, 8 | start: model.start, 9 | end: model.end, 10 | role: model.role, 11 | description: model.description, 12 | ); 13 | } 14 | 15 | ExperienceModel toModel(ExperienceEntity entity) { 16 | return ExperienceModel( 17 | company: entity.company, 18 | start: entity.start, 19 | end: entity.end, 20 | role: entity.role, 21 | description: entity.description, 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/app/modules/home/data/repositories/datasources/experience_datasource.dart: -------------------------------------------------------------------------------- 1 | import '../models/experience_model.dart'; 2 | 3 | abstract interface class ExperienceDatasource { 4 | Future> getExperiences(bool isPtBr); 5 | } 6 | -------------------------------------------------------------------------------- /lib/app/modules/home/data/repositories/experience_repository_impl.dart: -------------------------------------------------------------------------------- 1 | import '../../domain/entities/experience_entity.dart'; 2 | import '../../domain/interfaces/experience_repository.dart'; 3 | import '../mappers/experience_mapper.dart'; 4 | import 'datasources/experience_datasource.dart'; 5 | 6 | class ExperienceRepositoryImpl implements ExperienceRepository { 7 | final ExperienceDatasource datasource; 8 | final ExperienceMapper mapper; 9 | 10 | ExperienceRepositoryImpl({required this.datasource, required this.mapper}); 11 | 12 | @override 13 | Future> getExperiences(bool isPtBr) async { 14 | final experiences = await datasource.getExperiences(isPtBr); 15 | 16 | return experiences.map(mapper.toEntity).toList(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/app/modules/home/data/repositories/models/experience_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:intl/intl.dart'; // Import the intl package for date formatting 2 | 3 | class ExperienceModel { 4 | final String company; 5 | final DateTime start; 6 | final DateTime? end; 7 | final String role; 8 | final List description; 9 | 10 | ExperienceModel({ 11 | required this.company, 12 | required this.start, 13 | this.end, 14 | required this.role, 15 | required this.description, 16 | }); 17 | 18 | 19 | static DateTime? _parseDate(String? dateString) { 20 | if (dateString == null || dateString.isEmpty) { 21 | return null; 22 | } 23 | return DateFormat('MM/yyyy').parseStrict(dateString); 24 | } 25 | 26 | static String? _formatDate(DateTime? date) { 27 | if (date == null) { 28 | return null; 29 | } 30 | return DateFormat('MM/yyyy').format(date); 31 | } 32 | 33 | /// Creates an ExperienceModel instance from a JSON map. 34 | factory ExperienceModel.fromJson(Map json) { 35 | List descriptionList = []; 36 | if (json['description'] is List) { 37 | descriptionList = 38 | List.from(json['description'].map((item) => item.toString())); 39 | } 40 | DateTime? startDate = _parseDate(json['start'] as String?); 41 | DateTime? endDate = 42 | _parseDate(json['end'] as String?); // end can be null in JSON 43 | 44 | // Validate required fields 45 | if (json['company'] == null || startDate == null || json['role'] == null) { 46 | throw FormatException( 47 | "Missing required fields (company, start, role) in Experience JSON: $json"); 48 | } 49 | 50 | return ExperienceModel( 51 | company: json['company'] as String, 52 | start: startDate, 53 | end: endDate, 54 | role: json['role'] as String, 55 | description: descriptionList, 56 | ); 57 | } 58 | 59 | /// Converts an ExperienceModel instance to a JSON map. 60 | Map toJson() { 61 | return { 62 | 'company': company, 63 | 'start': _formatDate(start), 64 | 'end': _formatDate(end), 65 | 'role': role, 66 | 'description': description, 67 | }; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/app/modules/home/domain/entities/experience_entity.dart: -------------------------------------------------------------------------------- 1 | import 'package:intl/intl.dart'; 2 | import 'package:localization/localization.dart'; 3 | 4 | class ExperienceEntity { 5 | final String company; 6 | final DateTime start; 7 | final DateTime? end; 8 | final String role; 9 | final List description; 10 | 11 | ExperienceEntity({ 12 | required this.company, 13 | required this.start, 14 | this.end, 15 | required this.role, 16 | required this.description, 17 | }); 18 | String get formattedStart => DateFormat('MM/yyyy').format(start); 19 | 20 | String get formattedEnd { 21 | if (end == null) { 22 | return "current".i18n(); 23 | } else { 24 | return DateFormat('MM/yyyy').format(end!); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/app/modules/home/domain/interfaces/experience_repository.dart: -------------------------------------------------------------------------------- 1 | import '../entities/experience_entity.dart'; // Adjust path if needed 2 | 3 | abstract class ExperienceRepository { 4 | Future> getExperiences(bool isPtBr); 5 | } 6 | -------------------------------------------------------------------------------- /lib/app/modules/home/domain/usecases/get_experiences_usecase.dart: -------------------------------------------------------------------------------- 1 | import '../entities/experience_entity.dart'; 2 | import '../interfaces/experience_repository.dart'; 3 | 4 | 5 | class GetExperiencesUsecase { 6 | final ExperienceRepository repository; 7 | 8 | GetExperiencesUsecase({required this.repository}); 9 | 10 | Future> call(bool isPtBr) { 11 | return repository.getExperiences(isPtBr); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/app/modules/home/home_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_modular/flutter_modular.dart'; 2 | import 'package:homepage/app/modules/home/data/repositories/datasources/experience_datasource.dart'; 3 | import 'package:homepage/app/modules/home/pages/initial/initial_page.dart'; 4 | import 'package:homepage/app/modules/home/pages/initial/initial_page_controller.dart'; 5 | 6 | import '../../../core_module.dart'; 7 | import 'data/datasource/experience_datasource_impl.dart'; 8 | import 'data/mappers/experience_mapper.dart'; 9 | import 'data/repositories/experience_repository_impl.dart'; 10 | import 'domain/interfaces/experience_repository.dart'; 11 | import 'domain/usecases/get_experiences_usecase.dart'; 12 | import 'pages/about/about_page.dart'; 13 | import 'pages/carrer/carrer_controller.dart'; 14 | import 'pages/carrer/carrer_page.dart'; 15 | import 'pages/carrer/carrer_store.dart'; 16 | import 'pages/contacts/contact_page.dart'; 17 | import 'pages/generator/experiences_pages.dart'; 18 | 19 | class HomeModule extends Module { 20 | @override 21 | List get imports => [CoreModule()]; 22 | @override 23 | void binds(Injector i) { 24 | i 25 | ..add(InitialPageController.new) 26 | ..add(CarrerStore.new) 27 | ..add(CarrerController.new) 28 | ..add(GetExperiencesUsecase.new) 29 | ..add(ExperienceRepositoryImpl.new) 30 | ..add(ExperienceMapper.new) 31 | ..add(ExperienceDatasourceImpl.new); 32 | } 33 | 34 | @override 35 | void routes(RouteManager r) { 36 | r 37 | ..child('/', 38 | child: (_) => InitialPage( 39 | controller: Modular.get(), 40 | ), 41 | children: [ 42 | ChildRoute('/about', child: (_) => AboutPage()), 43 | ChildRoute('/contact', child: (_) => ContactPage()), 44 | ChildRoute('/carrer', 45 | child: (_) => CarrerPage( 46 | controller: Modular.get(), 47 | )), 48 | ]) 49 | ..child('/experiences-generator', child: (_) => ExperiencesPage()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/about/about_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:homepage/app/modules/home/pages/about/widget/avatar_widget.dart'; 3 | import 'package:localization/localization.dart'; 4 | import 'package:url_launcher/url_launcher.dart'; 5 | 6 | import '../widgets/contact_widget.dart'; 7 | import 'widget/info_widget.dart'; 8 | 9 | class AboutPage extends StatefulWidget { 10 | const AboutPage({super.key}); 11 | 12 | @override 13 | State createState() => _AboutPageState(); 14 | } 15 | 16 | class _AboutPageState extends State { 17 | static const double _breakpoint = 700.0; 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | final screenWidth = MediaQuery.of(context).size.width; 22 | final bool isSmallScreen = screenWidth < _breakpoint; 23 | 24 | return Scaffold( 25 | appBar: AppBar( 26 | title: Text('about'.i18n()), 27 | backgroundColor: Colors.transparent, 28 | elevation: 0, 29 | ), 30 | body: SingleChildScrollView( 31 | padding: const EdgeInsets.all(16.0), 32 | child: Column( 33 | crossAxisAlignment: CrossAxisAlignment.center, 34 | children: [ 35 | isSmallScreen 36 | ? _buildSmallLayout(context) 37 | : _buildLargeLayout(context), 38 | const SizedBox(height: 32), 39 | ContactWidget( 40 | onPressed: _launchUrl, 41 | ), 42 | const SizedBox(height: 16), 43 | ], 44 | ), 45 | ), 46 | ); 47 | } 48 | 49 | Widget _buildSmallLayout(BuildContext context) { 50 | return Column( 51 | mainAxisAlignment: MainAxisAlignment.center, 52 | children: [ 53 | AvatarWidget(), 54 | const SizedBox(height: 24), 55 | InfoWidget(), 56 | ], 57 | ); 58 | } 59 | 60 | Widget _buildLargeLayout(BuildContext context) { 61 | return Row( 62 | crossAxisAlignment: CrossAxisAlignment.start, 63 | mainAxisAlignment: MainAxisAlignment.center, 64 | children: [ 65 | AvatarWidget(), 66 | const SizedBox(width: 32), 67 | Expanded(child: InfoWidget()), 68 | ], 69 | ); 70 | } 71 | 72 | Future _launchUrl(String urlString) async { 73 | final Uri url = Uri.parse(urlString); 74 | if (!await launchUrl(url, mode: LaunchMode.externalApplication)) { 75 | if (mounted) { 76 | ScaffoldMessenger.of(context).showSnackBar( 77 | SnackBar(content: Text('Não foi possível abrir $urlString')), 78 | ); 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/about/widget/avatar_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:homepage/app/modules/home/pages/about/widget/awards_widget.dart'; 3 | import 'package:seo_renderer/renderers/image_renderer/image_renderer_web.dart'; 4 | 5 | class AvatarWidget extends StatelessWidget { 6 | const AvatarWidget({super.key}); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Column( 11 | children: [ 12 | ImageRenderer( 13 | alt: 'Toshi Ossada Logo', 14 | child: Image.asset( 15 | 'assets/images/toshi.png', 16 | ), 17 | ), 18 | AwardsWidget(), 19 | ], 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/about/widget/awards_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:seo_renderer/renderers/image_renderer/image_renderer_web.dart'; 3 | import 'package:url_launcher/url_launcher.dart'; 4 | 5 | class AwardsWidget extends StatelessWidget { 6 | const AwardsWidget({super.key}); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Wrap( 11 | 12 | children: [ 13 | GestureDetector( 14 | onTap: () { 15 | launchUrl( 16 | Uri.parse( 17 | 'https://developers.google.com/profile/u/toshiossada'), 18 | mode: LaunchMode.externalApplication); 19 | }, 20 | child: ImageRenderer( 21 | alt: 'Google Developer Expert', 22 | child: Image.asset( 23 | 'assets/images/awards/gde.png', 24 | height: 62, 25 | ), 26 | ), 27 | ), 28 | SizedBox.square( 29 | dimension: 8, 30 | ), 31 | GestureDetector( 32 | onTap: () { 33 | launchUrl( 34 | Uri.parse( 35 | 'https://mvp.microsoft.com/pt-BR/MVP/profile/670f6b6b-0adf-498c-bb2d-d80b193d4e5d'), 36 | mode: LaunchMode.externalApplication); 37 | }, 38 | child: ImageRenderer( 39 | alt: 'Microsoft Most Value Professional', 40 | child: Image.asset( 41 | 'assets/images/awards/mvp.png', 42 | height: 62, 43 | ), 44 | ), 45 | ), 46 | ], 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/about/widget/info_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:localization/localization.dart'; 3 | import 'package:seo_renderer/seo_renderer.dart'; 4 | import 'package:url_launcher/url_launcher.dart'; 5 | 6 | class InfoWidget extends StatelessWidget { 7 | const InfoWidget({super.key}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return Column( 12 | crossAxisAlignment: CrossAxisAlignment.start, 13 | children: [ 14 | TextRenderer( 15 | style: TextRendererStyle.header1, 16 | child: Text( 17 | 'TOSHI OSSADA', 18 | style: TextStyle( 19 | fontSize: 42, 20 | ), 21 | ), 22 | ), 23 | SizedBox.square( 24 | dimension: 32, 25 | ), 26 | Wrap( 27 | children: [ 28 | ImageRenderer( 29 | alt: 'Dart', 30 | child: Image.asset( 31 | 'assets/images/awards/dart.png', 32 | height: 52, 33 | ), 34 | ), 35 | SizedBox.square( 36 | dimension: 32, 37 | ), 38 | ImageRenderer( 39 | alt: 'Flutter', 40 | child: Image.asset( 41 | 'assets/images/awards/flutter.png', 42 | height: 52, 43 | ), 44 | ), 45 | ], 46 | ), 47 | SizedBox.square( 48 | dimension: 32, 49 | ), 50 | TextRenderer( 51 | child: SelectableText( 52 | 'main_description'.i18n(), 53 | ), 54 | ), 55 | GestureDetector( 56 | onTap: () { 57 | launchUrl(Uri.parse('https://flutterbrasil.com.br/'), 58 | mode: LaunchMode.externalApplication); 59 | }, 60 | child: Padding( 61 | padding: const EdgeInsets.all(8.0), 62 | child: Wrap( 63 | children: [ 64 | ImageRenderer( 65 | alt: 'Flutter', 66 | child: Image.asset( 67 | 'assets/images/flutterbrasil/dash.png', 68 | height: 52, 69 | ), 70 | ), 71 | ImageRenderer( 72 | alt: 'Flutter', 73 | child: Image.asset( 74 | 'assets/images/flutterbrasil/flutter_br.png', 75 | height: 52, 76 | ), 77 | ), 78 | ], 79 | ), 80 | ), 81 | ) 82 | ], 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/carrer/carrer_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import '../../../../../app_store.dart'; 4 | import '../../domain/entities/experience_entity.dart'; 5 | import '../../domain/usecases/get_experiences_usecase.dart'; 6 | import 'carrer_store.dart'; 7 | 8 | class CarrerController { 9 | final GetExperiencesUsecase getExperiencesUsecase; 10 | final CarrerStore store; 11 | final AppStore appStore; 12 | 13 | CarrerController({ 14 | required this.getExperiencesUsecase, 15 | required this.store, 16 | required this.appStore, 17 | }); 18 | 19 | init() async { 20 | await getExperiences(); 21 | } 22 | 23 | Future> getExperiences() async { 24 | try { 25 | store.loading = true; 26 | 27 | var experiences = 28 | await getExperiencesUsecase.call(appStore.locale == Locale('pt', 'BR')); 29 | store.experience = experiences; 30 | 31 | return experiences; 32 | } catch (e) { 33 | return []; 34 | } finally { 35 | store.loading = false; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/carrer/carrer_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:localization/localization.dart'; 3 | import 'package:timeline_tile/timeline_tile.dart'; 4 | 5 | import 'carrer_controller.dart'; 6 | 7 | class CarrerPage extends StatefulWidget { 8 | final CarrerController controller; 9 | const CarrerPage({ 10 | super.key, 11 | required this.controller, 12 | }); 13 | 14 | @override 15 | State createState() => _CarrerPageState(); 16 | } 17 | 18 | class _CarrerPageState extends State { 19 | CarrerController get controller => widget.controller; 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | controller.init(); 25 | } 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | final theme = Theme.of(context); 30 | 31 | return Scaffold( 32 | appBar: AppBar( 33 | title: Text("experience".i18n()), 34 | backgroundColor: Colors.transparent, 35 | elevation: 0, 36 | ), 37 | body: ListenableBuilder( 38 | listenable: controller.store, 39 | builder: (context, child) { 40 | if (controller.store.loading) { 41 | return const Center(child: CircularProgressIndicator()); 42 | } 43 | 44 | if (controller.store.experience.isEmpty) { 45 | return const Center(child: Text("Nenhuma experiência encontrada.")); 46 | } 47 | 48 | return ListView.builder( 49 | padding: 50 | const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), 51 | itemCount: controller.store.experience.length, 52 | itemBuilder: (context, index) { 53 | final experience = controller.store.experience[index]; 54 | final isFirst = index == 0; 55 | final isLast = index == controller.store.experience.length - 1; 56 | 57 | return TimelineTile( 58 | alignment: TimelineAlign.manual, 59 | lineXY: 0.15, 60 | isFirst: isFirst, 61 | isLast: isLast, 62 | indicatorStyle: IndicatorStyle( 63 | width: 20, 64 | height: 20, 65 | indicatorXY: 0.5, 66 | indicator: Container( 67 | decoration: BoxDecoration( 68 | color: theme.colorScheme.primary, 69 | shape: BoxShape.circle, 70 | ), 71 | ), 72 | padding: const EdgeInsets.all(6), 73 | ), 74 | beforeLineStyle: LineStyle( 75 | color: theme.colorScheme.primary.withValues(alpha: (255 / 2)), 76 | thickness: 2, 77 | ), 78 | afterLineStyle: LineStyle( 79 | color: theme.colorScheme.primary.withValues(alpha: (255 / 2)), 80 | thickness: 2, 81 | ), 82 | endChild: Container( 83 | constraints: const BoxConstraints( 84 | minHeight: 120, 85 | ), 86 | padding: const EdgeInsets.only( 87 | left: 16.0, top: 8.0, bottom: 16.0, right: 8.0), 88 | child: Column( 89 | crossAxisAlignment: CrossAxisAlignment.start, 90 | mainAxisAlignment: MainAxisAlignment.center, 91 | children: [ 92 | Text( 93 | '${experience.formattedStart} - ${experience.formattedEnd}', 94 | style: theme.textTheme.bodySmall?.copyWith( 95 | color: theme.colorScheme.onSurface 96 | .withValues(alpha: (255 * 0.7)), 97 | fontWeight: FontWeight.w500, 98 | ), 99 | ), 100 | const SizedBox(height: 4), 101 | Text( 102 | experience.company, 103 | style: theme.textTheme.titleMedium?.copyWith( 104 | fontWeight: FontWeight.bold, 105 | ), 106 | ), 107 | const SizedBox(height: 4), 108 | Text( 109 | experience.role, 110 | style: theme.textTheme.titleSmall?.copyWith( 111 | fontStyle: FontStyle.italic, 112 | color: theme.colorScheme.onSurface 113 | .withValues(alpha: (255 * 0.8)), 114 | ), 115 | ), 116 | const SizedBox(height: 8), 117 | ExpansionTile( 118 | tilePadding: EdgeInsets.zero, 119 | title: Text( 120 | 'details'.i18n(), 121 | style: theme.textTheme.bodySmall?.copyWith( 122 | color: theme.colorScheme.primary, 123 | ), 124 | ), 125 | childrenPadding: 126 | const EdgeInsets.only(top: 4.0, bottom: 8.0), 127 | children: experience.description 128 | .map((desc) => Padding( 129 | padding: const EdgeInsets.only(bottom: 4.0), 130 | child: Row( 131 | crossAxisAlignment: 132 | CrossAxisAlignment.start, 133 | children: [ 134 | const Text("• ", 135 | style: TextStyle( 136 | fontWeight: FontWeight.bold)), 137 | Expanded( 138 | child: Text(desc, 139 | style: 140 | theme.textTheme.bodySmall)), 141 | ], 142 | ), 143 | )) 144 | .toList(), 145 | ), 146 | ], 147 | ), 148 | ), 149 | ); 150 | }, 151 | ); 152 | }, 153 | ), 154 | ); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/carrer/carrer_store.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:homepage/app/modules/home/domain/entities/experience_entity.dart'; 3 | 4 | class CarrerStore extends ChangeNotifier { 5 | List _experience = []; 6 | List get experience => _experience; 7 | set experience(List value) { 8 | _experience = value; 9 | notifyListeners(); 10 | } 11 | 12 | bool _loading = true; 13 | bool get loading => _loading; 14 | set loading(bool value) { 15 | _loading = value; 16 | notifyListeners(); 17 | } 18 | 19 | CarrerStore(); 20 | } 21 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/contacts/contact_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:localization/localization.dart'; 3 | import 'package:url_launcher/url_launcher.dart'; 4 | 5 | import '../widgets/contact_widget.dart'; 6 | import 'widgets/contact_tile_widget.dart'; 7 | 8 | class ContactPage extends StatelessWidget { 9 | const ContactPage({super.key}); 10 | 11 | Future _launchUrl(String urlString) async { 12 | final Uri url = Uri.parse(urlString); 13 | if (!await launchUrl(url, mode: LaunchMode.externalApplication)) { 14 | // Poderia mostrar um Snackbar ou log de erro aqui 15 | 16 | throw Exception('Could not launch $url'); // Ou lançar uma exceção 17 | } 18 | } 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return Scaffold( 23 | backgroundColor: Colors.grey[900], 24 | body: SingleChildScrollView( 25 | padding: const EdgeInsets.all(20.0), 26 | child: Column( 27 | crossAxisAlignment: CrossAxisAlignment.start, 28 | children: [ 29 | Text( 30 | 'get_in_touch'.i18n(), 31 | style: TextStyle( 32 | fontSize: 24, 33 | fontWeight: FontWeight.bold, 34 | color: Colors.white, 35 | ), 36 | ), 37 | const SizedBox(height: 30), 38 | ContactTileWidget( 39 | icon: Icons.phone_android, 40 | title: 'phone'.i18n(), 41 | subtitle: '+55 (19) 99120-0273', 42 | url: '5519991200273', 43 | urlType: UrlTypeEnum.tel, 44 | onPressed: _launchUrl, 45 | ), 46 | const Divider(color: Colors.grey, indent: 16, endIndent: 16), 47 | ContactTileWidget( 48 | icon: Icons.email_outlined, 49 | title: 'Email', 50 | subtitle: 'toshiossada@toshiossada.dev', 51 | url: 'toshiossada@toshiossada.dev', 52 | urlType: UrlTypeEnum.email, 53 | onPressed: _launchUrl, 54 | ), 55 | const Divider(color: Colors.grey, indent: 16, endIndent: 16), 56 | ContactTileWidget( 57 | icon: Icons.location_pin, 58 | title: 'address'.i18n(), 59 | subtitle: 'Americana - SP', 60 | url: 61 | 'https://www.google.com/maps/search/?api=1&query=Americana,SP', 62 | urlType: UrlTypeEnum.link, 63 | onPressed: _launchUrl, 64 | ), 65 | const SizedBox(height: 40), 66 | Text( 67 | 'follow'.i18n(), 68 | style: TextStyle( 69 | fontSize: 20, 70 | fontWeight: FontWeight.bold, 71 | color: Colors.white, 72 | ), 73 | ), 74 | const SizedBox(height: 20), 75 | ContactWidget( 76 | onPressed: _launchUrl, 77 | ), 78 | const SizedBox(height: 20), 79 | ], 80 | ), 81 | ), 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/contacts/widgets/contact_tile_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ContactTileWidget extends StatelessWidget { 4 | final IconData icon; 5 | final String title; 6 | final String subtitle; 7 | final String url; 8 | final UrlTypeEnum urlType; 9 | final Function(String) onPressed; 10 | 11 | const ContactTileWidget({ 12 | super.key, 13 | required this.onPressed, 14 | required this.icon, 15 | required this.title, 16 | required this.subtitle, 17 | required this.url, 18 | required this.urlType, 19 | }); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return ListTile( 24 | leading: Icon(icon, color: Colors.tealAccent[400]), 25 | title: Text(title, 26 | style: const TextStyle( 27 | color: Colors.white, fontWeight: FontWeight.bold)), 28 | subtitle: 29 | SelectableText(subtitle, style: TextStyle(color: Colors.grey[400])), 30 | onTap: () { 31 | String launchUrlString; 32 | if (urlType == UrlTypeEnum.tel) { 33 | launchUrlString = 'https://wa.me/$url'; 34 | } else if (urlType == UrlTypeEnum.email) { 35 | launchUrlString = 'mailto:$url'; 36 | } else { 37 | launchUrlString = url; 38 | } 39 | onPressed(launchUrlString); 40 | }, 41 | contentPadding: 42 | const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), 43 | ); 44 | } 45 | } 46 | 47 | enum UrlTypeEnum { 48 | tel, 49 | email, 50 | link; 51 | } 52 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/dne/dne_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_modular/flutter_modular.dart'; 2 | 3 | import 'pages/dne_page.dart'; 4 | 5 | class DNEModule extends Module { 6 | @override 7 | void routes(RouteManager r) { 8 | r.child( 9 | '/', 10 | child: (_) => DNEPage( 11 | name: r.args.queryParams['name'] ?? '', 12 | school: r.args.queryParams['school'] ?? '', 13 | course: r.args.queryParams['course'] ?? '', 14 | document: r.args.queryParams['document'] ?? '', 15 | photo: r.args.queryParams['photo'] ?? '', 16 | ), 17 | ); 18 | } 19 | } 20 | 21 | // '/dne/?name=Kevlin Toshinari Ossada&school=Faculdade de Tecnologia de Americana&course=Analise e Desenvolvimento de S&document=496271167&photo=https://avatars.githubusercontent.com/u/2637049' 22 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/dne/pages/dne_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:homepage/app/modules/home/pages/dne/pages/widegets/info_widget.dart'; 3 | 4 | import 'widegets/app_bar_widget.dart'; 5 | import 'widegets/certificate.dart'; 6 | import 'widegets/valid_widget.dart'; 7 | 8 | class DNEPage extends StatefulWidget { 9 | final String name; 10 | final String school; 11 | final String course; 12 | final String document; 13 | final String photo; 14 | 15 | const DNEPage({ 16 | super.key, 17 | required this.name, 18 | required this.school, 19 | required this.course, 20 | required this.document, 21 | required this.photo, 22 | }); 23 | 24 | @override 25 | State createState() => _DNEPageState(); 26 | } 27 | 28 | class _DNEPageState extends State { 29 | @override 30 | Widget build(BuildContext context) { 31 | return Theme( 32 | data: ThemeData.light(), 33 | child: Scaffold( 34 | backgroundColor: Colors.white, 35 | body: SingleChildScrollView( 36 | child: Column( 37 | children: [ 38 | AppBarwidget(), 39 | SingleChildScrollView( 40 | child: Padding( 41 | padding: const EdgeInsets.all(20.0), 42 | child: Column( 43 | crossAxisAlignment: CrossAxisAlignment.start, 44 | children: [ 45 | const Text( 46 | 'Validação de CIE (Carteira de Identificação Estudantil)', 47 | style: TextStyle( 48 | fontSize: 22, 49 | fontWeight: FontWeight.bold, 50 | color: Color(0xFF005e9e), 51 | ), 52 | ), 53 | const SizedBox(height: 5), 54 | const Divider( 55 | color: Color(0xFF005e9e), 56 | thickness: 2, 57 | height: 20, 58 | ), 59 | const SizedBox(height: 20), 60 | ValidWidget(), 61 | const SizedBox(height: 25), 62 | Text( 63 | 'UNE atesta que ${widget.name} é estudante e está regularmente matriculado(a) em ${widget.course} da instituição ${widget.school}', 64 | style: TextStyle(fontSize: 15), 65 | textAlign: TextAlign.center, 66 | ), 67 | const SizedBox(height: 30), 68 | InfoWidget( 69 | name: widget.name, 70 | school: widget.school, 71 | course: widget.course, 72 | document: widget.document.padLeft(15, '0'), 73 | photo: widget.photo, 74 | ), 75 | CertificateWidget( 76 | headerText: 'Certificado de Atributo em formato PEM:', 77 | certificateText: 78 | '''MIID6DCCAiACAgbhweKBhzMBgkqhkiG9w0BAQ0EwJUCCjUbegAMIGA1UECgvKUUNSUlUJUXYXpnbDEmMCQGA1UECwwdVU5JdUgU8gTKFDSU0QUJvigRE9TlEVTlVFTVFVQ5URVMxdTAVBgNVBAIMMddmgbpbU3BNoaW55hcmgtT3NyeW1HRlAlCBZlCBjy6SBByDcBXTEkMAkGA1UEBhMCRzEXARgNVBAoMEAoXMCkICU1CcmFzZWFVBgNVBAsMDE00MTIxOTU3MDMwTAVBMRMwMRkwdYDVQQDLDBwWRI2NVbhZmcZkmVU1hMC4wDAYDVQQDLDAVWOuxJRDEXBgEwHgYDVQQJExcwSUGVzc29hZz9hEp1cmKaWnhNEEzMrgiwFgYDVR0QLDdA9BQyBWQUXdURCbCUkFTsUkJxgNkgNVBAMMHVVOsuFPIIE5BC0jpTKhFMdERVpUBU1RFVREVFOVTMADGCSpSggS3IQD3DQEBBQUAA4GgAgZ6ZXMcjIyDzjuwMvMz4MTQzMIEzMvVHgPfMIAyNjAzMzEyMzU6NTlaMIHNMEYGBWMaA0OBmT0TOzE5MDkxOTkyNDE1MzcyMTc4MDAMWDAaMDAxOTEwMTlhWDAaMDAwMDA0MDOTYzExNjcgICAglCAgAQMHgGBWMaAQoC MW0Ta1ZH3Y3VsZGZGeksZBZsBUzwNzub2x2ihIGRIFEFzXxjvJpFy2ySAgLcbTVVBFUkPuKlAgICAgLcbBbmFSaXNiUGUGRGVvVzVzZb2x2aW1lhWRIFGRIFNB0yVVaWhtbnEgICAglCA glCAgfAQIfNAqmsASGBWMaA0QDTADBMgMDMGA1UdIh0wQmhCgYIKwYIHRoUCHjB6MHUuJ9I1bmUzZGtLZnI3YLXL2nYbcC9I6bmJuY3JSgpPTlMwHQYDVR0OBBYEFMIcLSs9s92KkXVR0N g1zkde73OMCEgcGsqG/uFEWBbwEUUwEwyYWKBQQHMAIIEAY4YFSSFRUUFMDQyJzlhcWcNAOEFAgEHQEBAjyxgq+pj195QySzjVsUDp/dIIKh3K2RoAyDnmrbeUhJ9PnBiN YgUDW4G9aYC9CspPdITspwvVsqyaT3bAUlLRD2YHjnYJ8QW6Gs6R7GsaR7pGUBApGTlNbHQvzaS+OkybiVb7DV4xA8mRvVXYKGjRqvW7f7LdlySbyYtsd475DK8T4fTA113zlbYtdgkgx+kgxEs v2gU5UZZAEOHphBda4PHz4aGmxvMatuyA66UBy9is1Bs3xrltNJUpHQNOZXchCWbGjmG38y7NE5pNA6FWS6uDIOn7yCUwmv6KBkBLtAbLbLc1cxwsuMN7Y7WkcbHeAhWgzvcS3zv3y1he0oQ9dpNQtfpc2o=''', 79 | ) 80 | ], 81 | ), 82 | ), 83 | ), 84 | ], 85 | ), 86 | ), 87 | ), 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/dne/pages/widegets/app_bar_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class AppBarwidget extends StatelessWidget { 4 | const AppBarwidget({super.key}); 5 | 6 | @override 7 | Widget build(BuildContext context) { 8 | const Color orangeColor = Color(0xFFF5A623); 9 | const Color blueColor = Color(0xFF0056B3); 10 | 11 | return Column( 12 | mainAxisAlignment: MainAxisAlignment.start, 13 | mainAxisSize: MainAxisSize.max, 14 | children: [ 15 | Container( 16 | height: 5, 17 | color: orangeColor, 18 | ), 19 | Container( 20 | height: 100, 21 | color: blueColor, 22 | padding: const EdgeInsets.symmetric(horizontal: 16.0), 23 | child: Row( 24 | children: [ 25 | SizedBox( 26 | width: 100, 27 | ), 28 | Image.asset( 29 | 'assets/images/meia_entrada.png', 30 | ), 31 | const Spacer(), 32 | 33 | Icon(Icons.menu, color: Colors.white), 34 | // LayoutBuilder( 35 | // builder: (context, constraints) { 36 | // if (constraints.maxWidth > 600) { 37 | // return Row( 38 | // children: [ 39 | // LinkWidget( 40 | // label: 'Lei da Meia-entrada', 41 | // ), 42 | // LinkWidget( 43 | // label: 'Validação', 44 | // ), 45 | // LinkWidget( 46 | // label: 'Chaves públicas', 47 | // ), 48 | // LinkWidget( 49 | // label: 'FAQ', 50 | // ), 51 | // LinkWidget( 52 | // label: 'Notícias', 53 | // ), 54 | // ], 55 | // ); 56 | // } else { 57 | // return Icon(Icons.menu, color: Colors.white); 58 | // } 59 | // }, 60 | // ) 61 | ], 62 | ), 63 | ), 64 | ], 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/dne/pages/widegets/certificate.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CertificateWidget extends StatelessWidget { 4 | final String headerText; 5 | final String certificateText; 6 | 7 | const CertificateWidget({ 8 | super.key, 9 | required this.headerText, 10 | required this.certificateText, 11 | }); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Wrap( 16 | children: [ 17 | Padding( 18 | padding: const EdgeInsets.all(16.0), 19 | child: Column( 20 | crossAxisAlignment: CrossAxisAlignment.start, 21 | children: [ 22 | Text( 23 | headerText, 24 | style: const TextStyle( 25 | fontSize: 18, 26 | fontWeight: FontWeight.bold, 27 | ), 28 | ), 29 | const SizedBox(height: 8), 30 | Text( 31 | certificateText, 32 | style: const TextStyle(fontFamily: 'monospace'), 33 | ), 34 | ], 35 | ), 36 | ), 37 | ], 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/dne/pages/widegets/detail_row_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class DetailRowWidget extends StatelessWidget { 4 | final String label; 5 | final String value; 6 | const DetailRowWidget({super.key, required this.label, required this.value}); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Column( 11 | children: [ 12 | Padding( 13 | padding: const EdgeInsets.symmetric(vertical: 8.0), 14 | child: Row( 15 | crossAxisAlignment: CrossAxisAlignment.start, 16 | children: [ 17 | SizedBox( 18 | width: 120, 19 | child: Text( 20 | label, 21 | style: const TextStyle(fontWeight: FontWeight.bold), 22 | ), 23 | ), 24 | const SizedBox(width: 10), 25 | Expanded( 26 | child: Text(value), 27 | ), 28 | ], 29 | ), 30 | ), 31 | const Divider(), 32 | ], 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/dne/pages/widegets/info_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'detail_row_widget.dart'; 4 | 5 | class InfoWidget extends StatelessWidget { 6 | final String name; 7 | final String school; 8 | final String course; 9 | final String document; 10 | final String photo; 11 | const InfoWidget( 12 | {super.key, 13 | required this.name, 14 | required this.school, 15 | required this.course, 16 | required this.document, 17 | required this.photo}); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return Row( 22 | crossAxisAlignment: CrossAxisAlignment.start, 23 | children: [ 24 | Expanded( 25 | flex: 3, 26 | child: Column( 27 | children: [ 28 | DetailRowWidget(label: 'Nome:', value: name), 29 | DetailRowWidget(label: 'Instituição:', value: school), 30 | DetailRowWidget(label: 'Curso:', value: course), 31 | DetailRowWidget( 32 | label: 'Documento de Identificação:', value: document), 33 | DetailRowWidget(label: 'Emissor:', value: 'UNE'), 34 | ], 35 | ), 36 | ), 37 | const SizedBox(width: 20), 38 | Expanded( 39 | flex: 1, 40 | child: Align( 41 | alignment: Alignment.topCenter, 42 | child: Image.network( 43 | photo, 44 | height: 150, 45 | fit: BoxFit.contain, 46 | errorBuilder: (context, error, stackTrace) { 47 | return Container( 48 | height: 150, 49 | width: 100, 50 | color: Colors.grey[200], 51 | child: const Center( 52 | child: Icon(Icons.person, size: 50, color: Colors.grey)), 53 | ); 54 | }, 55 | ), 56 | ), 57 | ), 58 | ], 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/dne/pages/widegets/link_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class LinkWidget extends StatelessWidget { 4 | final String label; 5 | final bool isLast; 6 | 7 | const LinkWidget({super.key, required this.label, this.isLast = false}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | final Color textColor = Theme.of(context).colorScheme.onPrimary; 12 | return Column( 13 | mainAxisAlignment: MainAxisAlignment.center, 14 | children: [ 15 | TextButton( 16 | style: TextButton.styleFrom( 17 | foregroundColor: textColor, 18 | padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), 19 | minimumSize: Size.zero, 20 | tapTargetSize: MaterialTapTargetSize.shrinkWrap, 21 | ), 22 | onPressed: () {}, 23 | child: Row( 24 | mainAxisSize: MainAxisSize.min, 25 | children: [ 26 | Text(label), 27 | ], 28 | ), 29 | ), 30 | const SizedBox(height: 3.0), 31 | if (!isLast) SizedBox(width: 10), 32 | ], 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/dne/pages/widegets/valid_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ValidWidget extends StatelessWidget { 4 | const ValidWidget({super.key}); 5 | 6 | @override 7 | Widget build(BuildContext context) { 8 | return Container( 9 | width: double.infinity, 10 | padding: const EdgeInsets.all(15.0), 11 | decoration: BoxDecoration( 12 | color: const Color(0xFFDFF0D8), 13 | borderRadius: BorderRadius.circular(4.0), 14 | border: Border.all(color: const Color(0xFFD6E9C6)), 15 | ), 16 | child: const Center( 17 | child: Text( 18 | 'Documento válido!', 19 | style: TextStyle( 20 | color: Color(0xFF3C763D), 21 | fontWeight: FontWeight.bold, 22 | fontSize: 16, 23 | ), 24 | ), 25 | ), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/generator/experiences_pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ExperiencesPage extends StatefulWidget { 4 | const ExperiencesPage({super.key}); 5 | 6 | @override 7 | State createState() => _ExperiencesPageState(); 8 | } 9 | 10 | class _ExperiencesPageState extends State { 11 | TextEditingController txt = TextEditingController(); 12 | TextEditingController txt2 = TextEditingController(); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Scaffold( 17 | appBar: AppBar( 18 | backgroundColor: Colors.transparent, 19 | elevation: 0, 20 | ), 21 | body: SingleChildScrollView( 22 | child: Column( 23 | children: [ 24 | TextFormField( 25 | controller: txt2, 26 | maxLines: 10, 27 | readOnly: true, 28 | ), 29 | TextFormField( 30 | controller: txt, 31 | maxLines: 10, 32 | ), 33 | ElevatedButton( 34 | onPressed: () { 35 | final companyRegex = RegExp( 36 | r'^(.+)( \W )(\d\d\/\d\d\d\d) [A-Za-zA-é]+ (\d\d\/\d\d\d\d)$', 37 | multiLine: true, 38 | ); 39 | final roleRegex = RegExp( 40 | r'^(Cargo|Role): (.+)$', 41 | multiLine: true, 42 | ); 43 | final descriptionRegex = RegExp( 44 | r'^• (.+)$', 45 | multiLine: true, 46 | ); 47 | final companyMatch = companyRegex.allMatches(txt.text); 48 | final roleMatch = roleRegex.allMatches(txt.text); 49 | final descriptionMatch = 50 | descriptionRegex.allMatches(txt.text); 51 | 52 | final company = companyMatch.first.group(1); 53 | final start = companyMatch.first.group(3); 54 | final end = companyMatch.first.group(4); 55 | final role = roleMatch.first.group(2); 56 | final description = 57 | descriptionMatch.map((e) => '"${e.group(1)}"').toList(); 58 | 59 | final json = '''{ 60 | "company": "$company", 61 | "start": "$start", 62 | "end": "$end", 63 | "role": "$role", 64 | "description": [ 65 | ${description.join(',')} 66 | ] 67 | }'''; 68 | 69 | txt2.text = json; 70 | }, 71 | child: Text('click')), 72 | ], 73 | ), 74 | ), 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/initial/initial_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_modular/flutter_modular.dart'; 3 | import 'package:localization/localization.dart'; 4 | import 'package:seo_renderer/seo_renderer.dart'; 5 | 6 | import 'initial_page_controller.dart'; 7 | 8 | class InitialPage extends StatefulWidget { 9 | final InitialPageController controller; 10 | const InitialPage({super.key, required this.controller}); 11 | 12 | @override 13 | State createState() => _InitialPageState(); 14 | } 15 | 16 | class _InitialPageState extends State { 17 | InitialPageController get controller => widget.controller; 18 | 19 | var selectedIndex = 0; 20 | 21 | static const double _breakpoint = 700.0; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | 27 | final currentRoute = Modular.to.path; 28 | bool routeMatched = false; 29 | for (var page in PagesEnum.values) { 30 | if (currentRoute.startsWith(page.route)) { 31 | selectedIndex = page.pageIndex; 32 | routeMatched = true; 33 | break; 34 | } 35 | } 36 | if (!routeMatched) { 37 | selectedIndex = PagesEnum.about.pageIndex; 38 | 39 | Modular.to.pushReplacementNamed(PagesEnum.about.route); 40 | } 41 | } 42 | 43 | List _buildNavigationItems(BuildContext context, bool isDrawer) { 44 | return List.generate(PagesEnum.values.length, (index) { 45 | final page = PagesEnum.values[index]; 46 | final isSelected = page.pageIndex == selectedIndex; 47 | 48 | if (isDrawer) { 49 | return ListTile( 50 | title: Text( 51 | page.description.i18n(), 52 | style: TextStyle( 53 | fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, 54 | ), 55 | ), 56 | selected: isSelected, 57 | onTap: () { 58 | Modular.to.navigate(page.route); 59 | Navigator.pop(context); 60 | setState(() { 61 | selectedIndex = page.pageIndex; 62 | }); 63 | }, 64 | ); 65 | } else { 66 | return Padding( 67 | padding: const EdgeInsets.symmetric(horizontal: 16.0), 68 | child: InkWell( 69 | onTap: () { 70 | Modular.to.navigate(page.route); 71 | setState(() { 72 | selectedIndex = page.pageIndex; 73 | }); 74 | }, 75 | child: Center( 76 | child: Text( 77 | page.description.i18n(), 78 | style: TextStyle( 79 | fontSize: 18, 80 | fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, 81 | decoration: isSelected 82 | ? TextDecoration.underline 83 | : TextDecoration.none, 84 | decorationThickness: 2.0, 85 | ), 86 | ), 87 | ), 88 | ), 89 | ); 90 | } 91 | }); 92 | } 93 | 94 | Widget _buildLanguageMenu() { 95 | return PopupMenuButton( 96 | tooltip: "change_language".i18n(), 97 | onSelected: (Locale newLocale) { 98 | controller.appStore.locale = newLocale; 99 | setState(() {}); 100 | }, 101 | child: Row( 102 | children: [ 103 | Text( 104 | controller.appStore.supportedLocales[controller.appStore.locale] ?? 105 | '', 106 | ), 107 | SizedBox.square( 108 | dimension: 10, 109 | ), 110 | Icon( 111 | Icons.language, 112 | color: Theme.of(context).appBarTheme.actionsIconTheme?.color, 113 | ), 114 | ], 115 | ), 116 | itemBuilder: (BuildContext context) { 117 | return controller.appStore.supportedLocales.entries.map((entry) { 118 | final locale = entry.key; 119 | final name = entry.value; 120 | 121 | final bool isSelected = controller.appStore.locale == locale || 122 | (controller.appStore.locale == null && 123 | WidgetsBinding.instance.platformDispatcher.locale == locale); 124 | 125 | return PopupMenuItem( 126 | value: locale, 127 | child: Text( 128 | name, 129 | style: TextStyle( 130 | fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, 131 | ), 132 | ), 133 | ); 134 | }).toList(); 135 | }, 136 | ); 137 | } 138 | 139 | @override 140 | Widget build(BuildContext context) { 141 | final screenWidth = MediaQuery.of(context).size.width; 142 | final bool isSmallScreen = screenWidth < _breakpoint; 143 | 144 | return Scaffold( 145 | drawer: isSmallScreen 146 | ? Drawer( 147 | child: ListView( 148 | padding: EdgeInsets.zero, 149 | children: [ 150 | DrawerHeader( 151 | decoration: BoxDecoration( 152 | color: Theme.of(context).primaryColor, 153 | ), 154 | child: Row( 155 | children: [ 156 | ImageRenderer( 157 | alt: 'Toshi Ossada Logo', 158 | child: Image.asset( 159 | 'assets/images/favicon.png', 160 | height: 40, 161 | ), 162 | ), 163 | const SizedBox(width: 15), 164 | const Text( 165 | 'Toshi Ossada', 166 | style: TextStyle(color: Colors.white, fontSize: 20), 167 | ), 168 | ], 169 | ), 170 | ), 171 | _buildLanguageMenu(), 172 | ..._buildNavigationItems(context, true), 173 | ], 174 | ), 175 | ) 176 | : null, 177 | appBar: AppBar( 178 | title: GestureDetector( 179 | onTap: () { 180 | Modular.to.navigate(PagesEnum.about.route); 181 | setState(() { 182 | selectedIndex = PagesEnum.about.pageIndex; 183 | }); 184 | }, 185 | child: Row( 186 | mainAxisSize: MainAxisSize.min, 187 | children: [ 188 | ImageRenderer( 189 | alt: 'Toshi Ossada Logo', 190 | child: Image.asset( 191 | 'assets/images/favicon.png', 192 | height: 40, 193 | ), 194 | ), 195 | const SizedBox(width: 15), 196 | const Text('Toshi Ossada'), 197 | ], 198 | ), 199 | ), 200 | actions: isSmallScreen 201 | ? null 202 | : [ 203 | _buildLanguageMenu(), 204 | ..._buildNavigationItems(context, false), 205 | const SizedBox(width: 16), 206 | ], 207 | ), 208 | body: const RouterOutlet(), 209 | ); 210 | } 211 | } 212 | 213 | enum PagesEnum { 214 | about( 215 | pageIndex: 0, 216 | route: '/about', 217 | description: 'about', 218 | ), 219 | carrer( 220 | pageIndex: 1, 221 | route: '/carrer', 222 | description: 'carrer', 223 | ), 224 | contact( 225 | pageIndex: 2, 226 | route: '/contact', 227 | description: 'contact', 228 | ); 229 | 230 | const PagesEnum({ 231 | required this.pageIndex, 232 | required this.route, 233 | required this.description, 234 | }); 235 | 236 | final int pageIndex; 237 | final String route; 238 | final String description; 239 | } 240 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/initial/initial_page_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:homepage/app_store.dart'; 2 | 3 | class InitialPageController { 4 | final AppStore appStore; 5 | 6 | InitialPageController({required this.appStore}); 7 | } 8 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/widgets/contact_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 3 | import 'package:localization/localization.dart'; 4 | 5 | import 'social_button_widget.dart'; 6 | 7 | class ContactWidget extends StatelessWidget { 8 | final Function(String) onPressed; 9 | const ContactWidget({super.key, required this.onPressed}); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Wrap( 14 | alignment: WrapAlignment.spaceEvenly, 15 | children: [ 16 | SocialButtonWidget( 17 | text: 'Flutter Brasil Youtube Channel', 18 | icon: FontAwesomeIcons.youtube, 19 | url: 'https://youtube.flutterbrasil.com.br', 20 | color: Colors.red, 21 | tooltip: 'YouTube', 22 | onPressed: onPressed, 23 | ), 24 | SocialButtonWidget( 25 | text: 'Toshi Ossada Facebook', 26 | icon: FontAwesomeIcons.facebook, 27 | url: 'https://facebook.com/toshiossada', 28 | color: Colors.blue, 29 | tooltip: 'Facebook', 30 | onPressed: onPressed, 31 | ), 32 | SocialButtonWidget( 33 | text: 'Toshi Ossada GitHub', 34 | icon: FontAwesomeIcons.github, 35 | url: 'https://github.com/toshiossada', 36 | color: Colors.white, 37 | tooltip: 'GitHub', 38 | onPressed: onPressed, 39 | ), 40 | SocialButtonWidget( 41 | text: 'Toshi Ossada Linkedin', 42 | icon: FontAwesomeIcons.linkedin, 43 | url: 'https://linkedin.com/in/toshiossada', 44 | color: Colors.lightBlue.shade300, 45 | tooltip: 'LinkedIn', 46 | onPressed: onPressed, 47 | ), 48 | SocialButtonWidget( 49 | text: 'Toshi Ossada Instagram', 50 | icon: FontAwesomeIcons.instagram, 51 | url: 'https://instagram.com/toshiossada', 52 | color: Colors.pinkAccent, 53 | tooltip: 'Instagram', 54 | onPressed: onPressed, 55 | ), 56 | SocialButtonWidget( 57 | text: 'Toshi Ossada Medium Article', 58 | icon: FontAwesomeIcons.medium, 59 | url: 'https://toshiossada.medium.com/', 60 | color: Colors.white, 61 | tooltip: 'Medium', 62 | onPressed: onPressed, 63 | ), 64 | SocialButtonWidget( 65 | text: 'Toshi Ossada Contato Email', 66 | icon: FontAwesomeIcons.solidEnvelope, 67 | url: 'mailto:toshiossada@toshiossada.dev', 68 | color: Colors.grey[400]!, 69 | tooltip: 'send_email'.i18n(), 70 | onPressed: onPressed, 71 | ), 72 | ], 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/app/modules/home/pages/widgets/social_button_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 3 | import 'package:seo_renderer/renderers/link_renderer/link_renderer_web.dart'; 4 | 5 | class SocialButtonWidget extends StatelessWidget { 6 | final IconData icon; 7 | final String url; 8 | final String text; 9 | final Color color; 10 | final String tooltip; 11 | final Function(String) onPressed; 12 | 13 | const SocialButtonWidget({ 14 | super.key, 15 | required this.icon, 16 | required this.url, 17 | required this.text, 18 | required this.color, 19 | required this.tooltip, 20 | required this.onPressed, 21 | }); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return LinkRenderer( 26 | text: 'Toshi Ossada Facebook', 27 | href: url, 28 | child: IconButton( 29 | icon: FaIcon(icon, color: color, size: 28.0), 30 | tooltip: tooltip, 31 | onPressed: () => onPressed(url), 32 | splashRadius: 25.0, 33 | constraints: const BoxConstraints(), 34 | padding: const EdgeInsets.all(10), 35 | ), 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/app_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_modular/flutter_modular.dart'; 2 | 3 | import 'app/modules/home/home_module.dart'; 4 | import 'app/modules/home/pages/dne/dne_module.dart'; 5 | import 'core_module.dart'; 6 | 7 | class AppModule extends Module { 8 | @override 9 | List get imports => [CoreModule()]; 10 | @override 11 | void routes(RouteManager r) { 12 | r 13 | ..module('/', module: HomeModule()) 14 | ..module('/dne', module: DNEModule()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/app_store.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class AppStore { 4 | final Map supportedLocales = { 5 | Locale('en', 'US'): 'English', 6 | Locale('pt', 'BR'): 'Português', 7 | }; 8 | 9 | final ValueNotifier _locale = ValueNotifier(null); 10 | 11 | ValueNotifier get localeNotifier => _locale; 12 | Locale? get locale => _locale.value; 13 | set locale(Locale? newLocale) { 14 | if (_locale.value != newLocale) { 15 | _locale.value = newLocale; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/app_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_localizations/flutter_localizations.dart'; 3 | import 'package:flutter_modular/flutter_modular.dart'; 4 | import 'package:localization/localization.dart'; 5 | import 'package:seo_renderer/seo_renderer.dart'; 6 | 7 | import 'app_store.dart'; 8 | 9 | class AppWidget extends StatefulWidget { 10 | const AppWidget({super.key}); 11 | 12 | @override 13 | State createState() => _AppWidgetState(); 14 | } 15 | 16 | class _AppWidgetState extends State { 17 | AppStore get controller => Modular.get(); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | Modular.setObservers([seoRouteObserver]); 22 | LocalJsonLocalization.delegate.directories = ['assets/lang']; 23 | return RobotDetector( 24 | child: ValueListenableBuilder( 25 | valueListenable: controller.localeNotifier, 26 | builder: (_, value, __) { 27 | return MaterialApp.router( 28 | title: 'Toshi Ossada', 29 | key: Key(value == null 30 | ? 'locale' 31 | : controller.supportedLocales[value]!.toString()), 32 | locale: value, 33 | localeResolutionCallback: (locale, supportedLocales) { 34 | Locale? finalLocale = Locale('en', 'US'); 35 | 36 | if (supportedLocales.contains(locale)) { 37 | finalLocale = locale; 38 | } 39 | 40 | if (locale?.languageCode == 'pt') { 41 | finalLocale == Locale('pt', 'BR'); 42 | } 43 | 44 | WidgetsBinding.instance.addPostFrameCallback((_) { 45 | if (mounted) { 46 | if (controller.locale != finalLocale) { 47 | controller.locale = finalLocale; 48 | } 49 | } 50 | }); 51 | 52 | return finalLocale; 53 | }, 54 | localizationsDelegates: [ 55 | GlobalMaterialLocalizations.delegate, 56 | GlobalWidgetsLocalizations.delegate, 57 | GlobalCupertinoLocalizations.delegate, 58 | LocalJsonLocalization.delegate, 59 | ], 60 | supportedLocales: controller.supportedLocales.keys, 61 | routerConfig: Modular.routerConfig, 62 | theme: ThemeData( 63 | colorScheme: const ColorScheme.dark(), 64 | ), 65 | ); 66 | }), 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/core_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_modular/flutter_modular.dart'; 2 | import 'package:homepage/app_store.dart'; 3 | 4 | class CoreModule extends Module { 5 | @override 6 | void exportedBinds(Injector i) { 7 | i.addSingleton(AppStore.new); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_modular/flutter_modular.dart'; 3 | 4 | import 'app_module.dart'; 5 | import 'app_widget.dart'; 6 | 7 | void main() { 8 | runApp(ModularApp(module: AppModule(), child: AppWidget())); 9 | } 10 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.12.0" 12 | auto_injector: 13 | dependency: transitive 14 | description: 15 | name: auto_injector 16 | sha256: ad7a95d7c381363d48b54e00cb680f024fd97009067244454e9b4850337608e8 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.0" 20 | boolean_selector: 21 | dependency: transitive 22 | description: 23 | name: boolean_selector 24 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "2.1.2" 28 | characters: 29 | dependency: transitive 30 | description: 31 | name: characters 32 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.4.0" 36 | clock: 37 | dependency: transitive 38 | description: 39 | name: clock 40 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.1.2" 44 | collection: 45 | dependency: transitive 46 | description: 47 | name: collection 48 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.19.1" 52 | crypto: 53 | dependency: transitive 54 | description: 55 | name: crypto 56 | sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "3.0.6" 60 | cupertino_icons: 61 | dependency: "direct main" 62 | description: 63 | name: cupertino_icons 64 | sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.0.8" 68 | dio: 69 | dependency: "direct main" 70 | description: 71 | name: dio 72 | sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "5.8.0+1" 76 | dio_web_adapter: 77 | dependency: transitive 78 | description: 79 | name: dio_web_adapter 80 | sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "2.1.1" 84 | fake_async: 85 | dependency: transitive 86 | description: 87 | name: fake_async 88 | sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "1.3.2" 92 | fixnum: 93 | dependency: transitive 94 | description: 95 | name: fixnum 96 | sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "1.1.1" 100 | flutter: 101 | dependency: "direct main" 102 | description: flutter 103 | source: sdk 104 | version: "0.0.0" 105 | flutter_lints: 106 | dependency: "direct dev" 107 | description: 108 | name: flutter_lints 109 | sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" 110 | url: "https://pub.dev" 111 | source: hosted 112 | version: "5.0.0" 113 | flutter_localizations: 114 | dependency: "direct main" 115 | description: flutter 116 | source: sdk 117 | version: "0.0.0" 118 | flutter_modular: 119 | dependency: "direct main" 120 | description: 121 | name: flutter_modular 122 | sha256: bc17a1eb1da676b9111e59d27834fb6673bdea01aead12f0803a0847ff9d451c 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "6.3.4" 126 | flutter_test: 127 | dependency: "direct dev" 128 | description: flutter 129 | source: sdk 130 | version: "0.0.0" 131 | flutter_web_plugins: 132 | dependency: "direct main" 133 | description: flutter 134 | source: sdk 135 | version: "0.0.0" 136 | font_awesome_flutter: 137 | dependency: "direct main" 138 | description: 139 | name: font_awesome_flutter 140 | sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a 141 | url: "https://pub.dev" 142 | source: hosted 143 | version: "10.8.0" 144 | http_parser: 145 | dependency: transitive 146 | description: 147 | name: http_parser 148 | sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" 149 | url: "https://pub.dev" 150 | source: hosted 151 | version: "4.1.2" 152 | intl: 153 | dependency: "direct main" 154 | description: 155 | name: intl 156 | sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf 157 | url: "https://pub.dev" 158 | source: hosted 159 | version: "0.19.0" 160 | leak_tracker: 161 | dependency: transitive 162 | description: 163 | name: leak_tracker 164 | sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec 165 | url: "https://pub.dev" 166 | source: hosted 167 | version: "10.0.8" 168 | leak_tracker_flutter_testing: 169 | dependency: transitive 170 | description: 171 | name: leak_tracker_flutter_testing 172 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 173 | url: "https://pub.dev" 174 | source: hosted 175 | version: "3.0.9" 176 | leak_tracker_testing: 177 | dependency: transitive 178 | description: 179 | name: leak_tracker_testing 180 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 181 | url: "https://pub.dev" 182 | source: hosted 183 | version: "3.0.1" 184 | lints: 185 | dependency: transitive 186 | description: 187 | name: lints 188 | sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 189 | url: "https://pub.dev" 190 | source: hosted 191 | version: "5.1.1" 192 | localization: 193 | dependency: "direct main" 194 | description: 195 | name: localization 196 | sha256: "9fa21644b75ca3fe844f8f115d03cd6fdc675054dd9aab6c5de5861145ea57b5" 197 | url: "https://pub.dev" 198 | source: hosted 199 | version: "2.1.1" 200 | mailto: 201 | dependency: "direct main" 202 | description: 203 | name: mailto 204 | sha256: f8c5ce39e0eaa94a856795b2855af7f66aac37f7c3b70ac5c26ab00b94685445 205 | url: "https://pub.dev" 206 | source: hosted 207 | version: "2.0.0" 208 | matcher: 209 | dependency: transitive 210 | description: 211 | name: matcher 212 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 213 | url: "https://pub.dev" 214 | source: hosted 215 | version: "0.12.17" 216 | material_color_utilities: 217 | dependency: transitive 218 | description: 219 | name: material_color_utilities 220 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 221 | url: "https://pub.dev" 222 | source: hosted 223 | version: "0.11.1" 224 | meta: 225 | dependency: transitive 226 | description: 227 | name: meta 228 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 229 | url: "https://pub.dev" 230 | source: hosted 231 | version: "1.16.0" 232 | modular_core: 233 | dependency: transitive 234 | description: 235 | name: modular_core 236 | sha256: bd60317c81cff3a510aca19d6ddd661c7c79e3cba97b9f39e9ad199156ff255d 237 | url: "https://pub.dev" 238 | source: hosted 239 | version: "3.3.3" 240 | path: 241 | dependency: transitive 242 | description: 243 | name: path 244 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 245 | url: "https://pub.dev" 246 | source: hosted 247 | version: "1.9.1" 248 | plugin_platform_interface: 249 | dependency: transitive 250 | description: 251 | name: plugin_platform_interface 252 | sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" 253 | url: "https://pub.dev" 254 | source: hosted 255 | version: "2.1.8" 256 | result_dart: 257 | dependency: transitive 258 | description: 259 | name: result_dart 260 | sha256: "3c69c864a08df0f413a86be211d07405e9a53cc1ac111e3cc8365845a0fb5288" 261 | url: "https://pub.dev" 262 | source: hosted 263 | version: "1.1.1" 264 | seo_renderer: 265 | dependency: "direct main" 266 | description: 267 | name: seo_renderer 268 | sha256: "2f687b566467387625404963ed0a58060d6d06639ff100611df3668dab14d3dc" 269 | url: "https://pub.dev" 270 | source: hosted 271 | version: "0.6.0" 272 | sky_engine: 273 | dependency: transitive 274 | description: flutter 275 | source: sdk 276 | version: "0.0.0" 277 | source_span: 278 | dependency: transitive 279 | description: 280 | name: source_span 281 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 282 | url: "https://pub.dev" 283 | source: hosted 284 | version: "1.10.1" 285 | sprintf: 286 | dependency: transitive 287 | description: 288 | name: sprintf 289 | sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" 290 | url: "https://pub.dev" 291 | source: hosted 292 | version: "7.0.0" 293 | stack_trace: 294 | dependency: transitive 295 | description: 296 | name: stack_trace 297 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 298 | url: "https://pub.dev" 299 | source: hosted 300 | version: "1.12.1" 301 | stream_channel: 302 | dependency: transitive 303 | description: 304 | name: stream_channel 305 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 306 | url: "https://pub.dev" 307 | source: hosted 308 | version: "2.1.4" 309 | string_scanner: 310 | dependency: transitive 311 | description: 312 | name: string_scanner 313 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 314 | url: "https://pub.dev" 315 | source: hosted 316 | version: "1.4.1" 317 | term_glyph: 318 | dependency: transitive 319 | description: 320 | name: term_glyph 321 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 322 | url: "https://pub.dev" 323 | source: hosted 324 | version: "1.2.2" 325 | test_api: 326 | dependency: transitive 327 | description: 328 | name: test_api 329 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 330 | url: "https://pub.dev" 331 | source: hosted 332 | version: "0.7.4" 333 | timeline_tile: 334 | dependency: "direct main" 335 | description: 336 | name: timeline_tile 337 | sha256: "85ec2023c67137397c2812e3e848b2fb20b410b67cd9aff304bb5480c376fc0c" 338 | url: "https://pub.dev" 339 | source: hosted 340 | version: "2.0.0" 341 | typed_data: 342 | dependency: transitive 343 | description: 344 | name: typed_data 345 | sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 346 | url: "https://pub.dev" 347 | source: hosted 348 | version: "1.4.0" 349 | url_launcher: 350 | dependency: "direct main" 351 | description: 352 | name: url_launcher 353 | sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" 354 | url: "https://pub.dev" 355 | source: hosted 356 | version: "6.3.1" 357 | url_launcher_android: 358 | dependency: transitive 359 | description: 360 | name: url_launcher_android 361 | sha256: "1d0eae19bd7606ef60fe69ef3b312a437a16549476c42321d5dc1506c9ca3bf4" 362 | url: "https://pub.dev" 363 | source: hosted 364 | version: "6.3.15" 365 | url_launcher_ios: 366 | dependency: transitive 367 | description: 368 | name: url_launcher_ios 369 | sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" 370 | url: "https://pub.dev" 371 | source: hosted 372 | version: "6.3.3" 373 | url_launcher_linux: 374 | dependency: transitive 375 | description: 376 | name: url_launcher_linux 377 | sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" 378 | url: "https://pub.dev" 379 | source: hosted 380 | version: "3.2.1" 381 | url_launcher_macos: 382 | dependency: transitive 383 | description: 384 | name: url_launcher_macos 385 | sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" 386 | url: "https://pub.dev" 387 | source: hosted 388 | version: "3.2.2" 389 | url_launcher_platform_interface: 390 | dependency: transitive 391 | description: 392 | name: url_launcher_platform_interface 393 | sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" 394 | url: "https://pub.dev" 395 | source: hosted 396 | version: "2.3.2" 397 | url_launcher_web: 398 | dependency: transitive 399 | description: 400 | name: url_launcher_web 401 | sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" 402 | url: "https://pub.dev" 403 | source: hosted 404 | version: "2.4.0" 405 | url_launcher_windows: 406 | dependency: transitive 407 | description: 408 | name: url_launcher_windows 409 | sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" 410 | url: "https://pub.dev" 411 | source: hosted 412 | version: "3.1.4" 413 | uuid: 414 | dependency: transitive 415 | description: 416 | name: uuid 417 | sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff 418 | url: "https://pub.dev" 419 | source: hosted 420 | version: "4.5.1" 421 | vector_math: 422 | dependency: transitive 423 | description: 424 | name: vector_math 425 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 426 | url: "https://pub.dev" 427 | source: hosted 428 | version: "2.1.4" 429 | vm_service: 430 | dependency: transitive 431 | description: 432 | name: vm_service 433 | sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" 434 | url: "https://pub.dev" 435 | source: hosted 436 | version: "14.3.1" 437 | web: 438 | dependency: transitive 439 | description: 440 | name: web 441 | sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" 442 | url: "https://pub.dev" 443 | source: hosted 444 | version: "1.1.1" 445 | sdks: 446 | dart: ">=3.7.0-0 <4.0.0" 447 | flutter: ">=3.27.0" 448 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: homepage 2 | description: A new Flutter project. 3 | 4 | publish_to: 'none' 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: '>=3.6.1 <4.0.0' 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | flutter_web_plugins: 15 | sdk: flutter 16 | flutter_localizations: 17 | sdk: flutter 18 | 19 | cupertino_icons: ^1.0.2 20 | font_awesome_flutter: ^10.8.0 21 | url_launcher: ^6.0.12 22 | mailto: ^2.0.0 23 | seo_renderer: ^0.6.0 24 | flutter_modular: ^6.3.4 25 | intl: ^0.19.0 26 | timeline_tile: ^2.0.0 27 | localization: ^2.1.1 28 | dio: ^5.8.0+1 29 | 30 | dev_dependencies: 31 | flutter_test: 32 | sdk: flutter 33 | 34 | flutter_lints: ^5.0.0 35 | 36 | flutter: 37 | uses-material-design: true 38 | assets: 39 | - assets/images/ 40 | - assets/images/awards/ 41 | - assets/images/flutterbrasil/ 42 | - assets/experiences.json 43 | - assets/experiences_enUs.json 44 | - assets/lang/ 45 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:homepage/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/favicon.ico -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/favicon.png -------------------------------------------------------------------------------- /web/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /web/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /web/icons/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/android-icon-144x144.png -------------------------------------------------------------------------------- /web/icons/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/android-icon-192x192.png -------------------------------------------------------------------------------- /web/icons/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/android-icon-36x36.png -------------------------------------------------------------------------------- /web/icons/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/android-icon-48x48.png -------------------------------------------------------------------------------- /web/icons/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/android-icon-72x72.png -------------------------------------------------------------------------------- /web/icons/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/android-icon-96x96.png -------------------------------------------------------------------------------- /web/icons/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-114x114.png -------------------------------------------------------------------------------- /web/icons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-120x120.png -------------------------------------------------------------------------------- /web/icons/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-144x144.png -------------------------------------------------------------------------------- /web/icons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-152x152.png -------------------------------------------------------------------------------- /web/icons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-180x180.png -------------------------------------------------------------------------------- /web/icons/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-57x57.png -------------------------------------------------------------------------------- /web/icons/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-60x60.png -------------------------------------------------------------------------------- /web/icons/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-72x72.png -------------------------------------------------------------------------------- /web/icons/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-76x76.png -------------------------------------------------------------------------------- /web/icons/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon-precomposed.png -------------------------------------------------------------------------------- /web/icons/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-icon.png -------------------------------------------------------------------------------- /web/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /web/icons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /web/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/favicon-16x16.png -------------------------------------------------------------------------------- /web/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/favicon-32x32.png -------------------------------------------------------------------------------- /web/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/favicon-96x96.png -------------------------------------------------------------------------------- /web/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/favicon.ico -------------------------------------------------------------------------------- /web/icons/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "App", 3 | "icons": [ 4 | { 5 | "src": "\/android-icon-36x36.png", 6 | "sizes": "36x36", 7 | "type": "image\/png", 8 | "density": "0.75" 9 | }, 10 | { 11 | "src": "\/android-icon-48x48.png", 12 | "sizes": "48x48", 13 | "type": "image\/png", 14 | "density": "1.0" 15 | }, 16 | { 17 | "src": "\/android-icon-72x72.png", 18 | "sizes": "72x72", 19 | "type": "image\/png", 20 | "density": "1.5" 21 | }, 22 | { 23 | "src": "\/android-icon-96x96.png", 24 | "sizes": "96x96", 25 | "type": "image\/png", 26 | "density": "2.0" 27 | }, 28 | { 29 | "src": "\/android-icon-144x144.png", 30 | "sizes": "144x144", 31 | "type": "image\/png", 32 | "density": "3.0" 33 | }, 34 | { 35 | "src": "\/android-icon-192x192.png", 36 | "sizes": "192x192", 37 | "type": "image\/png", 38 | "density": "4.0" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /web/icons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/ms-icon-144x144.png -------------------------------------------------------------------------------- /web/icons/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/ms-icon-150x150.png -------------------------------------------------------------------------------- /web/icons/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/ms-icon-310x310.png -------------------------------------------------------------------------------- /web/icons/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/icons/ms-icon-70x70.png -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Toshi Ossada 6 | 10 | 14 | 18 | 19 | 20 | 21 | 22 | 27 | 32 | 37 | 42 | 47 | 52 | 57 | 62 | 67 | 73 | 79 | 85 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 107 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /web/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/web/logo.png -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homepage", 3 | "short_name": "homepage", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/android-chrome-192x192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/android-chrome-512x512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/android-chrome-512x512.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/android-chrome-512x512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /web/style.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Roboto); 2 | 3 | @import url(/packages/font_awesome/css/all.css); /* font_awesome css file is imported here */ 4 | 5 | html, body { 6 | width: 100%; 7 | height: 100%; 8 | margin: 0; 9 | padding: 0; 10 | font-family: 'Roboto', sans-serif; 11 | } 12 | 13 | #output { 14 | padding: 20px; 15 | text-align: center; 16 | } -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(homepage LANGUAGES CXX) 3 | 4 | set(BINARY_NAME "homepage") 5 | 6 | cmake_policy(SET CMP0063 NEW) 7 | 8 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 9 | 10 | # Configure build options. 11 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 12 | if(IS_MULTICONFIG) 13 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 14 | CACHE STRING "" FORCE) 15 | else() 16 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 17 | set(CMAKE_BUILD_TYPE "Debug" CACHE 18 | STRING "Flutter build mode" FORCE) 19 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 20 | "Debug" "Profile" "Release") 21 | endif() 22 | endif() 23 | 24 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 25 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 26 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 27 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 28 | 29 | # Use Unicode for all projects. 30 | add_definitions(-DUNICODE -D_UNICODE) 31 | 32 | # Compilation settings that should be applied to most targets. 33 | function(APPLY_STANDARD_SETTINGS TARGET) 34 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 35 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 36 | target_compile_options(${TARGET} PRIVATE /EHsc) 37 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 38 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 39 | endfunction() 40 | 41 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 42 | 43 | # Flutter library and tool build rules. 44 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 45 | 46 | # Application build 47 | add_subdirectory("runner") 48 | 49 | # Generated plugin build rules, which manage building the plugins and adding 50 | # them to the application. 51 | include(flutter/generated_plugins.cmake) 52 | 53 | 54 | # === Installation === 55 | # Support files are copied into place next to the executable, so that it can 56 | # run in place. This is done instead of making a separate bundle (as on Linux) 57 | # so that building and running from within Visual Studio will work. 58 | set(BUILD_BUNDLE_DIR "$") 59 | # Make the "install" step default, as it's required to run. 60 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 61 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 62 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 63 | endif() 64 | 65 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 66 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 67 | 68 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 69 | COMPONENT Runtime) 70 | 71 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 72 | COMPONENT Runtime) 73 | 74 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 75 | COMPONENT Runtime) 76 | 77 | if(PLUGIN_BUNDLED_LIBRARIES) 78 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 79 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 80 | COMPONENT Runtime) 81 | endif() 82 | 83 | # Fully re-copy the assets directory on each build to avoid having stale files 84 | # from a previous install. 85 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 86 | install(CODE " 87 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 88 | " COMPONENT Runtime) 89 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 90 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 91 | 92 | # Install the AOT library on non-Debug builds only. 93 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 94 | CONFIGURATIONS Profile;Release 95 | COMPONENT Runtime) 96 | -------------------------------------------------------------------------------- /windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 11 | 12 | # Set fallback configurations for older versions of the flutter tool. 13 | if (NOT DEFINED FLUTTER_TARGET_PLATFORM) 14 | set(FLUTTER_TARGET_PLATFORM "windows-x64") 15 | endif() 16 | 17 | # === Flutter Library === 18 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 19 | 20 | # Published to parent scope for install step. 21 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 22 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 23 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 24 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 25 | 26 | list(APPEND FLUTTER_LIBRARY_HEADERS 27 | "flutter_export.h" 28 | "flutter_windows.h" 29 | "flutter_messenger.h" 30 | "flutter_plugin_registrar.h" 31 | "flutter_texture_registrar.h" 32 | ) 33 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 34 | add_library(flutter INTERFACE) 35 | target_include_directories(flutter INTERFACE 36 | "${EPHEMERAL_DIR}" 37 | ) 38 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 39 | add_dependencies(flutter flutter_assemble) 40 | 41 | # === Wrapper === 42 | list(APPEND CPP_WRAPPER_SOURCES_CORE 43 | "core_implementations.cc" 44 | "standard_codec.cc" 45 | ) 46 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 47 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 48 | "plugin_registrar.cc" 49 | ) 50 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 51 | list(APPEND CPP_WRAPPER_SOURCES_APP 52 | "flutter_engine.cc" 53 | "flutter_view_controller.cc" 54 | ) 55 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 56 | 57 | # Wrapper sources needed for a plugin. 58 | add_library(flutter_wrapper_plugin STATIC 59 | ${CPP_WRAPPER_SOURCES_CORE} 60 | ${CPP_WRAPPER_SOURCES_PLUGIN} 61 | ) 62 | apply_standard_settings(flutter_wrapper_plugin) 63 | set_target_properties(flutter_wrapper_plugin PROPERTIES 64 | POSITION_INDEPENDENT_CODE ON) 65 | set_target_properties(flutter_wrapper_plugin PROPERTIES 66 | CXX_VISIBILITY_PRESET hidden) 67 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 68 | target_include_directories(flutter_wrapper_plugin PUBLIC 69 | "${WRAPPER_ROOT}/include" 70 | ) 71 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 72 | 73 | # Wrapper sources needed for the runner. 74 | add_library(flutter_wrapper_app STATIC 75 | ${CPP_WRAPPER_SOURCES_CORE} 76 | ${CPP_WRAPPER_SOURCES_APP} 77 | ) 78 | apply_standard_settings(flutter_wrapper_app) 79 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 80 | target_include_directories(flutter_wrapper_app PUBLIC 81 | "${WRAPPER_ROOT}/include" 82 | ) 83 | add_dependencies(flutter_wrapper_app flutter_assemble) 84 | 85 | # === Flutter tool backend === 86 | # _phony_ is a non-existent file to force this command to run every time, 87 | # since currently there's no way to get a full input/output list from the 88 | # flutter tool. 89 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 90 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 91 | add_custom_command( 92 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 93 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 94 | ${CPP_WRAPPER_SOURCES_APP} 95 | ${PHONY_OUTPUT} 96 | COMMAND ${CMAKE_COMMAND} -E env 97 | ${FLUTTER_TOOL_ENVIRONMENT} 98 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 99 | ${FLUTTER_TARGET_PLATFORM} $ 100 | VERBATIM 101 | ) 102 | add_custom_target(flutter_assemble DEPENDS 103 | "${FLUTTER_LIBRARY}" 104 | ${FLUTTER_LIBRARY_HEADERS} 105 | ${CPP_WRAPPER_SOURCES_CORE} 106 | ${CPP_WRAPPER_SOURCES_PLUGIN} 107 | ${CPP_WRAPPER_SOURCES_APP} 108 | ) 109 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | 11 | void RegisterPlugins(flutter::PluginRegistry* registry) { 12 | UrlLauncherWindowsRegisterWithRegistrar( 13 | registry->GetRegistrarForPlugin("UrlLauncherWindows")); 14 | } 15 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | url_launcher_windows 7 | ) 8 | 9 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 10 | ) 11 | 12 | set(PLUGIN_BUNDLED_LIBRARIES) 13 | 14 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 15 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 16 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 18 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 19 | endforeach(plugin) 20 | 21 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 22 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 23 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 24 | endforeach(ffi_plugin) 25 | -------------------------------------------------------------------------------- /windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(runner LANGUAGES CXX) 3 | 4 | add_executable(${BINARY_NAME} WIN32 5 | "flutter_window.cpp" 6 | "main.cpp" 7 | "utils.cpp" 8 | "win32_window.cpp" 9 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 10 | "Runner.rc" 11 | "runner.exe.manifest" 12 | ) 13 | apply_standard_settings(${BINARY_NAME}) 14 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 15 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 16 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 17 | add_dependencies(${BINARY_NAME} flutter_assemble) 18 | -------------------------------------------------------------------------------- /windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "br.com.toshiossada" "\0" 93 | VALUE "FileDescription", "A new Flutter project." "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "homepage" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2021 br.com.toshiossada. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "homepage.exe" "\0" 98 | VALUE "ProductName", "homepage" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | return true; 30 | } 31 | 32 | void FlutterWindow::OnDestroy() { 33 | if (flutter_controller_) { 34 | flutter_controller_ = nullptr; 35 | } 36 | 37 | Win32Window::OnDestroy(); 38 | } 39 | 40 | LRESULT 41 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 42 | WPARAM const wparam, 43 | LPARAM const lparam) noexcept { 44 | // Give Flutter, including plugins, an opportunity to handle window messages. 45 | if (flutter_controller_) { 46 | std::optional result = 47 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 48 | lparam); 49 | if (result) { 50 | return *result; 51 | } 52 | } 53 | 54 | switch (message) { 55 | case WM_FONTCHANGE: 56 | flutter_controller_->engine()->ReloadSystemFonts(); 57 | break; 58 | } 59 | 60 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 61 | } 62 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.CreateAndShow(L"homepage", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toshiossada/flutter_web_site/f8199459b83efa10d698d08633217ada9aaa86c2/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | if (target_length == 0) { 52 | return std::string(); 53 | } 54 | std::string utf8_string; 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /windows/runner/win32_window.cpp: -------------------------------------------------------------------------------- 1 | #include "win32_window.h" 2 | 3 | #include 4 | 5 | #include "resource.h" 6 | 7 | namespace { 8 | 9 | constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; 10 | 11 | // The number of Win32Window objects that currently exist. 12 | static int g_active_window_count = 0; 13 | 14 | using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); 15 | 16 | // Scale helper to convert logical scaler values to physical using passed in 17 | // scale factor 18 | int Scale(int source, double scale_factor) { 19 | return static_cast(source * scale_factor); 20 | } 21 | 22 | // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. 23 | // This API is only needed for PerMonitor V1 awareness mode. 24 | void EnableFullDpiSupportIfAvailable(HWND hwnd) { 25 | HMODULE user32_module = LoadLibraryA("User32.dll"); 26 | if (!user32_module) { 27 | return; 28 | } 29 | auto enable_non_client_dpi_scaling = 30 | reinterpret_cast( 31 | GetProcAddress(user32_module, "EnableNonClientDpiScaling")); 32 | if (enable_non_client_dpi_scaling != nullptr) { 33 | enable_non_client_dpi_scaling(hwnd); 34 | FreeLibrary(user32_module); 35 | } 36 | } 37 | 38 | } // namespace 39 | 40 | // Manages the Win32Window's window class registration. 41 | class WindowClassRegistrar { 42 | public: 43 | ~WindowClassRegistrar() = default; 44 | 45 | // Returns the singleton registar instance. 46 | static WindowClassRegistrar* GetInstance() { 47 | if (!instance_) { 48 | instance_ = new WindowClassRegistrar(); 49 | } 50 | return instance_; 51 | } 52 | 53 | // Returns the name of the window class, registering the class if it hasn't 54 | // previously been registered. 55 | const wchar_t* GetWindowClass(); 56 | 57 | // Unregisters the window class. Should only be called if there are no 58 | // instances of the window. 59 | void UnregisterWindowClass(); 60 | 61 | private: 62 | WindowClassRegistrar() = default; 63 | 64 | static WindowClassRegistrar* instance_; 65 | 66 | bool class_registered_ = false; 67 | }; 68 | 69 | WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; 70 | 71 | const wchar_t* WindowClassRegistrar::GetWindowClass() { 72 | if (!class_registered_) { 73 | WNDCLASS window_class{}; 74 | window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); 75 | window_class.lpszClassName = kWindowClassName; 76 | window_class.style = CS_HREDRAW | CS_VREDRAW; 77 | window_class.cbClsExtra = 0; 78 | window_class.cbWndExtra = 0; 79 | window_class.hInstance = GetModuleHandle(nullptr); 80 | window_class.hIcon = 81 | LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); 82 | window_class.hbrBackground = 0; 83 | window_class.lpszMenuName = nullptr; 84 | window_class.lpfnWndProc = Win32Window::WndProc; 85 | RegisterClass(&window_class); 86 | class_registered_ = true; 87 | } 88 | return kWindowClassName; 89 | } 90 | 91 | void WindowClassRegistrar::UnregisterWindowClass() { 92 | UnregisterClass(kWindowClassName, nullptr); 93 | class_registered_ = false; 94 | } 95 | 96 | Win32Window::Win32Window() { 97 | ++g_active_window_count; 98 | } 99 | 100 | Win32Window::~Win32Window() { 101 | --g_active_window_count; 102 | Destroy(); 103 | } 104 | 105 | bool Win32Window::CreateAndShow(const std::wstring& title, 106 | const Point& origin, 107 | const Size& size) { 108 | Destroy(); 109 | 110 | const wchar_t* window_class = 111 | WindowClassRegistrar::GetInstance()->GetWindowClass(); 112 | 113 | const POINT target_point = {static_cast(origin.x), 114 | static_cast(origin.y)}; 115 | HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); 116 | UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); 117 | double scale_factor = dpi / 96.0; 118 | 119 | HWND window = CreateWindow( 120 | window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 121 | Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), 122 | Scale(size.width, scale_factor), Scale(size.height, scale_factor), 123 | nullptr, nullptr, GetModuleHandle(nullptr), this); 124 | 125 | if (!window) { 126 | return false; 127 | } 128 | 129 | return OnCreate(); 130 | } 131 | 132 | // static 133 | LRESULT CALLBACK Win32Window::WndProc(HWND const window, 134 | UINT const message, 135 | WPARAM const wparam, 136 | LPARAM const lparam) noexcept { 137 | if (message == WM_NCCREATE) { 138 | auto window_struct = reinterpret_cast(lparam); 139 | SetWindowLongPtr(window, GWLP_USERDATA, 140 | reinterpret_cast(window_struct->lpCreateParams)); 141 | 142 | auto that = static_cast(window_struct->lpCreateParams); 143 | EnableFullDpiSupportIfAvailable(window); 144 | that->window_handle_ = window; 145 | } else if (Win32Window* that = GetThisFromHandle(window)) { 146 | return that->MessageHandler(window, message, wparam, lparam); 147 | } 148 | 149 | return DefWindowProc(window, message, wparam, lparam); 150 | } 151 | 152 | LRESULT 153 | Win32Window::MessageHandler(HWND hwnd, 154 | UINT const message, 155 | WPARAM const wparam, 156 | LPARAM const lparam) noexcept { 157 | switch (message) { 158 | case WM_DESTROY: 159 | window_handle_ = nullptr; 160 | Destroy(); 161 | if (quit_on_close_) { 162 | PostQuitMessage(0); 163 | } 164 | return 0; 165 | 166 | case WM_DPICHANGED: { 167 | auto newRectSize = reinterpret_cast(lparam); 168 | LONG newWidth = newRectSize->right - newRectSize->left; 169 | LONG newHeight = newRectSize->bottom - newRectSize->top; 170 | 171 | SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, 172 | newHeight, SWP_NOZORDER | SWP_NOACTIVATE); 173 | 174 | return 0; 175 | } 176 | case WM_SIZE: { 177 | RECT rect = GetClientArea(); 178 | if (child_content_ != nullptr) { 179 | // Size and position the child window. 180 | MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, 181 | rect.bottom - rect.top, TRUE); 182 | } 183 | return 0; 184 | } 185 | 186 | case WM_ACTIVATE: 187 | if (child_content_ != nullptr) { 188 | SetFocus(child_content_); 189 | } 190 | return 0; 191 | } 192 | 193 | return DefWindowProc(window_handle_, message, wparam, lparam); 194 | } 195 | 196 | void Win32Window::Destroy() { 197 | OnDestroy(); 198 | 199 | if (window_handle_) { 200 | DestroyWindow(window_handle_); 201 | window_handle_ = nullptr; 202 | } 203 | if (g_active_window_count == 0) { 204 | WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); 205 | } 206 | } 207 | 208 | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { 209 | return reinterpret_cast( 210 | GetWindowLongPtr(window, GWLP_USERDATA)); 211 | } 212 | 213 | void Win32Window::SetChildContent(HWND content) { 214 | child_content_ = content; 215 | SetParent(content, window_handle_); 216 | RECT frame = GetClientArea(); 217 | 218 | MoveWindow(content, frame.left, frame.top, frame.right - frame.left, 219 | frame.bottom - frame.top, true); 220 | 221 | SetFocus(child_content_); 222 | } 223 | 224 | RECT Win32Window::GetClientArea() { 225 | RECT frame; 226 | GetClientRect(window_handle_, &frame); 227 | return frame; 228 | } 229 | 230 | HWND Win32Window::GetHandle() { 231 | return window_handle_; 232 | } 233 | 234 | void Win32Window::SetQuitOnClose(bool quit_on_close) { 235 | quit_on_close_ = quit_on_close; 236 | } 237 | 238 | bool Win32Window::OnCreate() { 239 | // No-op; provided for subclasses. 240 | return true; 241 | } 242 | 243 | void Win32Window::OnDestroy() { 244 | // No-op; provided for subclasses. 245 | } 246 | -------------------------------------------------------------------------------- /windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates and shows a win32 window with |title| and position and size using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size to will treat the width height passed in to this function 35 | // as logical pixels and scale to appropriate for the default monitor. Returns 36 | // true if the window was created successfully. 37 | bool CreateAndShow(const std::wstring& title, 38 | const Point& origin, 39 | const Size& size); 40 | 41 | // Release OS resources associated with window. 42 | void Destroy(); 43 | 44 | // Inserts |content| into the window tree. 45 | void SetChildContent(HWND content); 46 | 47 | // Returns the backing Window handle to enable clients to set icon and other 48 | // window properties. Returns nullptr if the window has been destroyed. 49 | HWND GetHandle(); 50 | 51 | // If true, closing this window will quit the application. 52 | void SetQuitOnClose(bool quit_on_close); 53 | 54 | // Return a RECT representing the bounds of the current client area. 55 | RECT GetClientArea(); 56 | 57 | protected: 58 | // Processes and route salient window messages for mouse handling, 59 | // size change and DPI. Delegates handling of these to member overloads that 60 | // inheriting classes can handle. 61 | virtual LRESULT MessageHandler(HWND window, 62 | UINT const message, 63 | WPARAM const wparam, 64 | LPARAM const lparam) noexcept; 65 | 66 | // Called when CreateAndShow is called, allowing subclass window-related 67 | // setup. Subclasses should return false if setup fails. 68 | virtual bool OnCreate(); 69 | 70 | // Called when Destroy is called. 71 | virtual void OnDestroy(); 72 | 73 | private: 74 | friend class WindowClassRegistrar; 75 | 76 | // OS callback called by message pump. Handles the WM_NCCREATE message which 77 | // is passed when the non-client area is being created and enables automatic 78 | // non-client DPI scaling so that the non-client area automatically 79 | // responsponds to changes in DPI. All other messages are handled by 80 | // MessageHandler. 81 | static LRESULT CALLBACK WndProc(HWND const window, 82 | UINT const message, 83 | WPARAM const wparam, 84 | LPARAM const lparam) noexcept; 85 | 86 | // Retrieves a class instance pointer for |window| 87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 88 | 89 | bool quit_on_close_ = false; 90 | 91 | // window handle for top level window. 92 | HWND window_handle_ = nullptr; 93 | 94 | // window handle for hosted content. 95 | HWND child_content_ = nullptr; 96 | }; 97 | 98 | #endif // RUNNER_WIN32_WINDOW_H_ 99 | --------------------------------------------------------------------------------