-
Notifications
You must be signed in to change notification settings - Fork 306
profile: Implement profile screen for users #287
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
Changes from all commits
1976a6a
fd8a839
0b1502b
42c8675
a20f120
7149a64
c3df03e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,8 +23,6 @@ class InitialSnapshot { | |
|
||
final List<CustomProfileField> customProfileFields; | ||
|
||
// TODO etc., etc. | ||
|
||
final List<RecentDmConversation> recentPrivateConversations; | ||
|
||
final List<Subscription> subscriptions; | ||
|
@@ -41,6 +39,8 @@ class InitialSnapshot { | |
// TODO(server-5) remove pre-5.0 comment | ||
final UserSettings? userSettings; // TODO(server-5) | ||
|
||
final Map<String, RealmDefaultExternalAccount> realmDefaultExternalAccounts; | ||
|
||
final int maxFileUploadSizeMib; | ||
|
||
@JsonKey(readValue: _readUsersIsActiveFallbackTrue) | ||
|
@@ -84,6 +84,7 @@ class InitialSnapshot { | |
required this.unreadMsgs, | ||
required this.streams, | ||
required this.userSettings, | ||
required this.realmDefaultExternalAccounts, | ||
Comment on lines
86
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tree isn't clean on rerunning |
||
required this.maxFileUploadSizeMib, | ||
required this.realmUsers, | ||
required this.realmNonActiveUsers, | ||
|
@@ -96,6 +97,30 @@ class InitialSnapshot { | |
Map<String, dynamic> toJson() => _$InitialSnapshotToJson(this); | ||
} | ||
|
||
/// An item in `realm_default_external_accounts`. | ||
/// | ||
/// For docs, search for "realm_default_external_accounts:" | ||
/// in <https://zulip.com/api/register-queue>. | ||
@JsonSerializable(fieldRename: FieldRename.snake) | ||
class RealmDefaultExternalAccount { | ||
final String name; | ||
final String text; | ||
final String hint; | ||
final String urlPattern; | ||
|
||
RealmDefaultExternalAccount({ | ||
required this.name, | ||
required this.text, | ||
required this.hint, | ||
required this.urlPattern, | ||
}); | ||
|
||
factory RealmDefaultExternalAccount.fromJson(Map<String, dynamic> json) => | ||
_$RealmDefaultExternalAccountFromJson(json); | ||
|
||
Map<String, dynamic> toJson() => _$RealmDefaultExternalAccountToJson(this); | ||
} | ||
|
||
/// An item in `recent_private_conversations`. | ||
/// | ||
/// For docs, search for "recent_private_conversations:" | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,8 @@ part 'model.g.dart'; | |
@JsonSerializable(fieldRename: FieldRename.snake) | ||
class CustomProfileField { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason for moving this out of My inclination would be to keep it in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't realize there were other structures in |
||
final int id; | ||
final int type; // TODO enum; also TODO(server-6) a value added | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you do move this class's definition, definitely should go in a separate commit from converting this field from int to an enum — that sort of separation helps make both of the changes easier to read and review. (But I think it's actually already in the right place — see above about what file it goes in, and then within this file I think up at the top is good because it's part of realm-wide settings and not specific to a user or a stream etc.) |
||
@JsonKey(unknownEnumValue: CustomProfileFieldType.unknown) | ||
final CustomProfileFieldType type; | ||
final int order; | ||
final String name; | ||
final String hint; | ||
|
@@ -32,17 +33,72 @@ class CustomProfileField { | |
Map<String, dynamic> toJson() => _$CustomProfileFieldToJson(this); | ||
} | ||
|
||
/// As in [CustomProfileField.type]. | ||
@JsonEnum(fieldRename: FieldRename.snake, valueField: "apiValue") | ||
enum CustomProfileFieldType { | ||
shortText(apiValue: 1), | ||
longText(apiValue: 2), | ||
choice(apiValue: 3), | ||
date(apiValue: 4), | ||
link(apiValue: 5), | ||
user(apiValue: 6), | ||
externalAccount(apiValue: 7), | ||
pronouns(apiValue: 8), // TODO(server-6) newly added | ||
unknown(apiValue: null); | ||
|
||
const CustomProfileFieldType({ | ||
required this.apiValue | ||
}); | ||
|
||
final int? apiValue; | ||
|
||
int? toJson() => apiValue; | ||
} | ||
|
||
/// An item in the realm-level field data for a "choice" custom profile field. | ||
/// | ||
/// The value of [CustomProfileField.fieldData] decodes to a | ||
/// `List<CustomProfileFieldChoiceDataItem>` when | ||
/// the [CustomProfileField.type] is [CustomProfileFieldType.choice]. | ||
/// | ||
/// TODO(server): This isn't really documented. But see chat thread: | ||
/// https://chat.zulip.org/#narrow/stream/378-api-design/topic/custom.20profile.20fields/near/1383005 | ||
@JsonSerializable(fieldRename: FieldRename.snake) | ||
class ProfileFieldUserData { | ||
final String value; | ||
final String? renderedValue; | ||
class CustomProfileFieldChoiceDataItem { | ||
final String text; | ||
|
||
ProfileFieldUserData({required this.value, this.renderedValue}); | ||
const CustomProfileFieldChoiceDataItem({required this.text}); | ||
|
||
factory ProfileFieldUserData.fromJson(Map<String, dynamic> json) => | ||
_$ProfileFieldUserDataFromJson(json); | ||
factory CustomProfileFieldChoiceDataItem.fromJson(Map<String, dynamic> json) => | ||
_$CustomProfileFieldChoiceDataItemFromJson(json); | ||
|
||
Map<String, dynamic> toJson() => _$ProfileFieldUserDataToJson(this); | ||
Map<String, dynamic> toJson() => _$CustomProfileFieldChoiceDataItemToJson(this); | ||
|
||
static Map<String, CustomProfileFieldChoiceDataItem> parseFieldDataChoices(Map<String, dynamic> json) => | ||
json.map((k, v) => MapEntry(k, CustomProfileFieldChoiceDataItem.fromJson(v))); | ||
} | ||
|
||
/// The realm-level field data for an "external account" custom profile field. | ||
/// | ||
/// This is the decoding of [CustomProfileField.fieldData] when | ||
/// the [CustomProfileField.type] is [CustomProfileFieldType.externalAccount]. | ||
/// | ||
/// TODO(server): This is undocumented. See chat thread: | ||
/// https://chat.zulip.org/#narrow/stream/378-api-design/topic/external.20account.20custom.20profile.20fields/near/1387213 | ||
@JsonSerializable(fieldRename: FieldRename.snake) | ||
class CustomProfileFieldExternalAccountData { | ||
final String subtype; | ||
final String? urlPattern; | ||
|
||
const CustomProfileFieldExternalAccountData({ | ||
required this.subtype, | ||
required this.urlPattern, | ||
}); | ||
|
||
factory CustomProfileFieldExternalAccountData.fromJson(Map<String, dynamic> json) => | ||
_$CustomProfileFieldExternalAccountDataFromJson(json); | ||
|
||
Map<String, dynamic> toJson() => _$CustomProfileFieldExternalAccountDataToJson(this); | ||
} | ||
|
||
/// As in [InitialSnapshot.realmUsers], [InitialSnapshot.realmNonActiveUsers], and [InitialSnapshot.crossRealmBots]. | ||
|
@@ -69,7 +125,8 @@ class User { | |
bool isBot; | ||
int? botType; // TODO enum | ||
int? botOwnerId; | ||
int role; // TODO enum | ||
@JsonKey(unknownEnumValue: UserRole.unknown) | ||
UserRole role; | ||
Comment on lines
+128
to
+129
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's separate out adding this enum as its own commit. (I.e. adding the class, changing this field to use it, and other closely-connected changes like in RealmUserUpdateEvent, as one commit; but separate from adding the CustomProfileFieldsEvent type, moving the definition of ProfileFieldUserData, adding the new UI, and so on.) |
||
String timezone; | ||
String? avatarUrl; // TODO distinguish null from missing https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/flutter.3A.20omitted.20vs.2E.20null.20in.20JSON/near/1551759 | ||
int avatarVersion; | ||
|
@@ -120,6 +177,39 @@ class User { | |
Map<String, dynamic> toJson() => _$UserToJson(this); | ||
} | ||
|
||
/// As in [User.profileData]. | ||
@JsonSerializable(fieldRename: FieldRename.snake) | ||
class ProfileFieldUserData { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm yeah, moving this to come after Let's do that in its own commit, though, or I guess combined with adding that handy line of dartdoc, and perhaps combined with any other code moves of a similar nature. That commit can then also be labeled as NFC. |
||
final String value; | ||
final String? renderedValue; | ||
|
||
ProfileFieldUserData({required this.value, this.renderedValue}); | ||
|
||
factory ProfileFieldUserData.fromJson(Map<String, dynamic> json) => | ||
_$ProfileFieldUserDataFromJson(json); | ||
|
||
Map<String, dynamic> toJson() => _$ProfileFieldUserDataToJson(this); | ||
} | ||
|
||
/// As in [User.role]. | ||
@JsonEnum(valueField: "apiValue") | ||
enum UserRole{ | ||
owner(apiValue: 100), | ||
administrator(apiValue: 200), | ||
moderator(apiValue: 300), | ||
member(apiValue: 400), | ||
guest(apiValue: 600), | ||
unknown(apiValue: null); | ||
|
||
const UserRole({ | ||
required this.apiValue, | ||
}); | ||
|
||
final int? apiValue; | ||
|
||
int? toJson() => apiValue; | ||
} | ||
|
||
/// As in `streams` in the initial snapshot. | ||
/// | ||
/// Not called `Stream` because dart:async uses that name. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: spelling in commit message: