Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/src/app/shell/navigation/link_navigation_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void handleLink(BuildContext context, {required String url, bool forceOpenInBrow
}

// Try navigating to post
int? postId = await getLemmyPostId(context, url);
int? postId = await getLemmyPostId(context, checkEmbeddedInstance(url));
if (postId != null) {
try {
// Show the loading page while we fetch the post
Expand Down
16 changes: 16 additions & 0 deletions lib/src/features/instance/domain/utils/instance_link_utils.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';

import 'package:thunder/src/features/instance/data/constants/known_instances.dart';
import 'package:thunder/src/foundation/primitives/primitives.dart';
import 'package:thunder/src/features/search/search.dart';
import 'package:thunder/src/features/session/api.dart';
Expand Down Expand Up @@ -33,6 +34,21 @@ Future<String?> getLemmyUser(String text) async {
return result?.qualified;
}

// Check for URLs from instance-agnostic shareable links like lemmyverse.link and threadiverse.link.
// Users and communities are already parsed correctly, this adds detection and handling for posts.
String checkEmbeddedInstance(String text) {
final uri = Uri.tryParse(text);
if (uri == null || uri.host.isEmpty) return text;
if (uri.pathSegments.isEmpty) return text;

final first = uri.pathSegments.first;
// Only rewrite if the first path segment exactly matches a known instance host.
if (!knownInstances.containsKey(first)) return text;

final remaining = uri.pathSegments.sublist(1);
return uri.replace(host: first, pathSegments: remaining).toString();
}

/// Gets the post ID from a Lemmy/PieFed URL.
/// If the URL is from a different instance, it will attempt to resolve it.
Future<int?> getLemmyPostId(BuildContext context, String text) async {
Expand Down
4 changes: 3 additions & 1 deletion lib/src/foundation/utils/threadiverse_link_parser_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ final RegExp _lemmyUserMention = RegExp(r'^@?(https?:\/\/)?((?:(?!\/u\/u).)*)@(.

/// Matches instance.tld/post/123
/// Groups: 2=instance, 3=postId
final RegExp _lemmyPostUrl = RegExp(r'^(https?:\/\/)(.*)/post/([0-9]+)$');
// final RegExp _lemmyPostUrl = RegExp(r'^(https?:\/\/)(.*)/post/([0-9]+)$');
// Modified to allow query parameters, e.g. /post/123?foo=bar
final RegExp _lemmyPostUrl = RegExp(r'^(https?:\/\/)(.*)/post/([0-9]+)(?:\?.*)?$');

/// Matches instance.tld/comment/123
/// Groups: 2=instance, 3=commentId
Expand Down