4
2
Fork 0

Merge remote-tracking branch 'origin/master' into WIP#feat#heartbeat-manager

pull/37/head
UnicodingUnicorn 2019-03-17 17:56:46 +08:00
commit 7cca6f3740
11 changed files with 160 additions and 56 deletions

View File

@ -2,5 +2,5 @@
final String baseUrlCore = "http://localhost/core";
final String baseUrlSignaling = "http://localhost/signal";
final String baseUrlLogin = "http://localhost/login";
final String baseUrlLogin = "http://localhost:1837";
final String globalUserId = "u-fb91825f564a3cc110f11836fedea6f4";

View File

@ -1,18 +1,26 @@
import "dart:async";
import "package:http/http.dart" as http;
import "dart:io";
import "dart:convert";
import "../models/user_model.dart";
import "../services/cache_http.dart";
import "../services/login_manager.dart";
import "../../settings.dart";
class ContactApiProvider {
CacheHttp cache = CacheHttp();
LoginManager loginManager = LoginManager();
Future<List<User>> fetchContacts() async {
final jwt = await loginManager.getToken();
try {
final responseBody =
await this.cache.fetch("$baseUrlCore/user/$globalUserId/contact/");
await this.cache.fetch("$baseUrlCore/user/contact", headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
});
return jsonDecode(responseBody)
.map<User>((user) => User.fromJson(user))
.toList();
@ -21,7 +29,14 @@ class ContactApiProvider {
}
}
void createContact(User user) async =>
await http.post("$baseUrlCore/user/contact",
headers: {"Content-Type": "application/json"}, body: user.toJson);
void createContact(User user) async {
final jwt = await loginManager.getToken();
await http.post("$baseUrlCore/user/contact",
headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
},
body: user.toJson);
}
}

View File

