feat: implement new repository structure

This commit is contained in:
mike doornenbal 2025-02-18 15:30:33 +01:00
parent 2333689471
commit 25b3988aea
144 changed files with 2454 additions and 2857 deletions

View file

@ -0,0 +1,8 @@
# This is a generated file; do not edit or check into version control.
cloud_firestore=/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/cloud_firestore-5.6.3/
cloud_firestore_web=/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/cloud_firestore_web-4.4.3/
device_info_plus=/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/
firebase_auth=/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_auth-5.4.2/
firebase_auth_web=/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_auth_web-5.13.8/
firebase_core=/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_core-3.11.0/
firebase_core_web=/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_core_web-2.20.0/

View file

@ -0,0 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"cloud_firestore","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/cloud_firestore-5.6.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"device_info_plus","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_auth-5.4.2/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_core-3.11.0/","native_build":true,"dependencies":[]}],"android":[{"name":"cloud_firestore","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/cloud_firestore-5.6.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"device_info_plus","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_auth-5.4.2/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_core-3.11.0/","native_build":true,"dependencies":[]}],"macos":[{"name":"cloud_firestore","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/cloud_firestore-5.6.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"device_info_plus","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"firebase_auth","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_auth-5.4.2/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_core-3.11.0/","native_build":true,"dependencies":[]}],"linux":[{"name":"device_info_plus","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":false,"dependencies":[]}],"windows":[{"name":"cloud_firestore","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/cloud_firestore-5.6.3/","native_build":true,"dependencies":["firebase_core"]},{"name":"device_info_plus","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":false,"dependencies":[]},{"name":"firebase_auth","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_auth-5.4.2/","native_build":true,"dependencies":["firebase_core"]},{"name":"firebase_core","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_core-3.11.0/","native_build":true,"dependencies":[]}],"web":[{"name":"cloud_firestore_web","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/cloud_firestore_web-4.4.3/","dependencies":["firebase_core_web"]},{"name":"device_info_plus","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","dependencies":[]},{"name":"firebase_auth_web","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_auth_web-5.13.8/","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","path":"/Users/mikedoornenbal/.pub-cache/hosted/pub.dev/firebase_core_web-2.20.0/","dependencies":[]}]},"dependencyGraph":[{"name":"cloud_firestore","dependencies":["cloud_firestore_web","firebase_core"]},{"name":"cloud_firestore_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"device_info_plus","dependencies":[]},{"name":"firebase_auth","dependencies":["firebase_auth_web","firebase_core"]},{"name":"firebase_auth_web","dependencies":["firebase_core","firebase_core_web"]},{"name":"firebase_core","dependencies":["firebase_core_web"]},{"name":"firebase_core_web","dependencies":[]}],"date_created":"2025-02-18 11:25:55.718721","version":"3.24.3","swift_package_manager_enabled":false}

View file

@ -19,14 +19,11 @@ migrate_working_dir/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
.vscode/
#.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/
.metadata

View file

@ -4,6 +4,6 @@ include: package:flutter_iconica_analysis/analysis_options.yaml
analyzer:
exclude:
linter:
rules:

View file

@ -0,0 +1,4 @@
///
library firebase_introduction_repository;
export "src/firebase_introduction_repository.dart";

View file

@ -0,0 +1,86 @@
import "dart:io";
import "package:cloud_firestore/cloud_firestore.dart";
import "package:device_info_plus/device_info_plus.dart";
import "package:firebase_auth/firebase_auth.dart";
import "package:introduction_repository_interface/introduction_repository_interface.dart";
class FirebaseIntroductionRepository
implements IntroductionRepositoryInterface {
final _introductionCollection = FirebaseFirestore.instance
.collection("flutter_introduction")
.doc("flutter_introduction");
@override
Future<List<IntroductionPageData>> fetchIntroductionPages() async {
try {
var introductionPagesData = await _introductionCollection
.collection("pages")
.withConverter(
fromFirestore: (snapshot, _) => IntroductionPageData.fromJson(
snapshot.data()!,
),
toFirestore: (model, _) => model.toJson(),
)
.get();
var introductionPages =
introductionPagesData.docs.map((e) => e.data()).toList();
introductionPages.sort((a, b) => a.id.compareTo(b.id));
return introductionPages;
} on Exception catch (_) {
throw Exception();
}
}
@override
Future<void> setCompleted({bool value = true}) async {
try {
await FirebaseAuth.instance.signInAnonymously();
var deviceId = await _getDeviceId();
if (deviceId == null) {
throw Exception("Failed to get device id");
}
await _introductionCollection.collection("devices").doc(deviceId).set({
"introduction_completed": value,
});
} catch (e) {
throw Exception("Failed to set introduction completed: $e");
}
}
@override
Future<bool> shouldShow() async {
try {
await FirebaseAuth.instance.signInAnonymously();
var deviceId = await _getDeviceId();
if (deviceId == null) {
throw Exception("Failed to get device id");
}
var introductionCompleted = await _introductionCollection
.collection("devices")
.doc(deviceId)
.get();
if (!introductionCompleted.exists) {
return true;
}
// ignore: avoid_dynamic_calls
return !introductionCompleted.data()!["introduction_completed"];
} on Exception catch (_) {
throw Exception();
}
}
Future<String?> _getDeviceId() async {
var deviceInfo = DeviceInfoPlugin();
if (Platform.isAndroid) {
var androidInfo = await deviceInfo.androidInfo;
return androidInfo.id;
} else if (Platform.isIOS) {
var iosInfo = await deviceInfo.iosInfo;
return iosInfo.identifierForVendor;
}
return null;
}
}

View file

@ -0,0 +1,23 @@
name: firebase_introduction_repository
description: "A new Flutter package project."
version: 0.0.1
publish_to: none
environment:
sdk: ^3.5.3
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
firebase_auth: ^5.4.2
cloud_firestore: ^5.6.3
introduction_repository_interface:
path: ../introduction_repository_interface
device_info_plus: ^11.3.0
dev_dependencies:
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis
ref: 7.0.0

View file

@ -1,7 +1,3 @@
# SPDX-FileCopyrightText: 2022 Iconica
#
# SPDX-License-Identifier: GPL-3.0-or-later
# Miscellaneous
*.class
*.log
@ -23,19 +19,11 @@ migrate_working_dir/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
.vscode/
#.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
# /pubspec.lock
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/
.flutter-plugins-dependencies
.flutter-plugins
.metadata
pubspec.lock
pubspec_overrides.yaml

View file

@ -1 +0,0 @@
../../CHANGELOG.md

View file

@ -1 +0,0 @@
../../LICENSE

View file

@ -1 +0,0 @@
../../README.md

View file

@ -4,6 +4,6 @@ include: package:flutter_iconica_analysis/analysis_options.yaml
analyzer:
exclude:
linter:
rules:

View file

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View file

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View file

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -27,7 +27,6 @@ migrate_working_dir/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

View file

@ -1 +1,16 @@
# example
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View file

@ -1,9 +1,28 @@
include: package:flutter_iconica_analysis/analysis_options.yaml
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# Possible to overwrite the rules from the package
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

View file

@ -0,0 +1,34 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>

View file

@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View file

@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View file

@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

View file

@ -0,0 +1,23 @@
PODS:
- Flutter (1.0.0)
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
DEPENDENCIES:
- Flutter (from `Flutter`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
COCOAPODS: 1.16.2

View file

@ -0,0 +1,731 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
AAC0EBC3B2AED5B0E05C5B4E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A6279E8D6C10D87A207346A /* Pods_Runner.framework */; };
EEC7FB96545FA97CD379A6AD /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395AAD3A2E008ED809D166E5 /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0A6279E8D6C10D87A207346A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
395AAD3A2E008ED809D166E5 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
397FD6F47DA357A8D69AF1C6 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
3B2D76FBD9CF3BD3A5E0FA45 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
61AE2D460E19D6A0245EFA0F /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9A2BB7986837B8FCF654D3BF /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
CFE1C62C5CF2914467393A95 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
E0AB649FB19F5AAA6CE2A1C4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
7105146EAB56D623D73CCB82 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
EEC7FB96545FA97CD379A6AD /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
AAC0EBC3B2AED5B0E05C5B4E /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0CCA99B31EB592B821B9B9B7 /* Pods */ = {
isa = PBXGroup;
children = (
E0AB649FB19F5AAA6CE2A1C4 /* Pods-Runner.debug.xcconfig */,
CFE1C62C5CF2914467393A95 /* Pods-Runner.release.xcconfig */,
9A2BB7986837B8FCF654D3BF /* Pods-Runner.profile.xcconfig */,
3B2D76FBD9CF3BD3A5E0FA45 /* Pods-RunnerTests.debug.xcconfig */,
397FD6F47DA357A8D69AF1C6 /* Pods-RunnerTests.release.xcconfig */,
61AE2D460E19D6A0245EFA0F /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
545585EA07D653BF26DC9A95 /* Frameworks */ = {
isa = PBXGroup;
children = (
0A6279E8D6C10D87A207346A /* Pods_Runner.framework */,
395AAD3A2E008ED809D166E5 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
0CCA99B31EB592B821B9B9B7 /* Pods */,
545585EA07D653BF26DC9A95 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
B46DFC93FEEE82B438CEFD5D /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
7105146EAB56D623D73CCB82 /* Frameworks */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
EF7A156F27275134CE16972E /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
AAD28D6AADDD0350DB09B76E /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
AAD28D6AADDD0350DB09B76E /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
B46DFC93FEEE82B438CEFD5D /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
EF7A156F27275134CE16972E /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 36XLC98BCM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3B2D76FBD9CF3BD3A5E0FA45 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 397FD6F47DA357A8D69AF1C6 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 61AE2D460E19D6A0245EFA0F /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 36XLC98BCM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 36XLC98BCM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View file

@ -0,0 +1,13 @@
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

View file

@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View file

@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
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.

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Example</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>example</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"

View file

@ -0,0 +1,12 @@
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}

View file

@ -1,12 +1,8 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:example/theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_introduction/flutter_introduction.dart';
import 'package:flutter_introduction_shared_preferences/flutter_introduction_shared_preferences.dart';
void main() {
void main(List<String> args) {
runApp(const MyApp());
}
@ -14,79 +10,23 @@ class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
Widget build(BuildContext context) {
return MaterialApp(
theme: theme,
home: const Introduction(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
class Introduction extends StatelessWidget {
const Introduction({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
IntroductionService service =
IntroductionService(SharedPreferencesIntroductionDataProvider());
@override
Widget build(BuildContext context) => Scaffold(
body: Introduction(
options: IntroductionOptions(
pages: (context) => [
const IntroductionPage(
title: Text('First page'),
text: Text('Wow a page'),
graphic: FlutterLogo(),
),
const IntroductionPage(
title: Text('Second page'),
text: Text('Another page'),
graphic: FlutterLogo(),
),
const IntroductionPage(
title: Text('Third page'),
text: Text('The final page of this app'),
graphic: FlutterLogo(),
),
],
introductionTranslations: const IntroductionTranslations(
skipButton: 'Skip it!',
nextButton: 'Next',
previousButton: 'Previous',
finishButton: 'To the app!',
),
tapEnabled: true,
displayMode: IntroductionDisplayMode.multiPageHorizontal,
buttonMode: IntroductionScreenButtonMode.text,
indicatorMode: IndicatorMode.dash,
skippable: true,
buttonBuilder: (context, onPressed, child, type) =>
ElevatedButton(onPressed: onPressed, child: child),
),
service: service,
navigateTo: () async {
await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const Home(),
),
);
},
child: const Home(),
),
);
}
class Home extends StatelessWidget {
const Home({
super.key,
});
@override
Widget build(BuildContext context) => Container();
Widget build(BuildContext context) {
return IntroductionScreen(
onDone: () {
debugPrint("done");
},
);
}
}

View file

@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
const Color primaryColor = Color(0xFF71C6D1);
ThemeData theme = ThemeData(
useMaterial3: false,
scaffoldBackgroundColor: const Color(0xFFFAF9F6),
fontFamily: "Merriweather",
textTheme: const TextTheme(
headlineLarge: TextStyle(
fontWeight: FontWeight.w900,
fontSize: 24,
color: Color(0xFF71C6D1),
),
bodyMedium: TextStyle(
fontFamily: "Avenir",
fontWeight: FontWeight.w400,
fontSize: 16,
color: Colors.black,
),
),
);

View file

@ -1,31 +1,33 @@
name: example
description: A new Flutter project.
description: "A new Flutter project."
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
publish_to: "none"
version: 1.0.0+1
environment:
sdk: '>=2.18.0 <3.0.0'
sdk: ^3.5.3
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
flutter_introduction:
flutter_introduction:
path: ../
flutter_introduction_shared_preferences:
path: ../../flutter_introduction_shared_preferences
shared_preferences_introduction_repository:
path: ../../shared_preferences_introduction_repository
dev_dependencies:
flutter_test:
sdk: flutter
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis
ref: 6.0.0
flutter_lints: ^4.0.0
flutter:
uses-material-design: true
assets:
- ../assets/
fonts:
- family: Merriweather
fonts:
- asset: fonts/Merriweather-Regular.ttf
- family: Avenir
fonts:
- asset: fonts/Avenir-Regular.ttf

View file

@ -1,82 +1,25 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
///
// ignore_for_file: directives_ordering
import 'package:flutter/material.dart';
import 'package:flutter_introduction_service/flutter_introduction_service.dart';
import 'package:flutter_introduction_widget/flutter_introduction_widget.dart';
library flutter_introduction;
export 'package:flutter_introduction_service/flutter_introduction_service.dart';
export 'package:flutter_introduction_widget/flutter_introduction_widget.dart';
/// screens
export "src/screens/introduction_screen.dart";
class Introduction extends StatefulWidget {
const Introduction({
required this.navigateTo,
required this.options,
this.child,
this.physics,
this.service,
super.key,
});
/// widgets
export "src/widgets/introduction_page.dart";
export "src/widgets/button.dart";
export "src/widgets/dot_indicator.dart";
export "src/widgets/dash_indicator.dart";
/// Callback function to navigate to the next screen.
final VoidCallback navigateTo;
/// enums
export "src/enums/introduction_layout_style.dart";
export "src/enums/indicator_mode.dart";
export "src/enums/introduction_screen_mode.dart";
/// The introduction service to use.
final IntroductionService? service;
/// config
export "src/config/introduction_options.dart";
export "src/config/introduction_translations.dart";
export "src/config/introduction_theme.dart";
/// Options for configuring the introduction screen.
final IntroductionOptions options;
/// The scrolling physics for the introduction screen.
final ScrollPhysics? physics;
/// Child widget to display.
final Widget? child;
@override
State<Introduction> createState() => _IntroductionState();
}
class _IntroductionState extends State<Introduction> {
late IntroductionService _service;
@override
void initState() {
super.initState();
if (widget.service == null) {
_service = IntroductionService();
} else {
_service = widget.service!;
}
}
@override
Widget build(BuildContext context) => FutureBuilder(
// ignore: discarded_futures
future: _service.shouldShow(),
builder: (context, snapshot) {
if (snapshot.data == null ||
snapshot.data! ||
widget.options.mode == IntroductionScreenMode.showAlways) {
return IntroductionScreen(
options: widget.options,
onComplete: () async {
await _service.onComplete();
widget.navigateTo();
},
physics: widget.physics,
onSkip: () async {
await _service.onComplete();
widget.navigateTo();
},
);
} else {
WidgetsBinding.instance.addPostFrameCallback((_) {
widget.navigateTo();
});
return widget.child ?? const CircularProgressIndicator();
}
},
);
}
export "package:introduction_repository_interface/introduction_repository_interface.dart";

View file

@ -0,0 +1,50 @@
import "package:flutter/material.dart";
import "package:flutter_introduction/flutter_introduction.dart";
class IntroductionOptions {
const IntroductionOptions({
this.indicatorMode = IndicatorMode.dot,
this.layoutStyle = IntroductionLayoutStyle.imageBottom,
this.introductionScreenMode = IntroductionScreenMode.showOnce,
this.indicatorBuilder,
this.introductionPages = const [
IntroductionPageData(
id: 1,
title: "welcome to iconinstagram",
description: "Welcome to the world of iconinstagram, where creativity"
" knows no bounds and connections are made through"
" captivating visuals.",
graphic: "packages/flutter_introduction/assets/first.png",
),
IntroductionPageData(
id: 2,
title: "discover iconinstagram",
description: "Dive into the vibrant world of iconinstagram and"
" discover endless possibilities. From stunning"
" photography to engaging videos, iconinstagram"
" offers a diverse range of content to explore.",
graphic: "packages/flutter_introduction/assets/second.png",
),
IntroductionPageData(
id: 3,
title: "elevate your experience",
description: "Whether promoting your business, or connecting"
" with friends and family, iconinstagram provides"
" the tools and platform to make your voice heard.",
graphic: "packages/flutter_introduction/assets/third.png",
),
],
});
final IndicatorMode indicatorMode;
final IntroductionLayoutStyle layoutStyle;
final IntroductionScreenMode introductionScreenMode;
final Function(
BuildContext context,
PageController controller,
int currentPage,
int totalPages,
)? indicatorBuilder;
final List<IntroductionPageData> introductionPages;
}

View file

@ -0,0 +1,26 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import "package:flutter/material.dart";
class IntroductionTheme {
final TextStyle? titleTextStyle;
final TextStyle? descriptionTextStyle;
final TextStyle? buttonTextStyle;
final Color? backgroundColor;
final Color indicatorColor;
final Color? buttonBackgroundColor;
final Color buttonBorderColor;
final double indicatorSize;
final double indicatorSpacing;
const IntroductionTheme({
this.titleTextStyle,
this.descriptionTextStyle,
this.buttonTextStyle,
this.backgroundColor,
this.indicatorColor = Colors.black,
this.buttonBackgroundColor = Colors.transparent,
this.buttonBorderColor = const Color(0xfb979797),
this.indicatorSize = 12,
this.indicatorSpacing = 12,
});
}

View file

@ -0,0 +1,11 @@
class IntroductionTranslations {
const IntroductionTranslations({
this.nextButton = "Next",
this.previousButton = "Previous",
this.doneButton = "Get started",
});
final String nextButton;
final String previousButton;
final String doneButton;
}

View file

@ -0,0 +1,5 @@
enum IndicatorMode {
dot,
dash,
custom,
}

View file

@ -0,0 +1,5 @@
enum IntroductionLayoutStyle {
imageTop,
imageCenter,
imageBottom,
}

View file

@ -0,0 +1,5 @@
enum IntroductionScreenMode {
showAlways,
showNever,
showOnce,
}

View file

@ -0,0 +1,281 @@
import "dart:async";
import "package:flutter/material.dart";
import "package:flutter_introduction/src/config/introduction_options.dart";
import "package:flutter_introduction/src/config/introduction_theme.dart";
import "package:flutter_introduction/src/config/introduction_translations.dart";
import "package:flutter_introduction/src/enums/indicator_mode.dart";
import "package:flutter_introduction/src/enums/introduction_screen_mode.dart";
import "package:flutter_introduction/src/widgets/button.dart";
import "package:flutter_introduction/src/widgets/dash_indicator.dart";
import "package:flutter_introduction/src/widgets/dot_indicator.dart";
import "package:flutter_introduction/src/widgets/introduction_page.dart";
import "package:introduction_repository_interface/introduction_repository_interface.dart";
class IntroductionScreen extends StatefulWidget {
const IntroductionScreen({
required this.onDone,
this.introductionService,
this.options = const IntroductionOptions(),
this.translations = const IntroductionTranslations(),
this.introductionTheme = const IntroductionTheme(),
super.key,
});
final IntroductionService? introductionService;
final IntroductionOptions options;
final IntroductionTranslations translations;
final IntroductionTheme introductionTheme;
final Function() onDone;
@override
State<IntroductionScreen> createState() => _IntroductionScreenState();
}
class _IntroductionScreenState extends State<IntroductionScreen> {
IntroductionService? introductionService;
bool? shouldShow;
@override
void initState() {
introductionService = widget.introductionService ?? IntroductionService();
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
await checkShouldShow();
});
}
Future<void> checkShouldShow() async {
shouldShow = await introductionService?.shouldShow();
if (widget.options.introductionScreenMode ==
IntroductionScreenMode.showAlways) {
shouldShow = true;
}
if (widget.options.introductionScreenMode ==
IntroductionScreenMode.showNever) {
shouldShow = false;
}
if (!shouldShow!) {
await widget.onDone();
}
}
Future<List<IntroductionPageData>> fetchIntroductionPages() async {
try {
var pages = await introductionService!.fetchIntroductionPages();
if (pages.isEmpty) {
return widget.options.introductionPages;
}
return pages;
} on Exception catch (_) {
return widget.options.introductionPages;
}
}
@override
Widget build(BuildContext context) {
var pages = <IntroductionPage>[];
return Scaffold(
body: FutureBuilder(
// ignore: discarded_futures
future: fetchIntroductionPages(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (shouldShow != null && !shouldShow!) {
return const SizedBox.shrink();
}
for (var page in snapshot.data!) {
pages.add(
IntroductionPage(
title: page.title,
description: page.description,
graphic: page.graphic,
imageMode: page.imageMode,
introductionTheme: widget.introductionTheme,
),
);
}
return _IntroductionScreen(
pages: pages,
options: widget.options,
translations: widget.translations,
introductionTheme: widget.introductionTheme,
onDone: () async {
await introductionService?.setCompleted();
await widget.onDone();
},
);
},
),
);
}
}
class _IntroductionScreen extends StatefulWidget {
const _IntroductionScreen({
required this.pages,
required this.onDone,
required this.options,
required this.translations,
required this.introductionTheme,
});
final IntroductionOptions options;
final IntroductionTranslations translations;
final List<IntroductionPage> pages;
final Function() onDone;
final IntroductionTheme introductionTheme;
@override
State<_IntroductionScreen> createState() => __IntroductionScreenState();
}
class __IntroductionScreenState extends State<_IntroductionScreen> {
PageController controller = PageController();
bool isAnimating = false;
int currentPage = 0;
@override
void initState() {
super.initState();
controller.addListener(() {
var newPage = controller.page?.round() ?? 0;
if (newPage != currentPage) {
setState(() {
currentPage = newPage;
});
}
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
var options = widget.options;
var introductionTheme = widget.introductionTheme;
var showNextButton = currentPage < widget.pages.length - 1;
var showPreviousButton = currentPage > 0;
var isLastPage = currentPage == widget.pages.length - 1;
return Scaffold(
backgroundColor: widget.introductionTheme.backgroundColor ??
Theme.of(context).scaffoldBackgroundColor,
body: SafeArea(
bottom: true,
child: Column(
children: [
Expanded(
child: PageView(
controller: controller,
scrollDirection: Axis.horizontal,
physics: const PageScrollPhysics(),
children: [
...widget.pages,
],
),
),
Column(
children: [
...switch (options.indicatorMode) {
IndicatorMode.dot => [
DotsIndicator(
controller: controller,
pageCount: widget.pages.length,
indicatorSize: introductionTheme.indicatorSize,
indicatorSpacing: introductionTheme.indicatorSpacing,
indicatorColor: introductionTheme.indicatorColor,
),
],
IndicatorMode.dash => [
DashIndicator(
controller: controller,
pageCount: widget.pages.length,
indicatorSize: introductionTheme.indicatorSize,
indicatorSpacing: introductionTheme.indicatorSpacing,
indicatorColor: introductionTheme.indicatorColor,
),
],
IndicatorMode.custom => [
widget.options.indicatorBuilder?.call(
context,
controller,
currentPage,
widget.pages.length,
),
],
},
const SizedBox(
height: 40,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Button(
showButton: showPreviousButton,
text: widget.translations.previousButton,
introductionTheme: widget.introductionTheme,
onPressed: () async {
if (isAnimating) return;
isAnimating = true;
setState(() {});
await controller.previousPage(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
isAnimating = false;
setState(() {});
},
),
const SizedBox(
width: 16,
),
if (!isLastPage)
Button(
showButton: showNextButton,
text: widget.translations.nextButton,
introductionTheme: widget.introductionTheme,
onPressed: () async {
if (isAnimating) return;
isAnimating = true;
setState(() {});
await controller.nextPage(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
isAnimating = false;
setState(() {});
},
),
if (isLastPage)
Button(
introductionTheme: widget.introductionTheme,
showButton: true,
text: widget.translations.doneButton,
onPressed: () async {
widget.onDone();
},
),
],
),
),
],
),
],
),
),
);
}
}

View file

@ -0,0 +1,54 @@
import "package:flutter/material.dart";
import "package:flutter_introduction/src/config/introduction_theme.dart";
class Button extends StatelessWidget {
const Button({
required this.text,
required this.onPressed,
required this.showButton,
required this.introductionTheme,
super.key,
});
final String text;
final Function() onPressed;
final bool showButton;
final IntroductionTheme introductionTheme;
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
return Expanded(
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 180,
maxHeight: 32,
),
child: showButton
? FilledButton(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
introductionTheme.buttonBackgroundColor,
),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(16)),
side: BorderSide(
color: introductionTheme.buttonBorderColor,
width: 1,
),
),
),
),
onPressed: onPressed,
child: Text(
text,
style: introductionTheme.buttonTextStyle ??
theme.textTheme.bodyMedium,
),
)
: const SizedBox(),
),
);
}
}

View file

@ -0,0 +1,46 @@
import "package:flutter/material.dart";
class DashIndicator extends StatelessWidget {
const DashIndicator({
required this.controller,
required this.indicatorColor,
required this.indicatorSize,
required this.indicatorSpacing,
required this.pageCount,
super.key,
});
final PageController controller;
final Color indicatorColor;
final double indicatorSize;
final double indicatorSpacing;
final int pageCount;
@override
Widget build(BuildContext context) => AnimatedBuilder(
animation: controller,
builder: (context, child) => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
pageCount,
(index) => Container(
width: indicatorSize * 2,
height: indicatorSize / 2,
margin: EdgeInsets.symmetric(horizontal: indicatorSpacing / 2),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: index == (controller.page?.round() ?? 0)
? indicatorColor
: indicatorColor.withOpacity(0.5),
),
child: InkWell(
onTap: () async => controller.animateToPage(
index,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
),
),
),
),
),
);
}

View file

@ -0,0 +1,46 @@
import "package:flutter/material.dart";
class DotsIndicator extends StatelessWidget {
const DotsIndicator({
required this.controller,
required this.indicatorColor,
required this.indicatorSize,
required this.indicatorSpacing,
required this.pageCount,
super.key,
});
final PageController controller;
final Color indicatorColor;
final double indicatorSize;
final double indicatorSpacing;
final int pageCount;
@override
Widget build(BuildContext context) => AnimatedBuilder(
animation: controller,
builder: (context, child) => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
pageCount,
(index) => Container(
width: indicatorSize,
height: indicatorSize,
margin: EdgeInsets.symmetric(horizontal: indicatorSpacing / 2),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: index == (controller.page?.round() ?? 0)
? indicatorColor
: indicatorColor.withOpacity(0.3),
),
child: InkWell(
onTap: () async => controller.animateToPage(
index,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
),
),
),
),
),
);
}

View file

@ -0,0 +1,113 @@
import "package:flutter/material.dart";
import "package:flutter_introduction/flutter_introduction.dart";
import "package:flutter_introduction/src/config/introduction_theme.dart";
import "package:flutter_introduction/src/enums/introduction_layout_style.dart";
class IntroductionPage extends StatelessWidget {
const IntroductionPage({
required this.title,
required this.description,
required this.graphic,
required this.introductionTheme,
required this.imageMode,
this.layoutStyle = IntroductionLayoutStyle.imageBottom,
super.key,
});
final String title;
final String description;
final String graphic;
final IntroductionLayoutStyle layoutStyle;
final IntroductionTheme introductionTheme;
final ImageMode imageMode;
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
...switch (layoutStyle) {
IntroductionLayoutStyle.imageTop => [
const SizedBox(
height: 124,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: imageMode == ImageMode.asset
? Image.asset(graphic)
: Image.network(graphic),
),
const SizedBox(height: 40),
Text(
title,
style: introductionTheme.titleTextStyle ??
theme.textTheme.headlineLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
description,
style: introductionTheme.descriptionTextStyle ??
theme.textTheme.bodyMedium,
textAlign: TextAlign.center,
),
],
IntroductionLayoutStyle.imageCenter => [
const SizedBox(
height: 124,
),
Text(
title,
style: introductionTheme.titleTextStyle ??
theme.textTheme.headlineLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 40),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: imageMode == ImageMode.asset
? Image.asset(graphic)
: Image.network(graphic),
),
const SizedBox(height: 12),
Text(
description,
style: introductionTheme.descriptionTextStyle ??
theme.textTheme.bodyMedium,
textAlign: TextAlign.center,
),
],
IntroductionLayoutStyle.imageBottom => [
const SizedBox(
height: 124,
),
Text(
title,
style: introductionTheme.titleTextStyle ??
theme.textTheme.headlineLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
description,
style: introductionTheme.descriptionTextStyle ??
theme.textTheme.bodyMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 40),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: imageMode == ImageMode.asset
? Image.asset(graphic)
: Image.network(graphic),
),
],
},
],
),
);
}
}

View file

@ -1,28 +1,29 @@
name: flutter_introduction
description: Combined Package of Flutter Introduction Widget and Flutter Introduction Service
version: 5.0.0
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
description: "A flutter introduction project"
version: 6.0.0
homepage: none
publish_to: none
environment:
sdk: ">=3.0.0 <4.0.0"
sdk: ^3.5.3
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
flutter_introduction_widget:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: "^5.0.0"
flutter_introduction_service:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: "^5.0.0"
introduction_repository_interface:
path: ../introduction_repository_interface
dev_dependencies:
flutter_test:
sdk: flutter
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis
ref: 6.0.0
ref: 7.0.0
flutter:
uses-material-design: true
assets:
- assets/

View file

@ -1,41 +0,0 @@
# SPDX-FileCopyrightText: 2022 Iconica
#
# SPDX-License-Identifier: GPL-3.0-or-later
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
# /pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/
.flutter-plugins-dependencies
.flutter-plugins
.metadata
pubspec.lock
pubspec_overrides.yaml

View file

@ -1 +0,0 @@
../../CHANGELOG.md

View file

@ -1 +0,0 @@
../../LICENSE

View file

@ -1,9 +0,0 @@
// SPDX-FileCopyrightText: 2023 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
///
library flutter_introduction_firebase;
export 'src/firebase_service.dart';
export 'src/introduction_widget.dart';

View file

@ -1,75 +0,0 @@
// SPDX-FileCopyrightText: 2023 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_introduction_firebase/src/introduction_page.dart';
const _introductionDocumentRef = 'introduction/introduction';
class FirebaseIntroductionService {
FirebaseIntroductionService({
DocumentReference<Map<String, dynamic>>? documentRef,
}) : _documentRef = documentRef ??
FirebaseFirestore.instance.doc(_introductionDocumentRef);
final DocumentReference<Map<String, dynamic>> _documentRef;
List<IntroductionPageData> _pages = [];
Future<List<IntroductionPageData>> getIntroductionPages() async {
if (_pages.isNotEmpty) return _pages;
var pagesDocuments =
await _documentRef.collection('pages').orderBy('order').get();
return _pages = pagesDocuments.docs.map((document) {
var data = document.data();
// convert Map<String, dynamic> to Map<String, String>
var title = data['title'] != null
? (data['title'] as Map<String, dynamic>).cast<String, String>()
: <String, String>{};
var content = data['content'] != null
? (data['content'] as Map<String, dynamic>).cast<String, String>()
: <String, String>{};
return IntroductionPageData(
title: title,
content: content,
contentImage: data['image'] as String?,
backgroundImage: data['background_image'] as String?,
// the color is stored as a hex string
backgroundColor: data['background_color'] != null
? Color(int.parse(data['background_color'] as String, radix: 16))
: null,
);
}).toList();
}
Future<bool> introductionIsDisabled() async {
var document = await _documentRef.get();
return document.data()!['disabled'] as bool? ?? false;
}
Future<bool> shouldAlwaysShowIntroduction() async {
var document = await _documentRef.get();
return document.data()!['always_show'] as bool? ?? false;
}
Future<void> loadIntroductionPages(
BuildContext context,
) async {
for (var page in _pages) {
if (context.mounted && page.backgroundImage != null) {
await precacheImage(
CachedNetworkImageProvider(page.backgroundImage!),
context,
);
}
if (context.mounted && page.contentImage != null) {
await precacheImage(
CachedNetworkImageProvider(page.contentImage!),
context,
);
}
}
}
}

