Skip to content

Commit ef5b277

Browse files
committed
Add complete step, and various updates
1 parent 0b8696b commit ef5b277

File tree

66 files changed

+600
-497
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+600
-497
lines changed

in_app_purchases/codelab_rebuild.yaml

Lines changed: 192 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,32 @@ steps:
7474
+ </array>
7575
</dict>
7676
</plist>
77+
- name: Patch app/ios/Podfile
78+
path: steps/app/ios/Podfile
79+
patch-u: |
80+
--- b/in_app_purchases/step_00/app/ios/Podfile
81+
+++ a/in_app_purchases/step_00/app/ios/Podfile
82+
@@ -1,5 +1,5 @@
83+
-# Uncomment this line to define a global platform for your project
84+
-# platform :ios, '12.0'
85+
+# Per https://firebase.google.com/support/release-notes/ios cloud_firestore requires a minimum iOS version of 13.0
86+
+platform :ios, '13.0'
87+
88+
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
89+
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
90+
- name: Patch app/android/settings.gradle
91+
path: steps/app/android/settings.gradle
92+
patch-u: |
93+
--- b/in_app_purchases/step_00/app/android/settings.gradle
94+
+++ a/in_app_purchases/step_00/app/android/settings.gradle
95+
@@ -18,7 +18,7 @@ pluginManagement {
96+
97+
plugins {
98+
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
99+
- id "com.android.application" version "8.1.0" apply false
100+
+ id "com.android.application" version "8.2.1" apply false
101+
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
102+
}
77103
- name: Mkdir app/assets
78104
mkdir: steps/app/assets
79105
- name: Add app/assets/dash_old.png
@@ -16838,24 +16864,24 @@ steps:
1683816864
///
1683916865
/// [ProcessSignal.sigterm] is listened to on all platforms except Windows.
1684016866
Future<void> terminateRequestFuture() {
16841-
final completer = Completer<bool>.sync();
16867+
final completer = Completer<bool>();
1684216868

16843-
// sigIntSub is copied below to avoid a race condition - ignoring this lint
16844-
// ignore: cancel_subscriptions
1684516869
StreamSubscription? sigIntSub, sigTermSub;
1684616870

1684716871
Future<void> signalHandler(ProcessSignal signal) async {
1684816872
print('Received signal $signal - closing');
1684916873

16850-
final subCopy = sigIntSub;
16851-
if (subCopy != null) {
16852-
sigIntSub = null;
16853-
await subCopy.cancel();
16874+
if (sigIntSub != null) {
16875+
await sigIntSub!.cancel();
1685416876
sigIntSub = null;
16855-
if (sigTermSub != null) {
16856-
await sigTermSub!.cancel();
16857-
sigTermSub = null;
16858-
}
16877+
}
16878+
16879+
if (sigTermSub != null) {
16880+
await sigTermSub!.cancel();
16881+
sigTermSub = null;
16882+
}
16883+
16884+
if (!completer.isCompleted) {
1685916885
completer.complete(true);
1686016886
}
1686116887
}
@@ -18132,14 +18158,13 @@ steps:
1813218158
import 'dash_counter.dart';
1813318159
import 'firebase_notifier.dart';
1813418160

18135-
@@ -19,19 +20,21 @@ class DashPurchases extends ChangeNotifier {
18161+
@@ -19,19 +20,20 @@ class DashPurchases extends ChangeNotifier {
1813618162
StoreState storeState = StoreState.loading;
1813718163
late StreamSubscription<List<PurchaseDetails>> _subscription;
1813818164
List<PurchasableProduct> products = [];
1813918165
+ IAPRepo iapRepo;
1814018166

1814118167
bool get beautifiedDash => _beautifiedDashUpgrade;
18142-
+ // ignore: prefer_final_fields
1814318168
bool _beautifiedDashUpgrade = false;
1814418169
-
1814518170
final iapConnection = IAPConnection.instance;
@@ -18156,15 +18181,15 @@ steps:
1815618181
loadPurchases();
1815718182
}
1815818183

18159-
@@ -57,6 +60,7 @@ class DashPurchases extends ChangeNotifier {
18184+
@@ -57,6 +59,7 @@ class DashPurchases extends ChangeNotifier {
1816018185
@override
1816118186
void dispose() {
1816218187
_subscription.cancel();
1816318188
+ iapRepo.removeListener(purchasesUpdate);
1816418189
super.dispose();
1816518190
}
1816618191

18167-
@@ -136,4 +140,54 @@ class DashPurchases extends ChangeNotifier {
18192+
@@ -136,4 +139,54 @@ class DashPurchases extends ChangeNotifier {
1816818193
void _updateStreamOnError(dynamic error) {
1816918194
//Handle error here
1817018195
}
@@ -18504,6 +18529,158 @@ steps:
1850418529
from: steps
1850518530
to: step_10
1850618531

18532+
- name: complete
18533+
steps:
18534+
- name: Remove complete
18535+
rmdir: complete
18536+
- name: Patch app/lib/logic/dash_purchases.dart
18537+
path: steps/app/lib/logic/dash_purchases.dart
18538+
patch-u: |
18539+
--- b/in_app_purchases/complete/app/lib/logic/dash_purchases.dart
18540+
+++ a/in_app_purchases/complete/app/lib/logic/dash_purchases.dart
18541+
@@ -1,3 +1,5 @@
18542+
+// ignore_for_file: avoid_print
18543+
+
18544+
import 'dart:async';
18545+
import 'dart:convert';
18546+
18547+
@@ -17,10 +19,10 @@ import 'firebase_notifier.dart';
18548+
class DashPurchases extends ChangeNotifier {
18549+
DashCounter counter;
18550+
FirebaseNotifier firebaseNotifier;
18551+
+ IAPRepo iapRepo;
18552+
StoreState storeState = StoreState.loading;
18553+
late StreamSubscription<List<PurchaseDetails>> _subscription;
18554+
List<PurchasableProduct> products = [];
18555+
- IAPRepo iapRepo;
18556+
18557+
bool get beautifiedDash => _beautifiedDashUpgrade;
18558+
bool _beautifiedDashUpgrade = false;
18559+
@@ -44,6 +46,7 @@ class DashPurchases extends ChangeNotifier {
18560+
notifyListeners();
18561+
return;
18562+
}
18563+
+
18564+
const ids = <String>{
18565+
storeKeyConsumable,
18566+
storeKeySubscription,
18567+
@@ -58,8 +61,8 @@ class DashPurchases extends ChangeNotifier {
18568+
18569+
@override
18570+
void dispose() {
18571+
- _subscription.cancel();
18572+
iapRepo.removeListener(purchasesUpdate);
18573+
+ _subscription.cancel();
18574+
super.dispose();
18575+
}
18576+
18577+
@@ -126,8 +129,10 @@ class DashPurchases extends ChangeNotifier {
18578+
headers: headers,
18579+
);
18580+
if (response.statusCode == 200) {
18581+
+ print('Successfully verified purchase');
18582+
return true;
18583+
} else {
18584+
+ print('failed request: ${response.statusCode} - ${response.body}');
18585+
return false;
18586+
}
18587+
}
18588+
@@ -137,7 +142,7 @@ class DashPurchases extends ChangeNotifier {
18589+
}
18590+
18591+
void _updateStreamOnError(dynamic error) {
18592+
- //Handle error here
18593+
+ print(error);
18594+
}
18595+
18596+
void purchasesUpdate() {
18597+
@@ -158,21 +163,21 @@ class DashPurchases extends ChangeNotifier {
18598+
// purchases page.
18599+
if (iapRepo.hasActiveSubscription) {
18600+
counter.applyPaidMultiplier();
18601+
- for (var element in subscriptions) {
18602+
+ for (final element in subscriptions) {
18603+
_updateStatus(element, ProductStatus.purchased);
18604+
}
18605+
} else {
18606+
counter.removePaidMultiplier();
18607+
- for (var element in subscriptions) {
18608+
+ for (final element in subscriptions) {
18609+
_updateStatus(element, ProductStatus.purchasable);
18610+
}
18611+
}
18612+
18613+
- // Set the Dash beautifier and show/hide purchased on
18614+
+ // Set the dash beautifier and show/hide purchased on
18615+
// the purchases page.
18616+
if (iapRepo.hasUpgrade != _beautifiedDashUpgrade) {
18617+
_beautifiedDashUpgrade = iapRepo.hasUpgrade;
18618+
- for (var element in upgrades) {
18619+
+ for (final element in upgrades) {
18620+
_updateStatus(
18621+
element,
18622+
_beautifiedDashUpgrade
18623+
@@ -184,8 +189,8 @@ class DashPurchases extends ChangeNotifier {
18624+
}
18625+
18626+
void _updateStatus(PurchasableProduct product, ProductStatus status) {
18627+
- if (product.status != ProductStatus.purchased) {
18628+
- product.status = ProductStatus.purchased;
18629+
+ if (product.status != status) {
18630+
+ product.status = status;
18631+
notifyListeners();
18632+
}
18633+
}
18634+
- name: mkdir dart-backend/test
18635+
mkdir: steps/dart-backend/test
18636+
- name: Add dart-backend/test/firebase_backend_dart_test.dart
18637+
path: steps/dart-backend/test/firebase_backend_dart_test.dart
18638+
replace-contents: |
18639+
import 'package:firebase_backend_dart/google_play_purchase_handler.dart';
18640+
import 'package:firebase_backend_dart/products.dart';
18641+
import 'package:test/test.dart';
18642+
18643+
import '../bin/server.dart';
18644+
18645+
void main() {
18646+
test('extractOrderId with subscription suffix', () {
18647+
final orderId = extractOrderId('googleplay_GPA.3391-7354-8735-85865..0');
18648+
expect(orderId, 'googleplay_GPA.3391-7354-8735-85865');
18649+
});
18650+
18651+
test('extractOrderId without subscription suffix', () {
18652+
final orderId = extractOrderId('googleplay_GPA.3391-7354-8735-85865');
18653+
expect(orderId, 'googleplay_GPA.3391-7354-8735-85865');
18654+
});
18655+
18656+
test('Parse Purchase data should fail', () {
18657+
expect(() => getPurchaseData('{}'), throwsFormatException);
18658+
});
18659+
18660+
test('Parse Purchase data should succeed', () {
18661+
final (
18662+
:userId,
18663+
:source,
18664+
productData: ProductData(:productId, :type),
18665+
:token,
18666+
) = getPurchaseData({
18667+
'userId': 'USER_ID',
18668+
'source': 'google_play',
18669+
'productId': 'dash_consumable_2k',
18670+
'verificationData': 'TOKEN',
18671+
});
18672+
expect(userId, 'USER_ID');
18673+
expect(source, 'google_play');
18674+
expect(productId, 'dash_consumable_2k');
18675+
expect(type, ProductType.nonSubscription);
18676+
expect(token, 'TOKEN');
18677+
});
18678+
}
18679+
- name: Copy to complete
18680+
copydir:
18681+
from: steps
18682+
to: complete
18683+
1850718684
- name: Cleanup
1850818685
steps:
1850918686
- name: Remove steps

in_app_purchases/complete/app/.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
.buildlog/
99
.history
1010
.svn/
11+
migrate_working_dir/
1112

1213
# IntelliJ related
1314
*.iml
@@ -26,14 +27,10 @@
2627
.dart_tool/
2728
.flutter-plugins
2829
.flutter-plugins-dependencies
29-
.packages
3030
.pub-cache/
3131
.pub/
3232
/build/
3333

34-
# Web related
35-
lib/generated_plugin_registrant.dart
36-
3734
# Symbolication related
3835
app.*.symbols
3936

in_app_purchases/complete/app/android/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ gradle-wrapper.jar
77
GeneratedPluginRegistrant.java
88

99
# Remember to never publicly share your keystore.
10-
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
10+
# See https://flutter.dev/to/reference-keystore
1111
key.properties
12+
**/*.keystore
13+
**/*.jks
Lines changed: 21 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,44 @@
1-
def localProperties = new Properties()
2-
def localPropertiesFile = rootProject.file('local.properties')
3-
if (localPropertiesFile.exists()) {
4-
localPropertiesFile.withReader('UTF-8') { reader ->
5-
localProperties.load(reader)
6-
}
7-
}
8-
9-
def flutterRoot = localProperties.getProperty('flutter.sdk')
10-
if (flutterRoot == null) {
11-
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12-
}
13-
14-
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15-
if (flutterVersionCode == null) {
16-
flutterVersionCode = '1'
17-
}
18-
19-
def flutterVersionName = localProperties.getProperty('flutter.versionName')
20-
if (flutterVersionName == null) {
21-
flutterVersionName = '1.0'
1+
plugins {
2+
id "com.android.application"
3+
id "kotlin-android"
4+
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5+
id "dev.flutter.flutter-gradle-plugin"
226
}
237

24-
apply plugin: 'com.android.application'
25-
apply plugin: 'kotlin-android'
26-
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27-
288
android {
29-
compileSdkVersion 31
9+
namespace = "com.example.dashclicker"
10+
compileSdk = flutter.compileSdkVersion
11+
ndkVersion = flutter.ndkVersion
3012

3113
compileOptions {
32-
sourceCompatibility JavaVersion.VERSION_11
33-
targetCompatibility JavaVersion.VERSION_11
14+
sourceCompatibility = JavaVersion.VERSION_1_8
15+
targetCompatibility = JavaVersion.VERSION_1_8
3416
}
3517

3618
kotlinOptions {
37-
jvmTarget = '11'
38-
}
39-
40-
sourceSets {
41-
main.java.srcDirs += 'src/main/kotlin'
19+
jvmTarget = JavaVersion.VERSION_1_8
4220
}
4321

4422
defaultConfig {
45-
applicationId "com.example.dashclicker"
46-
minSdkVersion 19
47-
targetSdkVersion 30
48-
versionCode flutterVersionCode.toInteger()
49-
versionName flutterVersionName
50-
multiDexEnabled true
23+
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24+
applicationId = "com.example.dashclicker"
25+
// You can update the following values to match your application needs.
26+
// For more information, see: https://flutter.dev/to/review-gradle-config.
27+
minSdk = flutter.minSdkVersion
28+
targetSdk = flutter.targetSdkVersion
29+
versionCode = flutter.versionCode
30+
versionName = flutter.versionName
5131
}
5232

5333
buildTypes {
5434
release {
5535
// TODO: Add your own signing config for the release build.
5636
// Signing with the debug keys for now, so `flutter run --release` works.
57-
signingConfig signingConfigs.debug
37+
signingConfig = signingConfigs.debug
5838
}
5939
}
6040
}
6141

6242
flutter {
63-
source '../..'
43+
source = "../.."
6444
}
65-
66-
dependencies {
67-
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
68-
}
69-
70-
apply plugin: 'com.google.gms.google-services'

in_app_purchases/complete/app/android/app/src/debug/AndroidManifest.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="com.example.dashclicker">
3-
<!-- Flutter needs it to communicate with the running application
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<!-- The INTERNET permission is required for development. Specifically,
3+
the Flutter tool needs it to communicate with the running application
44
to allow setting breakpoints, to provide hot reload, etc.
55
-->
66
<uses-permission android:name="android.permission.INTERNET"/>

0 commit comments

Comments
 (0)