feat(proj): init

This commit is contained in:
vl.arkhangelskii
2026-09-21 04:06:43 +03:00
commit c956b94983
1076 changed files with 50876 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
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
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
/coverage/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
# Widget Preview related
.widget_preview/
+39
View File
@@ -0,0 +1,39 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "6a19cca56475dbfba1478ee68d7bd0c2ef891da1"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
base_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
- platform: android
create_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
base_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
- platform: ios
create_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
base_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
- platform: web
create_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
base_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
- platform: windows
create_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
base_revision: 6a19cca56475dbfba1478ee68d7bd0c2ef891da1
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
+96
View File
@@ -0,0 +1,96 @@
# Please Pay Me — Widgetbook
Portable component catalog for the mobile UI kit. Lives as a **separate package**
under `mobile/widgetbook/` and depends on the app package via path — no changes
required in production `lib/main.dart`.
## Run
```powershell
cd mobile\widgetbook
.\run.ps1 # chrome по умолчанию
.\run.ps1 -Device windows
```
Или из `mobile/`:
```powershell
.\run.ps1 -Target widgetbook -Device chrome
```
```bash
cd mobile/widgetbook
flutter pub get
flutter run -d chrome
# or
flutter run -d windows
```
## Structure
```
widgetbook/
├── lib/
│ ├── main.dart
│ ├── app.dart # WidgetbookRoot + addons
│ ├── catalog.dart # directory tree (also used by smoke tests)
│ ├── addons/ # theme / locale / device frame
│ ├── knobs/ # shared knob helpers
│ ├── support/preview.dart # iOS grouped-background canvas for use-cases
│ ├── support/demo_scope.dart # real screens on the in-memory DemoBackend
│ └── use_cases/ # Atoms → Molecules → Navigation → Feedback → Screens
└── test/catalog_smoke_test.dart
```
## iOS kit
Компоненты построены на Cupertino и следуют Apple HIG:
- семантические цвета (`label` / `separator` / `groupedBackground`) объявлены как
`CupertinoDynamicColor`, поэтому light/dark резолвится автоматически;
- типографика — шкала SF Pro (`largeTitle` 34 … `caption2` 11), в качестве
кросс-платформенной замены SF используется Inter;
- списки — inset-grouped секции с hairline-разделителями (0.5pt) и отступом
под leading-бейдж, как в Settings;
- контролы — `CupertinoButton`, `CupertinoTextField`, `CupertinoSwitch`,
`CupertinoSlidingSegmentedControl`, `CupertinoTabBar`, `CupertinoAlertDialog`,
`CupertinoActionSheet`, `CupertinoActivityIndicator`;
- вместо Material SnackBar — `AppToast`: плавающая blur-капсула поверх контента.
Бренд-тинт остался зелёным (`AppColors.accent`) и подменяет `systemBlue`.
Use-cases render **real widgets** from `package:please_pay_me/ui/...` and themes from
`package:please_pay_me/theme/...`.
Addons:
- **Theme** — Light / Dark (`CupertinoThemeAddon`, `buildLightTheme` / `buildDarkTheme`)
- **Locale** — `ru` / `en`
- **Viewport** — iPhone / Android frames
## Reuse in another Flutter project
1. Copy `widgetbook/` folder (or this package).
2. Point `please_pay_me` path dependency to your UI package (or rename dependency).
3. Keep exporting widgets from that package; use-cases only import them.
4. Run `flutter pub get && flutter run`.
Optional codegen (annotations already in `pubspec.yaml`):
```bash
dart run build_runner build --delete-conflicting-outputs
```
Current catalog is **manual** via `catalog.dart` so it stays easy to copy without
a generator step.
## Tests
```bash
cd mobile/widgetbook
flutter test
```
Smoke-тесты проверяют, что структура каталога на месте, и **рендерят каждый use-case
в светлой и тёмной теме** внутри `WidgetbookScope` (knobs читают состояние из контекста),
падая на любом исключении при построении.
+12
View File
@@ -0,0 +1,12 @@
analyzer:
exclude:
- build/**
- android/**
- ios/**
- web/**
- windows/**
include: package:flutter_lints/flutter.yaml
linter:
rules:
prefer_const_constructors: false
+14
View File
@@ -0,0 +1,14 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks
@@ -0,0 +1,49 @@
plugins {
id("com.android.application")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.example.please_pay_me_widgetbook"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.please_pay_me_widgetbook"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
// Uses the version code from pubspec.yaml. When using split APKs, 1000 * ABI_VERSION
// is added automatically by Flutter. (https://developer.android.com/studio/build/configure-apk-splits#configure-APK-versions)
// You can force using the value of versionCode by specifying the `-P force-version-code-ignoring-abi=true`
// flag during build.
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
flutter {
source = "../.."
}
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
@@ -0,0 +1,45 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="please_pay_me_widgetbook"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
@@ -0,0 +1,5 @@
package com.example.please_pay_me_widgetbook
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity()
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
@@ -0,0 +1,24 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
val newBuildDir: Directory =
rootProject.layout.buildDirectory
.dir("../../build")
.get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}
@@ -0,0 +1,6 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
# This newDsl flag was added by the Flutter template
android.newDsl=false
# This builtInKotlin flag was added by the Flutter template
android.builtInKotlin=false
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip
@@ -0,0 +1,26 @@
pluginManagement {
val flutterSdkPath =
run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "9.1.0" apply false
id("org.jetbrains.kotlin.android") version "2.4.0" apply false
}
include(":app")
+34
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
@@ -0,0 +1,24 @@
<?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>
</dict>
</plist>
@@ -0,0 +1 @@
#include "Generated.xcconfig"
@@ -0,0 +1 @@
#include "Generated.xcconfig"
@@ -0,0 +1,647 @@
// !$*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 */; };
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; };
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
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 */; };
/* 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 */
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; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; 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>"; };
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; 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>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
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 */,
);
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 */,
7884E8672EC3CC0400C636F2 /* SceneDelegate.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 = (
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
);
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 = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
packageProductDependencies = (
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
);
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;
packageReferences = (
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
);
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";
};
/* 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 */,
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift 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 = 15.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
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)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.pleasePayMeWidgetbook;
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;
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.pleasePayMeWidgetbook.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;
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.pleasePayMeWidgetbook.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;
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.pleasePayMeWidgetbook.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 = 15.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
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 = 15.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
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)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.pleasePayMeWidgetbook;
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)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.pleasePayMeWidgetbook;
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 */
/* Begin XCLocalSwiftPackageReference section */
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
isa = XCSwiftPackageProductDependency;
productName = FlutterGeneratedPluginSwiftPackage;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -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>
@@ -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>
@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Run Prepare Flutter Framework Script"
scriptText = "/bin/sh &quot;$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh&quot; prepare&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
<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"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
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"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
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>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
@@ -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>
@@ -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>
@@ -0,0 +1,16 @@
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
}
}
@@ -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

@@ -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

@@ -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.
@@ -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>
@@ -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>
+70
View File
@@ -0,0 +1,70 @@
<?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>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Please Pay Me Widgetbook</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>please_pay_me_widgetbook</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>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</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>
</dict>
</plist>
@@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"
@@ -0,0 +1,6 @@
import Flutter
import UIKit
class SceneDelegate: FlutterSceneDelegate {
}
@@ -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.
}
}
@@ -0,0 +1,11 @@
import 'package:widgetbook/widgetbook.dart';
/// Common phone frames for visual QA (ViewportAddon replaces DeviceFrameAddon).
ViewportAddon buildDeviceFrameAddon() {
return ViewportAddon([
Viewports.none,
IosViewports.iPhone13,
IosViewports.iPhone13Mini,
AndroidViewports.samsungGalaxyS20,
]);
}
@@ -0,0 +1,19 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:widgetbook/widgetbook.dart';
/// Locale switcher: Russian / English.
LocalizationAddon buildLocaleAddon() {
return LocalizationAddon(
locales: const [
Locale('ru'),
Locale('en'),
],
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
initialLocale: const Locale('ru'),
);
}
@@ -0,0 +1,12 @@
import 'package:please_pay_me/theme/theme.dart';
import 'package:widgetbook/widgetbook.dart';
/// Light / dark Cupertino theme built from the shared product tokens.
CupertinoThemeAddon buildThemeAddon() {
return CupertinoThemeAddon(
themes: [
WidgetbookTheme(name: 'Light', data: buildLightTheme()),
WidgetbookTheme(name: 'Dark', data: buildDarkTheme()),
],
);
}
+26
View File
@@ -0,0 +1,26 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me_widgetbook/addons/device_frame_addon.dart';
import 'package:please_pay_me_widgetbook/addons/locale_addon.dart';
import 'package:please_pay_me_widgetbook/addons/theme_addon.dart';
import 'package:please_pay_me_widgetbook/catalog.dart';
import 'package:widgetbook/widgetbook.dart';
/// Entry Widgetbook application — portable across projects that depend on the
/// same UI package (`please_pay_me`).
class WidgetbookRoot extends StatelessWidget {
const WidgetbookRoot({super.key});
@override
Widget build(BuildContext context) {
return Widgetbook.cupertino(
directories: buildCatalogDirectories(),
addons: [
buildThemeAddon(),
buildLocaleAddon(),
buildDeviceFrameAddon(),
InspectorAddon(),
AlignmentAddon(initialAlignment: Alignment.center),
],
);
}
}
+75
View File
@@ -0,0 +1,75 @@
import 'package:please_pay_me_widgetbook/use_cases/atoms/buttons_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/atoms/icons_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/atoms/text_fields_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/atoms/typography_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/feedback/progress_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/feedback/skeletons_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/feedback/toasts_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/molecules/avatars_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/molecules/cards_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/molecules/chips_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/molecules/list_tiles_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/molecules/switches_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/navigation/dialogs_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/navigation/nav_bar_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/navigation/segmented_control_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/navigation/tab_bar_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/screens/app_screens_use_cases.dart';
import 'package:please_pay_me_widgetbook/use_cases/screens/sheets_use_cases.dart';
import 'package:widgetbook/widgetbook.dart';
/// Single source of directory tree for Widgetbook + smoke tests.
List<WidgetbookNode> buildCatalogDirectories() {
return [
WidgetbookFolder(
name: 'Atoms',
children: [
buttonsComponent(),
textFieldsComponent(),
typographyComponent(),
iconsComponent(),
],
),
WidgetbookFolder(
name: 'Molecules',
children: [
cardsComponent(),
listTilesComponent(),
switchesComponent(),
chipsComponent(),
avatarsComponent(),
],
),
WidgetbookFolder(
name: 'Navigation',
children: [
navBarComponent(),
tabBarComponent(),
segmentedControlComponent(),
dialogsComponent(),
],
),
WidgetbookFolder(
name: 'Feedback',
children: [
progressComponent(),
skeletonsComponent(),
toastsComponent(),
],
),
WidgetbookFolder(
name: 'Screens',
children: [
overviewScreenComponent(),
journalScreenComponent(),
budgetsScreenComponent(),
workScreenComponent(),
profileScreenComponent(),
splashScreenComponent(),
loginScreenComponent(),
sheetsComponent(),
homeTabsComponent(),
],
),
];
}
@@ -0,0 +1,93 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:widgetbook/widgetbook.dart';
String knobText(
BuildContext context, {
required String label,
String initialValue = 'Label',
}) {
return context.knobs.string(label: label, initialValue: initialValue);
}
bool knobBool(
BuildContext context, {
required String label,
bool initialValue = false,
}) {
return context.knobs.boolean(label: label, initialValue: initialValue);
}
double knobDouble(
BuildContext context, {
required String label,
double initialValue = 0.5,
double min = 0,
double max = 1,
}) {
return context.knobs.double.slider(
label: label,
initialValue: initialValue,
min: min,
max: max,
);
}
int knobInt(
BuildContext context, {
required String label,
int initialValue = 0,
int min = 0,
int max = 10,
}) {
return context.knobs.int.slider(
label: label,
initialValue: initialValue,
min: min,
max: max,
);
}
Color knobColor(
BuildContext context, {
required String label,
Color? initialValue,
}) {
return context.knobs.color(
label: label,
initialValue: initialValue ?? AppColors.of(context, AppColors.accent),
);
}
/// Dropdown over iOS system tints used by badges and progress bars.
Color knobTint(BuildContext context, {String label = 'Tint'}) {
const options = <String, Color>{
'accent': AppColors.accent,
'red': AppColors.systemRed,
'orange': AppColors.systemOrange,
'green': AppColors.systemGreen,
'gray': AppColors.systemGray,
};
final key = context.knobs.object.dropdown(
label: label,
options: options.keys.toList(),
initialOption: 'accent',
);
return options[key]!;
}
T knobEnum<T extends Enum>(
BuildContext context, {
required String label,
required List<T> values,
required T initial,
}) {
return context.knobs.object.dropdown(
label: label,
options: values,
labelBuilder: (value) => value.name,
initialOption: initial,
);
}
@@ -0,0 +1,46 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:widgetbook/widgetbook.dart';
enum UiAsyncState { content, loading, empty, error }
UiAsyncState knobAsyncState(BuildContext context, {String label = 'State'}) {
return context.knobs.object.dropdown(
label: label,
options: UiAsyncState.values,
labelBuilder: (value) => value.name,
initialOption: UiAsyncState.content,
);
}
/// Shared empty / error / loading wrappers for molecules & screens.
Widget wrapAsyncState({
required BuildContext context,
required UiAsyncState state,
required Widget Function() builder,
String emptyLabel = 'Пока пусто',
String errorLabel = 'Что-то пошло не так',
}) {
return switch (state) {
UiAsyncState.loading => const Padding(
padding: EdgeInsets.all(AppSpacing.s6),
child: Center(child: AppSpinner()),
),
UiAsyncState.empty => Padding(
padding: const EdgeInsets.all(AppSpacing.s6),
child: Center(child: AppText.subhead(emptyLabel)),
),
UiAsyncState.error => Padding(
padding: const EdgeInsets.all(AppSpacing.s6),
child: Center(
child: AppText.subhead(
knobText(context, label: 'Error text', initialValue: errorLabel),
color: AppColors.systemRed,
),
),
),
UiAsyncState.content => builder(),
};
}
+10
View File
@@ -0,0 +1,10 @@
import 'package:flutter/widgets.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:please_pay_me_widgetbook/app.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeDateFormatting('ru');
runApp(const WidgetbookRoot());
}
@@ -0,0 +1,76 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/core/config/app_config.dart';
import 'package:please_pay_me/core/storage/session_storage.dart';
import 'package:please_pay_me/data/demo/demo_backend.dart';
import 'package:please_pay_me/features/auth/session_controller.dart';
import 'package:please_pay_me/features/budgets/budgets_controller.dart';
import 'package:please_pay_me/features/journal/journal_controller.dart';
import 'package:please_pay_me/features/work/jobs_controller.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:provider/provider.dart';
/// Wires real app screens to the in-memory [DemoBackend] so the catalog shows
/// production widgets with production state management.
class DemoScope extends StatefulWidget {
const DemoScope({super.key, required this.child, this.seeded = true});
final Widget child;
/// `false` renders the empty states (no budgets / jobs / operations).
final bool seeded;
@override
State<DemoScope> createState() => _DemoScopeState();
}
class _DemoScopeState extends State<DemoScope> {
late DemoBackend _backend;
late SessionController _session;
@override
void initState() {
super.initState();
_build();
}
@override
void didUpdateWidget(DemoScope oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.seeded != widget.seeded) _build();
}
void _build() {
_backend = widget.seeded ? DemoBackend() : DemoBackend.empty();
_session = SessionController(
config: AppConfig.demo,
storage: InMemorySessionStorage(),
demoBackend: _backend,
)..startDemo();
}
@override
Widget build(BuildContext context) {
return MultiProvider(
key: ValueKey(widget.seeded),
providers: [
ChangeNotifierProvider<SessionController>.value(value: _session),
ChangeNotifierProvider<ThemeController>(
create: (_) => ThemeController(store: MemoryThemeStore()),
),
ChangeNotifierProvider(
create: (_) => BudgetsController(
budgets: _backend.budgets,
expenses: _backend.expenses,
)..load(),
),
ChangeNotifierProvider(
create: (_) => JournalController(expenses: _backend.expenses)..load(),
),
ChangeNotifierProvider(
create: (_) => JobsController(jobs: _backend.jobs)..load(),
),
],
child: widget.child,
);
}
}
@@ -0,0 +1,56 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
/// Puts a use-case on the iOS grouped background so inset-grouped cards and
/// separators read the way they do inside the app.
class IosPreview extends StatelessWidget {
const IosPreview({
super.key,
required this.child,
this.padding = const EdgeInsets.symmetric(vertical: AppSpacing.s5),
this.maxWidth = 420,
this.stretch = false,
});
/// Preview for controls that should not be stretched (buttons, chips).
const IosPreview.centered({super.key, required this.child})
: padding = const EdgeInsets.all(AppSpacing.s5),
maxWidth = 420,
stretch = false;
final Widget child;
final EdgeInsetsGeometry padding;
final double maxWidth;
final bool stretch;
@override
Widget build(BuildContext context) {
return ColoredBox(
color: AppColors.of(context, AppColors.groupedBackground),
child: Center(
child: SingleChildScrollView(
padding: padding,
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: maxWidth),
child: Column(
crossAxisAlignment:
stretch ? CrossAxisAlignment.stretch : CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [child],
),
),
),
),
);
}
}
/// Full-screen preview (screens already bring their own scaffold).
class IosScreenPreview extends StatelessWidget {
const IosScreenPreview({super.key, required this.child});
final Widget child;
@override
Widget build(BuildContext context) => child;
}
@@ -0,0 +1,80 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent buttonsComponent() {
return WidgetbookComponent(
name: 'AppButton',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
return IosPreview(
stretch: true,
child: AppButton(
label: knobText(context, label: 'Label', initialValue: 'Сохранить'),
style: knobEnum(
context,
label: 'Style',
values: AppButtonStyle.values,
initial: AppButtonStyle.filled,
),
size: knobEnum(
context,
label: 'Size',
values: AppButtonSize.values,
initial: AppButtonSize.large,
),
expanded: knobBool(context, label: 'Expanded', initialValue: true),
loading: knobBool(context, label: 'Loading'),
icon: knobBool(context, label: 'Icon') ? CupertinoIcons.plus : null,
onPressed:
knobBool(context, label: 'Enabled', initialValue: true) ? () {} : null,
),
);
},
),
WidgetbookUseCase(
name: 'All styles',
builder: (context) {
return IosPreview(
stretch: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
for (final style in AppButtonStyle.values) ...[
AppButton(label: style.name, style: style, onPressed: () {}),
const SizedBox(height: AppSpacing.s3),
],
],
),
);
},
),
WidgetbookUseCase(
name: 'Sizes',
builder: (context) {
return IosPreview.centered(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
for (final size in AppButtonSize.values) ...[
AppButton(
label: 'Размер ${size.name}',
size: size,
expanded: false,
onPressed: () {},
),
const SizedBox(height: AppSpacing.s3),
],
],
),
);
},
),
],
);
}
@@ -0,0 +1,68 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
const _icons = <IconData>[
CupertinoIcons.house_fill,
CupertinoIcons.cart_fill,
CupertinoIcons.bag_fill,
CupertinoIcons.money_rubl_circle_fill,
CupertinoIcons.chart_pie_fill,
CupertinoIcons.calendar,
CupertinoIcons.bell_fill,
CupertinoIcons.gear_alt_fill,
CupertinoIcons.person_fill,
CupertinoIcons.creditcard_fill,
];
WidgetbookComponent iconsComponent() {
return WidgetbookComponent(
name: 'Icons',
useCases: [
WidgetbookUseCase(
name: 'Glyphs',
builder: (context) {
final size = knobDouble(context, label: 'Size', initialValue: 24, min: 12, max: 48);
final tint = knobTint(context);
return IosPreview(
child: Wrap(
spacing: AppSpacing.s5,
runSpacing: AppSpacing.s5,
alignment: WrapAlignment.center,
children: [
for (final icon in _icons) AppIcon(icon, size: size, color: tint),
],
),
);
},
),
WidgetbookUseCase(
name: 'Badges',
builder: (context) {
return IosPreview(
child: Wrap(
spacing: AppSpacing.s4,
runSpacing: AppSpacing.s4,
alignment: WrapAlignment.center,
children: [
for (final (index, icon) in _icons.indexed)
AppIconBadge(
icon: icon,
color: switch (index % 4) {
0 => AppColors.accent,
1 => AppColors.systemRed,
2 => AppColors.systemOrange,
_ => AppColors.systemGray,
},
),
],
),
);
},
),
],
);
}
@@ -0,0 +1,62 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent textFieldsComponent() {
return WidgetbookComponent(
name: 'AppTextField',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
final error = knobText(context, label: 'Error', initialValue: '');
return IosPreview(
stretch: true,
padding: const EdgeInsets.all(AppSpacing.s4),
child: AppTextField(
label: knobText(context, label: 'Label', initialValue: 'Сумма'),
placeholder: knobText(context, label: 'Placeholder', initialValue: '0 ₽'),
enabled: knobBool(context, label: 'Enabled', initialValue: true),
obscureText: knobBool(context, label: 'Obscure'),
clearable: knobBool(context, label: 'Clear button', initialValue: true),
prefixIcon: knobBool(context, label: 'Prefix icon')
? CupertinoIcons.search
: null,
errorText: error.isEmpty ? null : error,
),
);
},
),
WidgetbookUseCase(
name: 'Form group',
builder: (context) {
return const IosPreview(
stretch: true,
padding: EdgeInsets.all(AppSpacing.s4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AppTextField(label: 'Название', placeholder: 'Продукты'),
SizedBox(height: AppSpacing.s4),
AppTextField(
label: 'Сумма',
placeholder: '0 ₽',
keyboardType: TextInputType.number,
),
SizedBox(height: AppSpacing.s4),
AppTextField(
label: 'Комментарий',
placeholder: 'Необязательно',
errorText: 'Слишком длинный комментарий',
),
],
),
);
},
),
],
);
}
@@ -0,0 +1,63 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent typographyComponent() {
return WidgetbookComponent(
name: 'Typography',
useCases: [
WidgetbookUseCase(
name: 'iOS scale',
builder: (context) {
final sample = knobText(context, label: 'Sample', initialValue: 'Бюджет на неделю');
return IosPreview(
stretch: true,
padding: const EdgeInsets.all(AppSpacing.s4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppText.largeTitle(sample),
const SizedBox(height: AppSpacing.s3),
AppText.title(sample),
const SizedBox(height: AppSpacing.s3),
AppText.headline(sample),
const SizedBox(height: AppSpacing.s3),
AppText.body(sample),
const SizedBox(height: AppSpacing.s3),
AppText.callout(sample),
const SizedBox(height: AppSpacing.s3),
AppText.subhead(sample),
const SizedBox(height: AppSpacing.s3),
AppText.footnote(sample),
const SizedBox(height: AppSpacing.s3),
AppText.caption(sample),
],
),
);
},
),
WidgetbookUseCase(
name: 'Section header',
builder: (context) {
return IosPreview(
stretch: true,
child: AppListSection(
header: knobText(context, label: 'Header', initialValue: 'Настройки'),
footer: knobText(
context,
label: 'Footer',
initialValue: 'Пояснение под группой, как в iOS Settings.',
),
children: const [
AppListTile(title: 'Строка', value: 'Значение'),
],
),
);
},
),
],
);
}
@@ -0,0 +1,48 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent progressComponent() {
return WidgetbookComponent(
name: 'Progress',
useCases: [
WidgetbookUseCase(
name: 'Activity indicator',
builder: (context) {
return IosPreview.centered(
child: AppSpinner(
radius: knobDouble(context, label: 'Radius', initialValue: 14, min: 6, max: 28),
color: knobTint(context),
),
);
},
),
WidgetbookUseCase(
name: 'Progress bar',
builder: (context) {
return IosPreview(
stretch: true,
padding: const EdgeInsets.all(AppSpacing.s4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AppProgressBar(
value: knobDouble(context, label: 'Value', initialValue: 0.42),
color: knobTint(context),
height: knobDouble(context, label: 'Height', initialValue: 4, min: 2, max: 12),
),
const SizedBox(height: AppSpacing.s4),
const AppProgressBar(value: 0.15, color: AppColors.systemRed),
const SizedBox(height: AppSpacing.s4),
const AppProgressBar(value: 1, color: AppColors.systemGreen),
],
),
);
},
),
],
);
}
@@ -0,0 +1,38 @@
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent skeletonsComponent() {
return WidgetbookComponent(
name: 'AppSkeleton',
useCases: [
WidgetbookUseCase(
name: 'Block',
builder: (context) {
return IosPreview.centered(
child: AppSkeleton(
width: knobDouble(context, label: 'Width', initialValue: 200, min: 40, max: 320),
height: knobDouble(context, label: 'Height', initialValue: 16, min: 8, max: 80),
radius: knobDouble(context, label: 'Radius', initialValue: 6, min: 0, max: 24),
),
);
},
),
WidgetbookUseCase(
name: 'List loading',
builder: (context) {
final rows = knobInt(context, label: 'Rows', initialValue: 4, min: 1, max: 8);
return IosPreview(
stretch: true,
child: AppListSection(
header: 'Загрузка',
separatorIndent: 60,
children: List.generate(rows, (_) => const AppSkeletonRow()),
),
);
},
),
],
);
}
@@ -0,0 +1,46 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent toastsComponent() {
return WidgetbookComponent(
name: 'AppToast',
useCases: [
WidgetbookUseCase(
name: 'Static',
builder: (context) {
return IosPreview.centered(
child: AppToast(
message: knobText(context, label: 'Message', initialValue: 'Трата сохранена'),
tint: knobTint(context),
icon: knobBool(context, label: 'Icon', initialValue: true)
? CupertinoIcons.check_mark_circled_solid
: null,
),
);
},
),
WidgetbookUseCase(
name: 'Trigger',
builder: (context) {
return IosPreview(
stretch: true,
child: AppButton(
label: 'Показать toast',
onPressed: () => showAppToast(
context,
message: knobText(
context,
label: 'Message',
initialValue: 'Трата сохранена',
),
),
),
);
},
),
],
);
}
@@ -0,0 +1,48 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent avatarsComponent() {
return WidgetbookComponent(
name: 'AppAvatar',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
final initials = knobText(context, label: 'Initials', initialValue: 'ВА');
return IosPreview.centered(
child: AppAvatar(
initials: knobBool(context, label: 'Use initials', initialValue: true)
? initials
: null,
radius: knobDouble(context, label: 'Radius', initialValue: 32, min: 12, max: 56),
),
);
},
),
WidgetbookUseCase(
name: 'Sizes',
builder: (context) {
return const IosPreview.centered(
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
AppAvatar(initials: 'А', radius: 16),
SizedBox(width: AppSpacing.s4),
AppAvatar(initials: 'ВА', radius: 22),
SizedBox(width: AppSpacing.s4),
AppAvatar(radius: 32),
SizedBox(width: AppSpacing.s4),
AppAvatar(initials: 'ППМ', radius: 44),
],
),
);
},
),
],
);
}
@@ -0,0 +1,72 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent cardsComponent() {
return WidgetbookComponent(
name: 'AppCard',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
final subtitle = knobText(context, label: 'Subtitle', initialValue: 'До 25 сентября');
return IosPreview(
stretch: true,
child: AppCard(
title: knobText(context, label: 'Title', initialValue: 'Бюджет'),
subtitle: subtitle.isEmpty ? null : subtitle,
onTap: knobBool(context, label: 'Tappable') ? () {} : null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppText.largeTitle(
knobText(context, label: 'Amount', initialValue: '18 420 ₽'),
),
const SizedBox(height: AppSpacing.s4),
AppProgressBar(
value: knobDouble(context, label: 'Progress', initialValue: 0.42),
),
],
),
),
);
},
),
WidgetbookUseCase(
name: 'Metrics row',
builder: (context) {
return const IosPreview(
stretch: true,
child: AppCard(
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppText.footnote('Доход'),
AppText.title('64 000 ₽'),
],
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppText.footnote('Расход'),
AppText.title('45 580 ₽', color: AppColors.systemRed),
],
),
),
],
),
),
);
},
),
],
);
}
@@ -0,0 +1,45 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent chipsComponent() {
return WidgetbookComponent(
name: 'AppChip',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
return IosPreview.centered(
child: AppChip(
label: knobText(context, label: 'Label', initialValue: 'Еда'),
selected: knobBool(context, label: 'Selected'),
icon: knobBool(context, label: 'Icon') ? CupertinoIcons.tag_fill : null,
onPressed: () {},
),
);
},
),
WidgetbookUseCase(
name: 'Filter row',
builder: (context) {
final selected = knobInt(context, label: 'Selected index', min: 0, max: 3);
const labels = ['Все', 'Еда', 'Транспорт', 'Подписки'];
return IosPreview.centered(
child: Wrap(
spacing: AppSpacing.s2,
runSpacing: AppSpacing.s2,
alignment: WrapAlignment.center,
children: [
for (final (index, label) in labels.indexed)
AppChip(label: label, selected: index == selected, onPressed: () {}),
],
),
);
},
),
],
);
}
@@ -0,0 +1,80 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/knobs/state_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent listTilesComponent() {
return WidgetbookComponent(
name: 'AppListTile',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
final subtitle = knobText(context, label: 'Subtitle', initialValue: 'Супермаркет');
final value = knobText(context, label: 'Value', initialValue: '1 840 ₽');
return IosPreview(
stretch: true,
child: AppListSection(
separatorIndent: 60,
children: [
AppListTile(
leading: knobBool(context, label: 'Leading badge', initialValue: true)
? const AppIconBadge(icon: CupertinoIcons.cart_fill)
: null,
title: knobText(context, label: 'Title', initialValue: 'Продукты'),
subtitle: subtitle.isEmpty ? null : subtitle,
value: value.isEmpty ? null : value,
destructive: knobBool(context, label: 'Destructive'),
showChevron: knobBool(context, label: 'Chevron', initialValue: true),
onTap: knobBool(context, label: 'Tappable', initialValue: true) ? () {} : null,
),
],
),
);
},
),
WidgetbookUseCase(
name: 'Grouped section',
builder: (context) {
final state = knobAsyncState(context);
return IosPreview(
stretch: true,
child: AppListSection(
header: 'Сегодня',
footer: 'Свайп по строке открывает действия.',
separatorIndent: 60,
children: [
wrapAsyncState(
context: context,
state: state,
builder: () => const Column(
children: [
AppListTile(
leading: AppIconBadge(icon: CupertinoIcons.cart_fill),
title: 'Продукты',
subtitle: 'Супермаркет',
value: '1 840 ₽',
),
AppListTile(
leading: AppIconBadge(
icon: CupertinoIcons.car_fill,
color: AppColors.systemOrange,
),
title: 'Такси',
subtitle: 'Транспорт',
value: '420 ₽',
),
],
),
),
],
),
);
},
),
],
);
}
@@ -0,0 +1,75 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent switchesComponent() {
return WidgetbookComponent(
name: 'AppSwitchRow',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
final subtitle = knobText(context, label: 'Subtitle', initialValue: '');
return IosPreview(
stretch: true,
child: AppListSection(
separatorIndent: 60,
children: [
AppSwitchRow(
leading: knobBool(context, label: 'Leading badge', initialValue: true)
? const AppIconBadge(
icon: CupertinoIcons.bell_fill,
color: AppColors.systemRed,
)
: null,
title: knobText(context, label: 'Title', initialValue: 'Уведомления'),
subtitle: subtitle.isEmpty ? null : subtitle,
value: knobBool(context, label: 'Value', initialValue: true),
onChanged: knobBool(context, label: 'Enabled', initialValue: true)
? (_) {}
: null,
),
],
),
);
},
),
WidgetbookUseCase(
name: 'Settings group',
builder: (context) {
return IosPreview(
stretch: true,
child: AppListSection(
header: 'Настройки',
footer: 'Push приходят за час до дедлайна бюджета.',
separatorIndent: 60,
children: [
AppSwitchRow(
leading: const AppIconBadge(
icon: CupertinoIcons.bell_fill,
color: AppColors.systemRed,
),
title: 'Уведомления',
value: true,
onChanged: (_) {},
),
AppSwitchRow(
leading: const AppIconBadge(
icon: CupertinoIcons.lock_fill,
color: AppColors.systemGray,
),
title: 'Face ID',
value: false,
onChanged: (_) {},
),
],
),
);
},
),
],
);
}
@@ -0,0 +1,73 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent dialogsComponent() {
return WidgetbookComponent(
name: 'AppAlert',
useCases: [
WidgetbookUseCase(
name: 'Alert',
builder: (context) {
final message = knobText(
context,
label: 'Message',
initialValue: 'Операция будет удалена без возможности восстановления.',
);
return IosPreview.centered(
child: AppAlert(
title: knobText(context, label: 'Title', initialValue: 'Удалить трату?'),
message: message.isEmpty ? null : message,
confirmLabel: knobText(context, label: 'Confirm', initialValue: 'Удалить'),
cancelLabel: knobBool(context, label: 'Cancel button', initialValue: true)
? 'Отмена'
: null,
destructive: knobBool(context, label: 'Destructive', initialValue: true),
),
);
},
),
WidgetbookUseCase(
name: 'Triggers',
builder: (context) {
return IosPreview(
stretch: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AppButton(
label: 'Показать alert',
onPressed: () => showAppAlert(
context: context,
title: 'Удалить трату?',
message: 'Действие необратимо.',
confirmLabel: 'Удалить',
cancelLabel: 'Отмена',
destructive: true,
),
),
const SizedBox(height: AppSpacing.s3),
AppButton(
label: 'Показать action sheet',
style: AppButtonStyle.gray,
onPressed: () => showAppActionSheet(
context: context,
title: 'Операция',
actions: const [
AppActionSheetAction(label: 'Редактировать', isDefault: true),
AppActionSheetAction(label: 'Дублировать'),
AppActionSheetAction(label: 'Удалить', destructive: true),
],
),
),
],
),
);
},
),
],
);
}
@@ -0,0 +1,83 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent navBarComponent() {
return WidgetbookComponent(
name: 'AppNavBar',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
final subtitle = knobText(context, label: 'Subtitle', initialValue: 'До 25 сентября');
return CupertinoPageScaffold(
backgroundColor: AppColors.of(context, AppColors.groupedBackground),
navigationBar: AppNavBar(
title: knobText(context, label: 'Title', initialValue: 'Бюджет'),
subtitle: subtitle.isEmpty ? null : subtitle,
previousPageTitle:
knobBool(context, label: 'Back button', initialValue: true) ? 'Назад' : null,
transparent: knobBool(context, label: 'Transparent'),
trailing: knobBool(context, label: 'Trailing action', initialValue: true)
? CupertinoButton(
padding: EdgeInsets.zero,
minimumSize: Size.zero,
onPressed: () {},
child: const AppIcon(
CupertinoIcons.ellipsis_circle,
color: AppColors.accent,
),
)
: null,
),
child: const SafeArea(
child: Padding(
padding: EdgeInsets.all(AppSpacing.s4),
child: AppText.subhead('Контент под навигационной панелью'),
),
),
);
},
),
WidgetbookUseCase(
name: 'Large title',
builder: (context) {
return CupertinoPageScaffold(
backgroundColor: AppColors.of(context, AppColors.groupedBackground),
child: CustomScrollView(
slivers: [
AppLargeNavBar(
title: knobText(context, label: 'Title', initialValue: 'Журнал'),
trailing: CupertinoButton(
padding: EdgeInsets.zero,
minimumSize: Size.zero,
onPressed: () {},
child: const AppIcon(
CupertinoIcons.add_circled,
color: AppColors.accent,
),
),
),
SliverToBoxAdapter(
child: AppListSection(
header: 'Сегодня',
separatorIndent: 60,
children: const [
AppListTile(
leading: AppIconBadge(icon: CupertinoIcons.cart_fill),
title: 'Продукты',
value: '1 840 ₽',
),
],
),
),
],
),
);
},
),
],
);
}
@@ -0,0 +1,93 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:please_pay_me_widgetbook/support/preview.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent segmentedControlComponent() {
return WidgetbookComponent(
name: 'AppSegmentedControl',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
final labels = knobText(
context,
label: 'Labels (comma separated)',
initialValue: 'Все,Расходы,Доходы',
).split(',').where((e) => e.trim().isNotEmpty).toList();
final safeLabels = labels.isEmpty ? ['Все'] : labels;
return IosPreview(
stretch: true,
child: _StatefulSegments(
labels: safeLabels,
initialIndex: knobInt(
context,
label: 'Initial index',
max: safeLabels.length - 1,
),
),
);
},
),
WidgetbookUseCase(
name: 'In screen header',
builder: (context) {
return CupertinoPageScaffold(
backgroundColor: AppColors.of(context, AppColors.groupedBackground),
navigationBar: const AppNavBar(title: 'Журнал'),
child: SafeArea(
child: Column(
children: [
const SizedBox(height: AppSpacing.s4),
const _StatefulSegments(labels: ['Неделя', 'Месяц', 'Год']),
const SizedBox(height: AppSpacing.s5),
AppListSection(
children: const [
AppListTile(title: 'Итого', value: '45 580 ₽'),
],
),
],
),
),
);
},
),
],
);
}
class _StatefulSegments extends StatefulWidget {
const _StatefulSegments({required this.labels, this.initialIndex = 0});
final List<String> labels;
final int initialIndex;
@override
State<_StatefulSegments> createState() => _StatefulSegmentsState();
}
class _StatefulSegmentsState extends State<_StatefulSegments> {
late int _index = widget.initialIndex;
@override
void didUpdateWidget(_StatefulSegments oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.initialIndex != widget.initialIndex ||
_index >= widget.labels.length) {
_index = widget.initialIndex.clamp(0, widget.labels.length - 1);
}
}
@override
Widget build(BuildContext context) {
return AppSegmentedControl(
labels: widget.labels,
index: _index,
onChanged: (i) => setState(() => _index = i),
);
}
}
@@ -0,0 +1,53 @@
import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
import 'package:please_pay_me_widgetbook/knobs/common_knobs.dart';
import 'package:widgetbook/widgetbook.dart';
const _items = [
AppTabItem(icon: CupertinoIcons.list_bullet, label: 'Журнал'),
AppTabItem(icon: CupertinoIcons.chart_pie, label: 'Бюджет'),
AppTabItem(
icon: CupertinoIcons.person,
activeIcon: CupertinoIcons.person_fill,
label: 'Профиль',
),
];
WidgetbookComponent tabBarComponent() {
return WidgetbookComponent(
name: 'AppTabBar',
useCases: [
WidgetbookUseCase(
name: 'Playground',
builder: (context) {
final index = knobInt(context, label: 'Current index', min: 0, max: 2);
return ColoredBox(
color: AppColors.of(context, AppColors.groupedBackground),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
AppTabBar(items: _items, currentIndex: index, onTap: (_) {}),
],
),
);
},
),
WidgetbookUseCase(
name: 'In scaffold',
builder: (context) {
return CupertinoTabScaffold(
tabBar: AppTabBar(items: _items, currentIndex: 0, onTap: (_) {}),
tabBuilder: (context, index) => CupertinoTabView(
builder: (context) => CupertinoPageScaffold(
backgroundColor: AppColors.of(context, AppColors.groupedBackground),
navigationBar: AppNavBar(title: _items[index].label),
child: Center(child: AppText.body(_items[index].label)),
),
),
);
},
),
],
);
}
@@ -0,0 +1,130 @@
import 'package:please_pay_me/app/home_tabs.dart';
import 'package:please_pay_me/features/auth/login_screen.dart';
import 'package:please_pay_me/features/budgets/budgets_screen.dart';
import 'package:please_pay_me/features/journal/journal_screen.dart';
import 'package:please_pay_me/features/overview/overview_screen.dart';
import 'package:please_pay_me/features/profile/profile_screen.dart';
import 'package:please_pay_me/features/splash/splash_screen.dart';
import 'package:please_pay_me/features/work/work_screen.dart';
import 'package:please_pay_me_widgetbook/support/demo_scope.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent overviewScreenComponent() {
return WidgetbookComponent(
name: 'OverviewScreen',
useCases: [
WidgetbookUseCase(
name: 'С активным бюджетом',
builder: (context) => const DemoScope(child: OverviewScreen()),
),
WidgetbookUseCase(
name: 'Без бюджетов',
builder: (context) => const DemoScope(seeded: false, child: OverviewScreen()),
),
],
);
}
WidgetbookComponent journalScreenComponent() {
return WidgetbookComponent(
name: 'JournalScreen',
useCases: [
WidgetbookUseCase(
name: 'С операциями',
builder: (context) => const DemoScope(child: JournalScreen()),
),
WidgetbookUseCase(
name: 'Пустой',
builder: (context) => const DemoScope(seeded: false, child: JournalScreen()),
),
],
);
}
WidgetbookComponent budgetsScreenComponent() {
return WidgetbookComponent(
name: 'BudgetsScreen',
useCases: [
WidgetbookUseCase(
name: 'Активные и завершённые',
builder: (context) => const DemoScope(child: BudgetsScreen()),
),
WidgetbookUseCase(
name: 'Пустой',
builder: (context) => const DemoScope(seeded: false, child: BudgetsScreen()),
),
],
);
}
WidgetbookComponent workScreenComponent() {
return WidgetbookComponent(
name: 'WorkScreen',
useCases: [
WidgetbookUseCase(
name: 'С работой',
builder: (context) => const DemoScope(child: WorkScreen()),
),
WidgetbookUseCase(
name: 'Пустой',
builder: (context) => const DemoScope(seeded: false, child: WorkScreen()),
),
],
);
}
WidgetbookComponent profileScreenComponent() {
return WidgetbookComponent(
name: 'ProfileScreen',
useCases: [
WidgetbookUseCase(
name: 'Демо-сессия',
builder: (context) => const DemoScope(child: ProfileScreen()),
),
],
);
}
WidgetbookComponent splashScreenComponent() {
return WidgetbookComponent(
name: 'SplashScreen',
useCases: [
WidgetbookUseCase(
name: 'Запуск',
builder: (context) => const SplashScreen(),
),
],
);
}
WidgetbookComponent loginScreenComponent() {
return WidgetbookComponent(
name: 'LoginScreen',
useCases: [
WidgetbookUseCase(
name: 'Вход через Telegram',
builder: (context) => DemoScope(
// Desktop has no WebView, so the catalog stubs the launcher to show
// the mobile layout.
child: LoginScreen(launchTelegramLogin: (_, __) async => null),
),
),
WidgetbookUseCase(
name: 'Вход по токену',
builder: (context) => const DemoScope(child: LoginScreen()),
),
],
);
}
WidgetbookComponent homeTabsComponent() {
return WidgetbookComponent(
name: 'HomeTabs',
useCases: [
WidgetbookUseCase(
name: 'Полное приложение',
builder: (context) => const DemoScope(child: HomeTabs()),
),
],
);
}
@@ -0,0 +1,64 @@
import 'package:please_pay_me/data/demo/demo_backend.dart';
import 'package:please_pay_me/features/budgets/budget_form_sheet.dart';
import 'package:please_pay_me/features/expenses/expense_form_sheet.dart';
import 'package:please_pay_me/features/work/job_form_sheet.dart';
import 'package:please_pay_me_widgetbook/support/demo_scope.dart';
import 'package:widgetbook/widgetbook.dart';
WidgetbookComponent sheetsComponent() {
return WidgetbookComponent(
name: 'Формы',
useCases: [
WidgetbookUseCase(
name: 'Новая трата',
builder: (context) => DemoScope(
child: ExpenseFormSheet(
budgetName: 'До аванса',
remainingToday: 1420,
onSubmit: ({required amount, note, required spentAt}) async => null,
),
),
),
WidgetbookUseCase(
name: 'Новый бюджет',
builder: (context) => DemoScope(
child: BudgetFormSheet(
onSubmit: ({
required name,
required totalAmount,
required startDate,
required endDate,
required resetExpenses,
}) async =>
null,
),
),
),
WidgetbookUseCase(
name: 'Новая работа',
builder: (context) => DemoScope(
child: JobFormSheet(
onSubmit: ({
required name,
required salaryAmount,
required payDays,
required firstPayPercent,
required weekendPolicy,
}) async =>
null,
),
),
),
WidgetbookUseCase(
name: 'Ошибка сохранения',
builder: (context) => DemoScope(
child: ExpenseFormSheet(
budgetName: DemoBackend.user.displayName,
onSubmit: ({required amount, note, required spentAt}) async =>
'Бюджет уже завершён',
),
),
),
],
);
}
+918
View File
@@ -0,0 +1,918 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "1b0e6a07425a3e460666e88bf1c949ccc7bb0116ad562ce94a1eca60fe820725"
url: "https://pub.dev"
source: hosted
version: "103.0.0"
accessibility_tools:
dependency: transitive
description:
name: accessibility_tools
sha256: c29732e423175a51e0a6ace7df1255f5d77812c7c7b7101d8ba0186a43d533aa
url: "https://pub.dev"
source: hosted
version: "2.8.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "61c04d0c1bfed555c681ea079519933f071a5a026578ff73c4ff0df2d3462e5e"
url: "https://pub.dev"
source: hosted
version: "13.3.0"
args:
dependency: transitive
description:
name: args
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
url: "https://pub.dev"
source: hosted
version: "2.7.0"
async:
dependency: transitive
description:
name: async
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
url: "https://pub.dev"
source: hosted
version: "2.13.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
build:
dependency: transitive
description:
name: build
sha256: "8a5c5761af8e31748bba3c82f68925ace40f3225c3eea25be9beb57eca7cd7a8"
url: "https://pub.dev"
source: hosted
version: "4.0.11"
build_config:
dependency: transitive
description:
name: build_config
sha256: d466ed2dc9c6cd1d169948879b84ee061eb5e22c64a7c6089879c6296d272a8d
url: "https://pub.dev"
source: hosted
version: "1.3.3"
build_daemon:
dependency: transitive
description:
name: build_daemon
sha256: e1d40ef3f7934986d5da2271b1ba07794921ce263e44d622fb6c406d76589e33
url: "https://pub.dev"
source: hosted
version: "4.1.6"
build_runner:
dependency: "direct dev"
description:
name: build_runner
sha256: "894c243f6bc32015fec466ce30a6925bd537a77a426ee5bf481120477eb3de67"
url: "https://pub.dev"
source: hosted
version: "2.16.1"
built_collection:
dependency: transitive
description:
name: built_collection
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
url: "https://pub.dev"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
sha256: f87ea98192116f7093cb214551ce1929caae0681fdba282b3d8b4462adee7bb7
url: "https://pub.dev"
source: hosted
version: "8.13.0"
characters:
dependency: transitive
description:
name: characters
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev"
source: hosted
version: "1.4.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
url: "https://pub.dev"
source: hosted
version: "2.0.4"
clock:
dependency: transitive
description:
name: clock
sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e
url: "https://pub.dev"
source: hosted
version: "1.1.3"
code_assets:
dependency: transitive
description:
name: code_assets
sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
url: "https://pub.dev"
source: hosted
version: "1.2.1"
code_builder:
dependency: transitive
description:
name: code_builder
sha256: aa5932e94c6c39c2f9ec4e5e06dfdd11a9430a61f6c41b6ba75b28ce0c481baf
url: "https://pub.dev"
source: hosted
version: "4.12.0"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.1"
convert:
dependency: transitive
description:
name: convert
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
url: "https://pub.dev"
source: hosted
version: "3.1.2"
crypto:
dependency: transitive
description:
name: crypto
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
url: "https://pub.dev"
source: hosted
version: "3.0.7"
cupertino_icons:
dependency: transitive
description:
name: cupertino_icons
sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
url: "https://pub.dev"
source: hosted
version: "1.0.9"
dart_style:
dependency: transitive
description:
name: dart_style
sha256: "82ade9fc4273f29ed673e33166944465225b4f7fc5d4aaef48605cc751c18fc1"
url: "https://pub.dev"
source: hosted
version: "3.1.13"
device_frame_plus:
dependency: transitive
description:
name: device_frame_plus
sha256: ccc94abccd4d9f0a9f19ef239001b3a59896e678ad42601371d7065889f2bf78
url: "https://pub.dev"
source: hosted
version: "1.5.0"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
version: "1.3.3"
ffi:
dependency: transitive
description:
name: ffi
sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
file:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
url: "https://pub.dev"
source: hosted
version: "7.0.1"
fixnum:
dependency: transitive
description:
name: fixnum
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
url: "https://pub.dev"
source: hosted
version: "1.1.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
url: "https://pub.dev"
source: hosted
version: "5.0.0"
flutter_localizations:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
glob:
dependency: transitive
description:
name: glob
sha256: "218aeb56050c714f62a3182775320dfa04602b55074873e24e31bbd39bda96fb"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
google_fonts:
dependency: "direct dev"
description:
name: google_fonts
sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055
url: "https://pub.dev"
source: hosted
version: "6.3.3"
graphs:
dependency: transitive
description:
name: graphs
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
hooks:
dependency: transitive
description:
name: hooks
sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
http:
dependency: transitive
description:
name: http
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
url: "https://pub.dev"
source: hosted
version: "1.6.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
url: "https://pub.dev"
source: hosted
version: "3.2.2"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
version: "4.1.2"
inspector:
dependency: transitive
description:
name: inspector
sha256: "60782d94c8851b0eee3ffdfea9fd43e7c37f919b54cb587e4de9da0e09d491b5"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
intl:
dependency: "direct main"
description:
name: intl
sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867"
url: "https://pub.dev"
source: hosted
version: "0.20.3"
io:
dependency: transitive
description:
name: io
sha256: "2635216ca6a737e60de577ffa1a48a0bec76ca8a62917cfc1bb88c14c570646f"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
jni:
dependency: transitive
description:
name: jni
sha256: f038e58b4dc2c9037f50e233175086337e0b305e356d28211bf55f21c504cbd3
url: "https://pub.dev"
source: hosted
version: "1.0.3"
jni_flutter:
dependency: transitive
description:
name: jni_flutter
sha256: b2310cdd4c18c65c081ab141a41efa94aa26c65431803703ece51996f174f351
url: "https://pub.dev"
source: hosted
version: "1.0.3"
jni_util:
dependency: transitive
description:
name: jni_util
sha256: "1ba86da04a5f2bf18fde2edb235587e70c5b0fc5bd4ba955f46b00942c3fc35f"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80"
url: "https://pub.dev"
source: hosted
version: "4.12.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev"
source: hosted
version: "11.0.2"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
lints:
dependency: transitive
description:
name: lints
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
url: "https://pub.dev"
source: hosted
version: "5.1.1"
logging:
dependency: transitive
description:
name: logging
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
url: "https://pub.dev"
source: hosted
version: "1.3.0"
matcher:
dependency: transitive
description:
name: matcher
sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
url: "https://pub.dev"
source: hosted
version: "0.12.20"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev"
source: hosted
version: "0.13.0"
meta:
dependency: transitive
description:
name: meta
sha256: c82594181e3312f3d0695fc95aaaf7758d75b8d4ae2bbecf223b9fd5109a059d
url: "https://pub.dev"
source: hosted
version: "1.18.3"
mime:
dependency: transitive
description:
name: mime
sha256: bd47de35f07e27267e69c8c8b22edf9473bfee170a60d60fcc93730c5144b7f6
url: "https://pub.dev"
source: hosted
version: "2.1.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
objective_c:
dependency: transitive
description:
name: objective_c
sha256: b7fb95a6d9a4f009edd63dc5ac69f07420b23a16161c6dd8660290b59c602e8e
url: "https://pub.dev"
source: hosted
version: "9.5.0"
package_config:
dependency: transitive
description:
name: package_config
sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d
url: "https://pub.dev"
source: hosted
version: "3.0.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
path_provider:
dependency: transitive
description:
name: path_provider
sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825
url: "https://pub.dev"
source: hosted
version: "2.1.6"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699"
url: "https://pub.dev"
source: hosted
version: "2.6.0"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: "58c2005f147315b11e9b4a7bc889cd5203e250cba8e3f012dae259b4972b5c16"
url: "https://pub.dev"
source: hosted
version: "2.2.2"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda"
url: "https://pub.dev"
source: hosted
version: "2.1.3"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.dev"
source: hosted
version: "2.3.0"
platform:
dependency: transitive
description:
name: platform
sha256: a36d119c13416516a7b5913fbe8af8531e11633d784c550b2125f76c758524ec
url: "https://pub.dev"
source: hosted
version: "3.2.0"
please_pay_me:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.1.0+1"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
pool:
dependency: transitive
description:
name: pool
sha256: "4177f68c237ea2128d1bee66ac17b2ce05ba3dbaafcbdd54c5d40a39d0b6b11c"
url: "https://pub.dev"
source: hosted
version: "1.5.3"
provider:
dependency: "direct main"
description:
name: provider
sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
url: "https://pub.dev"
source: hosted
version: "6.1.5+1"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "261236774e8b1d69cfc6b9eabbc96c40f25e7a2d6b171f3385d4f65d5734fb24"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
sha256: c38b81cbf34450b67e0265d73433569d12e34782e30ed769c9cc99c9d5f2e796
url: "https://pub.dev"
source: hosted
version: "1.6.0"
record_use:
dependency: transitive
description:
name: record_use
sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
url: "https://pub.dev"
source: hosted
version: "0.6.0"
resizable_widget:
dependency: transitive
description:
name: resizable_widget
sha256: db2919754b93f386b9b3fb15e9f48f6c9d6d41f00a24397629133c99df86606a
url: "https://pub.dev"
source: hosted
version: "1.0.5"
shared_preferences:
dependency: transitive
description:
name: shared_preferences
sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
url: "https://pub.dev"
source: hosted
version: "2.5.5"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "1e12aafe408aa50da80edfd679a2a6bf63ba7ab37c7fa98286da459a757b3399"
url: "https://pub.dev"
source: hosted
version: "2.4.28"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "2ec3934efa51e46117f23031cc141b8fc878e8525b94ec1ea4f7f586cf1b47ea"
url: "https://pub.dev"
source: hosted
version: "2.5.7"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
url: "https://pub.dev"
source: hosted
version: "2.4.3"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shelf:
dependency: transitive
description:
name: shelf
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.dev"
source: hosted
version: "1.4.2"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_gen:
dependency: transitive
description:
name: source_gen
sha256: a603f1fb984a7391ae5978d1b92bfaaa08b350dca5c825256f925818f7943bf5
url: "https://pub.dev"
source: hosted
version: "4.2.4"
source_span:
dependency: transitive
description:
name: source_span
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
url: "https://pub.dev"
source: hosted
version: "1.10.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490"
url: "https://pub.dev"
source: hosted
version: "1.12.2"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: a00e5f18bffc764f923e7dec1038527f7fe7a1791361a7117f0358193f13d53a
url: "https://pub.dev"
source: hosted
version: "2.1.2"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.dev"
source: hosted
version: "1.4.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.dev"
source: hosted
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
url: "https://pub.dev"
source: hosted
version: "0.7.12"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
version: "1.4.0"
url_launcher:
dependency: transitive
description:
name: url_launcher
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
url: "https://pub.dev"
source: hosted
version: "6.3.2"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
sha256: "611e87fb320b70d1dd721dc46af89c98aceccea9b31fde49e084591414e0c610"
url: "https://pub.dev"
source: hosted
version: "6.3.33"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: "8faa1aab294f1ab4040b43660c887b0418d5fa4f0cffef76a484e6aa1092eb4a"
url: "https://pub.dev"
source: hosted
version: "6.4.2"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: "10f86fef4c2c43563fa6c211ff9cf757adf4d3ab762c56bd430664a947d70cd0"
url: "https://pub.dev"
source: hosted
version: "3.2.3"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
sha256: "5e835a3b869c2d70325349c81c5a45c28e20791265b67b2669da6b08c5cd5201"
url: "https://pub.dev"
source: hosted
version: "3.2.6"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34"
url: "https://pub.dev"
source: hosted
version: "2.4.3"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "6c5ad3f22cd4c38e089b81963b3cd7bb83b111b2df5dce008bb066162f42e429"
url: "https://pub.dev"
source: hosted
version: "3.1.6"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "1d774bbdf6b72a0b12122fc1560c9c2d2a67db5a4a4cc2bd8a5c990ab20e3188"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0"
url: "https://pub.dev"
source: hosted
version: "15.3.0"
watcher:
dependency: transitive
description:
name: watcher
sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
url: "https://pub.dev"
source: hosted
version: "3.0.3"
webview_flutter:
dependency: transitive
description:
name: webview_flutter
sha256: d53e1ccf5516f25017e3c9d44c39034db352d20fa34fe200674270242c2c5111
url: "https://pub.dev"
source: hosted
version: "4.14.1"
webview_flutter_android:
dependency: transitive
description:
name: webview_flutter_android
sha256: "4de8b3d1ff4ebe1bdb42e68a5e4f809194a3cb0117a8f495f590004f00da3964"
url: "https://pub.dev"
source: hosted
version: "4.14.1"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04"
url: "https://pub.dev"
source: hosted
version: "2.15.1"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: fe359c7fac1002124b5b9e2ba3a41906bbb9b2d029ccb4a0067404d8f3704730
url: "https://pub.dev"
source: hosted
version: "3.26.1"
widgetbook:
dependency: "direct main"
description:
name: widgetbook
sha256: "88b10102d294d0bec64ca294c81f15b1a620ce66df950067ff8f89274f1c95e8"
url: "https://pub.dev"
source: hosted
version: "3.25.0"
widgetbook_annotation:
dependency: "direct main"
description:
name: widgetbook_annotation
sha256: ec98130f23579f14e304b6b45516612676ae4e0b0e6bb1debe9dba4ea604ab42
url: "https://pub.dev"
source: hosted
version: "3.11.0"
widgetbook_generator:
dependency: "direct dev"
description:
name: widgetbook_generator
sha256: "8fd3b4208bb74cbe60cd6fc99b443561b65542658b20d6dd700a2496edbd5647"
url: "https://pub.dev"
source: hosted
version: "3.24.0"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: f67cdd8e07d3c6329146aaef1ba043542b3134c12489f553ca9a7435d1068aea
url: "https://pub.dev"
source: hosted
version: "3.1.4"
sdks:
dart: ">=3.12.0 <4.0.0"
flutter: ">=3.44.0"
+31
View File
@@ -0,0 +1,31 @@
name: please_pay_me_widgetbook
description: Portable Widgetbook catalog for Please Pay Me UI kit
publish_to: "none"
version: 0.1.0+1
environment:
sdk: ">=3.5.0 <4.0.0"
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: any
please_pay_me:
path: ../
provider: ^6.1.2
widgetbook: ^3.14.0
widgetbook_annotation: ^3.5.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^5.0.0
build_runner: ^2.4.13
# Smoke tests disable runtime font fetching.
google_fonts: ^6.2.1
widgetbook_generator: ^3.13.0
flutter:
uses-material-design: true
+60
View File
@@ -0,0 +1,60 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Запуск Widgetbook (каталог UI-компонентов).
.EXAMPLE
.\run.ps1
.\run.ps1 -Device windows
.\run.ps1 -Device chrome -SkipPubGet
#>
param(
[ValidateSet("chrome", "windows", "edge")]
[string]$Device = "chrome",
[switch]$SkipPubGet
)
$ErrorActionPreference = "Stop"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Set-Location $ScriptDir
function Find-Flutter {
$cmd = Get-Command flutter -ErrorAction SilentlyContinue
if ($cmd) { return $cmd.Source }
$candidates = @(
"$env:USERPROFILE\flutter\bin\flutter.bat",
"$env:LOCALAPPDATA\flutter\bin\flutter.bat",
"C:\flutter\bin\flutter.bat",
"C:\src\flutter\bin\flutter.bat"
)
foreach ($path in $candidates) {
if (Test-Path $path) { return $path }
}
return $null
}
$flutter = Find-Flutter
if (-not $flutter) {
Write-Error @"
Flutter не найден в PATH и в стандартных путях.
Установи SDK или добавь в PATH, например:
`$env:Path = `"$env:USERPROFILE\flutter\bin;`$env:Path`"
"@
}
Write-Host "Flutter: $flutter" -ForegroundColor DarkGray
Write-Host "Device: $Device" -ForegroundColor DarkGray
Write-Host "Dir: $ScriptDir" -ForegroundColor DarkGray
Write-Host ""
if (-not $SkipPubGet) {
Write-Host ">> flutter pub get" -ForegroundColor Cyan
& $flutter pub get
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
Write-Host ">> flutter run -d $Device" -ForegroundColor Cyan
& $flutter run -d $Device
exit $LASTEXITCODE
@@ -0,0 +1,89 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me_widgetbook/catalog.dart';
import 'package:widgetbook/widgetbook.dart';
List<WidgetbookUseCase> _collectUseCases() {
final useCases = <WidgetbookUseCase>[];
void walk(WidgetbookNode node) {
if (node is WidgetbookUseCase) useCases.add(node);
for (final child in node.children ?? const <WidgetbookNode>[]) {
walk(child);
}
}
for (final root in buildCatalogDirectories()) {
walk(root);
}
return useCases;
}
/// Knobs read `WidgetbookState` from the context, so use-cases can only be
/// pumped inside a scope.
Widget _host({required CupertinoThemeData theme, required WidgetbookUseCase useCase}) {
return WidgetbookScope(
state: WidgetbookState(
path: useCase.path,
root: WidgetbookRoot(children: buildCatalogDirectories()),
),
child: CupertinoApp(
theme: theme,
locale: const Locale('ru'),
home: Builder(builder: useCase.builder),
),
);
}
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
// No network access in tests — fall back to the default font instead.
GoogleFonts.config.allowRuntimeFetching = false;
setUpAll(() => initializeDateFormatting('ru'));
test('catalog directories are non-empty', () {
expect(buildCatalogDirectories(), isNotEmpty);
});
test('every use-case has a name and a builder', () {
final useCases = _collectUseCases();
for (final useCase in useCases) {
expect(useCase.name, isNotEmpty);
expect(useCase.builder, isNotNull);
}
expect(useCases.length, greaterThanOrEqualTo(20));
});
test('expected category folders exist', () {
final names = buildCatalogDirectories().map((n) => n.name).toSet();
expect(
names,
containsAll(<String>{'Atoms', 'Molecules', 'Navigation', 'Feedback', 'Screens'}),
);
});
group('use-cases render', () {
final themes = <String, CupertinoThemeData Function()>{
'Light': buildLightTheme,
'Dark': buildDarkTheme,
};
for (final entry in themes.entries) {
for (final useCase in _collectUseCases()) {
testWidgets('${useCase.path} (${entry.key})', (tester) async {
await tester.pumpWidget(_host(theme: entry.value(), useCase: useCase));
await tester.pump(const Duration(milliseconds: 300));
expect(tester.takeException(), isNull);
});
}
}
});
}
+10
View File
@@ -0,0 +1,10 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:please_pay_me_widgetbook/app.dart';
void main() {
testWidgets('WidgetbookRoot builds', (WidgetTester tester) async {
await tester.pumpWidget(const WidgetbookRoot());
await tester.pump();
expect(find.byType(WidgetbookRoot), findsOneWidget);
});
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

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