kopia lustrzana https://gitlab.com/mysocialportal/relatica
Merge branch 'login-fixes' into 'main'
Login fixes See merge request mysocialportal/relatica!41codemagic-setup
commit
0130514e0c
|
@ -86,7 +86,7 @@ Future<void> dependencyInjectionInitialization() async {
|
|||
if (serviceInit.isFailure) {
|
||||
_logger.severe('Error initializing credentials');
|
||||
} else {
|
||||
await accountsService.initialize();
|
||||
accountsService.initialize();
|
||||
}
|
||||
getIt.registerSingleton<AccountsService>(accountsService);
|
||||
getIt<ActiveProfileSelector<IConnectionsRepo>>().subscribeToProfileSwaps();
|
||||
|
|
|
@ -1082,26 +1082,28 @@ abstract class FriendicaClient {
|
|||
|
||||
FutureResult<PagedResponse<List<dynamic>>, ExecError> _getApiListRequest(
|
||||
Uri url) async {
|
||||
return (await getUrl(url, headers: _headers).andThenSuccessAsync(
|
||||
(response) async =>
|
||||
response.map((data) => jsonDecode(data) as List<dynamic>),
|
||||
))
|
||||
.mapError((error) => error as ExecError);
|
||||
return await getUrl(url, headers: _headers).transformAsync(
|
||||
(response) async {
|
||||
return response.map((data) => jsonDecode(data) as List<dynamic>);
|
||||
},
|
||||
).execErrorCastAsync();
|
||||
}
|
||||
|
||||
FutureResult<PagedResponse<dynamic>, ExecError> _getApiPagedRequest(
|
||||
Uri url) async {
|
||||
return (await getUrl(url, headers: _headers).andThenSuccessAsync(
|
||||
(response) async => response.map((data) => jsonDecode(data)),
|
||||
))
|
||||
.mapError((error) => error as ExecError);
|
||||
return await getUrl(url, headers: _headers).transformAsync(
|
||||
(response) async {
|
||||
return response.map((data) => jsonDecode(data));
|
||||
},
|
||||
).execErrorCastAsync();
|
||||
}
|
||||
|
||||
FutureResult<dynamic, ExecError> _getApiRequest(Uri url) async {
|
||||
return (await getUrl(url, headers: _headers).andThenSuccessAsync(
|
||||
(response) async => jsonDecode(response.data),
|
||||
))
|
||||
.execErrorCastAsync();
|
||||
return await getUrl(url, headers: _headers).transformAsync(
|
||||
(response) async {
|
||||
return jsonDecode(response.data);
|
||||
},
|
||||
).execErrorCastAsync();
|
||||
}
|
||||
|
||||
Map<String, String> get _headers => {
|
||||
|
|
|
@ -22,6 +22,7 @@ const maxViewPortalWidth = 750.0;
|
|||
|
||||
const maxProcessingMillis = 3;
|
||||
const processingSleep = Duration(milliseconds: 1);
|
||||
const apiCallTimeout = Duration(seconds: 30);
|
||||
|
||||
Future<bool?> showConfirmDialog(BuildContext context, String caption) {
|
||||
return showDialog<bool>(
|
||||
|
|
|
@ -56,7 +56,14 @@ extension ExecErrorExtension<T, E> on Result<T, E> {
|
|||
? error
|
||||
: ExecError(type: ErrorType.localError, message: error.toString()));
|
||||
|
||||
FutureResult<T, ExecError> execErrorCastAsync() async => execErrorCast();
|
||||
FutureResult<T, ExecError> execErrorCastAsync() async {
|
||||
return this.execErrorCast();
|
||||
}
|
||||
}
|
||||
|
||||
extension ExecErrorExtensionFuture<T, E> on FutureResult<T, E> {
|
||||
FutureResult<T, ExecError> execErrorCastAsync() async =>
|
||||
(await this).execErrorCast();
|
||||
}
|
||||
|
||||
void logError(ExecError error, Logger logger,
|
||||
|
|
|
@ -67,6 +67,11 @@ final appRouter = GoRouter(
|
|||
refreshListenable: _authService,
|
||||
redirect: (context, state) async {
|
||||
final loggedIn = _authService.loggedIn;
|
||||
|
||||
if (!loggedIn && _authService.initializing) {
|
||||
return ScreenPaths.splash;
|
||||
}
|
||||
|
||||
if (!loggedIn && !allowedLoggedOut.contains(state.location)) {
|
||||
return ScreenPaths.signin;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
import '../controls/padding.dart';
|
||||
import '../globals.dart';
|
||||
import '../services/auth_service.dart';
|
||||
|
||||
class SplashScreen extends StatelessWidget {
|
||||
@override
|
||||
|
@ -9,7 +14,18 @@ class SplashScreen extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Text('Relatica'),
|
||||
SvgPicture.asset('icon/relatica_logo.svg', width: 128),
|
||||
const VerticalPadding(),
|
||||
Text(
|
||||
'Relatica',
|
||||
style: Theme.of(context).textTheme.headlineLarge,
|
||||
),
|
||||
const VerticalPadding(),
|
||||
if (getIt<AccountsService>().initializing) ...[
|
||||
const CircularProgressIndicator(),
|
||||
const VerticalPadding(),
|
||||
const Text('Logging in accounts...'),
|
||||
],
|
||||
],
|
||||
)),
|
||||
);
|
||||
|
|
|
@ -18,6 +18,7 @@ class AccountsService extends ChangeNotifier {
|
|||
Profile? _currentProfile;
|
||||
final _loggedInProfiles = <Profile>{};
|
||||
final _loggedOutProfiles = <Profile>{};
|
||||
var _initializing = false;
|
||||
|
||||
final SecretsService secretsService;
|
||||
|
||||
|
@ -25,6 +26,8 @@ class AccountsService extends ChangeNotifier {
|
|||
|
||||
bool get loggedIn => _currentProfile != null;
|
||||
|
||||
bool get initializing => _initializing;
|
||||
|
||||
List<Profile> get loggedInProfiles => UnmodifiableListView(_loggedInProfiles);
|
||||
|
||||
List<Profile> get loggedOutProfiles =>
|
||||
|
@ -35,6 +38,7 @@ class AccountsService extends ChangeNotifier {
|
|||
FutureResult<bool, ExecError> initialize() async {
|
||||
final lastActiveProfile = await _getStoredLoginState();
|
||||
|
||||
_initializing = true;
|
||||
final result = await runCatchingAsync(() async {
|
||||
final initialProfiles = secretsService.profiles;
|
||||
for (final p in initialProfiles) {
|
||||
|
@ -60,9 +64,11 @@ class AccountsService extends ChangeNotifier {
|
|||
await setActiveProfile(_loggedInProfiles.first);
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
return Result.ok(loggedIn);
|
||||
});
|
||||
|
||||
_initializing = false;
|
||||
return result.execErrorCast();
|
||||
}
|
||||
|
||||
|
@ -157,10 +163,6 @@ class AccountsService extends ChangeNotifier {
|
|||
Future<void> setActiveProfile(Profile profile,
|
||||
{bool withNotification = true}) async {
|
||||
_currentProfile = profile;
|
||||
Future.delayed(
|
||||
const Duration(seconds: 10),
|
||||
() async => await executeUpdatesForProfile(profile),
|
||||
);
|
||||
if (withNotification) {
|
||||
notifyListeners();
|
||||
}
|
||||
|
|
|
@ -29,11 +29,15 @@ Future<void> executeUpdatesForProfile(Profile profile) async {
|
|||
return;
|
||||
}
|
||||
|
||||
if (getIt<AccountsService>().currentProfile != profile) {
|
||||
return;
|
||||
}
|
||||
|
||||
await getIt<ActiveProfileSelector<PersistentInfoService>>()
|
||||
.getForProfile(profile)
|
||||
.withResultAsync((info) async {
|
||||
final dt = DateTime.now().difference(info.lastMyConnectionsUpdate);
|
||||
_logger.finer('Time since last connections update: $dt');
|
||||
_logger.finer('Time since last update for ${profile.id}: $dt');
|
||||
if (dt >= _connectionsRefreshInterval) {
|
||||
await getIt<ActiveProfileSelector<ConnectionsManager>>()
|
||||
.getForProfile(profile)
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:logging/logging.dart';
|
||||
import '../globals.dart';
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
import '../friendica_client/paged_response.dart';
|
||||
|
@ -9,17 +10,24 @@ import '../models/exec_error.dart';
|
|||
|
||||
final _logger = Logger('NetworkUtils');
|
||||
|
||||
http.Response requestTimeout() => http.Response('Client side timeout', 408);
|
||||
|
||||
FutureResult<PagedResponse<String>, ExecError> getUrl(
|
||||
Uri url, {
|
||||
Map<String, String>? headers,
|
||||
}) async {
|
||||
_logger.finer('GET: $url');
|
||||
try {
|
||||
final response = await http.get(
|
||||
final request = http.get(
|
||||
url,
|
||||
headers: headers,
|
||||
);
|
||||
|
||||
final response = await request.timeout(
|
||||
apiCallTimeout,
|
||||
onTimeout: requestTimeout,
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
return Result.error(ExecError(
|
||||
type: ErrorType.authentication,
|
||||
|
@ -42,12 +50,17 @@ FutureResult<String, ExecError> postUrl(
|
|||
}) async {
|
||||
_logger.finer('POST: $url \n Body: $body');
|
||||
try {
|
||||
final response = await http.post(
|
||||
final request = http.post(
|
||||
url,
|
||||
headers: headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
|
||||
final response = await request.timeout(
|
||||
apiCallTimeout,
|
||||
onTimeout: requestTimeout,
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
return Result.error(ExecError(
|
||||
type: ErrorType.authentication,
|
||||
|
@ -67,12 +80,17 @@ FutureResult<String, ExecError> putUrl(
|
|||
}) async {
|
||||
_logger.finer('PUT: $url \n Body: $body');
|
||||
try {
|
||||
final response = await http.put(
|
||||
final request = http.put(
|
||||
url,
|
||||
headers: headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
|
||||
final response = await request.timeout(
|
||||
apiCallTimeout,
|
||||
onTimeout: requestTimeout,
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
return Result.error(ExecError(
|
||||
type: ErrorType.authentication,
|
||||
|
@ -92,12 +110,17 @@ FutureResult<String, ExecError> deleteUrl(
|
|||
}) async {
|
||||
_logger.finer('DELETE: $url');
|
||||
try {
|
||||
final response = await http.delete(
|
||||
final request = http.delete(
|
||||
url,
|
||||
headers: headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
|
||||
final response = await request.timeout(
|
||||
apiCallTimeout,
|
||||
onTimeout: requestTimeout,
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
return Result.error(ExecError(
|
||||
type: ErrorType.authentication,
|
||||
|
|
40
pubspec.lock
40
pubspec.lock
|
@ -451,6 +451,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_svg
|
||||
sha256: f991fdb1533c3caeee0cdc14b04f50f0c3916f0dbcbc05237ccbe4e3c6b93f3f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
@ -861,6 +869,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.2"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_parsing
|
||||
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1307,6 +1323,30 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.7"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: ea8d3fc7b2e0f35de38a7465063ecfcf03d8217f7962aa2a6717132cb5d43a79
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.5"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_codec
|
||||
sha256: a5eaa5d19e123ad4f61c3718ca1ed921c4e6254238d9145f82aa214955d9aced
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.5"
|
||||
vector_graphics_compiler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: "15edc42f7eaa478ce854eaf1fbb9062a899c0e4e56e775dd73b7f4709c97c4ca"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.5"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
28
pubspec.yaml
28
pubspec.yaml
|
@ -11,8 +11,12 @@ dependencies:
|
|||
flutter:
|
||||
sdk: flutter
|
||||
cached_network_image: ^3.2.2
|
||||
color_blindness: ^0.1.2
|
||||
cupertino_icons: ^1.0.2
|
||||
carousel_slider: ^4.2.1
|
||||
desktop_window: ^0.4.0
|
||||
device_info_plus: ^8.0.0
|
||||
device_preview: ^1.1.0
|
||||
file_picker: ^5.2.4
|
||||
flutter_dotenv: ^5.0.2
|
||||
flutter_file_dialog: ^3.0.0
|
||||
|
@ -22,6 +26,7 @@ dependencies:
|
|||
get_it: ^7.2.0
|
||||
get_it_mixin: ^4.1.1
|
||||
go_router: ^6.5.0
|
||||
html: ^0.15.2
|
||||
image: ^4.0.15
|
||||
image_picker: ^0.8.6
|
||||
logging: ^1.1.0
|
||||
|
@ -36,7 +41,10 @@ dependencies:
|
|||
media_kit_libs_linux: ^1.0.2 # GNU/Linux dependency package. metadata_fetch: ^0.4.1
|
||||
multi_trigger_autocomplete: ^0.1.1
|
||||
network_to_file_image: ^4.0.1
|
||||
objectbox: ^2.0.0
|
||||
objectbox_flutter_libs: ^2.0.0
|
||||
path: ^1.8.2
|
||||
path_provider: ^2.0.11
|
||||
provider: ^6.0.4
|
||||
result_monad:
|
||||
git:
|
||||
|
@ -44,20 +52,14 @@ dependencies:
|
|||
scrollable_positioned_list: ^0.3.5
|
||||
shared_preferences: ^2.0.15
|
||||
sqlite3: ^1.9.1
|
||||
stack_trace: ^1.11.0
|
||||
string_validator: ^0.3.0
|
||||
time_machine: ^0.9.17
|
||||
url_launcher: ^6.1.6
|
||||
uuid: ^3.0.6
|
||||
video_player: ^2.4.10
|
||||
objectbox: ^2.0.0
|
||||
objectbox_flutter_libs: ^2.0.0
|
||||
path_provider: ^2.0.11
|
||||
carousel_slider: ^4.2.1
|
||||
device_info_plus: ^8.0.0
|
||||
string_validator: ^0.3.0
|
||||
device_preview: ^1.1.0
|
||||
color_blindness: ^0.1.2
|
||||
stack_trace: ^1.11.0
|
||||
html: ^0.15.2
|
||||
flutter_svg: ^2.0.5
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -68,9 +70,9 @@ dev_dependencies:
|
|||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
# assets:
|
||||
# Add assets from the images directory to the application.
|
||||
#- .env
|
||||
assets:
|
||||
- icon/relatica_logo.svg
|
||||
|
||||
parts:
|
||||
uet-lms:
|
||||
source: .
|
||||
|
|
Ładowanie…
Reference in New Issue