View file

@ -1,32 +0,0 @@
// SPDX-FileCopyrightText: 2023 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
@immutable
class IntroductionPageData {
const IntroductionPageData({
required this.title,
required this.content,
this.contentImage,
this.backgroundImage,
this.backgroundColor,
});
/// The title of the introduction page in different languages
final Map<String, String> title;
/// The content of the introduction page in different languages
final Map<String, String> content;
/// The imageUrl of the graphic on the introduction page
final String? contentImage;
/// The imageUrl of the background image of the introduction page
final String? backgroundImage;
/// Optional background color of the introduction page
/// (defaults to transparent)
final Color? backgroundColor;
}

View file

@ -1,184 +0,0 @@
// SPDX-FileCopyrightText: 2023 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
// ignore_for_file: discarded_futures
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_introduction_firebase/flutter_introduction_firebase.dart';
import 'package:flutter_introduction_service/flutter_introduction_service.dart';
export 'package:flutter_introduction_firebase/src/introduction_page.dart';
export 'package:flutter_introduction_widget/flutter_introduction_widget.dart';
class IntroductionFirebase extends StatefulWidget {
const IntroductionFirebase({
required this.options,
required this.onComplete,
this.decoration,
this.layoutStyle,
this.titleBuilder,
this.contentBuilder,
this.imageBuilder,
this.onSkip,
this.firebaseService,
this.introductionService,
this.physics,
this.child,
this.languageCodeOverride,
super.key,
});
/// The options used to build the introduction screen
final IntroductionOptions options;
/// The service used to determine if the introduction screen should be shown
final IntroductionService? introductionService;
/// The service used to get the introduction pages
final FirebaseIntroductionService? firebaseService;
/// A function called when the introductionSceen changes
final VoidCallback onComplete;
/// A function called when the introductionScreen is skipped
final VoidCallback? onSkip;
/// How the single child scroll view should respond to scrolling
final ScrollPhysics? physics;
/// The widget to show when the introduction screen is loading
final Widget? child;
/// The decoration of an introduction page if it doesn't have
/// a backgroundImage or backgroundColor
final BoxDecoration? decoration;
/// The layout style of all the introduction pages
final IntroductionLayoutStyle? layoutStyle;
/// The builder used to build the title of the introduction page
final Widget Function(String)? titleBuilder;
/// The builder used to build the content of the introduction page
final Widget Function(String)? contentBuilder;
/// The builder used to build the image of the introduction page
final Widget Function(String)? imageBuilder;
/// Use this to override the language code that is in the context
/// used for showing the introduction in a different language
final String? languageCodeOverride;
@override
State<IntroductionFirebase> createState() => _IntroductionState();
}
class _IntroductionState extends State<IntroductionFirebase> {
late IntroductionService _service;
late FirebaseIntroductionService _firebaseService;
@override
void initState() {
super.initState();
if (widget.introductionService == null) {
_service = IntroductionService();
} else {
_service = widget.introductionService!;
}
if (widget.firebaseService == null) {
_firebaseService = FirebaseIntroductionService();
} else {
_firebaseService = widget.firebaseService!;
}
}
@override
Widget build(BuildContext context) {
Future<bool> shouldShow() async =>
!await _firebaseService.introductionIsDisabled() &&
(await _service.shouldShow() ||
await _firebaseService.shouldAlwaysShowIntroduction());
var languageCode = widget.languageCodeOverride ??
Localizations.localeOf(context).languageCode;
return FutureBuilder(
future: shouldShow(),
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data != null && snapshot.data!) {
return FutureBuilder(
future: _firebaseService.getIntroductionPages(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.data != null &&
snapshot.data is List<IntroductionPageData>) {
return IntroductionScreen(
options: widget.options.copyWith(
pages: (context) => snapshot.data!.map(
(e) {
var title = e.title.isEmpty
? ''
: e.title.containsKey(languageCode)
? e.title[languageCode]!
: e.title.values.first;
var content = e.content.isEmpty
? ''
: e.content.containsKey(languageCode)
? e.content[languageCode]!
: e.content.values.first;
return IntroductionPage(
title:
widget.titleBuilder?.call(title) ?? Text(title),
graphic: e.contentImage != null &&
e.contentImage!.isNotEmpty
? widget.imageBuilder?.call(e.contentImage!) ??
CachedNetworkImage(imageUrl: e.contentImage!)
: null,
text: widget.contentBuilder?.call(content) ??
Text(content),
decoration: widget.decoration?.copyWith(
color: e.backgroundColor,
image: e.backgroundImage != null &&
e.backgroundImage!.isNotEmpty
? DecorationImage(
image: CachedNetworkImageProvider(
e.backgroundImage!,
),
fit: BoxFit.cover,
)
: null,
),
layoutStyle: widget.layoutStyle,
);
},
).toList(),
),
onComplete: () async {
await _service.onComplete();
widget.onComplete();
},
physics: widget.physics,
onSkip: () async {
await _service.onSkip();
widget.onComplete();
},
);
} else {
return widget.child ?? const CircularProgressIndicator();
}
},
);
} else {
if (snapshot.hasData && snapshot.data != null && !snapshot.data!) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
await _service.onComplete();
widget.onComplete();
});
}
return widget.child ?? const CircularProgressIndicator();
}
},
);
}
}

