1
0
mirror of https://github.com/git-touch/git-touch synced 2024-12-18 03:09:36 +01:00
git-touch-android-ios-app/lib/models/settings.dart

263 lines
7.0 KiB
Dart
Raw Normal View History

import 'dart:io';
2019-02-07 07:35:19 +01:00
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:uni_links/uni_links.dart';
import 'package:nanoid/nanoid.dart';
import 'package:url_launcher/url_launcher.dart';
2019-02-07 07:35:19 +01:00
// import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
2019-02-07 07:35:19 +01:00
import 'package:shared_preferences/shared_preferences.dart';
2019-02-21 14:21:16 +01:00
// import '../utils/utils.dart';
import '../utils/constants.dart';
2019-03-10 09:09:26 +01:00
import '../utils/utils.dart';
2019-09-08 14:07:35 +02:00
import 'account.dart';
2019-02-21 14:21:16 +01:00
class PlatformType {
static const github = 'github';
static const gitlab = 'gitlab';
}
// abstract class Model<T> {
// Future<T> query(BuildContext context) {
2019-09-08 14:07:35 +02:00
// var settings = Provider.of<SettingsModel>(context);
// switch (settings.platformType) {
// case PlatformType.github:
// return queryGithub(settings);
// case PlatformType.gitlab:
// return queryGitlab(settings);
// default:
// return null;
// }
// }
// Future<T> queryGithub(SettingsProviderState settings);
// Future<T> queryGitlab(SettingsProviderState settings);
// }
2019-01-30 07:46:18 +01:00
2019-09-08 14:07:35 +02:00
class SettingsModel with ChangeNotifier {
2019-09-26 16:14:14 +02:00
static const _apiPrefix = 'https://api.github.com';
2019-02-21 14:21:16 +01:00
2019-09-26 16:14:14 +02:00
List<AccountModel> _accounts;
int activeAccountIndex;
2019-02-07 07:35:19 +01:00
StreamSubscription<Uri> _sub;
bool loading = false;
2019-02-07 07:35:19 +01:00
2019-09-26 16:14:14 +02:00
List<AccountModel> get accounts => _accounts;
bool get ready => _accounts != null;
AccountModel get activeAccount {
if (activeAccountIndex == null || _accounts == null) return null;
return _accounts[activeAccountIndex];
2019-02-07 07:35:19 +01:00
}
2019-01-30 07:46:18 +01:00
2019-09-26 16:14:14 +02:00
String get token => activeAccount.token;
_setAccounts(AccountModel account) async {
// Remove previous if duplicated
List<AccountModel> newAccounts = [];
for (var a in _accounts) {
if (!account.equals(a)) {
newAccounts.add(a);
}
}
newAccounts.add(account);
_accounts = newAccounts;
// Save
final prefs = await SharedPreferences.getInstance();
await prefs.setString(StorageKeys.accounts, json.encode(_accounts));
}
2019-02-07 07:35:19 +01:00
// https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#web-application-flow
Future<void> _onSchemeDetected(Uri uri) async {
await closeWebView();
2019-09-08 14:07:35 +02:00
loading = true;
notifyListeners();
2019-09-26 16:14:14 +02:00
// Get token by code
final res = await http.post(
2019-02-07 07:35:19 +01:00
'https://github.com/login/oauth/access_token',
headers: {
HttpHeaders.acceptHeader: 'application/json',
HttpHeaders.contentTypeHeader: 'application/json',
},
body: json.encode({
'client_id': clientId,
'client_secret': clientSecret,
2019-09-26 16:14:14 +02:00
'code': uri.queryParameters['code'],
'state': _oauthState,
2019-02-07 07:35:19 +01:00
}),
);
2019-09-26 16:14:14 +02:00
final token = json.decode(res.body)['access_token'] as String;
await _loginWithToken(token);
}
2019-02-07 07:35:19 +01:00
Future<void> _loginWithToken(String token) async {
2019-09-26 16:14:14 +02:00
// Get login and avatar url
final queryData = await query('''
2019-02-07 07:35:19 +01:00
{
viewer {
login
avatarUrl
}
}
''', token);
2019-02-07 07:35:19 +01:00
await _setAccounts(AccountModel(
2019-09-26 16:14:14 +02:00
platform: PlatformType.github,
2019-09-26 16:40:53 +02:00
domain: 'https://github.com',
2019-09-26 16:14:14 +02:00
token: token,
login: queryData['viewer']['login'] as String,
avatarUrl: queryData['viewer']['avatarUrl'] as String,
));
2019-02-07 07:35:19 +01:00
2019-09-08 14:07:35 +02:00
loading = false;
notifyListeners();
2019-02-07 07:35:19 +01:00
}
2019-02-21 14:21:16 +01:00
Future<void> loginToGitlab(String domain, String token) async {
try {
2019-09-26 16:14:14 +02:00
loading = true;
notifyListeners();
final res = await http
2019-02-21 14:21:16 +01:00
.get('$domain/api/v4/user', headers: {'Private-Token': token});
2019-09-26 16:14:14 +02:00
final info = json.decode(res.body);
2019-02-21 14:21:16 +01:00
if (info['message'] != null) {
throw info['message'];
}
await _setAccounts(AccountModel(
2019-09-26 16:14:14 +02:00
platform: PlatformType.gitlab,
domain: domain,
token: token,
login: info['username'] as String,
avatarUrl: info['avatar_url'] as String,
));
2019-02-21 14:21:16 +01:00
} catch (err) {
print(err);
// TODO: show errors
} finally {
2019-09-08 14:07:35 +02:00
loading = false;
notifyListeners();
2019-02-21 14:21:16 +01:00
}
}
2019-09-08 14:07:35 +02:00
void init() async {
2019-09-26 16:14:14 +02:00
// Listen scheme
2019-09-08 14:07:35 +02:00
_sub = getUriLinksStream().listen(_onSchemeDetected, onError: (err) {
print(err);
});
var prefs = await SharedPreferences.getInstance();
2019-02-07 07:35:19 +01:00
2019-09-26 16:14:14 +02:00
// Read accounts
2019-02-21 14:21:16 +01:00
try {
2019-09-26 16:14:14 +02:00
String str = prefs.getString(StorageKeys.accounts);
print('read accounts: $str');
_accounts = (json.decode(str ?? '[]') as List)
.map((item) => AccountModel.fromJson(item))
.toList();
2019-02-21 14:21:16 +01:00
} catch (err) {
print(err);
2019-09-26 16:14:14 +02:00
_accounts = [];
2019-02-21 14:21:16 +01:00
}
2019-09-08 14:07:35 +02:00
notifyListeners();
2019-02-07 07:35:19 +01:00
}
2019-09-26 16:14:14 +02:00
void setActiveAccountIndex(int index) {
activeAccountIndex = index;
2019-09-08 14:07:35 +02:00
notifyListeners();
2019-02-07 07:35:19 +01:00
}
Map<String, String> get _headers =>
{HttpHeaders.authorizationHeader: 'token $token'};
// http timeout
var _timeoutDuration = Duration(seconds: 10);
// var _timeoutDuration = Duration(seconds: 1);
2019-02-07 07:35:19 +01:00
Future<dynamic> query(String query, [String _token]) async {
if (_token == null) {
_token = token;
}
if (_token == null) {
2019-09-26 16:14:14 +02:00
throw 'token is null';
2019-02-07 07:35:19 +01:00
}
final res = await http
2019-09-08 14:07:35 +02:00
.post(_apiPrefix + '/graphql',
headers: {
HttpHeaders.authorizationHeader: 'token $_token',
HttpHeaders.contentTypeHeader: 'application/json'
},
body: json.encode({'query': query}))
.timeout(_timeoutDuration);
2019-03-10 16:34:34 +01:00
// print(res.body);
2019-02-07 07:35:19 +01:00
final data = json.decode(res.body);
if (data['errors'] != null) {
2019-09-26 16:14:14 +02:00
throw data['errors'][0]['message'];
2019-02-07 07:35:19 +01:00
}
2019-02-10 12:15:50 +01:00
2019-02-07 07:35:19 +01:00
return data['data'];
}
Future<dynamic> getWithCredentials(String url, {String contentType}) async {
var headers = _headers;
2019-02-07 07:35:19 +01:00
if (contentType != null) {
// https://developer.github.com/v3/repos/contents/#custom-media-types
headers[HttpHeaders.contentTypeHeader] = contentType;
}
final res = await http
2019-09-08 14:07:35 +02:00
.get(_apiPrefix + url, headers: headers)
.timeout(_timeoutDuration);
2019-02-08 16:20:28 +01:00
// print(res.body);
2019-02-07 07:35:19 +01:00
final data = json.decode(res.body);
return data;
}
Future<void> patchWithCredentials(String url) async {
2019-09-08 14:07:35 +02:00
await http
.patch(_apiPrefix + url, headers: _headers)
.timeout(_timeoutDuration);
2019-02-07 07:35:19 +01:00
}
Future<void> putWithCredentials(String url,
2019-02-07 07:35:19 +01:00
{String contentType, String body}) async {
await http
2019-09-08 14:07:35 +02:00
.put(_apiPrefix + url, headers: _headers, body: body ?? {})
.timeout(_timeoutDuration);
2019-02-07 07:35:19 +01:00
}
Future<void> postWithCredentials(String url,
2019-04-05 15:19:00 +02:00
{String contentType, String body}) async {
final res = await http
2019-09-08 14:07:35 +02:00
.post(_apiPrefix + url, headers: _headers, body: body ?? {})
2019-04-05 15:19:00 +02:00
.timeout(_timeoutDuration);
// print(res.body);
}
Future<void> deleteWithCredentials(String url) async {
await http
2019-09-08 14:07:35 +02:00
.delete(_apiPrefix + url, headers: _headers)
.timeout(_timeoutDuration);
}
String _oauthState;
void redirectToGithubOauth() {
_oauthState = nanoid();
2019-09-21 19:02:14 +02:00
var scope = Uri.encodeComponent('user,repo,read:org');
launch(
2019-09-21 19:02:14 +02:00
'https://github.com/login/oauth/authorize?client_id=$clientId&redirect_uri=gittouch://login&scope=$scope&state=$_oauthState',
);
}
2019-01-30 07:46:18 +01:00
}