@ -1,33 +1,47 @@
import "dart:async";
import "package:http/http.dart" as http;
import "dart:io";
import "dart:convert";
import "../models/conversation_model.dart";
import "../models/user_model.dart";
import "../services/cache_http.dart";
import "../services/login_manager.dart";
import "../../settings.dart";
class ConversationApiProvider {
CacheHttp cache = CacheHttp();
LoginManager loginManager = LoginManager();
Future<Conversation> createConversation(String title) async {
final jwt = await loginManager.getToken();
final response = await http.post("$baseUrlCore/user/conversation",
headers: {"Content-Type": "application/json"},
headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
},
body: jsonEncode({"title": title}));
return Conversation.fromJson(jsonDecode(response.body));
}
void deleteConversation(String id) async =>
await http.delete("$baseUrlCore/user/conversation/$id");
void deleteConversation(String id) async {
final jwt = await loginManager.getToken();
await http.delete("$baseUrlCore/user/conversation/$id", headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
});
}
Future<List<Conversation>> fetchConversations() async {
final jwt = await loginManager.getToken();
print("jwt: ${jwt}");
try {
final responseBody = await this
.cache
.fetch("$baseUrlCore/user/$globalUserId/conversation/");
final responseBody =
await this.cache.fetch("$baseUrlCore/user/conversation", headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
});
return jsonDecode(responseBody)
.map<Conversation>(
(conversation) => Conversation.fromJson(conversation))
@ -38,9 +52,14 @@ class ConversationApiProvider {
}
Future<Conversation> fetchConversation(String id) async {
final jwt = await loginManager.getToken();
try {
final responseBody =
await this.cache.fetch("$baseUrlCore/user/conversation/$id");
final responseBody = await this
.cache
.fetch("$baseUrlCore/user/conversation/$id", headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
});
return Conversation.fromJson(jsonDecode(responseBody));
} catch (e) {
throw e;
@ -48,10 +67,14 @@ class ConversationApiProvider {
}
Future<List<User>> fetchConversationMembers(String id) async {
final jwt = await loginManager.getToken();
try {
final responseBody = await this
.cache
.fetch("$baseUrlCore/user/$globalUserId/conversation/$id/member/");
.fetch("$baseUrlCore/user/conversation/$id/member", headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
});
return jsonDecode(responseBody)
.map<User>((user) => User.fromJson(user))
.toList();

View File

@ -1,16 +1,15 @@
import "dart:async";
import "package:http/http.dart" as http;
import "dart:convert";
import "../models/user_model.dart";
import "dart:io";
import "../../settings.dart";
class LoginApiProvider {
Future<String> initAuthentication(User user) async {
Future<String> initAuthentication(String phoneNumber) async {
final response = await http.post("$baseUrlLogin/init",
headers: {"Content-Type": "application/json"},
body: jsonEncode({"phone_number": user.phoneNumber}));
headers: {HttpHeaders.contentTypeHeader: "application/json"},
body: jsonEncode({"phone_number": phoneNumber}));
if (response.statusCode == 400 || response.statusCode == 500) {
throw response.statusCode;
}
@ -19,9 +18,11 @@ class LoginApiProvider {
Future<String> verifyOtp(String otp, String nonce, String clientid) async {
final response = await http.post("$baseUrlLogin/verify",
headers: {"Content-Type": "application/json"},
headers: {HttpHeaders.contentTypeHeader: "application/json"},
body: jsonEncode({"code": otp, "nonce": nonce, "clientid": clientid}));
if (response.statusCode == 400 || response.statusCode == 404 || response.statusCode == 500) {
if (response.statusCode == 400 ||
response.statusCode == 404 ||
response.statusCode == 500) {
throw response.statusCode;
}
return response.body;
@ -29,7 +30,7 @@ class LoginApiProvider {
Future<String> loginTest(String userId, String clientId) async {
final response = await http.post("$baseUrlLogin/login",
headers: {"Content-Type": "application/json"},
headers: {HttpHeaders.contentTypeHeader: "application/json"},
body: jsonEncode({"userid": userId, "clientid": clientId}));
return response.body;

View File

@ -1,26 +1,38 @@
import "dart:async";
import "dart:convert";
import "dart:io";
import "package:http/http.dart" as http;
import "../models/user_model.dart";
import "../services/cache_http.dart";
import "../services/login_manager.dart";
import "../../settings.dart";
class UserApiProvider {
CacheHttp cache;
CacheHttp cache = CacheHttp();
LoginManager loginManager = LoginManager();
Future<User> createUser(User user) async {
// Prob need to add the headers
final jwt = loginManager.getToken();
final response = await http.post("$baseUrlCore/user",
headers: {"Content-Type": "application/json"}, body: user.toJson());
headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
},
body: user.toJson());
return User.fromJson(jsonDecode(response.body));
}
Future<User> fetchUserByPhone(String phoneNumber) async {
final jwt = loginManager.getToken();
try {
final responseBody =
await this.cache.fetch("$baseUrlCore/user?phone_number=$phoneNumber");
final responseBody = await this
.cache
.fetch("$baseUrlCore/user?phone_number=$phoneNumber", headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
});
return User.fromJson(jsonDecode(responseBody));
} catch (e) {
throw e;
@ -28,8 +40,13 @@ class UserApiProvider {
}
Future<User> fetchUserById(String id) async {
final jwt = loginManager.getToken();
try {
final responseBody = await this.cache.fetch("$baseUrlCore/user/id/$id");
final responseBody =
await this.cache.fetch("$baseUrlCore/user/id/$id", headers: {
HttpHeaders.contentTypeHeader: "application/json",
HttpHeaders.authorizationHeader: "Bearer $jwt"
});
return User.fromJson(jsonDecode(responseBody));
} catch (e) {
throw e;

View File

@ -29,13 +29,14 @@ class CacheHttp {
}
// Returns raw response body
Future<String> fetch(String url, {bool update = false}) async {
Future<String> fetch(String url,
{bool update = false, Map<String, String> headers = const {}}) async {
if (!this.hasInit) {
this.hasInit = true;
await this.init();
}
try {
final response = await http.get(url);
final response = await http.get(url, headers: headers);
if (response.statusCode < 200 || response.statusCode >= 300) {
// Unsuccessful response, use cache
final body = await this.getCache(url);

View File

@ -1,20 +1,15 @@
import "../resources/login_api_provider.dart";
import "../models/user_model.dart";
import "../resources/user_api_provider.dart";
import "../../settings.dart";
import 'package:shared_preferences/shared_preferences.dart';
class LoginManager {
final loginApiProvider = LoginApiProvider();
User user;
String clientid;
String nonce;
LoginManager(User user, String clientid) {
this.user = user;
this.clientid = clientid;
this.nonce = "";
}
// Returns JWT, blank string if nothing is found
Future<String> getToken() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
@ -23,23 +18,35 @@ class LoginManager {
}
// Throws error status code if it occurs
Future<void> initAuthentication(User user) async {
Future<void> initAuthentication(String phoneNumber) async {
try {
final nonce = await loginApiProvider.initAuthentication(user);
final nonce = await loginApiProvider.initAuthentication(phoneNumber);
this.nonce = nonce;
} catch(e) {
} catch (e) {
throw e;
}
}
// Throws error status code if it occurs, otherwise returns jwt
Future<String> processOTP(String otp) async {
Future<String> processOtp(String otp) async {
try {
final jwt = await loginApiProvider.verifyOtp(otp, this.nonce, this.clientid);
final jwt =
await loginApiProvider.verifyOtp(otp, this.nonce, this.clientid);
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString("token", jwt);
return jwt;
} catch(e) {
} catch (e) {
throw e;
}
}
Future<String> loginTest() async {
try {
final jwt = await loginApiProvider.loginTest(globalUserId, "1");
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString("token", jwt);
return jwt;
} catch (e) {
throw e;
}
}

View File

@ -1,12 +1,14 @@
import "package:flutter/material.dart";
import "package:flutter_svg/flutter_svg.dart";
import "../../services/login_manager.dart";
import "./widgets/welcome_page.dart";
import "./widgets/login_page.dart";
import "./widgets/otp_page.dart";
class Welcome extends StatelessWidget {
final String logo = "assets/logo.png";
final LoginManager loginManager = LoginManager();
final Map<String, String> user = {};
@override
Widget build(BuildContext context) {
@ -42,10 +44,13 @@ class Welcome extends StatelessWidget {
builder = (BuildContext _) => WelcomePage();
break;
case "welcome/login":
builder = (BuildContext _) => LoginPage();
builder = (BuildContext _) =>
LoginPage(loginManager: loginManager);
break;
case "welcome/otp":
builder = (BuildContext _) => OtpPage(buttonCallback: () {
builder = (BuildContext _) =>
OtpPage(buttonCallback: (String otp) async {
// loginManager.processOtp(otp); disabled for testing
Navigator.of(context).pushNamed("/home");
});
break;

View File

@ -2,10 +2,27 @@ import "package:flutter/material.dart";
import "package:flutter_svg/flutter_svg.dart";
import "../../widgets/text_button.dart";
import "../../../services/login_manager.dart";
import "phone_input.dart";
class LoginPage extends StatelessWidget {
class LoginPage extends StatefulWidget {
final LoginManager loginManager;
LoginPage({@required this.loginManager});
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final String phoneSvg = "assets/phoneno.svg";
final controller = TextEditingController();
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
@ -30,13 +47,16 @@ class LoginPage extends StatelessWidget {
.title
.copyWith(fontWeight: FontWeight.w400)),
Padding(
padding: EdgeInsets.only(top: 20.0), child: PhoneInput()),
padding: EdgeInsets.only(top: 20.0),
child: PhoneInput(controller: controller)),
]),
Spacer(),
TextButton(
text: "Continue",
onClickCallback: () =>
Navigator.pushNamed(context, 'welcome/otp')),
onClickCallback: () {
widget.loginManager.loginTest();
Navigator.pushNamed(context, 'welcome/otp');
}),
]));
}
}

View File

@ -5,14 +5,21 @@ import "package:flutter_svg/flutter_svg.dart";
import "../../widgets/text_button.dart";
// Callback types
typedef void ButtonCallback();
typedef void ButtonCallback(String otp);
class OtpPage extends StatelessWidget {
final String phoneSvg = "assets/authenticate.svg";
class OtpPage extends StatefulWidget {
final ButtonCallback buttonCallback;
OtpPage({@required this.buttonCallback});
@override
_OtpPageState createState() => _OtpPageState();
}
class _OtpPageState extends State<OtpPage> {
final String phoneSvg = "assets/authenticate.svg";
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Padding(
@ -39,6 +46,7 @@ class OtpPage extends StatelessWidget {
padding: EdgeInsets.only(top: 20.0),
child: Center(
child: PinCodeTextField(
controller: controller,
highlight: true,
highlightColor: Colors.white,
/*hideCharacter: true,*/
@ -52,7 +60,9 @@ class OtpPage extends StatelessWidget {
Theme.of(context).accentTextTheme.display3))),
]),
Spacer(),
TextButton(text: "Done", onClickCallback: () => buttonCallback()),
TextButton(
text: "Done",
onClickCallback: () => widget.buttonCallback(controller.text)),
]));
}
}

View File

@ -1,6 +1,10 @@
import "package:flutter/material.dart";
class PhoneInput extends StatelessWidget {
final TextEditingController controller;
PhoneInput({@required this.controller});
@override
Widget build(BuildContext context) {
return ClipRRect(
@ -21,6 +25,7 @@ class PhoneInput extends StatelessWidget {
)),
Expanded(
child: TextField(
controller: controller,
autocorrect: false,
cursorWidth: 2.0,
cursorColor: Colors.white,