View file

@ -1,30 +0,0 @@
name: flutter_introduction_firebase
description: Flutter Introduction Page that uses firebase for the pages and some settings
version: 5.0.0
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
environment:
sdk: ">=3.1.5 <4.0.0"
dependencies:
flutter:
sdk: flutter
cloud_firestore: "^4.12.2"
cached_network_image: "^3.3.0"
flutter_introduction_widget:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: "^5.0.0"
flutter_introduction_service:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: "^5.0.0"
dev_dependencies:
flutter_test:
sdk: flutter
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis
ref: 6.0.0
flutter:

View file

@ -1,11 +0,0 @@
// SPDX-FileCopyrightText: 2023 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter_test/flutter_test.dart';
void main() {
test('test', () {
expect(true, true);
});
}

View file

@ -1 +0,0 @@
../../CHANGELOG.md

View file

@ -1 +0,0 @@
../../LICENSE

View file

@ -1 +0,0 @@
../../README.md

View file

@ -1,9 +0,0 @@
include: package:flutter_iconica_analysis/analysis_options.yaml
# Possible to overwrite the rules from the package
analyzer:
exclude:
linter:
rules:

View file

@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
export './src/introduction_interface.dart';
export './src/local_introduction.dart';

View file

@ -1,40 +0,0 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter_data_interface/flutter_data_interface.dart';
import 'package:flutter_introduction_interface/src/local_introduction.dart';
abstract class IntroductionInterface extends DataInterface {
/// Constructs an instance of [IntroductionInterface].
///
/// The [token] is used for verification purposes.
IntroductionInterface() : super(token: _token);
static final Object _token = Object();
static IntroductionInterface _instance = LocalIntroductionDataProvider();
/// Retrieves the current instance of [IntroductionInterface].
static IntroductionInterface get instance => _instance;
/// Sets the current instance of [IntroductionInterface].
///
/// Throws an error if the provided instance does not match the token.
static set instance(IntroductionInterface instance) {
DataInterface.verify(instance, _token);
_instance = instance;
}
/// Sets whether the introduction is completed or not.
///
/// The [value] parameter specifies whether the introduction is completed.
/// By default, it is set to `true`.
Future<void> setCompleted({bool value = true});
/// Checks if the introduction should be shown.
///
/// Returns `true` if the introduction should be shown;
/// otherwise, returns `false`.
Future<bool> shouldShow();
}

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter_introduction_interface/src/introduction_interface.dart';
/// Provides local data storage for managing introduction data.
///
/// This class extends [IntroductionInterface] and implements methods to manage
/// introduction data locally.
class LocalIntroductionDataProvider extends IntroductionInterface {
/// Constructs an instance of [LocalIntroductionDataProvider].
///
/// Initializes the [hasViewed] flag to `false`.
LocalIntroductionDataProvider();
/// Flag indicating whether the introduction has been viewed or not.
bool hasViewed = false;
@override
Future<void> setCompleted({bool value = true}) async {
hasViewed = value;
}
@override
Future<bool> shouldShow() async => hasViewed;
}

View file

@ -1,25 +0,0 @@
name: flutter_introduction_interface
description: A new Flutter package project.
version: 5.0.0
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
environment:
sdk: '>=3.0.0 <4.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
flutter_data_interface:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: "^1.0.0"
dev_dependencies:
flutter_test:
sdk: flutter
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis
ref: 6.0.0
flutter:

View file

@ -1 +0,0 @@
../../CHANGELOG.md

View file

@ -1 +0,0 @@
../../LICENSE

View file

@ -1 +0,0 @@
../../README.md

View file

@ -1,7 +0,0 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
export 'package:flutter_introduction_interface/flutter_introduction_interface.dart';
export './src/introduction_service.dart';

View file

@ -1,39 +0,0 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter_introduction_interface/flutter_introduction_interface.dart';
/// A service for managing introduction-related operations.
///
/// This class provides methods for handling introduction-related actions
/// such as skipping, completing,
/// and determining whether to show the introduction.
class IntroductionService {
/// Constructs an instance of [IntroductionService].
///
/// Optionally takes a [dataProvider] parameter,
/// which is an implementation of [IntroductionInterface].
/// If no data provider is provided,
/// it defaults to [LocalIntroductionDataProvider].
IntroductionService([IntroductionInterface? dataProvider])
: _dataProvider = dataProvider ?? LocalIntroductionDataProvider();
late final IntroductionInterface _dataProvider;
/// Marks the introduction as skipped.
///
/// Calls [_dataProvider.setCompleted] with the value `true`.
Future<void> onSkip() => _dataProvider.setCompleted(value: true);
/// Marks the introduction as completed.
///
/// Calls [_dataProvider.setCompleted] with the value `true`.
Future<void> onComplete() => _dataProvider.setCompleted(value: true);
/// Checks whether the introduction should be shown.
///
/// Returns a `Future<bool>` indicating whether the
/// introduction should be shown.
Future<bool> shouldShow() => _dataProvider.shouldShow();
}

Some files were not shown because too many files have changed in this diff Show more