Compare commits
2 Commits
master
...
error-hand
Author | SHA1 | Date |
---|---|---|
NaiJi ✨ | 3a5cb0f81b | |
NaiJi ✨ | 0df5940c68 |
|
@ -1,6 +1,11 @@
|
||||||
{
|
{
|
||||||
"test": "en-test",
|
"test": "en-test",
|
||||||
"locale": "en",
|
"locale": "en",
|
||||||
|
"error": {
|
||||||
|
"page_title": "Oops, something happened...",
|
||||||
|
"page_description": "We couldn't handle an exception, but it is important for us to know what just happened. Please share this log to our support!",
|
||||||
|
"page_share": "Share:"
|
||||||
|
},
|
||||||
"basis": {
|
"basis": {
|
||||||
"providers": "Providers",
|
"providers": "Providers",
|
||||||
"providers_title": "Your Data Center",
|
"providers_title": "Your Data Center",
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
{
|
{
|
||||||
"test": "ru-test",
|
"test": "ru-test",
|
||||||
"locale": "ru",
|
"locale": "ru",
|
||||||
|
"error": {
|
||||||
|
"page_title": "Упс, что-то случилось...",
|
||||||
|
"page_description": "Нам не удалось обработать исключение, но нам важно знать, что только что произошло. Пожалуйста, отправьте нашей поддержке данный лог!",
|
||||||
|
"page_share": "Поделиться:"
|
||||||
|
},
|
||||||
"basis": {
|
"basis": {
|
||||||
"providers": "Провайдеры",
|
"providers": "Провайдеры",
|
||||||
"providers_title": "Ваш Дата Центр",
|
"providers_title": "Ваш Дата Центр",
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
import 'package:selfprivacy/config/brand_colors.dart';
|
||||||
import 'package:selfprivacy/config/hive_config.dart';
|
import 'package:selfprivacy/config/hive_config.dart';
|
||||||
import 'package:selfprivacy/theming/factory/app_theme_factory.dart';
|
import 'package:selfprivacy/theming/factory/app_theme_factory.dart';
|
||||||
|
import 'package:selfprivacy/ui/pages/error_page.dart';
|
||||||
import 'package:selfprivacy/ui/pages/setup/initializing.dart';
|
import 'package:selfprivacy/ui/pages/setup/initializing.dart';
|
||||||
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
|
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
|
||||||
import 'package:selfprivacy/ui/pages/root_route.dart';
|
import 'package:selfprivacy/ui/pages/root_route.dart';
|
||||||
|
@ -93,13 +95,15 @@ class MyApp extends StatelessWidget {
|
||||||
? const OnboardingPage(nextPage: InitializingPage())
|
? const OnboardingPage(nextPage: InitializingPage())
|
||||||
: const RootPage(),
|
: const RootPage(),
|
||||||
builder: (final BuildContext context, final Widget? widget) {
|
builder: (final BuildContext context, final Widget? widget) {
|
||||||
Widget error = const Text('...rendering error...');
|
|
||||||
if (widget is Scaffold || widget is Navigator) {
|
|
||||||
error = Scaffold(body: Center(child: error));
|
|
||||||
}
|
|
||||||
ErrorWidget.builder =
|
ErrorWidget.builder =
|
||||||
(final FlutterErrorDetails errorDetails) => error;
|
(final FlutterErrorDetails errorDetails) => ErrorPage(
|
||||||
return widget!;
|
log:
|
||||||
|
'${errorDetails.stack?.toString() ?? ''}\n\n${errorDetails.exception}',
|
||||||
|
);
|
||||||
|
if (widget != null) {
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
throw 'widget is null';
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:selfprivacy/config/brand_theme.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||||
|
import 'package:selfprivacy/utils/ui_helpers.dart';
|
||||||
|
|
||||||
|
class ErrorPage extends StatelessWidget {
|
||||||
|
const ErrorPage({required this.log, super.key});
|
||||||
|
|
||||||
|
final String log;
|
||||||
|
final String telegramUrl = 'https://t.me/selfprivacy';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => BrandHeroScreen(
|
||||||
|
heroTitle: 'error.page_title'.tr(),
|
||||||
|
heroSubtitle: 'error.page_description'.tr(),
|
||||||
|
hasBackButton: false,
|
||||||
|
hasFlashButton: false,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: 320,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.content_copy_outlined),
|
||||||
|
onPressed: () async => Clipboard.setData(
|
||||||
|
ClipboardData(text: log),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 48),
|
||||||
|
Text('error.page_share'.tr()),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
InkWell(
|
||||||
|
onTap: () async => UiHelpers.launchExternalApplicationURL(
|
||||||
|
telegramUrl,
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.telegram_outlined),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
log,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontFamily: 'RobotoMono',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
|
@ -33,6 +33,18 @@ class MorePage extends StatelessWidget {
|
||||||
final bool? usesBinds =
|
final bool? usesBinds =
|
||||||
context.watch<ApiServerVolumeCubit>().state.usesBinds;
|
context.watch<ApiServerVolumeCubit>().state.usesBinds;
|
||||||
|
|
||||||
|
return ListView(
|
||||||
|
children: [
|
||||||
|
ListView(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [Text("jfkhskdjfhdkjs")],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
/*
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: PreferredSize(
|
appBar: PreferredSize(
|
||||||
preferredSize: const Size.fromHeight(52),
|
preferredSize: const Size.fromHeight(52),
|
||||||
|
@ -132,7 +144,7 @@ class MorePage extends StatelessWidget {
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
); */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:selfprivacy/ui/pages/services/service_page.dart';
|
import 'package:selfprivacy/ui/pages/services/service_page.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||||
import 'package:selfprivacy/utils/ui_helpers.dart';
|
import 'package:selfprivacy/utils/ui_helpers.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
const switchableServices = [
|
const switchableServices = [
|
||||||
'bitwarden',
|
'bitwarden',
|
||||||
|
@ -36,18 +35,6 @@ class ServicesPage extends StatefulWidget {
|
||||||
State<ServicesPage> createState() => _ServicesPageState();
|
State<ServicesPage> createState() => _ServicesPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _launchURL(final url) async {
|
|
||||||
try {
|
|
||||||
final Uri uri = Uri.parse(url);
|
|
||||||
await launchUrl(
|
|
||||||
uri,
|
|
||||||
mode: LaunchMode.externalApplication,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ServicesPageState extends State<ServicesPage> {
|
class _ServicesPageState extends State<ServicesPage> {
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) {
|
Widget build(final BuildContext context) {
|
||||||
|
@ -181,7 +168,8 @@ class _Card extends StatelessWidget {
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => _launchURL(
|
onTap: () async =>
|
||||||
|
UiHelpers.launchExternalApplicationURL(
|
||||||
'https://${service.url}',
|
'https://${service.url}',
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|
|
@ -1,8 +1,27 @@
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
/// it's ui helpers use only for ui components, don't use for logic components.
|
/// it's ui helpers use only for ui components, don't use for logic components.
|
||||||
|
|
||||||
class UiHelpers {
|
class UiHelpers {
|
||||||
static String getDomainName(final ServerInstallationState config) =>
|
static String getDomainName(final ServerInstallationState config) =>
|
||||||
config.isDomainSelected ? config.serverDomain!.domainName : 'example.com';
|
config.isDomainSelected ? config.serverDomain!.domainName : 'example.com';
|
||||||
|
|
||||||
|
static Future<bool> launchExternalApplicationURL(final url) async {
|
||||||
|
bool launched = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Uri uri = Uri.parse(url);
|
||||||
|
if (await canLaunchUrl(uri)) {
|
||||||
|
launched = await launchUrl(
|
||||||
|
uri,
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return launched;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue