Skip to content

internal_links: Add "/" before fragment identifier #874

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

satyam372
Copy link

Fixes: #845

This adds a '/ ' after hostname. when this Url is posted in Zulip message it gets linkified.
Screenshot_20240809-213108 1

@gnprice gnprice added the maintainer review PR ready for review by Zulip maintainers label Aug 11, 2024
@gnprice gnprice requested a review from PIG208 August 11, 2024 22:25
Comment on lines 62 to 65
for (final testCase in testCases) {
final String inputUrl = testCase.$1;
final String expectedUrl = testCase.$2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
for (final testCase in testCases) {
final String inputUrl = testCase.$1;
final String expectedUrl = testCase.$2;
for (final (inputUrl, expectedUrl) in testCases) {

I can see that this helper parallels testExpectedNarrows, where the same pattern is also applicable.

@@ -98,7 +98,7 @@ Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) {
fragment.write('/near/$nearMessageId');
}

return store.realmUrl.replace(fragment: fragment.toString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

96593ba internal_links [nit]: Add path: '/' to store.realmUrl.replace for proper Url handling
I think we don't ever use [nit] in commit summaries, so we can just drop that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have tests in this commit, and the tests added in the other commit do not fail if we remove this change. We need to do some testing here.

@@ -54,6 +54,37 @@ void main() {
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3010732 internal_link_test: Create 'parseInternalLink full url cases' test

We usually use internal_link test for changes like this. git log --oneline -- path/to/file is a way to look for predecessors.

('https://example.com/#narrow/stream/check', 'https://example.com/#narrow/stream/check'),
('https://example.com/#narrow/stream/3-mobile/topic/topic1', 'https://example.com/#narrow/stream/3-mobile/topic/topic1'),
('https://another.com/#narrow/stream/mobile', 'https://another.com/#narrow/stream/mobile'),
('https://example.com/#narrow/stream/check/topic/test', 'https://example.com/#narrow/stream/check/topic/test'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I understand the purpose of these test cases, as the input and the expected output are the same.

@PIG208
Copy link
Member

PIG208 commented Aug 12, 2024

Thanks for the PR! Left some comments.

@satyam372 satyam372 marked this pull request as draft August 15, 2024 06:14
@satyam372 satyam372 force-pushed the add-trailing-slash branch 2 times, most recently from 231512d to e617802 Compare September 11, 2024 18:14
@PIG208 PIG208 self-requested a review September 11, 2024 18:15
@satyam372 satyam372 marked this pull request as ready for review September 11, 2024 19:10
Copy link
Member

@PIG208 PIG208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update! Went over this and left some comments. One other suggestion is to add the tests in the same commit that makes the change.

@@ -59,7 +59,7 @@ String? decodeHashComponent(String str) {
Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) {
// TODO(server-7)
final apiNarrow = resolveDmElements(
narrow.apiEncode(), store.connection.zulipFeatureLevel!);
narrow.apiEncode(), store.connection.zulipFeatureLevel!);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the indentation change here is unintentional.

@@ -95,8 +95,11 @@ Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) {
if (nearMessageId != null) {
fragment.write('/near/$nearMessageId');
}
final realmUrlWithSlash = store.realmUrl.path.endsWith('/')
? store.realmUrl
: store.realmUrl.replace(path: '${store.realmUrl.path}/');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
: store.realmUrl.replace(path: '${store.realmUrl.path}/');
final realmUrlWithSlash = store.realmUrl.path.endsWith('/')
? store.realmUrl
: store.realmUrl.replace(path: '${store.realmUrl.path}/');

final messageLink = narrowLink(store, narrow, nearMessageId: 12345);
final urlString = messageLink.toString();
final fragmentIndex = urlString.indexOf('#');
expect(fragmentIndex, greaterThan(0));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually use checks for our tests. So this can be check(fragmentIndex).isGreaterThan(0); instead. This applies to the other checks here too.

eg.stream(streamId: 123, name: 'check'),
];
test('narrowLink should generate the full URL correctly', () async {
final store = await setupStore(realmUrl: realmUrl, streams: streams);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This realmUrl is https://example.com/, which comes with a trailing /. So we might want to override this for testing.

expect(
urlString.startsWith('https://example.com/#narrow/stream/123-check/topic'),
isTrue
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this test and the one before it can be combined into one. However, looking at this more, it might be simpler to just check if urlString equals the URL we expect (i.e.: 'https://example.com/#narrow/stream/123-check/topic').

Or, even better, we can add the test to test/widgets/action_sheet_test.dart, as a test similar to "copies message link to clipboard". This way we get to test it end-to-end. In this case, no change is needed for test/model/internal_link_test.dart.

@@ -59,7 +59,7 @@ String? decodeHashComponent(String str) {
Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nits on commit message:

  • updates -> Updates
  • ...fragment identifier This... -> ...fragment identifier. This...
  • likified -> linkified

and an empty space between the paragraph and Fixes: #845.

@satyam372 satyam372 marked this pull request as draft September 13, 2024 05:13
@satyam372 satyam372 force-pushed the add-trailing-slash branch 3 times, most recently from 74b44f3 to 0bc2e39 Compare September 15, 2024 20:35
@satyam372 satyam372 marked this pull request as ready for review September 15, 2024 20:57
Copy link
Member

@PIG208 PIG208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update! The implementation now looks good to me. Added some comments on the new test.

@@ -553,6 +553,21 @@ void main() {
});
});


group('narrowLink URL generation tests', () {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra empty line here and above the group.

testWidgets('Full Url Testing', (tester) async {
final message = eg.streamMessage();
final narrow = TopicNarrow.ofMessage(message);
await setupToMessageActionSheet(tester, message: message, narrow: narrow);
Copy link
Member

@PIG208 PIG208 Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this test, it matters for us that the store.realmUrl used does not end with a slash. However, the default value is "https://chat.example/" (see eg.account). We should find a way to override that when setting up the store.

final narrow = TopicNarrow.ofMessage(message);
await setupToMessageActionSheet(tester, message: message, narrow: narrow);
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
final generatedLink = narrowLink(store, narrow, nearMessageId: message.id).toString();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make this end-to-end, let's generate the link through tapCopyMessageLinkButton. We should move this test to the "CopyMessageLinkButton" group.

Comment on lines 565 to 567
const expectedPrefix = 'https://chat.example/#narrow/stream/123-stream-123/topic';
final truncatedLink = generatedLink.split('/example').first;
check(truncatedLink).equals(expectedPrefix);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
const expectedPrefix = 'https://chat.example/#narrow/stream/123-stream-123/topic';
final truncatedLink = generatedLink.split('/example').first;
check(truncatedLink).equals(expectedPrefix);
check(generatedLink).startsWith('https://chat.example/#narrow/stream/123-stream-123/topic');

@@ -96,7 +96,11 @@ Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) {
fragment.write('/near/$nearMessageId');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I missed this in the last round. "Variable" in the commit summary is capitalized, but we should use "variable" instead.

@satyam372 satyam372 marked this pull request as draft September 16, 2024 19:47
@@ -24,6 +24,7 @@ import '../api/fake_api.dart';
import '../example_data.dart' as eg;
import '../flutter_checks.dart';
import '../model/binding.dart';
import '../model/internal_link_test.dart';
import '../model/test_store.dart';
Copy link
Author

@satyam372 satyam372 Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import internal_link_test.dart to use setupstore to generate link without an '/' before '#'.

final expectedLink = narrowLink(store, narrow, nearMessageId: message.id).toString();
final generatedLink = (await Clipboard.getData('text/plain'))?.text ?? '';
final normalizedExpectedLink = expectedLink.replaceAll('123-unknown', '123-stream-123');
check(generatedLink).equals(normalizedExpectedLink);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

before normalization, the test was failing due to mismatch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, interesting. Looks like that could be a result of not having the stream in store. This is because expectedLink and generatedLink are generated from separate instances of PerAccountStore:
expectedLink uses the store created with setupStore above;
generatedLink uses the store set up from setupToMessageActionSheet.

How about adding an optional parameter Account? account to setupToMessageActionSheet, which can be used to override the realmUrl?

@satyam372 satyam372 marked this pull request as ready for review September 19, 2024 20:07
@satyam372
Copy link
Author

PTAL @PIG208

Copy link
Member

@PIG208 PIG208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the revision! Left a comment regarding the output mismatch issue.

final expectedLink = narrowLink(store, narrow, nearMessageId: message.id).toString();
final generatedLink = (await Clipboard.getData('text/plain'))?.text ?? '';
final normalizedExpectedLink = expectedLink.replaceAll('123-unknown', '123-stream-123');
check(generatedLink).equals(normalizedExpectedLink);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, interesting. Looks like that could be a result of not having the stream in store. This is because expectedLink and generatedLink are generated from separate instances of PerAccountStore:
expectedLink uses the store created with setupStore above;
generatedLink uses the store set up from setupToMessageActionSheet.

How about adding an optional parameter Account? account to setupToMessageActionSheet, which can be used to override the realmUrl?

@satyam372 satyam372 marked this pull request as draft September 23, 2024 19:14
@satyam372 satyam372 force-pushed the add-trailing-slash branch 2 times, most recently from bc34132 to 51a53fb Compare September 26, 2024 19:07
@@ -38,11 +38,12 @@ late FakeApiConnection connection;
Future<void> setupToMessageActionSheet(WidgetTester tester, {
required Message message,
required Narrow narrow,
Account? account,
}) async {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add parameter Account so that we can override realmUrl to produce Url without '/' before '#'.

@satyam372 satyam372 marked this pull request as ready for review September 27, 2024 20:33
Copy link
Member

@PIG208 PIG208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall! Some small comments, and I going to mark this for integration review.

testWidgets('Full Url Testing', (tester) async {
final message = eg.streamMessage();
final narrow = TopicNarrow.ofMessage(message);
await setupToMessageActionSheet(tester, message: message, narrow: narrow);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need to setup the action sheet again. We did that at line 566.

Comment on lines +562 to +585
await tapCopyMessageLinkButton(tester);
await tester.pump(Duration.zero);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Move this to just before the line where we define expectedLink, so the reader gets the contextual information about where the clipboard data comes from

Comment on lines 565 to 569
final customAccount = eg.selfAccount.copyWith(id: 2, realmUrl: Uri.parse('https://chat.example'));
await setupToMessageActionSheet(tester, message: message, narrow: narrow, account: customAccount);
final customAccountStore = await testBinding.globalStore.perAccount(customAccount.id);

final expectedLink = narrowLink(customAccountStore, narrow, nearMessageId: message.id).toString();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines are too long. Try to wrap them so that they are under 80 columns wide.

For example:

-     await setupToMessageActionSheet(tester, message: message, narrow: narrow, account: customAccount);
+     await setupToMessageActionSheet(
+       tester, message: message, narrow: narrow, account: customAccount);

@PIG208 PIG208 added integration review Added by maintainers when PR may be ready for integration and removed maintainer review PR ready for review by Zulip maintainers labels Sep 27, 2024
@satyam372 satyam372 force-pushed the add-trailing-slash branch 2 times, most recently from 11d5c2f to 3169ff4 Compare September 28, 2024 10:58
@@ -60,8 +63,8 @@ Future<void> setupToMessageActionSheet(WidgetTester tester, {
historyLimited: false,
messages: [message],
).toJson());

await tester.pumpWidget(TestZulipApp(accountId: eg.selfAccount.id,
await tester.pumpAndSettle();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this can be removed, unless I missed something?

Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @satyam372 for the contribution, and @PIG208 for the previous reviews!

Initial comments from me below, in addition to @PIG208's remaining comments above.

This PR also lacks the kind of test that was specified in the issue:

as part of a PR fixing this issue, we should also add a few tests that include, verbatim, the full URL they expect as the output.

It will need to add those.

Comment on lines 99 to 101
final realmUrlWithSlash = store.realmUrl.path.endsWith('/')
? store.realmUrl
: store.realmUrl.replace(path: '${store.realmUrl.path}/');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic seems too broad. If the realm URL looks like https://chat.example/foo, we don't have a reason to turn that to https://chat.example/foo/.

Unless https://chat.example/foo#narrow/etc fails to linkify in a Zulip message, that is. Does it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I tested some URLs and Here are the results:

In a browser: The browser automatically adds a / before the #.

In Zulip Flutter application: When I paste the URL, it does not linkify and is not clickable.
Based on this behavior, I have added a / before the #.

Copy link
Member

@gnprice gnprice Oct 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question is about what Zulip does, though, when you put such a URL into a message. That's what this issue #845 is about:

This is still a valid URL, I believe — but it looks funny, and more concretely it means that if you post it in a Zulip message it doesn't get linkified.

So I tested that just now. The answer is that it does linkify:
https://chat.zulip.org/#narrow/stream/7-test-here/topic/linkification/near/1957680

That is, if you send a message with this text:
https://chat.example/foo#narrow/etc
it becomes a link.

That's the same as what happens if you send a message with this text:
https://chat.example/#narrow/etc

By contrast if you send a message with this text:
https://chat.example#narrow/etc
it doesn't become a link. That's the reason #845 is an issue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Zulip Flutter application: When I paste the URL, it does not linkify and is not clickable.

This is puzzling because it's different from what I observed in my test just now. (I used the web app to send that test message — but the message content gets turned to HTML on the server, so it doesn't matter what client is used.)

Can you post a link to a test message where you found the URL did not linkify? That would make it possible to pin down what variable is controlling the difference in behavior.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The link https://chat.example/foo#narrow/etc does linkify for me. So we probably don't need the slash in this case.

I think the fix for this will just be using startswith instead of endsWith, so that we don't process https://chat.example/foo, but still handle https://chat.example#anything.

These are something that are good to have tests for.

Copy link
Member

@gnprice gnprice Oct 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even simpler than startsWith — check path.isNotEmpty. I believe a URL path will always either be empty or start with /.

await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id);
account ??= eg.selfAccount;
final initialSnapshot = eg.initialSnapshot(zulipFeatureLevel: account.zulipFeatureLevel);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to start mentioning zulipFeatureLevel? If not, keep the story simpler by leaving it out.

@@ -616,4 +634,4 @@ void main() {
check(mockSharePlus.sharedString).isNull();
});
});
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Not an empty line — the problem is that every line should end with a newline, and this commit is editing the file's last line by removing its terminating newline. Previous discussion: #534 (comment) )

@satyam372
Copy link
Author

Thanks @gnprice and @PIG208 for the review. just a small question.
In the current tests, we are dynamically generating and verifying the URL.
Should we be comparing the generated URL directly against a hardcoded, literal full URL string within the test (e.g., including specific realm URLs and message IDs), rather than dynamically building it?

@satyam372 satyam372 marked this pull request as draft October 2, 2024 17:56
@gnprice
Copy link
Member

gnprice commented Oct 4, 2024

Yes. As the issue says:

we should also add a few tests that include, verbatim, the full URL they expect as the output.

For further questions about how to complete the PR, I recommend a chat thread in #mobile-dev-help. That may get a faster response.

@satyam372 satyam372 requested a review from PIG208 October 8, 2024 10:15
@satyam372 satyam372 marked this pull request as ready for review October 8, 2024 10:15
@satyam372
Copy link
Author

PTAL @PIG208

Copy link
Member

@PIG208 PIG208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the revision! I know there has been many review comments, but we are making some progress. I think the structure of the test looks fine. You can go to #mobile-dev-help anytime if you run into issues.

@@ -616,4 +634,4 @@ void main() {
check(mockSharePlus.sharedString).isNull();
});
});
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The newline still seems to be missing. Could you add it there?

Comment on lines 99 to 101
final realmUrlWithSlash = store.realmUrl.path.endsWith('/')
? store.realmUrl
: store.realmUrl.replace(path: '${store.realmUrl.path}/');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The link https://chat.example/foo#narrow/etc does linkify for me. So we probably don't need the slash in this case.

I think the fix for this will just be using startswith instead of endsWith, so that we don't process https://chat.example/foo, but still handle https://chat.example#anything.

These are something that are good to have tests for.


await tapCopyMessageLinkButton(tester);
await tester.pump(Duration.zero);
const expectedLink = 'https://chat.zulip.org/#narrow/stream/123-stream-123/topic/example.20topic.20341/near/13579';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These expectedLinks look good to me.

testWidgets('Copies message link with verbatim, full URL output', (tester) async {
final stream = eg.stream(streamId: 123, name: 'stream 123');
final message = eg.streamMessage(
id: 13579, stream: stream, topic: 'example topic 341');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation, and some other places in this file.

});

group('Message link verbatim URL tests', () {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can remove the line here.

id: 98765, stream: stream, topic: 'Whats up? 123!');
final narrow = TopicNarrow.ofMessage(message);
final account = eg.selfAccount.copyWith(
realmUrl: Uri.parse('https://chat.zulip.org'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be fine to reuse the same set of stream and topic, because we are more interested in the variants of realmUrl. In addition to this one, let's also try something like https://chat.zulip.org/path and https://chat.zulip.org/. Since most of these tests will be similar, extracting a helper will be simplify the code.

@@ -551,6 +554,93 @@ void main() {
final expectedLink = narrowLink(store, narrow, nearMessageId: message.id).toString();
check(await Clipboard.getData('text/plain')).isNotNull().text.equals(expectedLink);
});

testWidgets('Full Url Testing', (tester) async {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have the new tests, we should be able to remove this one.

@satyam372 satyam372 marked this pull request as draft October 12, 2024 10:09
@satyam372 satyam372 force-pushed the add-trailing-slash branch 2 times, most recently from ba6047e to d4733c3 Compare October 14, 2024 06:23
Updates the URL construction to include a trailing slash
before the fragment identifier. This ensures that the URL
is properly formatted and makes the url linkified.

Co-authored-by: Greg Price <[email protected]>
Fixes: zulip#845
@satyam372 satyam372 requested a review from PIG208 October 14, 2024 07:01
@satyam372 satyam372 marked this pull request as ready for review October 14, 2024 07:01
@satyam372
Copy link
Author

PTAL @PIG208

@satyam372
Copy link
Author

Please review @gnprice.

Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking again at this PR, the commit still doesn't make it at all clear to me that it makes things work the way we want them to. When sending a PR to Zulip (or really anywhere), it's important to make the code clear and the explanations clear. See the Zulip guide on submitting reviewable PRs:
https://zulip.readthedocs.io/en/latest/contributing/reviewable-prs.html

This has been a long thread, because @PIG208 and I have already spent a substantial amount of time working with you to try to improve the PR. But given the PR's current state, it would still take a substantial amount more work to get it to be something that we can merge.

It's particularly concerning that even the latest revision introduces new problems that should have been easy to catch if you re-read your changes and think through what they're doing. (I've flagged two such problems below.) As our guide says, it's important to review your own work before asking others to do so.

Closing this PR because it's not on track to become something we can merge with a reasonable amount of effort from the core team.


Based on this thread and #1013, I think you don't yet have the skills to learn to contribute productively in the Zulip project. You're welcome to try again after at least 6 months.

I recommend you spend time working on other projects, and reading a lot of code, especially reading code in well-maintained codebases like Zulip or upstream Flutter (i.e., any of the main repositories at https://github.com/zulip or https://github.com/flutter). This advice from our contributing guide is applicable to a wide variety of codebases:

  • Set up a development environment following the instructions in the project README.
  • Start reading recent commits to see the code we’re writing. Use either a graphical Git viewer like gitk, or git log -p with the “secret” to reading its output.
  • Pick some of the code that appears in those Git commits and that looks interesting. Use your IDE to visit that code and to navigate to related code, reading to see how it works and how the codebase is organized.

I recommend also investing effort in clearly explaining why your changes work correctly. As our guide to reviewable PRs says, that begins with clearly reasoning through that question yourself:

When you write code, you should make sure that you understand why it works as intended. This is the foundation for being able to explain your proposed changes to others.

Even in personal projects where nobody else is reading your explanations, taking the time to clearly write them down will help you write higher-quality code. It will also be useful practice for contributing to projects like Zulip where there are other people you need to explain your changes to.

Comment on lines +99 to +101
final realmUrlWithSlash = store.realmUrl.path.isNotEmpty
? store.realmUrl
: store.realmUrl.replace(path: '${store.realmUrl.path}/');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the "else" case here, the path will have to be empty. So this expression is unnecessarily complicated.

Comment on lines +589 to +592
testWidgets('Copies link with custom realm path', (tester) async {
await testMessageLink(
tester: tester,
realmUrl: 'https://chat.example/foo',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is difficult to read because it's missing indentation:

Suggested change
testWidgets('Copies link with custom realm path', (tester) async {
await testMessageLink(
tester: tester,
realmUrl: 'https://chat.example/foo',
testWidgets('Copies link with custom realm path', (tester) async {
await testMessageLink(
tester: tester,
realmUrl: 'https://chat.example/foo',

The same is true of each of the other test cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integration review Added by maintainers when PR may be ready for integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Include / after hostname in generated links
3 participants