mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: launch url on all platforms (#4797)
* fix: error handled launchUrl * chore: update links to use new subdomain * feat: show toast if onFailure is not provided
This commit is contained in:
parent
1fadb15351
commit
63464cbf2e
50
frontend/appflowy_flutter/lib/core/helpers/url_launcher.dart
Normal file
50
frontend/appflowy_flutter/lib/core/helpers/url_launcher.dart
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart' as launcher;
|
||||||
|
|
||||||
|
typedef OnFailureCallback = void Function(Uri uri);
|
||||||
|
|
||||||
|
Future<bool> afLaunchUrl(
|
||||||
|
Uri uri, {
|
||||||
|
BuildContext? context,
|
||||||
|
OnFailureCallback? onFailure,
|
||||||
|
launcher.LaunchMode mode = launcher.LaunchMode.platformDefault,
|
||||||
|
String? webOnlyWindowName,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await launcher.launchUrl(
|
||||||
|
uri,
|
||||||
|
mode: mode,
|
||||||
|
webOnlyWindowName: webOnlyWindowName,
|
||||||
|
);
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
Log.error("Failed to open uri: $e");
|
||||||
|
if (onFailure != null) {
|
||||||
|
onFailure(uri);
|
||||||
|
} else {
|
||||||
|
showMessageToast(
|
||||||
|
LocaleKeys.failedToOpenUrl.tr(args: [e.message ?? "PlatformException"]),
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> afLaunchUrlString(String url) async {
|
||||||
|
try {
|
||||||
|
final uri = Uri.parse(url);
|
||||||
|
|
||||||
|
await launcher.launchUrl(uri);
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
Log.error("Failed to open uri: $e");
|
||||||
|
} on FormatException catch (e) {
|
||||||
|
Log.error("Failed to parse url: $e");
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/startup/tasks/device_info_task.dart';
|
import 'package:appflowy/startup/tasks/device_info_task.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import '../widgets/widgets.dart';
|
import '../widgets/widgets.dart';
|
||||||
|
|
||||||
@ -22,14 +23,14 @@ class AboutSettingGroup extends StatelessWidget {
|
|||||||
trailing: const Icon(
|
trailing: const Icon(
|
||||||
Icons.chevron_right,
|
Icons.chevron_right,
|
||||||
),
|
),
|
||||||
onTap: () => safeLaunchUrl('https://appflowy.io/privacy/app'),
|
onTap: () => afLaunchUrlString('https://appflowy.io/privacy/app'),
|
||||||
),
|
),
|
||||||
MobileSettingItem(
|
MobileSettingItem(
|
||||||
name: LocaleKeys.settings_mobile_termsAndConditions.tr(),
|
name: LocaleKeys.settings_mobile_termsAndConditions.tr(),
|
||||||
trailing: const Icon(
|
trailing: const Icon(
|
||||||
Icons.chevron_right,
|
Icons.chevron_right,
|
||||||
),
|
),
|
||||||
onTap: () => safeLaunchUrl('https://appflowy.io/terms/app'),
|
onTap: () => afLaunchUrlString('https://appflowy.io/terms/app'),
|
||||||
),
|
),
|
||||||
MobileSettingItem(
|
MobileSettingItem(
|
||||||
name: LocaleKeys.settings_mobile_version.tr(),
|
name: LocaleKeys.settings_mobile_version.tr(),
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||||
import 'package:appflowy/util/share_log_files.dart';
|
import 'package:appflowy/util/share_log_files.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
import 'widgets/widgets.dart';
|
import 'widgets/widgets.dart';
|
||||||
@ -28,7 +29,7 @@ class SupportSettingGroup extends StatelessWidget {
|
|||||||
trailing: const Icon(
|
trailing: const Icon(
|
||||||
Icons.chevron_right,
|
Icons.chevron_right,
|
||||||
),
|
),
|
||||||
onTap: () => safeLaunchUrl('https://discord.gg/JucBXeU2FE'),
|
onTap: () => afLaunchUrlString('https://discord.gg/JucBXeU2FE'),
|
||||||
),
|
),
|
||||||
MobileSettingItem(
|
MobileSettingItem(
|
||||||
name: LocaleKeys.workspace_errorActions_reportIssue.tr(),
|
name: LocaleKeys.workspace_errorActions_reportIssue.tr(),
|
||||||
@ -73,7 +74,7 @@ class _ReportIssuesWidget extends StatelessWidget {
|
|||||||
text: LocaleKeys.workspace_errorActions_reportIssueOnGithub.tr(),
|
text: LocaleKeys.workspace_errorActions_reportIssueOnGithub.tr(),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
final String os = Platform.operatingSystem;
|
final String os = Platform.operatingSystem;
|
||||||
safeLaunchUrl(
|
afLaunchUrlString(
|
||||||
'https://github.com/AppFlowy-IO/AppFlowy/issues/new?assignees=&labels=&projects=&template=bug_report.yaml&title=[Bug]%20Mobile:%20&version=$version&os=$os',
|
'https://github.com/AppFlowy-IO/AppFlowy/issues/new?assignees=&labels=&projects=&template=bug_report.yaml&title=[Bug]%20Mobile:%20&version=$version&os=$os',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
enum _FlowyMobileStateContainerType {
|
enum _FlowyMobileStateContainerType {
|
||||||
@ -80,7 +81,7 @@ class FlowyMobileStateContainer extends StatelessWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
final String? version = snapshot.data?.version;
|
final String? version = snapshot.data?.version;
|
||||||
final String os = Platform.operatingSystem;
|
final String os = Platform.operatingSystem;
|
||||||
safeLaunchUrl(
|
afLaunchUrlString(
|
||||||
'https://github.com/AppFlowy-IO/AppFlowy/issues/new?assignees=&labels=&projects=&template=bug_report.yaml&title=[Bug]%20Mobile:%20&version=$version&os=$os&context=Error%20log:%20$errorMsg',
|
'https://github.com/AppFlowy-IO/AppFlowy/issues/new?assignees=&labels=&projects=&template=bug_report.yaml&title=[Bug]%20Mobile:%20&version=$version&os=$os&context=Error%20log:%20$errorMsg',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -90,7 +91,7 @@ class FlowyMobileStateContainer extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
safeLaunchUrl('https://discord.gg/JucBXeU2FE'),
|
afLaunchUrlString('https://discord.gg/JucBXeU2FE'),
|
||||||
child: Text(
|
child: Text(
|
||||||
LocaleKeys.workspace_errorActions_reachOut.tr(),
|
LocaleKeys.workspace_errorActions_reachOut.tr(),
|
||||||
),
|
),
|
||||||
|
@ -4,7 +4,7 @@ import 'cell_controller.dart';
|
|||||||
|
|
||||||
/// CellMemCache is used to cache cell data of each block.
|
/// CellMemCache is used to cache cell data of each block.
|
||||||
/// We use CellContext to index the cell in the cache.
|
/// We use CellContext to index the cell in the cache.
|
||||||
/// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid
|
/// Read https://docs.appflowy.io/docs/documentation/software-contributions/architecture/frontend/frontend/grid
|
||||||
/// for more information
|
/// for more information
|
||||||
class CellMemCache {
|
class CellMemCache {
|
||||||
CellMemCache();
|
CellMemCache();
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
import '../cell/cell_cache.dart';
|
import '../cell/cell_cache.dart';
|
||||||
import '../cell/cell_controller.dart';
|
import '../cell/cell_controller.dart';
|
||||||
|
|
||||||
import 'row_list.dart';
|
import 'row_list.dart';
|
||||||
import 'row_service.dart';
|
import 'row_service.dart';
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ abstract mixin class RowLifeCycle {
|
|||||||
void onRowDisposed();
|
void onRowDisposed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid for more information.
|
/// Read https://docs.appflowy.io/docs/documentation/software-contributions/architecture/frontend/frontend/grid for more information.
|
||||||
|
|
||||||
class RowCache {
|
class RowCache {
|
||||||
RowCache({
|
RowCache({
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/database/application/row/row_service.dart';
|
import 'package:appflowy/plugins/database/application/row/row_service.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
|
||||||
import '../defines.dart';
|
import '../defines.dart';
|
||||||
import '../field/field_controller.dart';
|
import '../field/field_controller.dart';
|
||||||
import '../row/row_cache.dart';
|
import '../row/row_cache.dart';
|
||||||
|
|
||||||
import 'view_listener.dart';
|
import 'view_listener.dart';
|
||||||
|
|
||||||
class DatabaseViewCallbacks {
|
class DatabaseViewCallbacks {
|
||||||
@ -30,7 +33,7 @@ class DatabaseViewCallbacks {
|
|||||||
final OnRowsDeleted? onRowsDeleted;
|
final OnRowsDeleted? onRowsDeleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid for more information
|
/// Read https://docs.appflowy.io/docs/documentation/software-contributions/architecture/frontend/frontend/grid for more information
|
||||||
class DatabaseViewCache {
|
class DatabaseViewCache {
|
||||||
DatabaseViewCache({
|
DatabaseViewCache({
|
||||||
required this.viewId,
|
required this.viewId,
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||||
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
|
||||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
|
|
||||||
import '../editable_cell_skeleton/url.dart';
|
import '../editable_cell_skeleton/url.dart';
|
||||||
|
|
||||||
@ -189,7 +190,7 @@ class _VisitURLAccessoryState extends State<_VisitURLAccessory>
|
|||||||
final shouldAddScheme =
|
final shouldAddScheme =
|
||||||
!['http', 'https'].any((pattern) => content.startsWith(pattern));
|
!['http', 'https'].any((pattern) => content.startsWith(pattern));
|
||||||
final url = shouldAddScheme ? 'http://$content' : content;
|
final url = shouldAddScheme ? 'http://$content' : content;
|
||||||
canLaunchUrlString(url).then((value) => launchUrlString(url));
|
afLaunchUrlString(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||||
|
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||||
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
|
|
||||||
import '../editable_cell_skeleton/url.dart';
|
import '../editable_cell_skeleton/url.dart';
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ class MobileGridURLCellSkin extends IEditableURLCellSkin {
|
|||||||
final shouldAddScheme = !['http', 'https']
|
final shouldAddScheme = !['http', 'https']
|
||||||
.any((pattern) => content.startsWith(pattern));
|
.any((pattern) => content.startsWith(pattern));
|
||||||
final url = shouldAddScheme ? 'http://$content' : content;
|
final url = shouldAddScheme ? 'http://$content' : content;
|
||||||
canLaunchUrlString(url).then((value) => launchUrlString(url));
|
afLaunchUrlString(url);
|
||||||
},
|
},
|
||||||
onLongPress: () => showMobileBottomSheet(
|
onLongPress: () => showMobileBottomSheet(
|
||||||
context,
|
context,
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||||
|
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||||
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
|
|
||||||
import '../editable_cell_skeleton/url.dart';
|
import '../editable_cell_skeleton/url.dart';
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ class MobileRowDetailURLCellSkin extends IEditableURLCellSkin {
|
|||||||
final shouldAddScheme = !['http', 'https']
|
final shouldAddScheme = !['http', 'https']
|
||||||
.any((pattern) => content.startsWith(pattern));
|
.any((pattern) => content.startsWith(pattern));
|
||||||
final url = shouldAddScheme ? 'http://$content' : content;
|
final url = shouldAddScheme ? 'http://$content' : content;
|
||||||
canLaunchUrlString(url).then((value) => launchUrlString(url));
|
afLaunchUrlString(url);
|
||||||
},
|
},
|
||||||
onLongPress: () => _showURLEditor(context, bloc, content),
|
onLongPress: () => _showURLEditor(context, bloc, content),
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||||
@ -7,10 +10,8 @@ import 'package:appflowy/shared/appflowy_network_image.dart';
|
|||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
|
|
||||||
class CustomLinkPreviewWidget extends StatelessWidget {
|
class CustomLinkPreviewWidget extends StatelessWidget {
|
||||||
const CustomLinkPreviewWidget({
|
const CustomLinkPreviewWidget({
|
||||||
@ -113,7 +114,7 @@ class CustomLinkPreviewWidget extends StatelessWidget {
|
|||||||
|
|
||||||
if (PlatformExtension.isDesktopOrWeb) {
|
if (PlatformExtension.isDesktopOrWeb) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () => launchUrlString(url),
|
onTap: () => afLaunchUrlString(url),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
|
|
||||||
|
const String learnMoreUrl =
|
||||||
|
'https://docs.appflowy.io/docs/appflowy/product/appflowy-x-openai';
|
||||||
|
|
||||||
Future<void> openLearnMorePage() async {
|
Future<void> openLearnMorePage() async {
|
||||||
final uri = Uri.parse(
|
await afLaunchUrlString(learnMoreUrl);
|
||||||
'https://appflowy.gitbook.io/docs/essential-documentation/appflowy-x-openai',
|
|
||||||
);
|
|
||||||
if (await canLaunchUrl(uri)) {
|
|
||||||
await launchUrl(uri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import 'dart:math';
|
|||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart';
|
||||||
@ -293,7 +294,7 @@ class EditorStyleCustomizer {
|
|||||||
..onTap = () {
|
..onTap = () {
|
||||||
final editorState = context.read<EditorState>();
|
final editorState = context.read<EditorState>();
|
||||||
if (editorState.selection == null) {
|
if (editorState.selection == null) {
|
||||||
safeLaunchUrl(href);
|
afLaunchUrlString(href);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
|
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
|
||||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||||
@ -55,7 +56,7 @@ class AppFlowyCloudAuthService implements AuthService {
|
|||||||
(data) async {
|
(data) async {
|
||||||
// Open the webview with oauth url
|
// Open the webview with oauth url
|
||||||
final uri = Uri.parse(data.oauthUrl);
|
final uri = Uri.parse(data.oauthUrl);
|
||||||
final isSuccess = await launchUrl(
|
final isSuccess = await afLaunchUrl(
|
||||||
uri,
|
uri,
|
||||||
mode: LaunchMode.externalApplication,
|
mode: LaunchMode.externalApplication,
|
||||||
webOnlyWindowName: '_self',
|
webOnlyWindowName: '_self',
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/core/frameless_window.dart';
|
import 'package:appflowy/core/frameless_window.dart';
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
@ -15,9 +18,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra/language.dart';
|
import 'package:flowy_infra/language.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class SkipLogInScreen extends StatefulWidget {
|
class SkipLogInScreen extends StatefulWidget {
|
||||||
const SkipLogInScreen({super.key});
|
const SkipLogInScreen({super.key});
|
||||||
@ -158,9 +159,8 @@ class SubscribeButtons extends StatelessWidget {
|
|||||||
fontColor: Theme.of(context).colorScheme.primary,
|
fontColor: Theme.of(context).colorScheme.primary,
|
||||||
hoverColor: Colors.transparent,
|
hoverColor: Colors.transparent,
|
||||||
fillColor: Colors.transparent,
|
fillColor: Colors.transparent,
|
||||||
onPressed: () => _launchURL(
|
onPressed: () =>
|
||||||
'https://github.com/AppFlowy-IO/appflowy',
|
afLaunchUrlString('https://github.com/AppFlowy-IO/appflowy'),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -179,22 +179,14 @@ class SubscribeButtons extends StatelessWidget {
|
|||||||
fontColor: Theme.of(context).colorScheme.primary,
|
fontColor: Theme.of(context).colorScheme.primary,
|
||||||
hoverColor: Colors.transparent,
|
hoverColor: Colors.transparent,
|
||||||
fillColor: Colors.transparent,
|
fillColor: Colors.transparent,
|
||||||
onPressed: () => _launchURL('https://www.appflowy.io/blog'),
|
onPressed: () =>
|
||||||
|
afLaunchUrlString('https://www.appflowy.io/blog'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _launchURL(String url) async {
|
|
||||||
final uri = Uri.parse(url);
|
|
||||||
if (await canLaunchUrl(uri)) {
|
|
||||||
await launchUrl(uri);
|
|
||||||
} else {
|
|
||||||
throw 'Could not launch $url';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LanguageSelectorOnWelcomePage extends StatelessWidget {
|
class LanguageSelectorOnWelcomePage extends StatelessWidget {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
class WorkspaceFailedScreen extends StatefulWidget {
|
class WorkspaceFailedScreen extends StatefulWidget {
|
||||||
@ -51,7 +52,7 @@ class _WorkspaceFailedScreenState extends State<WorkspaceFailedScreen> {
|
|||||||
title:
|
title:
|
||||||
LocaleKeys.workspace_errorActions_reportIssue.tr(),
|
LocaleKeys.workspace_errorActions_reportIssue.tr(),
|
||||||
height: 40,
|
height: 40,
|
||||||
onPressed: () => safeLaunchUrl(
|
onPressed: () => afLaunchUrlString(
|
||||||
'https://github.com/AppFlowy-IO/AppFlowy/issues/new?assignees=&labels=&projects=&template=bug_report.yaml&title=[Bug]%20Workspace%20failed%20to%20load&version=$version&os=$os',
|
'https://github.com/AppFlowy-IO/AppFlowy/issues/new?assignees=&labels=&projects=&template=bug_report.yaml&title=[Bug]%20Workspace%20failed%20to%20load&version=$version&os=$os',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -62,7 +63,7 @@ class _WorkspaceFailedScreenState extends State<WorkspaceFailedScreen> {
|
|||||||
title: LocaleKeys.workspace_errorActions_reachOut.tr(),
|
title: LocaleKeys.workspace_errorActions_reachOut.tr(),
|
||||||
height: 40,
|
height: 40,
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
safeLaunchUrl('https://discord.gg/JucBXeU2FE'),
|
afLaunchUrlString('https://discord.gg/JucBXeU2FE'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
|
||||||
class FlowyMessageToast extends StatelessWidget {
|
class FlowyMessageToast extends StatelessWidget {
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
import 'package:flutter/gestures.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/env/cloud_env.dart';
|
import 'package:appflowy/env/cloud_env.dart';
|
||||||
import 'package:appflowy/env/env.dart';
|
import 'package:appflowy/env/env.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
@ -6,7 +10,6 @@ import 'package:appflowy/workspace/application/settings/appflowy_cloud_urls_bloc
|
|||||||
import 'package:appflowy/workspace/presentation/settings/widgets/_restart_app_button.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/_restart_app_button.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
|
||||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
|
||||||
import 'package:appflowy_result/appflowy_result.dart';
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
@ -14,10 +17,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class AppFlowyCloudViewSetting extends StatelessWidget {
|
class AppFlowyCloudViewSetting extends StatelessWidget {
|
||||||
const AppFlowyCloudViewSetting({
|
const AppFlowyCloudViewSetting({
|
||||||
@ -227,7 +227,8 @@ class AppFlowySelfhostTip extends StatelessWidget {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
decoration: TextDecoration.underline,
|
decoration: TextDecoration.underline,
|
||||||
),
|
),
|
||||||
recognizer: TapGestureRecognizer()..onTap = () => _launchURL(),
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () => afLaunchUrlString(url),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: LocaleKeys.settings_menu_selfHostEnd.tr(),
|
text: LocaleKeys.settings_menu_selfHostEnd.tr(),
|
||||||
@ -238,15 +239,6 @@ class AppFlowySelfhostTip extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _launchURL() async {
|
|
||||||
final uri = Uri.parse(url);
|
|
||||||
if (await canLaunchUrl(uri)) {
|
|
||||||
await launchUrl(uri);
|
|
||||||
} else {
|
|
||||||
Log.error("Could not launch $url");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
|
import 'package:flutter/gestures.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/setting_file_importer_bloc.dart';
|
import 'package:appflowy/workspace/application/settings/setting_file_importer_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/file_picker/file_picker_service.dart';
|
import 'package:flowy_infra/file_picker/file_picker_service.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class ImportAppFlowyData extends StatefulWidget {
|
class ImportAppFlowyData extends StatefulWidget {
|
||||||
const ImportAppFlowyData({super.key});
|
const ImportAppFlowyData({super.key});
|
||||||
@ -92,22 +92,14 @@ class AppFlowyDataImportTip extends StatelessWidget {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
decoration: TextDecoration.underline,
|
decoration: TextDecoration.underline,
|
||||||
),
|
),
|
||||||
recognizer: TapGestureRecognizer()..onTap = () => _launchURL(),
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () => afLaunchUrlString(url),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _launchURL() async {
|
|
||||||
final uri = Uri.parse(url);
|
|
||||||
if (await canLaunchUrl(uri)) {
|
|
||||||
await launchUrl(uri);
|
|
||||||
} else {
|
|
||||||
Log.error("Could not launch $url");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImportAppFlowyDataButton extends StatefulWidget {
|
class ImportAppFlowyDataButton extends StatefulWidget {
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
import 'package:flutter/gestures.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/supabase_cloud_setting_bloc.dart';
|
import 'package:appflowy/workspace/application/settings/supabase_cloud_setting_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/supabase_cloud_urls_bloc.dart';
|
import 'package:appflowy/workspace/application/settings/supabase_cloud_urls_bloc.dart';
|
||||||
@ -5,7 +10,6 @@ import 'package:appflowy/workspace/presentation/home/toast.dart';
|
|||||||
import 'package:appflowy/workspace/presentation/settings/widgets/_restart_app_button.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/_restart_app_button.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
|
||||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
|
||||||
import 'package:appflowy_result/appflowy_result.dart';
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
@ -14,11 +18,7 @@ import 'package:flowy_infra/size.dart';
|
|||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class SettingSupabaseCloudView extends StatelessWidget {
|
class SettingSupabaseCloudView extends StatelessWidget {
|
||||||
const SettingSupabaseCloudView({required this.restartAppFlowy, super.key});
|
const SettingSupabaseCloudView({required this.restartAppFlowy, super.key});
|
||||||
@ -330,7 +330,8 @@ class SupabaseSelfhostTip extends StatelessWidget {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
decoration: TextDecoration.underline,
|
decoration: TextDecoration.underline,
|
||||||
),
|
),
|
||||||
recognizer: TapGestureRecognizer()..onTap = () => _launchURL(),
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () => afLaunchUrlString(url),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: LocaleKeys.settings_menu_selfHostEnd.tr(),
|
text: LocaleKeys.settings_menu_selfHostEnd.tr(),
|
||||||
@ -341,13 +342,4 @@ class SupabaseSelfhostTip extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _launchURL() async {
|
|
||||||
final uri = Uri.parse(url);
|
|
||||||
if (await canLaunchUrl(uri)) {
|
|
||||||
await launchUrl(uri);
|
|
||||||
} else {
|
|
||||||
Log.error("Could not launch $url");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -8,11 +12,8 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
import '../../../../generated/locale_keys.g.dart';
|
import '../../../../generated/locale_keys.g.dart';
|
||||||
import '../../../../startup/startup.dart';
|
import '../../../../startup/startup.dart';
|
||||||
@ -234,9 +235,7 @@ class _OpenStorageButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final uri = Directory(usingPath).uri;
|
final uri = Directory(usingPath).uri;
|
||||||
if (await canLaunchUrl(uri)) {
|
await afLaunchUrl(uri, context: context);
|
||||||
await launchUrl(uri);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/theme_upload/theme_upload_view.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/theme_upload/theme_upload_view.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
@ -5,14 +8,12 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
||||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class ThemeUploadLearnMoreButton extends StatelessWidget {
|
class ThemeUploadLearnMoreButton extends StatelessWidget {
|
||||||
const ThemeUploadLearnMoreButton({super.key});
|
const ThemeUploadLearnMoreButton({super.key});
|
||||||
|
|
||||||
static const learnMoreURL =
|
static const learnMoreURL =
|
||||||
'https://appflowy.gitbook.io/docs/essential-documentation/themes';
|
'https://docs.appflowy.io/docs/appflowy/product/themes';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -30,27 +31,29 @@ class ThemeUploadLearnMoreButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final uri = Uri.parse(learnMoreURL);
|
final uri = Uri.parse(learnMoreURL);
|
||||||
if (await canLaunchUrl(uri)) {
|
await afLaunchUrl(
|
||||||
await launchUrl(uri);
|
uri,
|
||||||
} else {
|
context: context,
|
||||||
if (context.mounted) {
|
onFailure: (_) async {
|
||||||
await Dialogs.show(
|
if (context.mounted) {
|
||||||
context,
|
await Dialogs.show(
|
||||||
child: FlowyDialog(
|
context,
|
||||||
child: FlowyErrorPage.message(
|
child: FlowyDialog(
|
||||||
LocaleKeys
|
child: FlowyErrorPage.message(
|
||||||
.settings_appearance_themeUpload_urlUploadFailure
|
LocaleKeys
|
||||||
.tr()
|
.settings_appearance_themeUpload_urlUploadFailure
|
||||||
.replaceAll(
|
.tr()
|
||||||
'{}',
|
.replaceAll(
|
||||||
uri.toString(),
|
'{}',
|
||||||
),
|
uri.toString(),
|
||||||
howToFix: LocaleKeys.errorDialog_howToFixFallback.tr(),
|
),
|
||||||
|
howToFix: LocaleKeys.errorDialog_howToFixFallback.tr(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
},
|
||||||
}
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/startup/tasks/rust_sdk.dart';
|
import 'package:appflowy/startup/tasks/rust_sdk.dart';
|
||||||
@ -10,11 +14,8 @@ import 'package:flowy_infra/size.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class QuestionBubble extends StatelessWidget {
|
class QuestionBubble extends StatelessWidget {
|
||||||
const QuestionBubble({super.key});
|
const QuestionBubble({super.key});
|
||||||
@ -86,26 +87,26 @@ class _BubbleActionListState extends State<BubbleActionList> {
|
|||||||
if (action is BubbleActionWrapper) {
|
if (action is BubbleActionWrapper) {
|
||||||
switch (action.inner) {
|
switch (action.inner) {
|
||||||
case BubbleAction.whatsNews:
|
case BubbleAction.whatsNews:
|
||||||
_launchURL("https://www.appflowy.io/what-is-new");
|
afLaunchUrlString("https://www.appflowy.io/what-is-new");
|
||||||
break;
|
break;
|
||||||
case BubbleAction.help:
|
case BubbleAction.help:
|
||||||
_launchURL("https://discord.gg/9Q2xaN37tV");
|
afLaunchUrlString("https://discord.gg/9Q2xaN37tV");
|
||||||
break;
|
break;
|
||||||
case BubbleAction.debug:
|
case BubbleAction.debug:
|
||||||
_DebugToast().show();
|
_DebugToast().show();
|
||||||
break;
|
break;
|
||||||
case BubbleAction.shortcuts:
|
case BubbleAction.shortcuts:
|
||||||
_launchURL(
|
afLaunchUrlString(
|
||||||
"https://appflowy.gitbook.io/docs/essential-documentation/shortcuts",
|
"https://docs.appflowy.io/docs/appflowy/product/shortcuts",
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case BubbleAction.markdown:
|
case BubbleAction.markdown:
|
||||||
_launchURL(
|
afLaunchUrlString(
|
||||||
"https://appflowy.gitbook.io/docs/essential-documentation/markdown",
|
"https://docs.appflowy.io/docs/appflowy/product/markdown",
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case BubbleAction.github:
|
case BubbleAction.github:
|
||||||
_launchURL(
|
afLaunchUrlString(
|
||||||
'https://github.com/AppFlowy-IO/AppFlowy/issues/new/choose',
|
'https://github.com/AppFlowy-IO/AppFlowy/issues/new/choose',
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -116,15 +117,6 @@ class _BubbleActionListState extends State<BubbleActionList> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _launchURL(String url) async {
|
|
||||||
final uri = Uri.parse(url);
|
|
||||||
if (await canLaunchUrl(uri)) {
|
|
||||||
await launchUrl(uri);
|
|
||||||
} else {
|
|
||||||
throw 'Could not launch $url';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DebugToast {
|
class _DebugToast {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"title": "Title",
|
"title": "Title",
|
||||||
"youCanAlso": "You can also",
|
"youCanAlso": "You can also",
|
||||||
"and": "and",
|
"and": "and",
|
||||||
|
"failedToOpenUrl": "Failed to open url: {}",
|
||||||
"blockActions": {
|
"blockActions": {
|
||||||
"addBelowTooltip": "Click to add below",
|
"addBelowTooltip": "Click to add below",
|
||||||
"addAboveCmd": "Alt+click",
|
"addAboveCmd": "Alt+click",
|
||||||
|
Loading…
Reference in New Issue
Block a user