Skip to content

Commit d6f79fa

Browse files
authored
release: 1.0.0 πŸŽ‰ (#50)
* fix: prepare for 0.2.1 (#48) * fix(functions): stats contacts regression * fix: measurement creation for new contacts * fix: no decimals in lower android APIs * refactor: homepage landscape mode * chore: ui clean up * fix: material color * chore: update TASKS * release: prepare for 1.0 (#49) * chore: base template setup * feat: initial proposal for rate limit template * feat: first draft access denied template * chore(models): account status * chore: rework templates * refactor(redux): account status * refactor(home): with status templates * feat: implement premium accounts * feat: implement notice * chore: update notice on move to premium * feat: added common settings * chore: code clean up * chore: update TASKS * release: pre 1.0.0 ✨ * chore(functions): default account data * chore: code clean up * chore: added get_version * feat: had to bump to 1.0.1 * feat: ok, so no more 1.0.1 still on the road map to 1.0.0 * chore: update README
1 parent 0724a8f commit d6f79fa

36 files changed

+744
-184
lines changed

β€ŽREADME.mdβ€Ž

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
<img src="./assets/images/logo.png" style="margin: auto" width="90" />
22

3-
# TailorMade
3+
# TailorMade: Managing a Fashion designer's daily routine.
44

5-
A Flutter experiment for managing a Fashion designer's daily routine. Logo, Design & Concept by Me.
5+
TailorMade is what actually started out as an experiment with [Flutter](https://flutter.io/), [flutter_redux](https://github.com/brianegan/flutter_redux) and [Firebase Cloud Functions](https://github.com/flutter/plugins/tree/master/packages/cloud_functions) but instead turned out to be a valuable tool for managing a Fashion designer's daily routine. It is clean, easy on the eyes and overall has a very smooth feel. It also handles offline use cases with Firebase Cloud. Logo, Design & Concept by Me.
66

7-
> Android-only support
7+
<div>
8+
<a href='https://play.google.com/store/apps/details?id=io.github.jogboms.tailormade'><img alt='Get it on Google Play' src='./screenshots/google_play.png' height='40px'/></a>
9+
</div>
810

911
## Tools
1012

1113
1. Firebase Auth
1214
2. Firebase Cloud Firestore
1315
3. Firebase Cloud Functions
1416
4. Firebase Storage
15-
5. RxDart
16-
6. Redux
17-
7. Redux Epics
17+
5. Google SignIn
18+
6. RxDart
19+
7. Flutter Redux
20+
8. Redux Epics
21+
9. Image Picker
22+
10. Photo View
23+
11. Cached Network Image
24+
12. Flutter SpinKit
25+
13. Flutter Get Version
26+
14. Flutter Masked Text
1827

1928
For a full description of OSS used, see pubspec.yaml
2029

β€ŽTASKS.todoβ€Ž

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
PENDING:
22
☐ delete-able payment
3-
☐ delete-able images
4-
☐ implement share payment + image
5-
☐ filter + search jobs & contacts
6-
☐ create a new contact from phone contact
7-
☐ Collect account details on account creation
8-
☐ Generate invoice & share as SMS containing link to pay on paystack
9-
☐ Firebase function on successful payments w/ push notification
3+
☐ delete-able images
4+
☐ implement share payment + image
5+
☐ filter + search jobs & contacts
6+
☐ create a new contact from phone contact @high
7+
☐ Collect account details on account creation
8+
☐ Generate invoice & share as SMS containing link to pay on paystack
9+
☐ Firebase function on successful payments w/ push notification
10+
☐ On account create, send personal email + email to user @high
1011

1112
COMPLETED:
13+
βœ” Notice modal + indicator on home page @done(18-07-17 11:54)
14+
βœ” add rate limit danger + access blocked screens @critical @done(18-07-17 10:31)
15+
βœ” landscape scale on homepage @low @done(18-07-16 11:56)
16+
βœ” no decimals in measurements @critical @done(18-07-16 10:28)
17+
βœ” fix measurement creation on new contact @critical @done(18-07-16 10:20)
1218
βœ” remodel w/ authID @done(18-07-15 14:43)
1319
βœ” scope storage path to accounts @high @done(18-07-13 16:19)
1420
βœ” update stats db on creation @high @done(18-07-10 16:39)

β€Žandroid/.gitignoreβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
/captures
1010
GeneratedPluginRegistrant.java
1111
google-services.json
12+
key.properties

β€Žandroid/app/build.gradleβ€Ž

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ if (flutterRoot == null) {
1414
apply plugin: 'com.android.application'
1515
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
1616

17+
def keystorePropertiesFile = rootProject.file("key.properties")
18+
def keystoreProperties = new Properties()
19+
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
20+
21+
ext.versionMajor = 1
22+
ext.versionMinor = 0
23+
ext.versionPatch = 0
24+
ext.versionClassifier = null
25+
ext.isSnapshot = false
26+
ext.minimumSdkVersion = 16
27+
1728
android {
1829
compileSdkVersion 27
1930

@@ -25,16 +36,28 @@ android {
2536
applicationId "io.github.jogboms.tailormade"
2637
minSdkVersion 16
2738
targetSdkVersion 27
28-
versionCode 1
29-
versionName "1.0"
39+
versionCode generateVersionCode()
40+
versionName generateVersionName()
3041
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
3142
}
3243

44+
signingConfigs {
45+
release {
46+
keyAlias keystoreProperties['keyAlias']
47+
keyPassword keystoreProperties['keyPassword']
48+
storeFile file(keystoreProperties['storeFile'])
49+
storePassword keystoreProperties['storePassword']
50+
}
51+
}
52+
3353
buildTypes {
3454
release {
35-
// TODO: Add your own signing config for the release build.
36-
// Signing with the debug keys for now, so `flutter run --release` works.
37-
signingConfig signingConfigs.debug
55+
signingConfig signingConfigs.release
56+
57+
// minifyEnabled true
58+
// useProguard true
59+
60+
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
3861
}
3962
}
4063

@@ -52,6 +75,24 @@ android {
5275
}
5376
}
5477

78+
private Integer generateVersionCode() {
79+
return ext.versionMajor * 10000 + ext.versionMinor * 100 + ext.versionPatch
80+
}
81+
82+
private String generateVersionName() {
83+
String versionName = "${ext.versionMajor}.${ext.versionMinor}.${ext.versionPatch}"
84+
if (ext.versionClassifier == null) {
85+
if (ext.isSnapshot) {
86+
ext.versionClassifier = "SNAPSHOT"
87+
}
88+
}
89+
90+
if (ext.versionClassifier != null) {
91+
versionName += "-" + ext.versionClassifier
92+
}
93+
return versionName;
94+
}
95+
5596
flutter {
5697
source '../..'
5798
}

β€Žfunctions/functions/src/fn/auth.tsβ€Ž

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ export function _onAuth(onCreate: ChangeState) {
1414
email: user.email,
1515
displayName: user.displayName,
1616
phoneNumber: user.phoneNumber,
17-
photoURL: user.photoURL
17+
photoURL: user.photoURL,
18+
status: 0,
19+
hasPremiumEnabled: false,
20+
notice: "Its amazing to have you here, look around, Enjoy the experience!",
21+
hasReadNotice: false,
1822
});
1923

2024
const stats = db.collection("stats").doc(user.uid);

β€Žfunctions/functions/src/fn/stats_contacts.tsβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { EventContext, firestore } from "firebase-functions";
33
import { isArray } from "util";
44
import { ChangeState } from "../utils";
55

6-
export function _onStatsContacts(onCreate: ChangeState) {
6+
export function _onStatsContacts(state: ChangeState) {
77
return async (
88
snapshot: firestore.DocumentSnapshot,
99
context: EventContext
@@ -20,7 +20,7 @@ export function _onStatsContacts(onCreate: ChangeState) {
2020

2121
return stats.update({
2222
contacts: {
23-
total: total + (onCreate ? count : -count)
23+
total: total + (state === ChangeState.Created ? count : -count)
2424
}
2525
});
2626
};

β€Žlib/main.dartβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class TMApp extends StatelessWidget {
2626
debugShowCheckedModeBanner: false,
2727
title: TMStrings.appName,
2828
theme: new ThemeData(
29+
primaryColor: Colors.white,
2930
accentColor: kAccentColor,
3031
primarySwatch: kPrimarySwatch,
3132
fontFamily: TMFonts.raleway,

β€Žlib/models/account.dartβ€Ž

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ import 'package:cloud_firestore/cloud_firestore.dart';
22
import 'package:flutter/foundation.dart';
33
import 'package:tailor_made/models/main.dart';
44

5+
enum AccountModelStatus { enabled, disabled, warning, pending }
6+
57
class AccountModel extends Model {
68
String uid;
79
String storeName;
810
String email;
911
String displayName;
1012
int phoneNumber;
1113
String photoURL;
14+
AccountModelStatus status;
15+
bool hasPremiumEnabled;
16+
String notice;
17+
bool hasReadNotice;
1218

1319
AccountModel({
1420
@required this.uid,
@@ -17,6 +23,10 @@ class AccountModel extends Model {
1723
@required this.displayName,
1824
@required this.phoneNumber,
1925
@required this.photoURL,
26+
@required this.status,
27+
@required this.hasPremiumEnabled,
28+
@required this.notice,
29+
@required this.hasReadNotice,
2030
});
2131

2232
factory AccountModel.fromJson(Map<String, dynamic> json) {
@@ -28,13 +38,41 @@ class AccountModel extends Model {
2838
displayName: json['displayName'],
2939
phoneNumber: int.tryParse(json['phoneNumber'].toString()),
3040
photoURL: json['photoURL'],
41+
status: AccountModelStatus.values[int.tryParse(json['status'].toString())],
42+
hasPremiumEnabled: json['hasPremiumEnabled'],
43+
notice: json['notice'],
44+
hasReadNotice: json['hasReadNotice'],
3145
);
3246
}
3347

3448
factory AccountModel.fromDoc(DocumentSnapshot doc) {
3549
return AccountModel.fromJson(doc.data)..reference = doc.reference;
3650
}
3751

52+
AccountModel copyWith({
53+
String storeName,
54+
String displayName,
55+
int phoneNumber,
56+
String photoURL,
57+
AccountModelStatus status,
58+
bool hasPremiumEnabled,
59+
String notice,
60+
bool hasReadNotice,
61+
}) {
62+
return new AccountModel(
63+
uid: this.uid,
64+
storeName: storeName ?? this.storeName,
65+
email: this.email,
66+
displayName: displayName ?? this.displayName,
67+
phoneNumber: phoneNumber ?? this.phoneNumber,
68+
photoURL: photoURL ?? this.photoURL,
69+
status: status ?? this.status,
70+
hasPremiumEnabled: hasPremiumEnabled ?? this.hasPremiumEnabled,
71+
notice: notice ?? this.notice,
72+
hasReadNotice: hasReadNotice ?? this.hasReadNotice,
73+
);
74+
}
75+
3876
toMap() {
3977
return {
4078
"uid": uid,
@@ -43,6 +81,10 @@ class AccountModel extends Model {
4381
"displayName": displayName,
4482
"phoneNumber": phoneNumber,
4583
"photoURL": photoURL,
84+
"status": status.index,
85+
"hasPremiumEnabled": hasPremiumEnabled,
86+
"notice": notice,
87+
"hasReadNotice": hasReadNotice,
4688
};
4789
}
4890
}

β€Žlib/models/settings.dartβ€Ž

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class SettingsModel {
2+
String premiumNotice;
3+
4+
SettingsModel({
5+
this.premiumNotice,
6+
});
7+
8+
factory SettingsModel.fromJson(Map<String, dynamic> json) {
9+
assert(json != null);
10+
return new SettingsModel(
11+
premiumNotice: json['premiumNotice'],
12+
);
13+
}
14+
}

β€Žlib/pages/contacts/contact.dartβ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ class _ContactState extends State<ContactPage> {
9494
child: TabBar(
9595
labelStyle: ralewayMedium(14.0),
9696
tabs: [
97-
Tab(child: Text(TABS[0])),
98-
Tab(child: Text(TABS[1])),
99-
Tab(child: Text(TABS[2])),
97+
Tab(child: Text(TABS[0], style: TextStyle(color: Colors.white))),
98+
Tab(child: Text(TABS[1], style: TextStyle(color: Colors.white))),
99+
Tab(child: Text(TABS[2], style: TextStyle(color: Colors.white))),
100100
],
101101
),
102102
),

0 commit comments

Comments
Β (0)