├── analysis_options.yaml
├── ios
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── 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-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ └── project.pbxproj
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── .gitignore
├── Podfile.lock
└── Podfile
├── assets
└── readme
│ ├── arch.png
│ ├── demo.gif
│ ├── demo1.png
│ ├── demo2.png
│ └── testing.png
├── lib
├── src
│ ├── features
│ │ └── jokes
│ │ │ ├── views
│ │ │ ├── widgets.dart
│ │ │ ├── widgets
│ │ │ │ ├── loading.dart
│ │ │ │ └── joke_available.dart
│ │ │ └── joke_page.dart
│ │ │ └── logic
│ │ │ ├── jokes_state.dart
│ │ │ ├── jokes_state_notifier.dart
│ │ │ ├── jokes_provider.dart
│ │ │ └── jokes_state.freezed.dart
│ ├── core
│ │ ├── env
│ │ │ └── environment_config.dart
│ │ ├── providers
│ │ │ └── package_info_provider.dart
│ │ └── widgets
│ │ │ └── app_version.dart
│ └── app.dart
└── main.dart
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── 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
│ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ └── values
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── dev
│ │ │ │ │ └── noscope
│ │ │ │ │ └── flutter_jokes
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle
└── build.gradle
├── devtools_options.yaml
├── packages
└── jokes
│ ├── lib
│ ├── jokes.dart
│ └── src
│ │ ├── data
│ │ ├── datasources
│ │ │ └── remote
│ │ │ │ ├── remote_data_source.dart
│ │ │ │ ├── dio_data_source.dart
│ │ │ │ └── http_data_source.dart
│ │ ├── data.dart
│ │ ├── repositories
│ │ │ └── jokes_repository.dart
│ │ └── models
│ │ │ ├── flags_model.g.dart
│ │ │ ├── flags_model.dart
│ │ │ ├── joke_model.g.dart
│ │ │ └── joke_model.dart
│ │ └── domain
│ │ ├── domain.dart
│ │ ├── repositories
│ │ └── ijokes_repository.dart
│ │ ├── usecases
│ │ └── get_joke.dart
│ │ └── entities
│ │ ├── flags.dart
│ │ └── joke.dart
│ ├── analysis_options.yaml
│ ├── pubspec.yaml
│ └── pubspec.lock
├── .metadata
├── .vscode
└── launch.json
├── .gitignore
├── pubspec.yaml
├── coverage
└── lcov.info
├── README.md
├── test
└── jokes
│ ├── logic
│ └── jokes_state_notifier_test.dart
│ └── views
│ └── joke_page_test.dart
└── pubspec.lock
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | analyzer:
2 | plugins:
3 | - custom_lint
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/assets/readme/arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/assets/readme/arch.png
--------------------------------------------------------------------------------
/assets/readme/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/assets/readme/demo.gif
--------------------------------------------------------------------------------
/assets/readme/demo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/assets/readme/demo1.png
--------------------------------------------------------------------------------
/assets/readme/demo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/assets/readme/demo2.png
--------------------------------------------------------------------------------
/assets/readme/testing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/assets/readme/testing.png
--------------------------------------------------------------------------------
/lib/src/features/jokes/views/widgets.dart:
--------------------------------------------------------------------------------
1 | export 'widgets/joke_available.dart';
2 | export 'widgets/loading.dart';
3 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/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/NoScopeDevs/flutter_jokes/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NoScopeDevs/flutter_jokes/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/devtools_options.yaml:
--------------------------------------------------------------------------------
1 | description: This file stores settings for Dart & Flutter DevTools.
2 | documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
3 | extensions:
4 |
--------------------------------------------------------------------------------
/lib/src/core/env/environment_config.dart:
--------------------------------------------------------------------------------
1 | /// This class contains all the environment variables
2 | class EnvironmentConfig {
3 | /// URL for API
4 | static const apiUrl = String.fromEnvironment('apiUrl');
5 | }
6 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/dev/noscope/flutter_jokes/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.noscope.flutter_jokes
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_riverpod/flutter_riverpod.dart';
3 |
4 | import 'src/app.dart';
5 |
6 | void main() {
7 | runApp(ProviderScope(child: JokesApp()));
8 | }
9 |
--------------------------------------------------------------------------------
/packages/jokes/lib/jokes.dart:
--------------------------------------------------------------------------------
1 | /// Jokes library
2 | library;
3 |
4 | export 'src/data/data.dart'
5 | show DioDataSource, HttpDataSource, JokeModel, JokesRepository;
6 | export 'src/domain/domain.dart' show GetJoke, IJokesRepository, Joke;
7 |
--------------------------------------------------------------------------------
/packages/jokes/lib/src/data/datasources/remote/remote_data_source.dart:
--------------------------------------------------------------------------------
1 | // IDC
2 | // ignore_for_file: one_member_abstracts
3 |
4 | import 'package:jokes/src/domain/domain.dart' show Joke;
5 |
6 | abstract class IRemoteDataSource {
7 | Future getJoke();
8 | }
9 |
--------------------------------------------------------------------------------
/packages/jokes/lib/src/domain/domain.dart:
--------------------------------------------------------------------------------
1 | // Export Entities
2 | export 'entities/flags.dart';
3 | export 'entities/joke.dart';
4 |
5 | // Export Repositories
6 | export 'repositories/ijokes_repository.dart';
7 |
8 | // Export Use Cases
9 | export 'usecases/get_joke.dart';
10 |
--------------------------------------------------------------------------------
/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-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/packages/jokes/lib/src/domain/repositories/ijokes_repository.dart:
--------------------------------------------------------------------------------
1 | // IDC
2 | // ignore_for_file: one_member_abstracts
3 |
4 | import 'package:jokes/src/domain/entities/joke.dart';
5 |
6 | /// Repository interface for jokes
7 | abstract class IJokesRepository {
8 | Future getJoke();
9 | }
10 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/src/features/jokes/views/widgets/loading.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class LoadingWidget extends StatelessWidget {
4 | const LoadingWidget({Key? key}) : super(key: key);
5 |
6 | @override
7 | Widget build(BuildContext context) {
8 | return CircularProgressIndicator(strokeWidth: 2);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.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: 78910062997c3a836feee883712c241a5fd22983
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/packages/jokes/lib/src/data/data.dart:
--------------------------------------------------------------------------------
1 | // Export Data Sources
2 | export 'datasources/remote/dio_data_source.dart';
3 | export 'datasources/remote/http_data_source.dart';
4 |
5 | // Export Models
6 | export 'models/flags_model.dart';
7 | export 'models/joke_model.dart';
8 |
9 | // Export Repositories Implementations
10 | export 'repositories/jokes_repository.dart';
11 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/packages/jokes/lib/src/domain/usecases/get_joke.dart:
--------------------------------------------------------------------------------
1 | import 'package:jokes/jokes.dart';
2 |
3 | import 'package:jokes/src/domain/domain.dart';
4 |
5 | class GetJoke {
6 | GetJoke({
7 | required IJokesRepository repository,
8 | }) : _repository = repository;
9 |
10 | final IJokesRepository _repository;
11 |
12 | /// Callable class method
13 | Future call() => _repository.getJoke();
14 | }
15 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @main
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 |
--------------------------------------------------------------------------------
/packages/jokes/lib/src/domain/entities/flags.dart:
--------------------------------------------------------------------------------
1 | import 'package:equatable/equatable.dart';
2 |
3 | abstract class Flags extends Equatable {
4 | const Flags({
5 | this.nsfw,
6 | this.religious,
7 | this.political,
8 | this.racist,
9 | this.sexist,
10 | this.explicit,
11 | });
12 |
13 | final bool? nsfw;
14 | final bool? religious;
15 | final bool? political;
16 | final bool? racist;
17 | final bool? sexist;
18 | final bool? explicit;
19 | }
20 |
--------------------------------------------------------------------------------
/lib/src/app.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'features/jokes/views/joke_page.dart';
4 |
5 | class JokesApp extends StatelessWidget {
6 | @override
7 | Widget build(BuildContext context) {
8 | return MaterialApp(
9 | title: 'Flutter Jokes',
10 | debugShowCheckedModeBanner: false,
11 | theme: ThemeData.dark().copyWith(
12 | visualDensity: VisualDensity.adaptivePlatformDensity,
13 | ),
14 | home: JokePage(),
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/packages/jokes/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # Very Good Dart analyzer settings and best practices
2 | # used internally at Very Good Ventures.
3 | # For more info, see https://pub.dev/packages/very_good_analysis.
4 | include: package:very_good_analysis/analysis_options.yaml
5 |
6 | # For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
7 | # Uncomment to specify additional rules.
8 | linter:
9 | rules:
10 | public_member_api_docs: false
11 |
12 | analyzer:
13 | exclude:
14 | - "*/.g.dart"
15 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/src/core/providers/package_info_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_riverpod/flutter_riverpod.dart';
2 | import 'package:package_info/package_info.dart';
3 | import 'package:riverpod_annotation/riverpod_annotation.dart';
4 |
5 | final packageInfoProvider = FutureProvider(
6 | (_) async => await PackageInfo.fromPlatform(),
7 | );
8 |
9 | // @riverpod
10 | // Future packageInfo(Ref ref) async {
11 | // final packageInfo = await PackageInfo.fromPlatform();
12 | // return packageInfo;
13 | // }
14 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/packages/jokes/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: jokes
2 | description: Dart package to manage jokes data and domain layers.
3 | version: 0.0.1+1
4 |
5 | environment:
6 | sdk: ">=3.6.0 <4.0.0"
7 |
8 | dependencies:
9 | dio: ^5.8.0+1
10 | equatable: ^2.0.0
11 | http: ^1.3.0
12 | json_annotation: ^4.9.0
13 | meta: ^1.3.0
14 | path: ^1.8.0
15 |
16 | dev_dependencies:
17 | build_runner: ^2.4.14
18 | json_serializable: ^6.9.3
19 |
20 | # testing
21 | mockito: ^5.0.3
22 | test: ^1.16.8
23 |
24 | # static analysis
25 | very_good_analysis: ^7.0.0
26 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.0.1",
6 | "configurations": [
7 | {
8 | "name": "JokeAPI",
9 | "request": "launch",
10 | "type": "dart",
11 | "program": "lib/main.dart",
12 | "args": [
13 | "--dart-define",
14 | "apiUrl=https://v2.jokeapi.dev",
15 | ]
16 | },
17 | ]
18 | }
--------------------------------------------------------------------------------
/packages/jokes/lib/src/domain/entities/joke.dart:
--------------------------------------------------------------------------------
1 | import 'package:equatable/equatable.dart';
2 |
3 | import 'package:jokes/src/domain/entities/flags.dart';
4 |
5 | abstract class Joke extends Equatable {
6 | const Joke({
7 | required this.safe, this.category,
8 | this.type,
9 | this.setup,
10 | this.delivery,
11 | this.flags,
12 | this.id,
13 | this.lang,
14 | });
15 |
16 | final String? category;
17 | final String? type;
18 | final String? setup;
19 | final String? delivery;
20 | final Flags? flags;
21 | final int? id;
22 | final bool safe;
23 | final String? lang;
24 | }
25 |
--------------------------------------------------------------------------------
/lib/src/core/widgets/app_version.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_riverpod/flutter_riverpod.dart';
3 |
4 | import '../providers/package_info_provider.dart';
5 |
6 | class AppVersion extends ConsumerWidget {
7 | @override
8 | Widget build(BuildContext context, WidgetRef ref) {
9 | final textTheme = Theme.of(context).textTheme;
10 |
11 | return ref.watch(packageInfoProvider).when(
12 | data: (info) => Text('v${info.version}', style: textTheme.labelSmall),
13 | error: (error, _) => Text(error.toString()),
14 | loading: CircularProgressIndicator.new,
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/lib/src/features/jokes/logic/jokes_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:freezed_annotation/freezed_annotation.dart';
2 | import 'package:jokes/jokes.dart';
3 |
4 | part 'jokes_state.freezed.dart';
5 |
6 | extension JokesGetters on JokesState {
7 | bool get isLoading => this is _Loading;
8 | }
9 |
10 | @freezed
11 | abstract class JokesState with _$JokesState {
12 | /// Data is present state
13 | const factory JokesState.data({required Joke joke}) = _Data;
14 |
15 | /// Initial/default state
16 | const factory JokesState.initial() = _Initial;
17 |
18 | /// Data is loading state
19 | const factory JokesState.loading() = _Loading;
20 |
21 | /// Error when loading data state
22 | const factory JokesState.error([String? message]) = _Error;
23 | }
24 |
--------------------------------------------------------------------------------
/packages/jokes/lib/src/data/repositories/jokes_repository.dart:
--------------------------------------------------------------------------------
1 | import 'package:jokes/src/data/datasources/remote/remote_data_source.dart';
2 | import 'package:jokes/src/domain/domain.dart' show IJokesRepository, Joke;
3 |
4 | /// Jokes repository implementation
5 | class JokesRepository implements IJokesRepository {
6 | /// Jokes repository constructor
7 | JokesRepository({
8 | required IRemoteDataSource remoteDataSource,
9 | }) : _remoteDataSource = remoteDataSource;
10 |
11 | final IRemoteDataSource _remoteDataSource;
12 |
13 | @override
14 | Future getJoke() async {
15 | try {
16 | final joke = await _remoteDataSource.getJoke();
17 | return joke;
18 | } on Exception {
19 | rethrow;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/jokes/lib/src/data/datasources/remote/dio_data_source.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:jokes/src/data/datasources/remote/remote_data_source.dart';
3 | import 'package:jokes/src/data/models/joke_model.dart';
4 |
5 | class DioDataSource implements IRemoteDataSource {
6 | DioDataSource({
7 | required String url,
8 | required Dio client,
9 | }) : _url = url,
10 | _client = client;
11 |
12 | final String _url;
13 | final Dio _client;
14 |
15 | @override
16 | Future getJoke() async {
17 | final result = await _client.get