├── .github
├── FUNDING.yml
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── flutter-ci.yml
├── .gitignore
├── .idea
├── .gitignore
└── runConfigurations
│ ├── development.xml
│ └── production.xml
├── .metadata
├── .tool-versions
├── .vscode
├── launch.json
└── settings.json
├── CODE_OF_CONDUCT.md
├── LICENSE
├── Makefile
├── README.md
├── analysis_options.yaml
├── android
├── app
│ ├── build.gradle
│ ├── signingConfigs
│ │ ├── debug.gradle
│ │ ├── debug.keystore
│ │ ├── release.gradle
│ │ └── release.keystore
│ └── src
│ │ ├── development
│ │ ├── AndroidManifest.xml
│ │ ├── google-services.json
│ │ └── res
│ │ │ └── values
│ │ │ └── strings.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── jp
│ │ │ │ └── wasabeef
│ │ │ │ └── app
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── 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
│ │ │ └── styles.xml
│ │ └── production
│ │ ├── AndroidManifest.xml
│ │ ├── google-services.json
│ │ └── res
│ │ └── values
│ │ └── strings.xml
├── app_android.iml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── app.iml
├── assets
├── fonts
│ └── Rotunda-Bold.otf
├── images
│ ├── 2.0x
│ │ ├── article_placeholder.webp
│ │ └── icon_placeholder.jpg
│ ├── 3.0x
│ │ ├── article_placeholder.webp
│ │ └── icon_placeholder.jpg
│ ├── article_placeholder.webp
│ └── icon_placeholder.jpg
├── svgs
│ ├── firebase.svg
│ ├── news.svg
│ └── video.svg
└── videos
│ └── bigbuckbunny.mp4
├── bitrise.yml
├── codecov.yml
├── codemagic.yaml
├── ios
├── Config
│ ├── Development.xcconfig
│ └── Production.xcconfig
├── Flutter
│ └── AppFrameworkInfo.plist
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── Development.xcscheme
│ │ ├── Production.xcscheme
│ │ └── 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
│ ├── Resources
│ │ └── Firebase
│ │ │ ├── Development
│ │ │ └── GoogleService-Info.plist
│ │ │ └── Production
│ │ │ └── GoogleService-Info.plist
│ ├── Runner-Bridging-Header.h
│ └── ja.lproj
│ │ ├── LaunchScreen.strings
│ │ └── Main.strings
└── Scripts
│ └── copy_google_service.sh
├── l10n.yaml
├── lib
├── app.dart
├── data
│ ├── app_error.dart
│ ├── local
│ │ ├── app_user.dart
│ │ └── app_user.freezed.dart
│ ├── model
│ │ ├── article.dart
│ │ ├── article.freezed.dart
│ │ ├── article.g.dart
│ │ ├── news.dart
│ │ ├── news.freezed.dart
│ │ ├── news.g.dart
│ │ ├── result.dart
│ │ ├── result.freezed.dart
│ │ ├── source.dart
│ │ ├── source.freezed.dart
│ │ └── source.g.dart
│ ├── provider
│ │ └── firebase_auth_provider.dart
│ ├── remote
│ │ ├── app_dio.dart
│ │ ├── auth_data_source.dart
│ │ ├── auth_data_source_impl.dart
│ │ ├── news_data_source.dart
│ │ └── news_data_source.g.dart
│ └── repository
│ │ ├── auth_repository.dart
│ │ ├── auth_repository_impl.dart
│ │ ├── news_repository.dart
│ │ └── news_repository_impl.dart
├── foundation
│ ├── constants.dart
│ └── extension
│ │ ├── async_snapshot.dart
│ │ ├── date_time.dart
│ │ └── object.dart
├── gen
│ ├── assets.gen.dart
│ └── fonts.gen.dart
├── l10n
│ ├── intl_messages_en.arb
│ └── intl_messages_ja.arb
├── main.dart
└── ui
│ ├── component
│ ├── image
│ │ └── image.dart
│ ├── loading
│ │ ├── container_with_loading.dart
│ │ └── loading.dart
│ └── snack_bar
│ │ └── error_snackbar.dart
│ ├── detail
│ └── detail_page.dart
│ ├── home
│ └── home_page.dart
│ ├── hook
│ ├── use_asset_vide_player_controller.dart
│ ├── use_l10n.dart
│ └── use_router.dart
│ ├── loading_state_view_model.dart
│ ├── news
│ ├── article_item.dart
│ ├── connected_new_page.dart
│ ├── news_page.dart
│ └── news_view_model.dart
│ ├── route
│ ├── app_route.dart
│ └── app_route.gr.dart
│ ├── signIn
│ └── sign_in_page.dart
│ ├── theme
│ ├── app_colors.dart
│ ├── app_text_theme.dart
│ ├── app_theme.dart
│ └── font_size.dart
│ ├── user_view_model.dart
│ └── video
│ └── video_page.dart
├── package-lock.json
├── package.json
├── pubspec.lock
├── pubspec.yaml
├── renovate.json
├── scripts
└── codecov.sh
├── test
├── data
│ ├── app_error_test.dart
│ ├── dummy
│ │ ├── dummy_article.dart
│ │ ├── dummy_news.dart
│ │ └── dummy_response_news_api.dart
│ ├── remote
│ │ ├── fake_app_dio.dart
│ │ └── fake_news_data_source_impl.dart
│ └── repository
│ │ └── fake_news_repository_impl.dart
├── foundation
│ └── extension
│ │ └── date_time_test.dart
└── ui
│ ├── view_model_test.dart
│ └── widget_test.dart
└── web
├── favicon.png
├── icons
├── Icon-192.png
└── Icon-512.png
├── index.html
└── manifest.json
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: wasabeef # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### What does this change?
2 |
3 | ### Screenshots (Optional)
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.github/workflows/flutter-ci.yml:
--------------------------------------------------------------------------------
1 | name: Flutter CI
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 | build:
11 | runs-on: macos-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | - uses: actions/setup-java@v2
15 | with:
16 | distribution: 'zulu'
17 | java-version: '11'
18 | - uses: subosito/flutter-action@v1
19 | with:
20 | flutter-version: '2.5.3'
21 | - uses: dart-lang/setup-dart@v1
22 | with:
23 | sdk: '2.14.4'
24 |
25 | - name: Cache Gradle modules
26 | uses: actions/cache@v2.1.6
27 | env:
28 | cache-number: ${{ secrets.CACHE_NUMBER }}
29 | with:
30 | path: |
31 | ~/android/.gradle
32 | ~/.gradle/cache
33 | # ~/.gradle/wrapper
34 | key: ${{ runner.os }}-gradle-${{ env.cache-number }}-${{ hashFiles('android/build.gradle') }}-${{ hashFiles('android/app/build.gradle') }}
35 | restore-keys: |
36 | ${{ runner.os }}-gradle-${{ env.cache-name }}-${{ hashFiles('android/build.gradle') }}
37 | ${{ runner.os }}-gradle-${{ env.cache-name }}-
38 | ${{ runner.os }}-gradle-
39 | ${{ runner.os }}-
40 |
41 | - name: Cache CocoaPods modules
42 | uses: actions/cache@v2.1.6
43 | env:
44 | cache-number: ${{ secrets.CACHE_NUMBER }}
45 | with:
46 | path: Pods
47 | key: ${{ runner.os }}-pods-${{ env.cache-number }}-${{ hashFiles('ios/Podfile.lock') }}
48 | restore-keys: |
49 | ${{ runner.os }}-pods-${{ env.cache-name }}-
50 | ${{ runner.os }}-pods-
51 | ${{ runner.os }}-
52 |
53 | - name: Cache Flutter modules
54 | uses: actions/cache@v2.1.6
55 | env:
56 | cache-number: ${{ secrets.CACHE_NUMBER }}
57 | with:
58 | path: |
59 | ~/.pub-cache/bin
60 | key: ${{ runner.os }}-pub-${{ env.cache-number }}-${{ env.flutter_version }}-${{ hashFiles('pubspec.lock') }}
61 | restore-keys: |
62 | ${{ runner.os }}-pub-${{ env.flutter_version }}-
63 | ${{ runner.os }}-pub-
64 | ${{ runner.os }}-
65 |
66 | - name: Get flutter dependencies.
67 | run: |
68 | make setup
69 | export PATH="$PATH":"$HOME/.pub-cache/bin"
70 |
71 | make dependencies
72 |
73 | - name: Check for any formatting and statically analyze the code.
74 | run: make format-analyze
75 |
76 | - name: Run widget tests for our flutter project.
77 | env:
78 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
79 | run: |
80 | make unit-test
81 | make codecov
82 |
83 | - name: Build ipa and apk
84 | run: |
85 | make build-android-prd
86 | make build-ios-prd
87 |
88 | - name: Slack Notification
89 | uses: homoluctus/slatify@master
90 | if: always()
91 | with:
92 | type: ${{ job.status }}
93 | job_name: '*Flutter Build*'
94 | mention: 'here'
95 | mention_if: 'failure'
96 | channel: '#develop'
97 | username: 'Github Actions'
98 | icon_emoji: ':octocat:'
99 | url: ${{ secrets.SLACK_WEBHOOK_URL }}
100 | commit: true
101 | token: ${{ secrets.GITHUB_TOKEN }}
102 |
103 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://www.dartlang.org/guides/libraries/private-files
2 |
3 | # Miscellaneous
4 | *.class
5 | *.log
6 | *.pyc
7 | *.swp
8 | .DS_Store
9 | .atom/
10 | .buildlog/
11 | .history
12 | .svn/
13 |
14 | # IntelliJ related
15 | *.iml
16 | *.ipr
17 | *.iws
18 |
19 | .idea/.gitignore
20 | .idea/dictionaries/
21 | .idea/libraries/
22 | .idea/misc.xml
23 | .idea/modules.xml
24 | .idea/vcs.xml
25 | .idea/workspace.xml
26 | .idea/saveactions_settings.xml
27 | android/.idea/
28 | ios/.idea/
29 |
30 | # The .vscode folder contains launch configuration and tasks you configure in
31 | # VS Code which you may wish to be included in version control, so this line
32 | # is commented out by default.
33 | #.vscode/
34 |
35 | # Flutter/Dart/Pub related
36 | **/doc/api/
37 | .dart_tool/
38 | .flutter-plugins
39 | .flutter-plugins-dependencies
40 | .packages
41 | .pub-cache/
42 | .pub/
43 | /build/
44 | generated_plugin_registrant.dart
45 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
46 |
47 | # Fastlane related
48 | android/fastlane/report.xml
49 | ios/fastlane/report.xml
50 |
51 | # Android related
52 | **/android/**/gradle-wrapper.jar
53 | **/android/.gradle
54 | **/android/captures/
55 | **/android/gradlew
56 | **/android/gradlew.bat
57 | **/android/local.properties
58 | **/android/settings_aar.gradle
59 | **/android/**/GeneratedPluginRegistrant.java
60 | **/android/**/gen
61 |
62 | # iOS/XCode related
63 | **/ios/**/*.mode1v3
64 | **/ios/**/*.mode2v3
65 | **/ios/**/*.moved-aside
66 | **/ios/**/*.pbxuser
67 | **/ios/**/*.perspectivev3
68 | **/ios/**/*sync/
69 | **/ios/**/.sconsign.dblite
70 | **/ios/**/.tags*
71 | **/ios/**/.vagrant/
72 | **/ios/**/DerivedData/
73 | **/ios/**/Icon?
74 | **/ios/**/Pods/
75 | **/ios/**/.symlinks/
76 | **/ios/**/profile
77 | **/ios/**/xcuserdata
78 | **/ios/.generated/
79 | **/ios/build/
80 | **/ios/Flutter/.last_build_id
81 | **/ios/Flutter/App.framework
82 | **/ios/Flutter/Flutter.framework
83 | **/ios/Flutter/Generated.xcconfig
84 | **/ios/Flutter/app.flx
85 | **/ios/Flutter/app.zip
86 | **/ios/Flutter/flutter_assets/
87 | **/ios/Flutter/flutter_export_environment.sh
88 | **/ios/Flutter/Flutter.podspec
89 | **/ios/ServiceDefinitions.json
90 | **/ios/Runner/GeneratedPluginRegistrant.*
91 | **/ios/Runner/GoogleService-Info.plist
92 | !**/ios/**/default.mode1v3
93 | !**/ios/**/default.mode2v3
94 | !**/ios/**/default.pbxuser
95 | !**/ios/**/default.perspectivev3
96 |
97 | # Web related
98 | *.dart.js
99 | *.info.json # Produced by the --dump-info flag.
100 | *.js # When generated by dart2js. Don't specify *.js if your
101 | # project includes source files written in JavaScript.
102 | *.js_
103 | *.js.deps
104 | *.js.map
105 | node_modules/
106 |
107 | ## Generated code
108 | #*.gen.dart
109 | #*.g.dart
110 | #*.freezed.dart
111 | #*.gr.dart
112 | #l10n*.dart
113 |
114 | ## Test coverage
115 | coverage/
116 |
117 | # fvm
118 | .fvm/flutter_sdk
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/development.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/production.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.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: c5a4b4029c0798f37c4a39b479d7cb75daa7b05c
8 | channel: stable
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/.tool-versions:
--------------------------------------------------------------------------------
1 | dart 2.14.4
2 | flutter 2.5.3-stable
3 | nodejs 17.0.1
4 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Flutter development",
6 | "program": "lib/main.dart",
7 | "request": "launch",
8 | "type": "dart",
9 | "args": [
10 | "--dart-define=FLAVOR=development",
11 | "--flavor",
12 | "development"
13 | ]
14 | },
15 | {
16 | "name": "Flutter production",
17 | "program": "lib/main.dart",
18 | "request": "launch",
19 | "type": "dart",
20 | "args": [
21 | "--dart-define=FLAVOR=production",
22 | "--flavor",
23 | "production"
24 | ]
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "dart.flutterSdkPath": "~/.asdf/installs/flutter/2.5.3-stable",
3 | "dart.sdkPath": "~/.asdf/installs/dart/2.14.4/dart-sdk"
4 | }
5 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | [INSERT CONTACT METHOD].
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020-2021 Daichi Furiya
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: setup
2 | setup:
3 | npm install
4 |
5 | .PHONY: dependencies
6 | dependencies:
7 | flutter pub get
8 |
9 | .PHONY: analyze
10 | analyze:
11 | flutter analyze
12 |
13 | .PHONY: format
14 | format:
15 | flutter format lib/
16 |
17 | .PHONY: format-analyze
18 | format-analyze:
19 | flutter format --dry-run lib/
20 | flutter analyze
21 |
22 | .PHONY: build-runner
23 | build-runner:
24 | flutter packages pub run build_runner build --delete-conflicting-outputs
25 |
26 | .PHONY: run-dev
27 | run-dev:
28 | flutter run --flavor development --dart-define=FLAVOR=development --target lib/main.dart
29 |
30 | .PHONY: run-prd
31 | run-prd:
32 | flutter run --release --flavor production --dart-define=FLAVOR=production --target lib/main.dart
33 |
34 | .PHONY: build-android-dev
35 | build-android-dev:
36 | flutter build apk --flavor development --dart-define=FLAVOR=development --target lib/main.dart
37 |
38 | .PHONY: build-android-prd
39 | build-android-prd:
40 | flutter build apk --release --flavor production --dart-define=FLAVOR=production --target lib/main.dart
41 |
42 | .PHONY: build-ios-dev
43 | build-ios-dev:
44 | flutter build ios --no-codesign --flavor development --dart-define=FLAVOR=development --target lib/main.dart
45 |
46 | .PHONY: build-ios-prd
47 | build-ios-prd:
48 | flutter build ios --release --no-codesign --flavor production --dart-define=FLAVOR=production --target lib/main.dart
49 |
50 | .PHONY: unit-test
51 | unit-test:
52 | flutter test --coverage --coverage-path=./coverage/lcov.info
53 |
54 | .PHONY: codecov
55 | codecov:
56 | ./scripts/codecov.sh ${CODECOV_TOKEN}
57 |
58 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
2 | analyzer:
3 | exclude:
4 | - "**/generated_plugin_registrant.dart"
5 | - "**/build/**"
6 | - "**/generated_*.dart"
7 | - "**/*.g.dart"
8 | - "**/*.freezed.dart"
9 | - "**/*.gr.dart"
10 | - "**/l10n*.dart"
11 | - "**/*.gen.dart"
--------------------------------------------------------------------------------
/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 | apply plugin: 'com.google.firebase.crashlytics'
28 |
29 | android {
30 | // Workaround for support to multiple CIs (Bitrise and Codemagic).
31 | compileSdkVersion System.getenv('ANDROID_SDK_VERSION') ? System.getenv('ANDROID_SDK_VERSION').toInteger() : 30
32 |
33 | compileOptions {
34 | sourceCompatibility JavaVersion.VERSION_1_8
35 | targetCompatibility JavaVersion.VERSION_1_8
36 | }
37 |
38 | kotlinOptions {
39 | jvmTarget = '1.8'
40 | }
41 |
42 | sourceSets {
43 | main.java.srcDirs += 'src/main/kotlin'
44 | }
45 |
46 | lintOptions {
47 | disable 'InvalidPackage'
48 | checkReleaseBuilds false // issue https://github.com/flutter/flutter/issues/22397
49 | }
50 |
51 | defaultConfig {
52 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
53 | applicationId "jp.wasabeef.app"
54 | minSdkVersion 22
55 | targetSdkVersion 30
56 | versionCode flutterVersionCode.toInteger()
57 | versionName flutterVersionName
58 | }
59 |
60 | // SigningConfigs
61 | apply from: 'signingConfigs/debug.gradle', to: android
62 | apply from: 'signingConfigs/release.gradle', to: android
63 |
64 | buildTypes {
65 | release {
66 | signingConfig signingConfigs.release
67 | }
68 | debug {
69 | debuggable true
70 | signingConfig signingConfigs.debug
71 | }
72 | }
73 |
74 | flavorDimensions "environment"
75 | productFlavors {
76 | development {
77 | dimension "environment"
78 | applicationIdSuffix ".dev"
79 | versionNameSuffix "-Dev"
80 | }
81 |
82 | production {
83 | dimension "environment"
84 | }
85 | }
86 | }
87 |
88 | flutter {
89 | source '../..'
90 | }
91 |
92 | dependencies {
93 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
94 | }
95 |
96 | apply plugin: 'com.google.gms.google-services'
--------------------------------------------------------------------------------
/android/app/signingConfigs/debug.gradle:
--------------------------------------------------------------------------------
1 | signingConfigs {
2 | debug {
3 | storeFile file("debug.keystore")
4 | storePassword "android"
5 | keyAlias "androiddebugkey"
6 | keyPassword "android"
7 | }
8 | }
9 |
10 | // $ keytool -v -list -keystore
11 | // Certificate fingerprints:
12 | // MD5: 28:22:7C:A4:B9:2F:6E:C7:D5:58:62:48:EB:7E:82:C3
13 | // SHA1: 94:25:A9:50:9C:0E:AE:AA:00:37:5E:D6:71:E3:BC:ED:17:E5:0C:A3
14 | // SHA256: 04:92:39:09:3D:1C:B6:16:BE:55:58:A3:5F:3B:BB:CB:0B:E7:F1:DA:AA:26:C5:2D:BD:2F:44:CF:AE:47:CF:87
--------------------------------------------------------------------------------
/android/app/signingConfigs/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/android/app/signingConfigs/debug.keystore
--------------------------------------------------------------------------------
/android/app/signingConfigs/release.gradle:
--------------------------------------------------------------------------------
1 | // TODO Must be re-created.
2 | signingConfigs {
3 | release {
4 | storeFile file("release.keystore")
5 | storePassword "aabbccdd"
6 | keyAlias "fab"
7 | keyPassword "aabbccdd"
8 | }
9 | }
10 |
11 | // $ keytool -v -list -keystore
12 | // Certificate fingerprints:
13 | // MD5: 9A:69:D4:B6:BF:BE:C1:A5:C5:BB:05:7B:36:84:D7:5C
14 | // SHA1: AA:88:1A:A8:47:7A:90:73:16:D6:F1:B7:D5:25:7B:92:BC:C9:4B:FD
15 | // SHA256: 22:39:5E:46:8C:55:00:6C:3A:4B:68:7D:66:20:0A:42:07:75:90:71:29:31:DA:1C:6E:48:FC:60:58:6E:0C:2D
--------------------------------------------------------------------------------
/android/app/signingConfigs/release.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/android/app/signingConfigs/release.keystore
--------------------------------------------------------------------------------
/android/app/src/development/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/development/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "339920746703",
4 | "firebase_url": "https://flutter-arch-blueprints-dev.firebaseio.com",
5 | "project_id": "flutter-arch-blueprints-dev",
6 | "storage_bucket": "flutter-arch-blueprints-dev.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:339920746703:android:5a97ba145b698f05ee9fba",
12 | "android_client_info": {
13 | "package_name": "jp.wasabeef.app.dev"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "339920746703-28cfben1heai5p0aqk8p3nl73toi4n03.apps.googleusercontent.com",
19 | "client_type": 1,
20 | "android_info": {
21 | "package_name": "jp.wasabeef.app.dev",
22 | "certificate_hash": "aa881aa8477a907316d6f1b7d5257b92bcc94bfd"
23 | }
24 | },
25 | {
26 | "client_id": "339920746703-itjdedk624qhvhjjfipgdp62ororfho1.apps.googleusercontent.com",
27 | "client_type": 1,
28 | "android_info": {
29 | "package_name": "jp.wasabeef.app.dev",
30 | "certificate_hash": "9425a9509c0eaeaa00375ed671e3bced17e50ca3"
31 | }
32 | },
33 | {
34 | "client_id": "339920746703-g2k3mt9j2bva5v555d9ps2j2ord7ecba.apps.googleusercontent.com",
35 | "client_type": 3
36 | }
37 | ],
38 | "api_key": [
39 | {
40 | "current_key": "AIzaSyDmkQUMEuXgB4FM50dcizxumL12DUQG8ng"
41 | }
42 | ],
43 | "services": {
44 | "appinvite_service": {
45 | "other_platform_oauth_client": [
46 | {
47 | "client_id": "339920746703-g2k3mt9j2bva5v555d9ps2j2ord7ecba.apps.googleusercontent.com",
48 | "client_type": 3
49 | },
50 | {
51 | "client_id": "339920746703-140i3bhk3lqtpn2p2e7035btcp61p32i.apps.googleusercontent.com",
52 | "client_type": 2,
53 | "ios_info": {
54 | "bundle_id": "jp.wasabeef.app.dev"
55 | }
56 | }
57 | ]
58 | }
59 | }
60 | }
61 | ],
62 | "configuration_version": "1"
63 | }
--------------------------------------------------------------------------------
/android/app/src/development/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | FAB Dev
4 |
5 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
9 |
10 |
11 |
15 |
22 |
26 |
30 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
46 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/jp/wasabeef/app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.app
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/production/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/production/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "208498828836",
4 | "firebase_url": "https://flutter-arc-blueprints.firebaseio.com",
5 | "project_id": "flutter-arc-blueprints",
6 | "storage_bucket": "flutter-arc-blueprints.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:208498828836:android:58145629940ce4a96b5ab1",
12 | "android_client_info": {
13 | "package_name": "jp.wasabeef.app"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "208498828836-3323hr2v1b84i3s8sv4921462l1vtc1i.apps.googleusercontent.com",
19 | "client_type": 1,
20 | "android_info": {
21 | "package_name": "jp.wasabeef.app",
22 | "certificate_hash": "9425a9509c0eaeaa00375ed671e3bced17e50ca3"
23 | }
24 | },
25 | {
26 | "client_id": "208498828836-it7b64n6biakq3u964s0sudjbnklmkl2.apps.googleusercontent.com",
27 | "client_type": 1,
28 | "android_info": {
29 | "package_name": "jp.wasabeef.app",
30 | "certificate_hash": "aa881aa8477a907316d6f1b7d5257b92bcc94bfd"
31 | }
32 | },
33 | {
34 | "client_id": "208498828836-rbgoklet6680lrcccnov4a25vs9k5du8.apps.googleusercontent.com",
35 | "client_type": 3
36 | }
37 | ],
38 | "api_key": [
39 | {
40 | "current_key": "AIzaSyAzj4n6ihX9kVt_KI24xEgqFtfO7GOdZEE"
41 | }
42 | ],
43 | "services": {
44 | "appinvite_service": {
45 | "other_platform_oauth_client": [
46 | {
47 | "client_id": "208498828836-rbgoklet6680lrcccnov4a25vs9k5du8.apps.googleusercontent.com",
48 | "client_type": 3
49 | },
50 | {
51 | "client_id": "208498828836-139a9k718tbf1ijjmplm9sef21crjqv9.apps.googleusercontent.com",
52 | "client_type": 2,
53 | "ios_info": {
54 | "bundle_id": "jp.wasabeef.app"
55 | }
56 | }
57 | ]
58 | }
59 | }
60 | }
61 | ],
62 | "configuration_version": "1"
63 | }
--------------------------------------------------------------------------------
/android/app/src/production/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | FAB
4 |
5 |
--------------------------------------------------------------------------------
/android/app_android.iml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.5.31'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:7.0.3'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | classpath 'com.google.gms:google-services:4.3.10'
12 | classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.1'
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | google()
19 | mavenCentral()
20 | }
21 | }
22 |
23 | rootProject.buildDir = '../build'
24 | subprojects {
25 | project.buildDir = "${rootProject.buildDir}/${project.name}"
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 | kotlin.stdlib.default.dependency=false
--------------------------------------------------------------------------------
/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.2-all.zip
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/assets/fonts/Rotunda-Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/assets/fonts/Rotunda-Bold.otf
--------------------------------------------------------------------------------
/assets/images/2.0x/article_placeholder.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/assets/images/2.0x/article_placeholder.webp
--------------------------------------------------------------------------------
/assets/images/2.0x/icon_placeholder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/assets/images/2.0x/icon_placeholder.jpg
--------------------------------------------------------------------------------
/assets/images/3.0x/article_placeholder.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/assets/images/3.0x/article_placeholder.webp
--------------------------------------------------------------------------------
/assets/images/3.0x/icon_placeholder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/assets/images/3.0x/icon_placeholder.jpg
--------------------------------------------------------------------------------
/assets/images/article_placeholder.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/assets/images/article_placeholder.webp
--------------------------------------------------------------------------------
/assets/images/icon_placeholder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/assets/images/icon_placeholder.jpg
--------------------------------------------------------------------------------
/assets/svgs/news.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/svgs/video.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
56 |
--------------------------------------------------------------------------------
/assets/videos/bigbuckbunny.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/assets/videos/bigbuckbunny.mp4
--------------------------------------------------------------------------------
/bitrise.yml:
--------------------------------------------------------------------------------
1 | ---
2 | format_version: '8'
3 | default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
4 | project_type: flutter
5 | trigger_map:
6 | - push_branch: main
7 | workflow: main-build
8 | - pull_request_source_branch: "*"
9 | workflow: pull-request-build
10 | workflows:
11 | main-build:
12 | steps:
13 | - activate-ssh-key@4:
14 | run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
15 | - git-clone@4: {}
16 | - cache-pull@2: {}
17 | - script@1:
18 | inputs:
19 | - content: |-
20 | #!/usr/bin/env bash
21 | make setup
22 | export PATH=$PATH:$HOME/.pub-cache/bin
23 | envman add --key PATH --value $PATH
24 |
25 | make dependencies
26 | title: Get flutter dependencies
27 | - script@1:
28 | inputs:
29 | - content: |-
30 | #!/usr/bin/env bash
31 | make format-analyze
32 | title: Check for any formatting and statically analyze the code
33 | - script@1:
34 | inputs:
35 | - content: |-
36 | #!/usr/bin/env bash
37 | make unit-test
38 | title: Run widget tests for our flutter project
39 | - codecov@2.0:
40 | inputs:
41 | - CODECOV_TOKEN: "$CODECOV_TOKEN"
42 | - script@1:
43 | inputs:
44 | - content: |-
45 | #!/usr/bin/env bash
46 | make build-android-prd
47 | make build-ios-prd
48 | title: Build ipa and apk
49 | - deploy-to-bitrise-io@1: {}
50 | - cache-push@2: {}
51 | - slack@3:
52 | inputs:
53 | - webhook_url: "$SLACK_WEBHOOK_URL"
54 | pull-request-build:
55 | steps:
56 | - activate-ssh-key@4:
57 | run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
58 | - git-clone@4: {}
59 | - cache-pull@2: { }
60 | - script@1:
61 | inputs:
62 | - content: |-
63 | #!/usr/bin/env bash
64 | make setup
65 | export PATH=$PATH:$HOME/.pub-cache/bin
66 | envman add --key PATH --value $PATH
67 |
68 | make dependencies
69 | title: Get flutter dependencies
70 | - script@1:
71 | inputs:
72 | - content: |-
73 | #!/usr/bin/env bash
74 | make format-analyze
75 | title: Check for any formatting and statically analyze the code
76 | - script@1:
77 | inputs:
78 | - content: |-
79 | #!/usr/bin/env bash
80 | make unit-test
81 | title: Run widget tests for our flutter project
82 | - codecov@2.0:
83 | inputs:
84 | - CODECOV_TOKEN: "$CODECOV_TOKEN"
85 | - script@1:
86 | inputs:
87 | - content: |-
88 | #!/usr/bin/env bash
89 | make build-android-prd
90 | make build-ios-prd
91 | title: Build ipa and apk
92 | - deploy-to-bitrise-io@1: {}
93 | - cache-push@2: {}
94 | - slack@3:
95 | inputs:
96 | - webhook_url: "$SLACK_WEBHOOK_URL"
97 | app:
98 | envs:
99 | - opts:
100 | is_expand: false
101 | BITRISE_FLUTTER_PROJECT_LOCATION: "."
102 | - opts:
103 | is_expand: false
104 | BITRISE_PROJECT_PATH: ios/Runner.xcworkspace
105 | - opts:
106 | is_expand: false
107 | BITRISE_SCHEME: Production
108 | - opts:
109 | is_expand: false
110 | BITRISE_EXPORT_METHOD: production
111 | - opts:
112 | is_expand: false
113 | ANDROID_SDK_VERSION: 29
114 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | # https://docs.codecov.io/docs/commit-status
2 | codecov:
3 | notify:
4 | require_ci_to_pass: yes
5 |
6 | coverage:
7 | status:
8 | project:
9 | default:
10 | # basic
11 | target: 0%
12 | threshold: 0%
13 | base: 0%
14 | # advanced
15 | branches: null
16 | if_no_uploads: error
17 | if_not_found: success
18 | if_ci_failed: error
19 | only_pulls: false
20 | flags: null
21 | paths: null
22 |
23 | ignore:
24 | - "**/*.g.dart"
25 | - "**/*.freezed.dart"
--------------------------------------------------------------------------------
/codemagic.yaml:
--------------------------------------------------------------------------------
1 | # Automatically generated on 2020-08-07 UTC from https://codemagic.io/app/5f2c1b6a8ff73d000f7bc1e1/settings
2 | # Note that this configuration is not an exact match to UI settings. Review and adjust as necessary.
3 |
4 | workflows:
5 | main-merge:
6 | name: Main Workflow
7 | max_build_duration: 60
8 | environment:
9 | vars:
10 | FCI_FLUTTER_SCHEME: Production
11 | ANDROID_SDK_VERSION: 30
12 | CODECOV_TOKEN: Encrypted(Z0FBQUFBQmZMOXV6aEw2a0VyRWE0VTljem1XeG95MVFQRm5YNUhUaU94SE1FcU5pdDRya1ZnM29DR2FQOGpJS1dydm14UkU4eFE4TzdReDZZWlIxU1lEcU13dm8zRHdQd211R3pTNGFIeHJwUXE3N3VxTk1iMndYLWFnSE1JMHA2TndHVkw3MWRmbU0=)
13 | flutter: beta
14 | xcode: latest
15 | cocoapods: default
16 | cache:
17 | cache_paths:
18 | - $FLUTTER_ROOT/.pub-cache
19 | - $FCI_BUILD_DIR/ios/Pods
20 | - $FCI_BUILD_DIR/android/.gradle
21 | triggering:
22 | events:
23 | - push
24 | - pull_request
25 | - tag
26 | branch_patterns:
27 | - pattern: main
28 | include: true
29 | source: true
30 | scripts:
31 | - name: Setup local properties
32 | script: |
33 | # set up local properties
34 | echo "flutter.sdk=$HOME/programs/flutter" > "$FCI_BUILD_DIR/android/local.properties"
35 |
36 | - name: Get flutter dependencies
37 | script: |
38 | make setup
39 | export PATH="$PATH":"$HOME/.pub-cache/bin"
40 |
41 | make dependencies
42 |
43 | - name: Check for any formatting and statically analyze the code
44 | script: make format-analyze
45 |
46 | - name: Flutter Unit test
47 | script: make unit-test
48 |
49 | - name: Codecov upload
50 | script: make codecov
51 |
52 | - name: Build
53 | script: |
54 | #!/bin/sh
55 | set -e # exit on first failed commandset
56 | set -x # print all executed commands to the log
57 | /usr/bin/plutil -replace CFBundleIdentifier -string jp.wasabeef.app ios/Runner/Info.plist
58 | make build-android-prd
59 | make build-ios-prd
60 |
61 | artifacts:
62 | - build/**/outputs/**/*.apk
63 | - build/**/outputs/**/*.aab
64 | - build/**/outputs/**/mapping.txt
65 | - build/ios/ipa/*.ipa
66 | - /tmp/xcodebuild_logs/*.log
67 | - flutter_drive.log
68 |
69 | publishing:
70 | slack:
71 | channel: '#develop'
72 | notify_on_build_start: false
73 | github_releases:
74 | prerelease: false
75 | artifact_patterns:
76 | - 'app-production-release.apk'
77 | - 'Runner.ipa'
--------------------------------------------------------------------------------
/ios/Config/Development.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Flutter/Generated.xcconfig"
2 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release-development.xcconfig"
3 | TRACK_WIDGET_CREATION=
4 |
5 | FLUTTER_FLAVOR=development
6 | FLUTTER_TARGET=$PROJECT_DIR/../lib/main.dart
7 | PRODUCT_BUNDLE_IDENTIFIER=jp.wasabeef.app.dev
8 | DISPLAY_NAME=FAB-dev
9 |
10 | FIREBASE_DIR=$PROJECT_DIR/$PROJECT_NAME/Resources/Firebase/Development
11 |
12 | // GOOGLE prefix key configs were copied from GoogleService-Info.plist
13 | GOOGLE_REVERSED_CLIENT_ID = com.googleusercontent.apps.339920746703-140i3bhk3lqtpn2p2e7035btcp61p32i
14 |
--------------------------------------------------------------------------------
/ios/Config/Production.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Flutter/Generated.xcconfig"
2 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release-production.xcconfig"
3 | TRACK_WIDGET_CREATION=
4 |
5 | FLUTTER_FLAVOR=production
6 | FLUTTER_TARGET=$PROJECT_DIR/../lib/main.dart
7 | PRODUCT_BUNDLE_IDENTIFIER=jp.wasabeef.app
8 | DISPLAY_NAME=FAB
9 |
10 | FIREBASE_DIR=$PROJECT_DIR/$PROJECT_NAME/Resources/Firebase/Production
11 |
12 | // GOOGLE prefix key configs were copied from GoogleService-Info.plist
13 | GOOGLE_REVERSED_CLIENT_ID = com.googleusercontent.apps.208498828836-139a9k718tbf1ijjmplm9sef21crjqv9
14 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, '13.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug-Development' => :debug,
9 | 'Debug-Production' => :debug,
10 | 'Release-Development' => :release,
11 | 'Release-Production' => :release,
12 | }
13 |
14 | def flutter_root
15 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
16 | unless File.exist?(generated_xcode_build_settings_path)
17 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
18 | end
19 |
20 | File.foreach(generated_xcode_build_settings_path) do |line|
21 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
22 | return matches[1].strip if matches
23 | end
24 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
25 | end
26 |
27 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
28 |
29 | flutter_ios_podfile_setup
30 |
31 | target 'Runner' do
32 | use_frameworks!
33 | use_modular_headers!
34 |
35 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
36 | end
37 |
38 | post_install do |installer|
39 | installer.pods_project.targets.each do |target|
40 | flutter_additional_ios_build_settings(target)
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - AppAuth (1.4.0):
3 | - AppAuth/Core (= 1.4.0)
4 | - AppAuth/ExternalUserAgent (= 1.4.0)
5 | - AppAuth/Core (1.4.0)
6 | - AppAuth/ExternalUserAgent (1.4.0)
7 | - Firebase/Auth (8.8.0):
8 | - Firebase/CoreOnly
9 | - FirebaseAuth (~> 8.8.0)
10 | - Firebase/CoreOnly (8.8.0):
11 | - FirebaseCore (= 8.8.0)
12 | - Firebase/Crashlytics (8.8.0):
13 | - Firebase/CoreOnly
14 | - FirebaseCrashlytics (~> 8.8.0)
15 | - Firebase/Performance (8.8.0):
16 | - Firebase/CoreOnly
17 | - FirebasePerformance (~> 8.8.0)
18 | - firebase_auth (3.1.4):
19 | - Firebase/Auth (= 8.8.0)
20 | - firebase_core
21 | - Flutter
22 | - firebase_core (1.8.0):
23 | - Firebase/CoreOnly (= 8.8.0)
24 | - Flutter
25 | - firebase_crashlytics (2.2.4):
26 | - Firebase/Crashlytics (= 8.8.0)
27 | - firebase_core
28 | - Flutter
29 | - firebase_performance (0.7.1-2):
30 | - Firebase/Performance (= 8.8.0)
31 | - firebase_core
32 | - Flutter
33 | - FirebaseABTesting (8.8.0):
34 | - FirebaseCore (~> 8.0)
35 | - FirebaseAuth (8.8.0):
36 | - FirebaseCore (~> 8.0)
37 | - GoogleUtilities/AppDelegateSwizzler (~> 7.4)
38 | - GoogleUtilities/Environment (~> 7.4)
39 | - GTMSessionFetcher/Core (~> 1.5)
40 | - FirebaseCore (8.8.0):
41 | - FirebaseCoreDiagnostics (~> 8.0)
42 | - GoogleUtilities/Environment (~> 7.4)
43 | - GoogleUtilities/Logger (~> 7.4)
44 | - FirebaseCoreDiagnostics (8.8.0):
45 | - GoogleDataTransport (~> 9.0)
46 | - GoogleUtilities/Environment (~> 7.4)
47 | - GoogleUtilities/Logger (~> 7.4)
48 | - nanopb (~> 2.30908.0)
49 | - FirebaseCrashlytics (8.8.0):
50 | - FirebaseCore (~> 8.0)
51 | - FirebaseInstallations (~> 8.0)
52 | - GoogleDataTransport (~> 9.0)
53 | - GoogleUtilities/Environment (~> 7.4)
54 | - nanopb (~> 2.30908.0)
55 | - PromisesObjC (< 3.0, >= 1.2)
56 | - FirebaseInstallations (8.8.0):
57 | - FirebaseCore (~> 8.0)
58 | - GoogleUtilities/Environment (~> 7.4)
59 | - GoogleUtilities/UserDefaults (~> 7.4)
60 | - PromisesObjC (< 3.0, >= 1.2)
61 | - FirebasePerformance (8.8.0):
62 | - FirebaseCore (~> 8.0)
63 | - FirebaseInstallations (~> 8.0)
64 | - FirebaseRemoteConfig (~> 8.0)
65 | - GoogleDataTransport (~> 9.0)
66 | - GoogleUtilities/Environment (~> 7.4)
67 | - GoogleUtilities/ISASwizzler (~> 7.4)
68 | - GoogleUtilities/MethodSwizzler (~> 7.4)
69 | - nanopb (~> 2.30908.0)
70 | - FirebaseRemoteConfig (8.8.0):
71 | - FirebaseABTesting (~> 8.0)
72 | - FirebaseCore (~> 8.0)
73 | - FirebaseInstallations (~> 8.0)
74 | - GoogleUtilities/Environment (~> 7.4)
75 | - "GoogleUtilities/NSData+zlib (~> 7.4)"
76 | - Flutter (1.0.0)
77 | - google_sign_in (0.0.1):
78 | - Flutter
79 | - GoogleSignIn (~> 5.0)
80 | - GoogleDataTransport (9.1.2):
81 | - GoogleUtilities/Environment (~> 7.2)
82 | - nanopb (~> 2.30908.0)
83 | - PromisesObjC (< 3.0, >= 1.2)
84 | - GoogleSignIn (5.0.2):
85 | - AppAuth (~> 1.2)
86 | - GTMAppAuth (~> 1.0)
87 | - GTMSessionFetcher/Core (~> 1.1)
88 | - GoogleUtilities/AppDelegateSwizzler (7.6.0):
89 | - GoogleUtilities/Environment
90 | - GoogleUtilities/Logger
91 | - GoogleUtilities/Network
92 | - GoogleUtilities/Environment (7.6.0):
93 | - PromisesObjC (< 3.0, >= 1.2)
94 | - GoogleUtilities/ISASwizzler (7.6.0)
95 | - GoogleUtilities/Logger (7.6.0):
96 | - GoogleUtilities/Environment
97 | - GoogleUtilities/MethodSwizzler (7.6.0):
98 | - GoogleUtilities/Logger
99 | - GoogleUtilities/Network (7.6.0):
100 | - GoogleUtilities/Logger
101 | - "GoogleUtilities/NSData+zlib"
102 | - GoogleUtilities/Reachability
103 | - "GoogleUtilities/NSData+zlib (7.6.0)"
104 | - GoogleUtilities/Reachability (7.6.0):
105 | - GoogleUtilities/Logger
106 | - GoogleUtilities/UserDefaults (7.6.0):
107 | - GoogleUtilities/Logger
108 | - GTMAppAuth (1.2.2):
109 | - AppAuth/Core (~> 1.4)
110 | - GTMSessionFetcher/Core (~> 1.5)
111 | - GTMSessionFetcher/Core (1.7.0)
112 | - nanopb (2.30908.0):
113 | - nanopb/decode (= 2.30908.0)
114 | - nanopb/encode (= 2.30908.0)
115 | - nanopb/decode (2.30908.0)
116 | - nanopb/encode (2.30908.0)
117 | - path_provider (0.0.1):
118 | - Flutter
119 | - PromisesObjC (2.0.0)
120 | - ua_client_hints (1.1.0):
121 | - Flutter
122 | - video_player (0.0.1):
123 | - Flutter
124 |
125 | DEPENDENCIES:
126 | - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
127 | - firebase_core (from `.symlinks/plugins/firebase_core/ios`)
128 | - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
129 | - firebase_performance (from `.symlinks/plugins/firebase_performance/ios`)
130 | - Flutter (from `Flutter`)
131 | - google_sign_in (from `.symlinks/plugins/google_sign_in/ios`)
132 | - path_provider (from `.symlinks/plugins/path_provider/ios`)
133 | - ua_client_hints (from `.symlinks/plugins/ua_client_hints/ios`)
134 | - video_player (from `.symlinks/plugins/video_player/ios`)
135 |
136 | SPEC REPOS:
137 | trunk:
138 | - AppAuth
139 | - Firebase
140 | - FirebaseABTesting
141 | - FirebaseAuth
142 | - FirebaseCore
143 | - FirebaseCoreDiagnostics
144 | - FirebaseCrashlytics
145 | - FirebaseInstallations
146 | - FirebasePerformance
147 | - FirebaseRemoteConfig
148 | - GoogleDataTransport
149 | - GoogleSignIn
150 | - GoogleUtilities
151 | - GTMAppAuth
152 | - GTMSessionFetcher
153 | - nanopb
154 | - PromisesObjC
155 |
156 | EXTERNAL SOURCES:
157 | firebase_auth:
158 | :path: ".symlinks/plugins/firebase_auth/ios"
159 | firebase_core:
160 | :path: ".symlinks/plugins/firebase_core/ios"
161 | firebase_crashlytics:
162 | :path: ".symlinks/plugins/firebase_crashlytics/ios"
163 | firebase_performance:
164 | :path: ".symlinks/plugins/firebase_performance/ios"
165 | Flutter:
166 | :path: Flutter
167 | google_sign_in:
168 | :path: ".symlinks/plugins/google_sign_in/ios"
169 | path_provider:
170 | :path: ".symlinks/plugins/path_provider/ios"
171 | ua_client_hints:
172 | :path: ".symlinks/plugins/ua_client_hints/ios"
173 | video_player:
174 | :path: ".symlinks/plugins/video_player/ios"
175 |
176 | SPEC CHECKSUMS:
177 | AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
178 | Firebase: 629510f1a9ddb235f3a7c5c8ceb23ba887f0f814
179 | firebase_auth: 0b7168e2db1bff6e5b40a7dc268447b8dedb59c1
180 | firebase_core: 3b4c707f5a8eff38f52fd5580895bcd89357bf42
181 | firebase_crashlytics: 5e4c7b5695a7ffe144a55dacfddebbf8eb36028a
182 | firebase_performance: 01839bfbbc5c98b00b5a9172328f5bc21059e5ef
183 | FirebaseABTesting: 981336dd14d84787e33466e4247f77ec2343f8d9
184 | FirebaseAuth: bcf0adeff88bda5dcb3beeabe5760f1226ab7b2f
185 | FirebaseCore: 98b29e3828f0a53651c363937a7f7d92a19f1ba2
186 | FirebaseCoreDiagnostics: fe77f42da6329d6d83d21fd9d621a6b704413bfc
187 | FirebaseCrashlytics: 3660c045c8e45cc4276110562a0ef44cf43c8157
188 | FirebaseInstallations: 2563cb18a723ef9c6ef18318a49519b75dce613c
189 | FirebasePerformance: 0c01a7a496657d7cea86d40c0b1725259d164c6c
190 | FirebaseRemoteConfig: f6365883d7950d784ee97bcdbbf1e442d4fa6119
191 | Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
192 | google_sign_in: c5cecea71f3be43282263550556e311c4cc03582
193 | GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940
194 | GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213
195 | GoogleUtilities: 684ee790a24f73ebb2d1d966e9711c203f2a4237
196 | GTMAppAuth: ad5c2b70b9a8689e1a04033c9369c4915bfcbe89
197 | GTMSessionFetcher: 43748f93435c2aa068b1cbe39655aaf600652e91
198 | nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
199 | path_provider: d1e9807085df1f9cc9318206cd649dc0b76be3de
200 | PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58
201 | ua_client_hints: 314de6b4221bf713b1a6a5fb8bc68917ad3eaaec
202 | video_player: ecd305f42e9044793efd34846e1ce64c31ea6fcb
203 |
204 | PODFILE CHECKSUM: af976f751d801ced1cf35e237c7db47ea4b2ec3e
205 |
206 | COCOAPODS: 1.11.2
207 |
--------------------------------------------------------------------------------
/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/Development.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Production.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/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 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
6 |
7 | PreviewsEnabled
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/flutter-architecture-blueprints/a4d87a6d0a7f1d249b89795b567fd6325ac34d51/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 | CFBundleDisplayName
8 | $(DISPLAY_NAME)
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | app
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleURLTypes
24 |
25 |
26 | CFBundleIdentifier
27 |
28 | CFBundleTypeRole
29 | Editor
30 | CFBundleURLName
31 | SNS Sign In
32 | CFBundleURLSchemes
33 |
34 | $(GOOGLE_REVERSED_CLIENT_ID)
35 |
36 |
37 |
38 | CFBundleVersion
39 | $(FLUTTER_BUILD_NUMBER)
40 | LSRequiresIPhoneOS
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIMainStoryboardFile
45 | Main
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UISupportedInterfaceOrientations~ipad
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationPortraitUpsideDown
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 | UIViewControllerBasedStatusBarAppearance
60 |
61 | io.flutter.embedded_views_preview
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/ios/Runner/Resources/Firebase/Development/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CLIENT_ID
6 | 339920746703-140i3bhk3lqtpn2p2e7035btcp61p32i.apps.googleusercontent.com
7 | REVERSED_CLIENT_ID
8 | com.googleusercontent.apps.339920746703-140i3bhk3lqtpn2p2e7035btcp61p32i
9 | ANDROID_CLIENT_ID
10 | 339920746703-1omo33mfc8f7cfjm8pa8qutqpu2q3h7c.apps.googleusercontent.com
11 | API_KEY
12 | AIzaSyCxPP2BfUCFmWkYSNswVtT3PQrVXnAQJkg
13 | GCM_SENDER_ID
14 | 339920746703
15 | PLIST_VERSION
16 | 1
17 | BUNDLE_ID
18 | jp.wasabeef.app.dev
19 | PROJECT_ID
20 | flutter-arch-blueprints-dev
21 | STORAGE_BUCKET
22 | flutter-arch-blueprints-dev.appspot.com
23 | IS_ADS_ENABLED
24 |
25 | IS_ANALYTICS_ENABLED
26 |
27 | IS_APPINVITE_ENABLED
28 |
29 | IS_GCM_ENABLED
30 |
31 | IS_SIGNIN_ENABLED
32 |
33 | GOOGLE_APP_ID
34 | 1:339920746703:ios:96090bb3427da435ee9fba
35 | DATABASE_URL
36 | https://flutter-arch-blueprints-dev.firebaseio.com
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Resources/Firebase/Production/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CLIENT_ID
6 | 208498828836-139a9k718tbf1ijjmplm9sef21crjqv9.apps.googleusercontent.com
7 | REVERSED_CLIENT_ID
8 | com.googleusercontent.apps.208498828836-139a9k718tbf1ijjmplm9sef21crjqv9
9 | ANDROID_CLIENT_ID
10 | 208498828836-3323hr2v1b84i3s8sv4921462l1vtc1i.apps.googleusercontent.com
11 | API_KEY
12 | AIzaSyAjP8sr4gOdweOwfbrXKY0ya_hqP7GS2nY
13 | GCM_SENDER_ID
14 | 208498828836
15 | PLIST_VERSION
16 | 1
17 | BUNDLE_ID
18 | jp.wasabeef.app
19 | PROJECT_ID
20 | flutter-arc-blueprints
21 | STORAGE_BUCKET
22 | flutter-arc-blueprints.appspot.com
23 | IS_ADS_ENABLED
24 |
25 | IS_ANALYTICS_ENABLED
26 |
27 | IS_APPINVITE_ENABLED
28 |
29 | IS_GCM_ENABLED
30 |
31 | IS_SIGNIN_ENABLED
32 |
33 | GOOGLE_APP_ID
34 | 1:208498828836:ios:f3fcdda35b7c7aa16b5ab1
35 | DATABASE_URL
36 | https://flutter-arc-blueprints.firebaseio.com
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/Runner/ja.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ios/Runner/ja.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ios/Scripts/copy_google_service.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | BASE_PATH=$PROJECT_DIR/$PROJECT_NAME
4 |
5 | echo execute copy GoogleService-Info.plist
6 | FIREBASE_INFO_PLIST="GoogleService-Info.plist"
7 | FIREBASE_INFO_PLIST_DST=$BASE_PATH/$FIREBASE_INFO_PLIST
8 | FIREBASE_INFO_PLIST_SRC=$FIREBASE_DIR/$FIREBASE_INFO_PLIST
9 |
10 | echo $FIREBASE_INFO_PLIST_SRC
11 | cp -Rf $FIREBASE_INFO_PLIST_SRC $FIREBASE_INFO_PLIST_DST
12 |
--------------------------------------------------------------------------------
/l10n.yaml:
--------------------------------------------------------------------------------
1 | arb-dir: lib/l10n
2 | template-arb-file: intl_messages_en.arb
3 | output-localization-file: l10n.dart
4 | output-class: L10n
5 |
--------------------------------------------------------------------------------
/lib/app.dart:
--------------------------------------------------------------------------------
1 | import 'package:app/ui/route/app_route.dart';
2 | import 'package:app/ui/theme/app_theme.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_gen/gen_l10n/l10n.dart';
5 | import 'package:flutter_hooks/flutter_hooks.dart';
6 | import 'package:hooks_riverpod/hooks_riverpod.dart';
7 |
8 | class App extends HookConsumerWidget {
9 | const App({Key? key}) : super(key: key);
10 |
11 | @override
12 | Widget build(BuildContext context, WidgetRef ref) {
13 | final theme = ref.watch(appThemeProvider);
14 | final themeMode = ref.watch(appThemeModeProvider);
15 | final appRouter = useMemoized(() => AppRouter());
16 | return MaterialApp.router(
17 | theme: theme.data,
18 | darkTheme: AppTheme.dark().data,
19 | themeMode: themeMode,
20 | localizationsDelegates: L10n.localizationsDelegates,
21 | supportedLocales: L10n.supportedLocales,
22 | routeInformationParser: appRouter.defaultRouteParser(),
23 | routerDelegate: appRouter.delegate(),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/data/app_error.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:dio/dio.dart';
4 | import 'package:flutter/foundation.dart';
5 |
6 | enum AppErrorType {
7 | network,
8 | badRequest,
9 | unauthorized,
10 | cancel,
11 | timeout,
12 | server,
13 | unknown,
14 | }
15 |
16 | class AppError {
17 | late String message;
18 | late AppErrorType type;
19 |
20 | AppError(Exception? error) {
21 | if (error is DioError) {
22 | debugPrint('AppError(DioError): '
23 | 'type is ${error.type}, message is ${error.message}');
24 | message = error.message;
25 | switch (error.type) {
26 | case DioErrorType.other:
27 | if (error.error is SocketException) {
28 | // SocketException: Failed host lookup: '***'
29 | // (OS Error: No address associated with hostname, errno = 7)
30 | type = AppErrorType.network;
31 | } else {
32 | type = AppErrorType.unknown;
33 | }
34 | break;
35 | case DioErrorType.connectTimeout:
36 | case DioErrorType.receiveTimeout:
37 | type = AppErrorType.timeout;
38 | break;
39 | case DioErrorType.sendTimeout:
40 | type = AppErrorType.network;
41 | break;
42 | case DioErrorType.response:
43 | // TODO(api): need define more http status;
44 | switch (error.response?.statusCode) {
45 | case HttpStatus.badRequest: // 400
46 | type = AppErrorType.badRequest;
47 | break;
48 | case HttpStatus.unauthorized: // 401
49 | type = AppErrorType.unauthorized;
50 | break;
51 | case HttpStatus.internalServerError: // 500
52 | case HttpStatus.badGateway: // 502
53 | case HttpStatus.serviceUnavailable: // 503
54 | case HttpStatus.gatewayTimeout: // 504
55 | type = AppErrorType.server;
56 | break;
57 | default:
58 | type = AppErrorType.unknown;
59 | break;
60 | }
61 | break;
62 | case DioErrorType.cancel:
63 | type = AppErrorType.cancel;
64 | break;
65 | default:
66 | type = AppErrorType.unknown;
67 | }
68 | } else {
69 | debugPrint('AppError(UnKnown): $error');
70 | type = AppErrorType.unknown;
71 | message = 'AppError: $error';
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/lib/data/local/app_user.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_auth/firebase_auth.dart';
2 | import 'package:freezed_annotation/freezed_annotation.dart';
3 |
4 | part 'app_user.freezed.dart';
5 |
6 | @freezed
7 | abstract class AppUser with _$AppUser {
8 | factory AppUser({
9 | String? userId,
10 | String? imageUrl,
11 | String? name,
12 | String? email,
13 | }) = _AppUser;
14 |
15 | factory AppUser.from(User? firebaseUser) {
16 | return AppUser(
17 | userId: firebaseUser?.uid,
18 | imageUrl: firebaseUser?.photoURL,
19 | name: firebaseUser?.displayName,
20 | email: firebaseUser?.email,
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/data/local/app_user.freezed.dart:
--------------------------------------------------------------------------------
1 | // coverage:ignore-file
2 | // GENERATED CODE - DO NOT MODIFY BY HAND
3 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
4 |
5 | part of 'app_user.dart';
6 |
7 | // **************************************************************************
8 | // FreezedGenerator
9 | // **************************************************************************
10 |
11 | T _$identity(T value) => value;
12 |
13 | final _privateConstructorUsedError = UnsupportedError(
14 | 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
15 |
16 | /// @nodoc
17 | class _$AppUserTearOff {
18 | const _$AppUserTearOff();
19 |
20 | _AppUser call(
21 | {String? userId, String? imageUrl, String? name, String? email}) {
22 | return _AppUser(
23 | userId: userId,
24 | imageUrl: imageUrl,
25 | name: name,
26 | email: email,
27 | );
28 | }
29 | }
30 |
31 | /// @nodoc
32 | const $AppUser = _$AppUserTearOff();
33 |
34 | /// @nodoc
35 | mixin _$AppUser {
36 | String? get userId => throw _privateConstructorUsedError;
37 | String? get imageUrl => throw _privateConstructorUsedError;
38 | String? get name => throw _privateConstructorUsedError;
39 | String? get email => throw _privateConstructorUsedError;
40 |
41 | @JsonKey(ignore: true)
42 | $AppUserCopyWith get copyWith => throw _privateConstructorUsedError;
43 | }
44 |
45 | /// @nodoc
46 | abstract class $AppUserCopyWith<$Res> {
47 | factory $AppUserCopyWith(AppUser value, $Res Function(AppUser) then) =
48 | _$AppUserCopyWithImpl<$Res>;
49 | $Res call({String? userId, String? imageUrl, String? name, String? email});
50 | }
51 |
52 | /// @nodoc
53 | class _$AppUserCopyWithImpl<$Res> implements $AppUserCopyWith<$Res> {
54 | _$AppUserCopyWithImpl(this._value, this._then);
55 |
56 | final AppUser _value;
57 | // ignore: unused_field
58 | final $Res Function(AppUser) _then;
59 |
60 | @override
61 | $Res call({
62 | Object? userId = freezed,
63 | Object? imageUrl = freezed,
64 | Object? name = freezed,
65 | Object? email = freezed,
66 | }) {
67 | return _then(_value.copyWith(
68 | userId: userId == freezed
69 | ? _value.userId
70 | : userId // ignore: cast_nullable_to_non_nullable
71 | as String?,
72 | imageUrl: imageUrl == freezed
73 | ? _value.imageUrl
74 | : imageUrl // ignore: cast_nullable_to_non_nullable
75 | as String?,
76 | name: name == freezed
77 | ? _value.name
78 | : name // ignore: cast_nullable_to_non_nullable
79 | as String?,
80 | email: email == freezed
81 | ? _value.email
82 | : email // ignore: cast_nullable_to_non_nullable
83 | as String?,
84 | ));
85 | }
86 | }
87 |
88 | /// @nodoc
89 | abstract class _$AppUserCopyWith<$Res> implements $AppUserCopyWith<$Res> {
90 | factory _$AppUserCopyWith(_AppUser value, $Res Function(_AppUser) then) =
91 | __$AppUserCopyWithImpl<$Res>;
92 | @override
93 | $Res call({String? userId, String? imageUrl, String? name, String? email});
94 | }
95 |
96 | /// @nodoc
97 | class __$AppUserCopyWithImpl<$Res> extends _$AppUserCopyWithImpl<$Res>
98 | implements _$AppUserCopyWith<$Res> {
99 | __$AppUserCopyWithImpl(_AppUser _value, $Res Function(_AppUser) _then)
100 | : super(_value, (v) => _then(v as _AppUser));
101 |
102 | @override
103 | _AppUser get _value => super._value as _AppUser;
104 |
105 | @override
106 | $Res call({
107 | Object? userId = freezed,
108 | Object? imageUrl = freezed,
109 | Object? name = freezed,
110 | Object? email = freezed,
111 | }) {
112 | return _then(_AppUser(
113 | userId: userId == freezed
114 | ? _value.userId
115 | : userId // ignore: cast_nullable_to_non_nullable
116 | as String?,
117 | imageUrl: imageUrl == freezed
118 | ? _value.imageUrl
119 | : imageUrl // ignore: cast_nullable_to_non_nullable
120 | as String?,
121 | name: name == freezed
122 | ? _value.name
123 | : name // ignore: cast_nullable_to_non_nullable
124 | as String?,
125 | email: email == freezed
126 | ? _value.email
127 | : email // ignore: cast_nullable_to_non_nullable
128 | as String?,
129 | ));
130 | }
131 | }
132 |
133 | /// @nodoc
134 |
135 | class _$_AppUser implements _AppUser {
136 | _$_AppUser({this.userId, this.imageUrl, this.name, this.email});
137 |
138 | @override
139 | final String? userId;
140 | @override
141 | final String? imageUrl;
142 | @override
143 | final String? name;
144 | @override
145 | final String? email;
146 |
147 | @override
148 | String toString() {
149 | return 'AppUser(userId: $userId, imageUrl: $imageUrl, name: $name, email: $email)';
150 | }
151 |
152 | @override
153 | bool operator ==(dynamic other) {
154 | return identical(this, other) ||
155 | (other is _AppUser &&
156 | (identical(other.userId, userId) ||
157 | const DeepCollectionEquality().equals(other.userId, userId)) &&
158 | (identical(other.imageUrl, imageUrl) ||
159 | const DeepCollectionEquality()
160 | .equals(other.imageUrl, imageUrl)) &&
161 | (identical(other.name, name) ||
162 | const DeepCollectionEquality().equals(other.name, name)) &&
163 | (identical(other.email, email) ||
164 | const DeepCollectionEquality().equals(other.email, email)));
165 | }
166 |
167 | @override
168 | int get hashCode =>
169 | runtimeType.hashCode ^
170 | const DeepCollectionEquality().hash(userId) ^
171 | const DeepCollectionEquality().hash(imageUrl) ^
172 | const DeepCollectionEquality().hash(name) ^
173 | const DeepCollectionEquality().hash(email);
174 |
175 | @JsonKey(ignore: true)
176 | @override
177 | _$AppUserCopyWith<_AppUser> get copyWith =>
178 | __$AppUserCopyWithImpl<_AppUser>(this, _$identity);
179 | }
180 |
181 | abstract class _AppUser implements AppUser {
182 | factory _AppUser(
183 | {String? userId,
184 | String? imageUrl,
185 | String? name,
186 | String? email}) = _$_AppUser;
187 |
188 | @override
189 | String? get userId => throw _privateConstructorUsedError;
190 | @override
191 | String? get imageUrl => throw _privateConstructorUsedError;
192 | @override
193 | String? get name => throw _privateConstructorUsedError;
194 | @override
195 | String? get email => throw _privateConstructorUsedError;
196 | @override
197 | @JsonKey(ignore: true)
198 | _$AppUserCopyWith<_AppUser> get copyWith =>
199 | throw _privateConstructorUsedError;
200 | }
201 |
--------------------------------------------------------------------------------
/lib/data/model/article.dart:
--------------------------------------------------------------------------------
1 | import 'package:app/data/model/source.dart';
2 | import 'package:freezed_annotation/freezed_annotation.dart';
3 |
4 | part 'article.freezed.dart';
5 | part 'article.g.dart';
6 |
7 | @freezed
8 | abstract class Article with _$Article {
9 | factory Article({
10 | Source? source,
11 | String? author,
12 | String? title,
13 | String? description,
14 | String? url,
15 | String? urlToImage,
16 | DateTime? publishedAt,
17 | String? content,
18 | }) = _Article;
19 |
20 | factory Article.fromJson(Map json) =>
21 | _$ArticleFromJson(json);
22 | }
23 |
--------------------------------------------------------------------------------
/lib/data/model/article.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'article.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | _$_Article _$$_ArticleFromJson(Map json) => _$_Article(
10 | source: json['source'] == null
11 | ? null
12 | : Source.fromJson(json['source'] as Map),
13 | author: json['author'] as String?,
14 | title: json['title'] as String?,
15 | description: json['description'] as String?,
16 | url: json['url'] as String?,
17 | urlToImage: json['urlToImage'] as String?,
18 | publishedAt: json['publishedAt'] == null
19 | ? null
20 | : DateTime.parse(json['publishedAt'] as String),
21 | content: json['content'] as String?,
22 | );
23 |
24 | Map _$$_ArticleToJson(_$_Article instance) =>
25 | {
26 | 'source': instance.source,
27 | 'author': instance.author,
28 | 'title': instance.title,
29 | 'description': instance.description,
30 | 'url': instance.url,
31 | 'urlToImage': instance.urlToImage,
32 | 'publishedAt': instance.publishedAt?.toIso8601String(),
33 | 'content': instance.content,
34 | };
35 |
--------------------------------------------------------------------------------
/lib/data/model/news.dart:
--------------------------------------------------------------------------------
1 | import 'package:app/data/model/article.dart';
2 | import 'package:freezed_annotation/freezed_annotation.dart';
3 |
4 | part 'news.freezed.dart';
5 | part 'news.g.dart';
6 |
7 | @freezed
8 | abstract class News with _$News {
9 | factory News({
10 | required String status,
11 | required int totalResults,
12 | required List articles,
13 | }) = _News;
14 |
15 | factory News.fromJson(Map json) => _$NewsFromJson(json);
16 | }
17 |
--------------------------------------------------------------------------------
/lib/data/model/news.freezed.dart:
--------------------------------------------------------------------------------
1 | // coverage:ignore-file
2 | // GENERATED CODE - DO NOT MODIFY BY HAND
3 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
4 |
5 | part of 'news.dart';
6 |
7 | // **************************************************************************
8 | // FreezedGenerator
9 | // **************************************************************************
10 |
11 | T _$identity(T value) => value;
12 |
13 | final _privateConstructorUsedError = UnsupportedError(
14 | 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
15 |
16 | News _$NewsFromJson(Map json) {
17 | return _News.fromJson(json);
18 | }
19 |
20 | /// @nodoc
21 | class _$NewsTearOff {
22 | const _$NewsTearOff();
23 |
24 | _News call(
25 | {required String status,
26 | required int totalResults,
27 | required List articles}) {
28 | return _News(
29 | status: status,
30 | totalResults: totalResults,
31 | articles: articles,
32 | );
33 | }
34 |
35 | News fromJson(Map json) {
36 | return News.fromJson(json);
37 | }
38 | }
39 |
40 | /// @nodoc
41 | const $News = _$NewsTearOff();
42 |
43 | /// @nodoc
44 | mixin _$News {
45 | String get status => throw _privateConstructorUsedError;
46 | int get totalResults => throw _privateConstructorUsedError;
47 | List get articles => throw _privateConstructorUsedError;
48 |
49 | Map toJson() => throw _privateConstructorUsedError;
50 | @JsonKey(ignore: true)
51 | $NewsCopyWith get copyWith => throw _privateConstructorUsedError;
52 | }
53 |
54 | /// @nodoc
55 | abstract class $NewsCopyWith<$Res> {
56 | factory $NewsCopyWith(News value, $Res Function(News) then) =
57 | _$NewsCopyWithImpl<$Res>;
58 | $Res call({String status, int totalResults, List articles});
59 | }
60 |
61 | /// @nodoc
62 | class _$NewsCopyWithImpl<$Res> implements $NewsCopyWith<$Res> {
63 | _$NewsCopyWithImpl(this._value, this._then);
64 |
65 | final News _value;
66 | // ignore: unused_field
67 | final $Res Function(News) _then;
68 |
69 | @override
70 | $Res call({
71 | Object? status = freezed,
72 | Object? totalResults = freezed,
73 | Object? articles = freezed,
74 | }) {
75 | return _then(_value.copyWith(
76 | status: status == freezed
77 | ? _value.status
78 | : status // ignore: cast_nullable_to_non_nullable
79 | as String,
80 | totalResults: totalResults == freezed
81 | ? _value.totalResults
82 | : totalResults // ignore: cast_nullable_to_non_nullable
83 | as int,
84 | articles: articles == freezed
85 | ? _value.articles
86 | : articles // ignore: cast_nullable_to_non_nullable
87 | as List,
88 | ));
89 | }
90 | }
91 |
92 | /// @nodoc
93 | abstract class _$NewsCopyWith<$Res> implements $NewsCopyWith<$Res> {
94 | factory _$NewsCopyWith(_News value, $Res Function(_News) then) =
95 | __$NewsCopyWithImpl<$Res>;
96 | @override
97 | $Res call({String status, int totalResults, List articles});
98 | }
99 |
100 | /// @nodoc
101 | class __$NewsCopyWithImpl<$Res> extends _$NewsCopyWithImpl<$Res>
102 | implements _$NewsCopyWith<$Res> {
103 | __$NewsCopyWithImpl(_News _value, $Res Function(_News) _then)
104 | : super(_value, (v) => _then(v as _News));
105 |
106 | @override
107 | _News get _value => super._value as _News;
108 |
109 | @override
110 | $Res call({
111 | Object? status = freezed,
112 | Object? totalResults = freezed,
113 | Object? articles = freezed,
114 | }) {
115 | return _then(_News(
116 | status: status == freezed
117 | ? _value.status
118 | : status // ignore: cast_nullable_to_non_nullable
119 | as String,
120 | totalResults: totalResults == freezed
121 | ? _value.totalResults
122 | : totalResults // ignore: cast_nullable_to_non_nullable
123 | as int,
124 | articles: articles == freezed
125 | ? _value.articles
126 | : articles // ignore: cast_nullable_to_non_nullable
127 | as List,
128 | ));
129 | }
130 | }
131 |
132 | /// @nodoc
133 | @JsonSerializable()
134 | class _$_News implements _News {
135 | _$_News(
136 | {required this.status,
137 | required this.totalResults,
138 | required this.articles});
139 |
140 | factory _$_News.fromJson(Map json) => _$$_NewsFromJson(json);
141 |
142 | @override
143 | final String status;
144 | @override
145 | final int totalResults;
146 | @override
147 | final List articles;
148 |
149 | @override
150 | String toString() {
151 | return 'News(status: $status, totalResults: $totalResults, articles: $articles)';
152 | }
153 |
154 | @override
155 | bool operator ==(dynamic other) {
156 | return identical(this, other) ||
157 | (other is _News &&
158 | (identical(other.status, status) ||
159 | const DeepCollectionEquality().equals(other.status, status)) &&
160 | (identical(other.totalResults, totalResults) ||
161 | const DeepCollectionEquality()
162 | .equals(other.totalResults, totalResults)) &&
163 | (identical(other.articles, articles) ||
164 | const DeepCollectionEquality()
165 | .equals(other.articles, articles)));
166 | }
167 |
168 | @override
169 | int get hashCode =>
170 | runtimeType.hashCode ^
171 | const DeepCollectionEquality().hash(status) ^
172 | const DeepCollectionEquality().hash(totalResults) ^
173 | const DeepCollectionEquality().hash(articles);
174 |
175 | @JsonKey(ignore: true)
176 | @override
177 | _$NewsCopyWith<_News> get copyWith =>
178 | __$NewsCopyWithImpl<_News>(this, _$identity);
179 |
180 | @override
181 | Map toJson() {
182 | return _$$_NewsToJson(this);
183 | }
184 | }
185 |
186 | abstract class _News implements News {
187 | factory _News(
188 | {required String status,
189 | required int totalResults,
190 | required List articles}) = _$_News;
191 |
192 | factory _News.fromJson(Map json) = _$_News.fromJson;
193 |
194 | @override
195 | String get status => throw _privateConstructorUsedError;
196 | @override
197 | int get totalResults => throw _privateConstructorUsedError;
198 | @override
199 | List get articles => throw _privateConstructorUsedError;
200 | @override
201 | @JsonKey(ignore: true)
202 | _$NewsCopyWith<_News> get copyWith => throw _privateConstructorUsedError;
203 | }
204 |
--------------------------------------------------------------------------------
/lib/data/model/news.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'news.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | _$_News _$$_NewsFromJson(Map json) => _$_News(
10 | status: json['status'] as String,
11 | totalResults: json['totalResults'] as int,
12 | articles: (json['articles'] as List)
13 | .map((e) => Article.fromJson(e as Map))
14 | .toList(),
15 | );
16 |
17 | Map _$$_NewsToJson(_$_News instance) => {
18 | 'status': instance.status,
19 | 'totalResults': instance.totalResults,
20 | 'articles': instance.articles,
21 | };
22 |
--------------------------------------------------------------------------------
/lib/data/model/result.dart:
--------------------------------------------------------------------------------
1 | import 'package:app/data/app_error.dart';
2 | import 'package:flutter/foundation.dart';
3 | import 'package:freezed_annotation/freezed_annotation.dart';
4 |
5 | part 'result.freezed.dart';
6 |
7 | @freezed
8 | abstract class Result with _$Result {
9 | const Result._();
10 |
11 | const factory Result.success({required T data}) = Success;
12 |
13 | const factory Result.failure({required AppError error}) = Failure;
14 |
15 | static Result guard(T Function() body) {
16 | try {
17 | return Result.success(data: body());
18 | } on Exception catch (e) {
19 | return Result.failure(error: AppError(e));
20 | }
21 | }
22 |
23 | static Future> guardFuture(Future Function() future) async {
24 | try {
25 | return Result.success(data: await future());
26 | } on Exception catch (e) {
27 | return Result.failure(error: AppError(e));
28 | }
29 | }
30 |
31 | bool get isSuccess => when(success: (data) => true, failure: (e) => false);
32 |
33 | bool get isFailure => !isSuccess;
34 |
35 | void ifSuccess(Function(T data) body) {
36 | maybeWhen(
37 | success: (data) => body(data),
38 | orElse: () {
39 | // no-op
40 | },
41 | );
42 | }
43 |
44 | void ifFailure(Function(AppError e) body) {
45 | maybeWhen(
46 | failure: (e) => body(e),
47 | orElse: () {
48 | // no-op
49 | },
50 | );
51 | }
52 |
53 | T get dataOrThrow {
54 | return when(
55 | success: (data) => data,
56 | failure: (e) => throw e,
57 | );
58 | }
59 | }
60 |
61 | extension ResultObjectExt on T {
62 | Result get asSuccess => Result.success(data: this);
63 |
64 | Result asFailure(Exception e) => Result.failure(error: AppError(e));
65 | }
66 |
--------------------------------------------------------------------------------
/lib/data/model/result.freezed.dart:
--------------------------------------------------------------------------------
1 | // coverage:ignore-file
2 | // GENERATED CODE - DO NOT MODIFY BY HAND
3 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
4 |
5 | part of 'result.dart';
6 |
7 | // **************************************************************************
8 | // FreezedGenerator
9 | // **************************************************************************
10 |
11 | T _$identity(T value) => value;
12 |
13 | final _privateConstructorUsedError = UnsupportedError(
14 | 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
15 |
16 | /// @nodoc
17 | class _$ResultTearOff {
18 | const _$ResultTearOff();
19 |
20 | Success success({required T data}) {
21 | return Success(
22 | data: data,
23 | );
24 | }
25 |
26 | Failure failure({required AppError error}) {
27 | return Failure(
28 | error: error,
29 | );
30 | }
31 | }
32 |
33 | /// @nodoc
34 | const $Result = _$ResultTearOff();
35 |
36 | /// @nodoc
37 | mixin _$Result {
38 | @optionalTypeArgs
39 | TResult when({
40 | required TResult Function(T data) success,
41 | required TResult Function(AppError error) failure,
42 | }) =>
43 | throw _privateConstructorUsedError;
44 | @optionalTypeArgs
45 | TResult? whenOrNull({
46 | TResult Function(T data)? success,
47 | TResult Function(AppError error)? failure,
48 | }) =>
49 | throw _privateConstructorUsedError;
50 | @optionalTypeArgs
51 | TResult maybeWhen({
52 | TResult Function(T data)? success,
53 | TResult Function(AppError error)? failure,
54 | required TResult orElse(),
55 | }) =>
56 | throw _privateConstructorUsedError;
57 | @optionalTypeArgs
58 | TResult map({
59 | required TResult Function(Success value) success,
60 | required TResult Function(Failure value) failure,
61 | }) =>
62 | throw _privateConstructorUsedError;
63 | @optionalTypeArgs
64 | TResult? mapOrNull({
65 | TResult Function(Success value)? success,
66 | TResult Function(Failure value)? failure,
67 | }) =>
68 | throw _privateConstructorUsedError;
69 | @optionalTypeArgs
70 | TResult maybeMap({
71 | TResult Function(Success value)? success,
72 | TResult Function(Failure value)? failure,
73 | required TResult orElse(),
74 | }) =>
75 | throw _privateConstructorUsedError;
76 | }
77 |
78 | /// @nodoc
79 | abstract class $ResultCopyWith {
80 | factory $ResultCopyWith(Result value, $Res Function(Result) then) =
81 | _$ResultCopyWithImpl;
82 | }
83 |
84 | /// @nodoc
85 | class _$ResultCopyWithImpl implements $ResultCopyWith {
86 | _$ResultCopyWithImpl(this._value, this._then);
87 |
88 | final Result _value;
89 | // ignore: unused_field
90 | final $Res Function(Result) _then;
91 | }
92 |
93 | /// @nodoc
94 | abstract class $SuccessCopyWith {
95 | factory $SuccessCopyWith(Success value, $Res Function(Success) then) =
96 | _$SuccessCopyWithImpl;
97 | $Res call({T data});
98 | }
99 |
100 | /// @nodoc
101 | class _$SuccessCopyWithImpl extends _$ResultCopyWithImpl
102 | implements $SuccessCopyWith {
103 | _$SuccessCopyWithImpl(Success _value, $Res Function(Success) _then)
104 | : super(_value, (v) => _then(v as Success));
105 |
106 | @override
107 | Success get _value => super._value as Success;
108 |
109 | @override
110 | $Res call({
111 | Object? data = freezed,
112 | }) {
113 | return _then(Success(
114 | data: data == freezed
115 | ? _value.data
116 | : data // ignore: cast_nullable_to_non_nullable
117 | as T,
118 | ));
119 | }
120 | }
121 |
122 | /// @nodoc
123 |
124 | class _$Success extends Success with DiagnosticableTreeMixin {
125 | const _$Success({required this.data}) : super._();
126 |
127 | @override
128 | final T data;
129 |
130 | @override
131 | String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
132 | return 'Result<$T>.success(data: $data)';
133 | }
134 |
135 | @override
136 | void debugFillProperties(DiagnosticPropertiesBuilder properties) {
137 | super.debugFillProperties(properties);
138 | properties
139 | ..add(DiagnosticsProperty('type', 'Result<$T>.success'))
140 | ..add(DiagnosticsProperty('data', data));
141 | }
142 |
143 | @override
144 | bool operator ==(dynamic other) {
145 | return identical(this, other) ||
146 | (other is Success &&
147 | (identical(other.data, data) ||
148 | const DeepCollectionEquality().equals(other.data, data)));
149 | }
150 |
151 | @override
152 | int get hashCode =>
153 | runtimeType.hashCode ^ const DeepCollectionEquality().hash(data);
154 |
155 | @JsonKey(ignore: true)
156 | @override
157 | $SuccessCopyWith> get copyWith =>
158 | _$SuccessCopyWithImpl>(this, _$identity);
159 |
160 | @override
161 | @optionalTypeArgs
162 | TResult when({
163 | required TResult Function(T data) success,
164 | required TResult Function(AppError error) failure,
165 | }) {
166 | return success(data);
167 | }
168 |
169 | @override
170 | @optionalTypeArgs
171 | TResult? whenOrNull({
172 | TResult Function(T data)? success,
173 | TResult Function(AppError error)? failure,
174 | }) {
175 | return success?.call(data);
176 | }
177 |
178 | @override
179 | @optionalTypeArgs
180 | TResult maybeWhen({
181 | TResult Function(T data)? success,
182 | TResult Function(AppError error)? failure,
183 | required TResult orElse(),
184 | }) {
185 | if (success != null) {
186 | return success(data);
187 | }
188 | return orElse();
189 | }
190 |
191 | @override
192 | @optionalTypeArgs
193 | TResult map({
194 | required TResult Function(Success value) success,
195 | required TResult Function(Failure value) failure,
196 | }) {
197 | return success(this);
198 | }
199 |
200 | @override
201 | @optionalTypeArgs
202 | TResult? mapOrNull({
203 | TResult Function(Success value)? success,
204 | TResult Function(Failure value)? failure,
205 | }) {
206 | return success?.call(this);
207 | }
208 |
209 | @override
210 | @optionalTypeArgs
211 | TResult maybeMap({
212 | TResult Function(Success value)? success,
213 | TResult Function(Failure value)? failure,
214 | required TResult orElse(),
215 | }) {
216 | if (success != null) {
217 | return success(this);
218 | }
219 | return orElse();
220 | }
221 | }
222 |
223 | abstract class Success extends Result {
224 | const factory Success({required T data}) = _$Success;
225 | const Success._() : super._();
226 |
227 | T get data => throw _privateConstructorUsedError;
228 | @JsonKey(ignore: true)
229 | $SuccessCopyWith> get copyWith =>
230 | throw _privateConstructorUsedError;
231 | }
232 |
233 | /// @nodoc
234 | abstract class $FailureCopyWith {
235 | factory $FailureCopyWith(Failure value, $Res Function(Failure) then) =
236 | _$FailureCopyWithImpl;
237 | $Res call({AppError error});
238 | }
239 |
240 | /// @nodoc
241 | class _$FailureCopyWithImpl extends _$ResultCopyWithImpl
242 | implements $FailureCopyWith {
243 | _$FailureCopyWithImpl(Failure _value, $Res Function(Failure) _then)
244 | : super(_value, (v) => _then(v as Failure));
245 |
246 | @override
247 | Failure get _value => super._value as Failure;
248 |
249 | @override
250 | $Res call({
251 | Object? error = freezed,
252 | }) {
253 | return _then(Failure(
254 | error: error == freezed
255 | ? _value.error
256 | : error // ignore: cast_nullable_to_non_nullable
257 | as AppError,
258 | ));
259 | }
260 | }
261 |
262 | /// @nodoc
263 |
264 | class _$Failure extends Failure with DiagnosticableTreeMixin {
265 | const _$Failure({required this.error}) : super._();
266 |
267 | @override
268 | final AppError error;
269 |
270 | @override
271 | String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
272 | return 'Result<$T>.failure(error: $error)';
273 | }
274 |
275 | @override
276 | void debugFillProperties(DiagnosticPropertiesBuilder properties) {
277 | super.debugFillProperties(properties);
278 | properties
279 | ..add(DiagnosticsProperty('type', 'Result<$T>.failure'))
280 | ..add(DiagnosticsProperty('error', error));
281 | }
282 |
283 | @override
284 | bool operator ==(dynamic other) {
285 | return identical(this, other) ||
286 | (other is Failure &&
287 | (identical(other.error, error) ||
288 | const DeepCollectionEquality().equals(other.error, error)));
289 | }
290 |
291 | @override
292 | int get hashCode =>
293 | runtimeType.hashCode ^ const DeepCollectionEquality().hash(error);
294 |
295 | @JsonKey(ignore: true)
296 | @override
297 | $FailureCopyWith> get copyWith =>
298 | _$FailureCopyWithImpl>(this, _$identity);
299 |
300 | @override
301 | @optionalTypeArgs
302 | TResult when({
303 | required TResult Function(T data) success,
304 | required TResult Function(AppError error) failure,
305 | }) {
306 | return failure(error);
307 | }
308 |
309 | @override
310 | @optionalTypeArgs
311 | TResult? whenOrNull({
312 | TResult Function(T data)? success,
313 | TResult Function(AppError error)? failure,
314 | }) {
315 | return failure?.call(error);
316 | }
317 |
318 | @override
319 | @optionalTypeArgs
320 | TResult maybeWhen({
321 | TResult Function(T data)? success,
322 | TResult Function(AppError error)? failure,
323 | required TResult orElse(),
324 | }) {
325 | if (failure != null) {
326 | return failure(error);
327 | }
328 | return orElse();
329 | }
330 |
331 | @override
332 | @optionalTypeArgs
333 | TResult map({
334 | required TResult Function(Success value) success,
335 | required TResult Function(Failure value) failure,
336 | }) {
337 | return failure(this);
338 | }
339 |
340 | @override
341 | @optionalTypeArgs
342 | TResult? mapOrNull({
343 | TResult Function(Success value)? success,
344 | TResult Function(Failure value)? failure,
345 | }) {
346 | return failure?.call(this);
347 | }
348 |
349 | @override
350 | @optionalTypeArgs
351 | TResult maybeMap({
352 | TResult Function(Success value)? success,
353 | TResult Function(Failure value)? failure,
354 | required TResult orElse(),
355 | }) {
356 | if (failure != null) {
357 | return failure(this);
358 | }
359 | return orElse();
360 | }
361 | }
362 |
363 | abstract class Failure extends Result {
364 | const factory Failure({required AppError error}) = _$Failure;
365 | const Failure._() : super._();
366 |
367 | AppError get error => throw _privateConstructorUsedError;
368 | @JsonKey(ignore: true)
369 | $FailureCopyWith> get copyWith =>
370 | throw _privateConstructorUsedError;
371 | }
372 |
--------------------------------------------------------------------------------
/lib/data/model/source.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:freezed_annotation/freezed_annotation.dart';
3 |
4 | part 'source.freezed.dart';
5 | part 'source.g.dart';
6 |
7 | @freezed
8 | abstract class Source with _$Source {
9 | factory Source({
10 | String? id,
11 | String? name,
12 | }) = _Source;
13 |
14 | factory Source.fromJson(Map json) => _$SourceFromJson(json);
15 | }
16 |
--------------------------------------------------------------------------------
/lib/data/model/source.freezed.dart:
--------------------------------------------------------------------------------
1 | // coverage:ignore-file
2 | // GENERATED CODE - DO NOT MODIFY BY HAND
3 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
4 |
5 | part of 'source.dart';
6 |
7 | // **************************************************************************
8 | // FreezedGenerator
9 | // **************************************************************************
10 |
11 | T _$identity(T value) => value;
12 |
13 | final _privateConstructorUsedError = UnsupportedError(
14 | 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
15 |
16 | Source _$SourceFromJson(Map json) {
17 | return _Source.fromJson(json);
18 | }
19 |
20 | /// @nodoc
21 | class _$SourceTearOff {
22 | const _$SourceTearOff();
23 |
24 | _Source call({String? id, String? name}) {
25 | return _Source(
26 | id: id,
27 | name: name,
28 | );
29 | }
30 |
31 | Source fromJson(Map json) {
32 | return Source.fromJson(json);
33 | }
34 | }
35 |
36 | /// @nodoc
37 | const $Source = _$SourceTearOff();
38 |
39 | /// @nodoc
40 | mixin _$Source {
41 | String? get id => throw _privateConstructorUsedError;
42 | String? get name => throw _privateConstructorUsedError;
43 |
44 | Map toJson() => throw _privateConstructorUsedError;
45 | @JsonKey(ignore: true)
46 | $SourceCopyWith get copyWith => throw _privateConstructorUsedError;
47 | }
48 |
49 | /// @nodoc
50 | abstract class $SourceCopyWith<$Res> {
51 | factory $SourceCopyWith(Source value, $Res Function(Source) then) =
52 | _$SourceCopyWithImpl<$Res>;
53 | $Res call({String? id, String? name});
54 | }
55 |
56 | /// @nodoc
57 | class _$SourceCopyWithImpl<$Res> implements $SourceCopyWith<$Res> {
58 | _$SourceCopyWithImpl(this._value, this._then);
59 |
60 | final Source _value;
61 | // ignore: unused_field
62 | final $Res Function(Source) _then;
63 |
64 | @override
65 | $Res call({
66 | Object? id = freezed,
67 | Object? name = freezed,
68 | }) {
69 | return _then(_value.copyWith(
70 | id: id == freezed
71 | ? _value.id
72 | : id // ignore: cast_nullable_to_non_nullable
73 | as String?,
74 | name: name == freezed
75 | ? _value.name
76 | : name // ignore: cast_nullable_to_non_nullable
77 | as String?,
78 | ));
79 | }
80 | }
81 |
82 | /// @nodoc
83 | abstract class _$SourceCopyWith<$Res> implements $SourceCopyWith<$Res> {
84 | factory _$SourceCopyWith(_Source value, $Res Function(_Source) then) =
85 | __$SourceCopyWithImpl<$Res>;
86 | @override
87 | $Res call({String? id, String? name});
88 | }
89 |
90 | /// @nodoc
91 | class __$SourceCopyWithImpl<$Res> extends _$SourceCopyWithImpl<$Res>
92 | implements _$SourceCopyWith<$Res> {
93 | __$SourceCopyWithImpl(_Source _value, $Res Function(_Source) _then)
94 | : super(_value, (v) => _then(v as _Source));
95 |
96 | @override
97 | _Source get _value => super._value as _Source;
98 |
99 | @override
100 | $Res call({
101 | Object? id = freezed,
102 | Object? name = freezed,
103 | }) {
104 | return _then(_Source(
105 | id: id == freezed
106 | ? _value.id
107 | : id // ignore: cast_nullable_to_non_nullable
108 | as String?,
109 | name: name == freezed
110 | ? _value.name
111 | : name // ignore: cast_nullable_to_non_nullable
112 | as String?,
113 | ));
114 | }
115 | }
116 |
117 | /// @nodoc
118 | @JsonSerializable()
119 | class _$_Source with DiagnosticableTreeMixin implements _Source {
120 | _$_Source({this.id, this.name});
121 |
122 | factory _$_Source.fromJson(Map json) =>
123 | _$$_SourceFromJson(json);
124 |
125 | @override
126 | final String? id;
127 | @override
128 | final String? name;
129 |
130 | @override
131 | String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
132 | return 'Source(id: $id, name: $name)';
133 | }
134 |
135 | @override
136 | void debugFillProperties(DiagnosticPropertiesBuilder properties) {
137 | super.debugFillProperties(properties);
138 | properties
139 | ..add(DiagnosticsProperty('type', 'Source'))
140 | ..add(DiagnosticsProperty('id', id))
141 | ..add(DiagnosticsProperty('name', name));
142 | }
143 |
144 | @override
145 | bool operator ==(dynamic other) {
146 | return identical(this, other) ||
147 | (other is _Source &&
148 | (identical(other.id, id) ||
149 | const DeepCollectionEquality().equals(other.id, id)) &&
150 | (identical(other.name, name) ||
151 | const DeepCollectionEquality().equals(other.name, name)));
152 | }
153 |
154 | @override
155 | int get hashCode =>
156 | runtimeType.hashCode ^
157 | const DeepCollectionEquality().hash(id) ^
158 | const DeepCollectionEquality().hash(name);
159 |
160 | @JsonKey(ignore: true)
161 | @override
162 | _$SourceCopyWith<_Source> get copyWith =>
163 | __$SourceCopyWithImpl<_Source>(this, _$identity);
164 |
165 | @override
166 | Map toJson() {
167 | return _$$_SourceToJson(this);
168 | }
169 | }
170 |
171 | abstract class _Source implements Source {
172 | factory _Source({String? id, String? name}) = _$_Source;
173 |
174 | factory _Source.fromJson(Map json) = _$_Source.fromJson;
175 |
176 | @override
177 | String? get id => throw _privateConstructorUsedError;
178 | @override
179 | String? get name => throw _privateConstructorUsedError;
180 | @override
181 | @JsonKey(ignore: true)
182 | _$SourceCopyWith<_Source> get copyWith => throw _privateConstructorUsedError;
183 | }
184 |
--------------------------------------------------------------------------------
/lib/data/model/source.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'source.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | _$_Source _$$_SourceFromJson(Map json) => _$_Source(
10 | id: json['id'] as String?,
11 | name: json['name'] as String?,
12 | );
13 |
14 | Map _$$_SourceToJson(_$_Source instance) => {
15 | 'id': instance.id,
16 | 'name': instance.name,
17 | };
18 |
--------------------------------------------------------------------------------
/lib/data/provider/firebase_auth_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_auth/firebase_auth.dart';
2 | import 'package:hooks_riverpod/hooks_riverpod.dart';
3 |
4 | final firebaseAuthProvider = Provider((_) => FirebaseAuth.instance);
5 |
--------------------------------------------------------------------------------
/lib/data/remote/app_dio.dart:
--------------------------------------------------------------------------------
1 | import 'package:app/foundation/constants.dart';
2 | import 'package:dio/adapter.dart';
3 | import 'package:dio/dio.dart';
4 | import 'package:dio_firebase_performance/dio_firebase_performance.dart';
5 | import 'package:flutter/foundation.dart';
6 | import 'package:hooks_riverpod/hooks_riverpod.dart';
7 | import 'package:ua_client_hints/ua_client_hints.dart';
8 |
9 | final dioProvider = Provider((_) => AppDio.getInstance());
10 |
11 | // ignore: prefer_mixin
12 | class AppDio with DioMixin implements Dio {
13 | AppDio._([BaseOptions? options]) {
14 | options = BaseOptions(
15 | baseUrl: Constants.of().endpoint,
16 | contentType: 'application/json',
17 | connectTimeout: 30000,
18 | sendTimeout: 30000,
19 | receiveTimeout: 30000,
20 | );
21 |
22 | this.options = options;
23 | interceptors.add(InterceptorsWrapper(onRequest: (options, handler) async {
24 | options.headers.addAll(await userAgentClientHintsHeader());
25 | handler.next(options);
26 | }));
27 |
28 | // Firebase Performance
29 | interceptors.add(DioFirebasePerformanceInterceptor());
30 |
31 | if (kDebugMode) {
32 | // Local Log
33 | interceptors.add(LogInterceptor(responseBody: true, requestBody: true));
34 | }
35 |
36 | httpClientAdapter = DefaultHttpClientAdapter();
37 | }
38 |
39 | static Dio getInstance() => AppDio._();
40 | }
41 |
--------------------------------------------------------------------------------
/lib/data/remote/auth_data_source.dart:
--------------------------------------------------------------------------------
1 | import 'package:firebase_auth/firebase_auth.dart';
2 |
3 | abstract class AuthDataSource {
4 | Future signIn();
5 |
6 | Future signOut();
7 | }
8 |
--------------------------------------------------------------------------------
/lib/data/remote/auth_data_source_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:app/data/provider/firebase_auth_provider.dart';
2 | import 'package:app/data/remote/auth_data_source.dart';
3 | import 'package:firebase_auth/firebase_auth.dart' as firebase;
4 | import 'package:flutter/foundation.dart';
5 | import 'package:google_sign_in/google_sign_in.dart';
6 | import 'package:hooks_riverpod/hooks_riverpod.dart';
7 |
8 | final authDataSourceProvider = Provider((ref) => AuthDataSourceImpl(ref.read));
9 |
10 | class AuthDataSourceImpl implements AuthDataSource {
11 | AuthDataSourceImpl(this._reader);
12 |
13 | final Reader _reader;
14 |
15 | late final firebase.FirebaseAuth _firebaseAuth =
16 | _reader(firebaseAuthProvider);
17 |
18 | @override
19 | Future signIn() async {
20 | final account = await GoogleSignIn().signIn();
21 | if (account == null) {
22 | return throw StateError('Maybe user canceled.');
23 | }
24 | final auth = await account.authentication;
25 | final firebase.AuthCredential authCredential =
26 | firebase.GoogleAuthProvider.credential(
27 | idToken: auth.idToken,
28 | accessToken: auth.accessToken,
29 | );
30 |
31 | final credential = await _firebaseAuth.signInWithCredential(authCredential);
32 | final currentUser = firebase.FirebaseAuth.instance.currentUser;
33 | assert(credential.user?.uid == currentUser?.uid);
34 | return credential.user;
35 | }
36 |
37 | @override
38 | Future signOut() {
39 | return GoogleSignIn()
40 | .signOut()
41 | .then((_) => _firebaseAuth.signOut())
42 | .catchError((error) {
43 | debugPrint(error.toString());
44 | throw error;
45 | });
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/data/remote/news_data_source.dart:
--------------------------------------------------------------------------------
1 | import 'package:app/data/model/news.dart';
2 | import 'package:app/data/remote/app_dio.dart';
3 | import 'package:dio/dio.dart';
4 | import 'package:hooks_riverpod/hooks_riverpod.dart';
5 | import 'package:retrofit/retrofit.dart';
6 |
7 | part 'news_data_source.g.dart';
8 |
9 | final newsDataSourceProvider = Provider((ref) => NewsDataSource(ref.read));
10 |
11 | @RestApi()
12 | abstract class NewsDataSource {
13 | factory NewsDataSource(Reader reader) => _NewsDataSource(reader(dioProvider));
14 |
15 | @GET('/v2/everything')
16 | Future getNews({
17 | @Query("q") required String query,
18 | @Query("from") required String from,
19 | @Query("sortBy") String? sortBy = 'publishedAt',
20 | @Query("language") String? language = 'en',
21 | @Query("apiKey") required String apiKey,
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/lib/data/remote/news_data_source.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'news_data_source.dart';
4 |
5 | // **************************************************************************
6 | // RetrofitGenerator
7 | // **************************************************************************
8 |
9 | class _NewsDataSource implements NewsDataSource {
10 | _NewsDataSource(this._dio, {this.baseUrl});
11 |
12 | final Dio _dio;
13 |
14 | String? baseUrl;
15 |
16 | @override
17 | Future getNews(
18 | {required query,
19 | required from,
20 | sortBy = 'publishedAt',
21 | language = 'en',
22 | required apiKey}) async {
23 | const _extra = {};
24 | final queryParameters = {
25 | r'q': query,
26 | r'from': from,
27 | r'sortBy': sortBy,
28 | r'language': language,
29 | r'apiKey': apiKey
30 | };
31 | queryParameters.removeWhere((k, v) => v == null);
32 | final _headers = {};
33 | final _data = {};
34 | final _result = await _dio.fetch