kopia lustrzana https://gitlab.com/mysocialportal/relatica
Add opening tags in app feature
rodzic
d891d6fc53
commit
4f882df541
|
@ -20,9 +20,11 @@ import '../../riverpod_controllers/settings_services.dart';
|
|||
import '../../riverpod_controllers/timeline_entry_filter_services.dart';
|
||||
import '../../riverpod_controllers/timeline_entry_services.dart';
|
||||
import '../../riverpod_controllers/timeline_services.dart';
|
||||
import '../../routes.dart';
|
||||
import '../../utils/clipboard_utils.dart';
|
||||
import '../../utils/filter_runner.dart';
|
||||
import '../../utils/html_to_edit_text_helper.dart';
|
||||
import '../../utils/network_utils.dart';
|
||||
import '../../utils/responsive_sizes_calculator.dart';
|
||||
import '../../utils/snackbar_builder.dart';
|
||||
import '../../utils/url_opening_utils.dart';
|
||||
|
@ -198,7 +200,7 @@ class _StatusControlState extends ConsumerState<FlattenedTreeEntryControl> {
|
|||
child: Text(
|
||||
'Content Summary: ${entry.spoilerText} (Click to ${showContent ? "Hide" : "Show"})')),
|
||||
if (showContent || !showSpoilerControl) ...[
|
||||
buildContentField(context, entry),
|
||||
buildContentField(context, profile, entry),
|
||||
const VerticalPadding(
|
||||
height: 5,
|
||||
),
|
||||
|
@ -245,11 +247,28 @@ class _StatusControlState extends ConsumerState<FlattenedTreeEntryControl> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget buildContentField(BuildContext context, TimelineEntry entry) {
|
||||
Widget buildContentField(
|
||||
BuildContext context, Profile profile, TimelineEntry entry) {
|
||||
return HtmlTextViewerControl(
|
||||
content: entry.body,
|
||||
onTapUrl: (url) async =>
|
||||
await openUrlStringInSystembrowser(context, url, 'link'),
|
||||
onTapUrl: (url) async {
|
||||
await processUrlStringForTag(url).withResultAsync((tagName) async {
|
||||
final openInApp = ref.read(openTagsInAppProvider);
|
||||
if (openInApp) {
|
||||
await context.push('${ScreenPaths.tagView}/$tagName');
|
||||
return;
|
||||
}
|
||||
|
||||
final usersTagSearchPage =
|
||||
generateTagSearchFromProfile(profile, tagName);
|
||||
await openUrlStringInSystembrowser(
|
||||
context, usersTagSearchPage, 'link');
|
||||
}).withErrorAsync((_) async {
|
||||
await openUrlStringInSystembrowser(context, url, 'link');
|
||||
});
|
||||
|
||||
return true;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
const deepLinkScheme = 'relatica';
|
||||
|
||||
const macOsGroupId = 'T69YZGT58U.relatica';
|
||||
|
||||
String randomId() => const Uuid().v4().toString();
|
||||
|
|
|
@ -232,3 +232,19 @@ class ColorBlindnessTestingModeSetting
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class OpenTagsInApp extends _$SpoilerHidingSetting {
|
||||
static const _openTagsInAppKey = 'OpenTagsInApp';
|
||||
|
||||
@override
|
||||
bool build() {
|
||||
return ref.watch(sharedPreferencesProvider).getBool(_openTagsInAppKey) ??
|
||||
true;
|
||||
}
|
||||
|
||||
set value(bool value) {
|
||||
ref.read(sharedPreferencesProvider).setBool(_openTagsInAppKey, value);
|
||||
state = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,5 +156,20 @@ final colorBlindnessTestingModeSettingProvider = NotifierProvider<
|
|||
);
|
||||
|
||||
typedef _$ColorBlindnessTestingModeSetting = Notifier<ColorBlindnessType>;
|
||||
String _$openTagsInAppHash() => r'4aeee38bd8de61c8fdf84cd6cb30bc61fbeeca1b';
|
||||
|
||||
/// See also [OpenTagsInApp].
|
||||
@ProviderFor(OpenTagsInApp)
|
||||
final openTagsInAppProvider = NotifierProvider<OpenTagsInApp, bool>.internal(
|
||||
OpenTagsInApp.new,
|
||||
name: r'openTagsInAppProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$openTagsInAppHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$OpenTagsInApp = Notifier<bool>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
|
|
@ -45,7 +45,7 @@ class ScreenPaths {
|
|||
static String gallery = '/gallery';
|
||||
static String notifications = '/notifications';
|
||||
static String signin = '/signin';
|
||||
static String manageProfiles = '/switchProfiles';
|
||||
static String manageProfiles = '/switch_profiles';
|
||||
static String circleManagement = '/circle_management';
|
||||
static String signup = '/signup';
|
||||
static String userProfile = '/user_profile';
|
||||
|
@ -53,8 +53,8 @@ class ScreenPaths {
|
|||
static String likes = '/likes';
|
||||
static String reshares = '/reshares';
|
||||
static String explore = '/explore';
|
||||
static String logViewer = '/logViewer';
|
||||
static String tagView = '/tagView';
|
||||
static String logViewer = '/log_viewer';
|
||||
static String tagView = '/tag_view';
|
||||
}
|
||||
|
||||
bool needAuthChangeInitialized = true;
|
||||
|
|
|
@ -34,6 +34,7 @@ class SettingsScreen extends ConsumerWidget {
|
|||
_NetworkTimeoutWidget(),
|
||||
_NotificationGroupingWidget(),
|
||||
_SpoilerHidingWidget(),
|
||||
_OpenTagsInAppWidget(),
|
||||
_ThemeWidget(),
|
||||
if (!kReleaseMode) _ColorBlindnessWidget(),
|
||||
_ClearCachesWidget(),
|
||||
|
@ -223,6 +224,24 @@ class _SpoilerHidingWidget extends ConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class _OpenTagsInAppWidget extends ConsumerWidget {
|
||||
const _OpenTagsInAppWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final openTagsInApp = ref.watch(openTagsInAppProvider);
|
||||
return ListTile(
|
||||
title: const Text('Open Tags In App'),
|
||||
trailing: Switch(
|
||||
onChanged: (value) {
|
||||
ref.read(openTagsInAppProvider.notifier).value = value;
|
||||
},
|
||||
value: openTagsInApp,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ThemeWidget extends ConsumerWidget {
|
||||
const _ThemeWidget();
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ void _updateSwapTagLinks(Profile profile, Node node, List<String> tags) {
|
|||
.firstWhere((t) => t.toLowerCase() == tagLowercase, orElse: () => '')
|
||||
.isNotEmpty;
|
||||
if (hasExpectedTag) {
|
||||
final newTagUrl = generateTagUrlFromProfile(profile, tag);
|
||||
final newTagUrl = generateTagUriFromProfile(profile, tag);
|
||||
node.attributes['href'] = newTagUrl.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,32 @@
|
|||
import '../models/auth/profile.dart';
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
Uri generateTagUrlFromProfile(Profile profile, String tag) {
|
||||
return Uri.https(profile.serverName, '/search', {'tag': tag});
|
||||
import '../globals.dart';
|
||||
import '../models/auth/profile.dart';
|
||||
import '../routes.dart';
|
||||
|
||||
Uri generateTagUriFromProfile(Profile profile, String tag) {
|
||||
return Uri.parse('relatica://route${ScreenPaths.tagView}/$tag');
|
||||
}
|
||||
|
||||
Result<String, bool> processUrlStringForTag(String url) {
|
||||
final uri = Uri.parse(url);
|
||||
if (uri.scheme == deepLinkScheme &&
|
||||
uri.host == 'route' &&
|
||||
uri.pathSegments.length == 2) {
|
||||
final route = '/${uri.pathSegments[0]}';
|
||||
final tag = uri.pathSegments[1];
|
||||
if (route == ScreenPaths.tagView) {
|
||||
return Result.ok(tag);
|
||||
}
|
||||
}
|
||||
|
||||
return Result.error(false);
|
||||
}
|
||||
|
||||
String generateTagSearchFromProfile(Profile profile, String tagName) {
|
||||
return Uri.https(
|
||||
profile.serverName,
|
||||
'/search',
|
||||
{'tag': tagName},
|
||||
).toString();
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue