Skip to content

Conversation

rajveermalviya
Copy link
Member

@rajveermalviya rajveermalviya commented Sep 19, 2025

This doesn't yet handle RealmUpdateEvent, will send a follow-up PR for it.

Fixes: #1036

@rajveermalviya rajveermalviya added the maintainer review PR ready for review by Zulip maintainers label Sep 19, 2025
Copy link
Collaborator

@chrisbobbe chrisbobbe left a comment

Choose a reason for hiding this comment

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

Thanks, this will be helpful! Comments below.

Also:

  • Does the 'basic happy case' test in test/widgets/login_test.dart need to be updated in order to catch a bug where the values aren't stored properly on login? (Or to be more explicit about testing that?)
  • Let's leave a TODO(#668) to remember to update the database on events


final bool realmEnableReadReceipts;

final Uri realmIconUrl;
Copy link
Collaborator

Choose a reason for hiding this comment

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

api: Add realmName and realmIcon to InitialSnapshot

nit: realmIconUrl in commit message, right?

realmUrl: realmUrl ?? _realmUrl,
realmName: realmName ?? 'Example Zulip organization',
realmIcon: realmIcon ?? '$realmUrl/icon.png',
realmIcon: realmIcon ?? _realmIcon,
Copy link
Collaborator

Choose a reason for hiding this comment

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

_realmIcon is a relative URL, right? So this changes the behavior when realmIcon isn't passed to eg.serverSettings: before this change, it was an absolute URL (starting with realmUrl); now, it's a relative URL. Does the API specify what kind to expect? We should match that if so, otherwise probably just match the observed behavior. (Same with the initial snapshot.)

Copy link
Member Author

Choose a reason for hiding this comment

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

API docs don't specify that, but the example response there have "realm_icon": "https://secure.gravatar.com/…" URL, and on CZO the observed URL is /user_avatars/2/realm/icon.png?version=3. So, I guess it can be either ot those (absolute or relative).

Also GetServerSettingsResult.realmIcon was never read before so this change should be nfc, added a note for that in the commit message.

Copy link
Member Author

Choose a reason for hiding this comment

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

And separated this change to 6e0d9e4.

/// This corresponds to [GetServerSettingsResult.realmName].
Column<String> get realmName => text().nullable()();

/// The organization icon URL of the Zulip realm this account is on.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: can remove "organization", it's redundant with "Zulip realm"

Comment on lines 127 to 137
/// The name of the Zulip realm this account is on.
///
/// This corresponds to [GetServerSettingsResult.realmName].
Column<String> get realmName => text().nullable()();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we add a line like

  /// Nullable just because older versions of the app didn't store this.

here and on realmIcon?

Copy link
Collaborator

Choose a reason for hiding this comment

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

And in migrateLegacyAppData, maybe add lines like these:

--- lib/model/legacy_app_data.dart
+++ lib/model/legacy_app_data.dart
@@ -94,6 +94,8 @@ Future<void> migrateLegacyAppData(AppDatabase db) async {
     try {
       await db.createAccount(AccountsCompanion.insert(
         realmUrl: account.realm,
+        // no realmName; legacy app didn't record it
+        // no realmIcon; legacy app didn't record it
         userId: account.userId!,
         email: account.email,
         apiKey: account.apiKey,

import 'package:drift/remote.dart';
import 'package:sqlite3/common.dart';

import '../api/route/realm.dart';
Copy link
Collaborator

Choose a reason for hiding this comment

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

db: Store realmName and realmIcon in the Accounts table

And update account creation during login to populate
these fields from server settings.

Updates: #1036

Hmm I haven't seen an Updates: <issue> line before; what does that mean?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, I just meant to relate to the issue that this commit partly fixes. I guess Related: or the more direct Fixes-partly: fits better here.

Comment on lines 412 to 413
realmName: Value(widget.serverSettings.realmName),
realmIcon: Value(widget.serverSettings.realmIcon),
Copy link
Collaborator

Choose a reason for hiding this comment

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

db: Store realmName and realmIcon in the Accounts table

At this commit, the values are never updated when they change on the server, even when the user registers an event queue. So they can potentially be out-of-date by weeks, months, years; so let's add a TODO here to update them on /register, and remove the TODO in the next commit when that gets done.

required String realmName,
required Uri realmIcon,
}) async {
assert(_accounts.containsKey(accountId));
Copy link
Collaborator

Choose a reason for hiding this comment

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

There's an async gap before this caller, and normally we consider it possible that the account was logged out during an async gap. But I guess in this case, the async gap is for updating an account (await globalStore.updateZulipVersionData), and that can't successfully happen concurrently with deleting the account? Meaning this assert should actually always hold?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added a check at the callsite of updateRealmData.

@rajveermalviya rajveermalviya force-pushed the pr-realm-name-icon branch 2 times, most recently from 3abe521 to 4403816 Compare September 23, 2025 15:20
@rajveermalviya
Copy link
Member Author

Thanks for the review @chrisbobbe! Pushed an update, PTAL.

@chrisbobbe
Copy link
Collaborator

Thanks! Looks good except it looks like these are still pending, from #1860 (review) :

Also:

  • Does the 'basic happy case' test in test/widgets/login_test.dart need to be updated in order to catch a bug where the values aren't stored properly on login? (Or to be more explicit about testing that?)
  • Let's leave a TODO(#668) to remember to update the database on events

@rajveermalviya
Copy link
Member Author

Thanks @chrisbobbe! Sorry for missing those. Pushed another update, PTAL.

@chrisbobbe
Copy link
Collaborator

Thanks, LGTM! Marking for Greg's review.

@chrisbobbe chrisbobbe requested review from gnprice and removed request for chrisbobbe September 25, 2025 21:06
@chrisbobbe chrisbobbe assigned gnprice and unassigned chrisbobbe Sep 25, 2025
@chrisbobbe chrisbobbe 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 25, 2025
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 @rajveermalviya for building this, and @chrisbobbe for the previous reviews! Apologies this review is a few days delayed.


final String realmName;
final String realmIcon;
final Uri realmIcon;
Copy link
Member

Choose a reason for hiding this comment

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

nit: do this before adding the corresponding field on InitialSnapshot; that way they agree from the beginning

Comment on lines -128 to +131
realmIcon: realmIcon ?? '$realmUrl/icon.png',
realmIcon: realmIcon ?? _realmIcon,
Copy link
Member

Choose a reason for hiding this comment

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

nit: similarly, reorder so this and eg.realmIcon agree from the beginning

Comment on lines 388 to 389
realmName: Value('Some organization'),
realmIcon: Value(Uri.parse('/some-image.png'))));
Copy link
Member

Choose a reason for hiding this comment

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

This seems like it distracts from the narrative of this test (which is about the web-auth flow, not about the realm name and icon). This is a classic example of data that should exist in order to make things realistic, but is boring.

Can we arrange for eg.selfAccount to already have these fields, with the same boring values that eg.serverSettings puts there? For example that's how this test already handles realmUrl, which is similarly boring.

Comment on lines 387 to 388
check(globalStore.getAccount(selfAccount.id)).identicalTo(updated);
check(updated).equals(selfAccount.copyWith(
Copy link
Member

Choose a reason for hiding this comment

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

nit: can make the relationships here more explicit:

Suggested change
check(globalStore.getAccount(selfAccount.id)).identicalTo(updated);
check(updated).equals(selfAccount.copyWith(
check(globalStore.getAccount(selfAccount.id))
..identicalTo(updated)
..equals(selfAccount.copyWith(

await globalStore.updateZulipVersionData(accountId, zulipVersionData);
connection.zulipFeatureLevel = zulipVersionData.zulipFeatureLevel;
}
if (globalStore.getAccount(accountId) != null) {
Copy link
Member

Choose a reason for hiding this comment

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

Can this condition ever fail? /cc @chrisbobbe since you had a related question above.

Before this change, the next step here was to call PerAccountStore.fromInitialSnapshot, which already assumes (and asserts) that the account exists. So if there's a reason that can be untrue, then that's an existing bug.

But I don't think it can be. The step before this was either the previous conditional — which has a ! that throws if the account doesn't exist — or globalStore.updateZulipVersionData, which calls updateAccount, which returns the updated account and so guarantees that it exists.

@rajveermalviya
Copy link
Member Author

Thanks for the review @gnprice! Pushed an update, PTAL.

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 for the revision! This is quite close now; comments below.

What's the reason the PR and commit are labeled as fixing #1036 only partly — what's the remaining task you see as open before closing that issue?

Comment on lines -128 to +131
realmIcon: realmIcon ?? '$realmUrl/icon.png',
realmIcon: realmIcon ?? _realmIcon,
Copy link
Member

Choose a reason for hiding this comment

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

This commit message doesn't really capture what this change does:

example data [nfc]: Use _realmIcon as default value in eg.serverSettings

NFC, because GetServerSettingsResult.realmIcon was never being read.

It's true that the new value is called _realmIcon here; but more significant is that it's a different value, and in particular a relative URL where it previously was absolute.

(Related previous subthread above: #1860 (comment) .)


Then as a nit, I'd label this as not NFC. It's true that it's NFC for the tests as a whole, if this field is never read; but the change is already labeled as being a change to example data, and it does change the interface presented by example_data.dart: this piece of the data is now a relative URL instead of absolute.

Comment on lines 261 to 265
id: testBinding.globalStore.accounts.single.id,
// TODO store value from server settings during login flow
realmName: Value(null),
// TODO store value from server settings during login flow
realmIcon: Value(null)));
Copy link
Member

Choose a reason for hiding this comment

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

These get added in one commit and removed in the next. I think what that's pointing to is that the intermediate state between these two commits is somewhat inconsistent. Let's squash them together:
afbb80f db: Allow storing realmName and realmIcon to the Accounts table
ee1993f login: Store realmName and realmIcon while creating account

The resulting diff is only very slightly bigger than the first commit, because the second commit is fairly small already and much of it is reverting parts of the first one.

Comment on lines +344 to +349
.equals(eg.selfAccount.copyWith(
id: testBinding.globalStore.accounts.single.id,
realmName: Value('Some organization'),
realmIcon: Value(Uri.parse('/some-image.png')),
zulipFeatureLevel: 427,
zulipVersion: '12.0-dev-524-ga557b1e721',
Copy link
Member

Choose a reason for hiding this comment

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

Ah, good idea to test all these.

This could also go as a prep commit (with just the three version fields) — then the commit that adds the name/icon fields just adds those to this test case, rather than introducing the whole test case.

rajveermalviya added a commit to rajveermalviya/zulip-flutter that referenced this pull request Oct 8, 2025
Observed value for CZO is:

  /user_avatars/2/realm/icon.png?version=3

A relative URL rather than absolute, so change it to match that
observed value. API docs do not specify a format, see:
  zulip#1860 (comment)

Also `GetServerSettingsResult.realmIcon` was never read before so
it's NFC change in regards to the tests.
@rajveermalviya
Copy link
Member Author

Thanks for the review @gnprice! Pushed an update, PTAL.

what's the remaining task you see as open before closing that issue?

This PR doesn't include handling of realm update events for these fields, so I used Fixes-partly instead of Fixes.

@gnprice
Copy link
Member

gnprice commented Oct 8, 2025

Got it, thanks.

We have #668 tracking that, and this PR adds a TODO(#668) comment to ensure we see these fields when we go to do that issue. So I think we can declare #1036 complete without that part — the motivation for doing #1036 now is that we need the data for uses like #1779 and #1038, and for those it's perfectly fine if the name and icon don't update until the next fresh event queue.

Otherwise, this revision all looks good! So I'll edit that bit of metadata (in the commit message and the PR description), and merge.

Observed value for CZO is:

  /user_avatars/2/realm/icon.png?version=3

A relative URL rather than absolute, so change it to match that
observed value. API docs do not specify a format, see:
  zulip#1860 (comment)

Also `GetServerSettingsResult.realmIcon` was never read before so
it's NFC change in regards to the tests.
And update login flow to store realmName and realmIcon while creating
account in the database.

Fixes: zulip#1036
This will populate these fields for the currently opened account in
the database when the PerAccountStore loads.
@gnprice gnprice force-pushed the pr-realm-name-icon branch from ea0b4d5 to 673ff5b Compare October 8, 2025 22:44
@gnprice gnprice merged commit 673ff5b into zulip:main Oct 8, 2025
1 check passed
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.

Track each realm's name and icon in database

3 participants