Selaa lähdekoodia

Make free plan configurable

Vishnu Mohandas 4 vuotta sitten
vanhempi
commit
f986c9ae29

+ 122 - 0
lib/models/billing_plan.dart

@@ -1,5 +1,127 @@
 import 'dart:convert';
 
+import 'package:flutter/foundation.dart';
+
+class BillingPlans {
+  final List<BillingPlan> plans;
+  final FreePlan freePlan;
+
+  BillingPlans({
+    this.plans,
+    this.freePlan,
+  });
+
+  BillingPlans copyWith({
+    List<BillingPlan> plans,
+    FreePlan freePlan,
+  }) {
+    return BillingPlans(
+      plans: plans ?? this.plans,
+      freePlan: freePlan ?? this.freePlan,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'plans': plans?.map((x) => x?.toMap())?.toList(),
+      'freePlan': freePlan?.toMap(),
+    };
+  }
+
+  factory BillingPlans.fromMap(Map<String, dynamic> map) {
+    if (map == null) return null;
+
+    return BillingPlans(
+      plans: List<BillingPlan>.from(
+          map['plans']?.map((x) => BillingPlan.fromMap(x))),
+      freePlan: FreePlan.fromMap(map['freePlan']),
+    );
+  }
+
+  String toJson() => json.encode(toMap());
+
+  factory BillingPlans.fromJson(String source) =>
+      BillingPlans.fromMap(json.decode(source));
+
+  @override
+  String toString() => 'BillingPlans(plans: $plans, freePlan: $freePlan)';
+
+  @override
+  bool operator ==(Object o) {
+    if (identical(this, o)) return true;
+
+    return o is BillingPlans &&
+        listEquals(o.plans, plans) &&
+        o.freePlan == freePlan;
+  }
+
+  @override
+  int get hashCode => plans.hashCode ^ freePlan.hashCode;
+}
+
+class FreePlan {
+  final int storage;
+  final int duration;
+  final String period;
+  FreePlan({
+    this.storage,
+    this.duration,
+    this.period,
+  });
+
+  FreePlan copyWith({
+    int storage,
+    int duration,
+    String period,
+  }) {
+    return FreePlan(
+      storage: storage ?? this.storage,
+      duration: duration ?? this.duration,
+      period: period ?? this.period,
+    );
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'storage': storage,
+      'duration': duration,
+      'period': period,
+    };
+  }
+
+  factory FreePlan.fromMap(Map<String, dynamic> map) {
+    if (map == null) return null;
+
+    return FreePlan(
+      storage: map['storage'],
+      duration: map['duration'],
+      period: map['period'],
+    );
+  }
+
+  String toJson() => json.encode(toMap());
+
+  factory FreePlan.fromJson(String source) =>
+      FreePlan.fromMap(json.decode(source));
+
+  @override
+  String toString() =>
+      'FreePlan(storage: $storage, duration: $duration, period: $period)';
+
+  @override
+  bool operator ==(Object o) {
+    if (identical(this, o)) return true;
+
+    return o is FreePlan &&
+        o.storage == storage &&
+        o.duration == duration &&
+        o.period == period;
+  }
+
+  @override
+  int get hashCode => storage.hashCode ^ duration.hashCode ^ period.hashCode;
+}
+
 class BillingPlan {
   final String id;
   final String androidID;

+ 3 - 7
lib/services/billing_service.dart

@@ -24,7 +24,7 @@ class BillingService {
   bool _isOnSubscriptionPage = false;
 
   SharedPreferences _prefs;
-  Future<List<BillingPlan>> _future;
+  Future<BillingPlans> _future;
 
   Future<void> init() async {
     _prefs = await SharedPreferences.getInstance();
@@ -53,16 +53,12 @@ class BillingService {
     });
   }
 
-  Future<List<BillingPlan>> getBillingPlans() {
+  Future<BillingPlans> getBillingPlans() {
     if (_future == null) {
       _future = _dio
           .get(_config.getHttpEndpoint() + "/billing/plans")
           .then((response) {
-        final plans = List<BillingPlan>();
-        for (final plan in response.data["plans"]) {
-          plans.add(BillingPlan.fromMap(plan));
-        }
-        return plans;
+        return BillingPlans.fromMap(response.data);
       });
     }
     return _future;

+ 3 - 3
lib/ui/email_entry_page.dart

@@ -229,7 +229,7 @@ class PricingWidget extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return FutureBuilder<List<BillingPlan>>(
+    return FutureBuilder<BillingPlans>(
       future: BillingService.instance.getBillingPlans(),
       builder: (BuildContext context, AsyncSnapshot snapshot) {
         if (snapshot.hasData) {
@@ -242,9 +242,9 @@ class PricingWidget extends StatelessWidget {
     );
   }
 
-  Container _buildPlans(BuildContext context, List<BillingPlan> plans) {
+  Container _buildPlans(BuildContext context, BillingPlans plans) {
     final planWidgets = List<BillingPlanWidget>();
-    for (final plan in plans) {
+    for (final plan in plans.plans) {
       planWidgets.add(BillingPlanWidget(plan));
     }
     return Container(

+ 11 - 6
lib/ui/subscription_page.dart

@@ -131,7 +131,7 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
   }
 
   Widget _getBody(final appBarSize) {
-    return FutureBuilder<List<BillingPlan>>(
+    return FutureBuilder<BillingPlans>(
       future: _billingService.getBillingPlans(),
       builder: (BuildContext context, AsyncSnapshot snapshot) {
         if (snapshot.hasData) {
@@ -146,9 +146,9 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
   }
 
   Widget _buildPlans(
-      BuildContext context, List<BillingPlan> plans, final appBarSize) {
+      BuildContext context, BillingPlans plans, final appBarSize) {
     final planWidgets = List<Widget>();
-    for (final plan in plans) {
+    for (final plan in plans.plans) {
       final productID = Platform.isAndroid ? plan.androidID : plan.iosID;
       if (productID == null || productID.isEmpty) {
         continue;
@@ -376,7 +376,7 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
     if (widget.isOnboarding &&
         (_currentSubscription == null ||
             _currentSubscription.productID == kFreeProductID)) {
-      widgets.addAll([_getSkipButton()]);
+      widgets.addAll([_getSkipButton(plans.freePlan)]);
     }
     return SingleChildScrollView(
       child: Container(
@@ -389,7 +389,7 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
     );
   }
 
-  GestureDetector _getSkipButton() {
+  GestureDetector _getSkipButton(FreePlan plan) {
     return GestureDetector(
       behavior: HitTestBehavior.translucent,
       child: Container(
@@ -418,7 +418,12 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
             mainAxisSize: MainAxisSize.min,
             children: [
               Text(
-                "you will only be able to backup 100 MB for the next 14 days",
+                "you will only be able to backup " +
+                    convertBytesToReadableFormat(plan.storage) +
+                    " for the next " +
+                    plan.duration.toString() +
+                    " " +
+                    plan.period,
                 style: TextStyle(
                   height: 1.4,
                 ),

+ 11 - 0
lib/utils/data_util.dart

@@ -2,3 +2,14 @@ double convertBytesToGBs(final int bytes, {int precision = 2}) {
   return double.parse(
       (bytes / (1024 * 1024 * 1024)).toStringAsFixed(precision));
 }
+
+final kStorageUnits = ["bytes", "KB", "MB", "GB", "TB"];
+
+String convertBytesToReadableFormat(int bytes) {
+  int storageUnitIndex = 0;
+  while (bytes >= 1024) {
+    storageUnitIndex++;
+    bytes = (bytes / 1024).round();
+  }
+  return bytes.toString() + " " + kStorageUnits[storageUnitIndex];
+}