Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1155 commits
Select commit Hold shift + click to select a range
f9ec516
lightbox [nfc]: Go through MessageTimestampStyle for timestamp
chrisbobbe Jul 13, 2025
55b95d2
msglist [nfc]: Add two params to MessageTimestampStyle.format, to use…
chrisbobbe Jul 14, 2025
7704fd8
msglist [nfc]: Use ZulipBinding.instance.utcNow().toLocal() in DateText
chrisbobbe Jul 21, 2025
3703baa
msglist [nfc]: Finish centralizing on MessageTimestampStyle
chrisbobbe Jul 14, 2025
0a6b2f7
msglist test: Test all `MessageTimestampStyle`s, not just dateOnlyRel…
chrisbobbe Jul 23, 2025
4a77fbd
api: Start accepting null for user_settings.twenty_four_hour_time
chrisbobbe Jul 14, 2025
ddc9ade
model [nfc]: Pass TwentyFourHourTimeMode to MessageTimestampStyle.format
chrisbobbe Jul 15, 2025
1d1f426
msglist [nfc]: Remove a hard-coded 'en_US' which is the default
chrisbobbe Jul 15, 2025
b7146a7
msglist [nfc]: s/_timeOnlyFormat/_timeFormat/
chrisbobbe Jul 15, 2025
91d4ef3
msglist [nfc]: Pull out a _timeFormatWithSeconds helper
chrisbobbe Jul 15, 2025
4d4928f
msglist [nfc]: Add helpers to resolve TwentyFourHourTimeMode
chrisbobbe Jul 21, 2025
736dc4d
msglist [nfc]: Use a helper field we just added
chrisbobbe Jul 21, 2025
92bae68
msglist: Follow user_settings.twenty_four_hour_time for message times…
chrisbobbe Jul 21, 2025
e120e00
content: Follow user_settings.twenty_four_hour_time in global times
chrisbobbe Jul 22, 2025
55e7067
l10n: Update translations from Weblate.
weblate Jul 25, 2025
11ffac2
version: Sync version and changelog from v30.0.262 release
gnprice Jul 25, 2025
b50f6bb
unreads: Add/use locatorMap, to efficiently locate messages
chrisbobbe Jul 11, 2025
8c9a7b0
content test [nfc]: Drop skipped duplicate KaTeX font-size ratio test
rajveermalviya Jul 24, 2025
6459af6
content test [nfc]: Reorder KaTeX widget tests, enabled before disabled
rajveermalviya Jul 24, 2025
da5c1f7
katex: Remove renderKaTex experimental flag
rajveermalviya Jul 24, 2025
dc01e0a
readme: Link to Greg's "secret" to using `git log -p`
chrisbobbe Jul 28, 2025
632f8e0
check: Update expected format of Flutter version name
gnprice Jul 28, 2025
6c0c1d8
deps: Upgrade Flutter to 3.33.0-1.0.pre-1085
gnprice Jul 28, 2025
c87de41
msglist test: Wait through a nav-transition animation in a place we f…
chrisbobbe Jul 28, 2025
7c31282
icons: Add `link` icon, from Figma
sm-sayedi Jul 29, 2025
3e9b4de
action_sheet: Use `ZulipIcons.link` instead of `Icons.link`
sm-sayedi Jul 29, 2025
373cfb7
action_sheet: Add "Copy link to channel" button
sm-sayedi Jul 29, 2025
80b83e8
msglist: Pass last message id to topic action sheet instead of first
sm-sayedi Jul 28, 2025
8792876
action_sheet: Add "Copy link to topic" button
sm-sayedi Jul 27, 2025
4be28c1
button: Add ZulipMenuItemButton.subLabel
sm-sayedi Jul 6, 2025
da00324
button [nfc]: Make ZulipMenuItemButton.onPressed optional
sm-sayedi Jul 17, 2025
37e44e0
profile: Add button for setting/showing user status in self-user profile
sm-sayedi Jul 6, 2025
a55e988
model [nfc]: Add UserStatusChange.copyWith method
sm-sayedi Jul 7, 2025
ab625e9
user: Add `emoji` property to UserStatusEmoji widget
sm-sayedi Jul 7, 2025
eab11bb
emoji [nfc]: Make emoji picker return the selected emoji, for reuse
sm-sayedi Jul 7, 2025
9468767
api: Add route updateStatus
sm-sayedi Jul 18, 2025
dc24b4c
emoji: Add EmojiStore.getUnicodeEmojiNameByCode method
sm-sayedi Jul 19, 2025
1670a8c
icons: Add `chevron_down`, from Figma
sm-sayedi Jul 18, 2025
d7fac5d
nav test: Make TestNavigatorObserver extend TransitionDurationObserver
sm-sayedi Jul 24, 2025
caf1ddb
user-status: Add page for setting own user status
sm-sayedi Jul 18, 2025
8ca68d4
katex test [nfc]: Name the KatexExample statics without redundancy
gnprice Jul 29, 2025
79edb40
katex test [nfc]: Cut redundant group on KaTeX widget tests
gnprice Jul 29, 2025
0900820
user [nfc]: Clear out pre-7.0 backwards-compat code for display email
chrisbobbe Jul 29, 2025
a89d96e
user [nfc]: Inline store.userDisplayEmail, which has become trivial
chrisbobbe Jul 29, 2025
f9ea6c9
katex: Support colored text in KaTeX content
rajveermalviya Jul 4, 2025
314c83c
api [nfc]: Rename field UploadFileResult.url from "uri"
gnprice Jul 31, 2025
c7f336c
compose [nfc]: Take a URL string at inlineLink, rather than a Uri object
gnprice Jul 31, 2025
2e06a67
compose: For uploads, use verbatim URL string from server
gnprice Jul 31, 2025
6a35cc4
compose [nfc]: Simplify inlineLink by dropping null destination
gnprice Jul 31, 2025
58181da
lightbox: Make image zoom 10x instead of the default (2.5x)
sm-sayedi Jul 31, 2025
fded259
autocomplete: Remove a probably-wrong null assertion
chrisbobbe Jul 31, 2025
03cb3d3
autocomplete [nfc]: Construct user result in query.testUser
chrisbobbe Jul 24, 2025
2d217a0
autocomplete [nfc]: Construct wildcard result in query.testWildcardOp…
chrisbobbe Jul 24, 2025
fd51498
autocomplete [nfc]: Cut separate cache param on testUser, reuse store
gnprice Jul 24, 2025
b7ed9a7
autocomplete [nfc]: Add bucket-sort step in mention-autocomplete
chrisbobbe Jul 24, 2025
b10b058
autocomplete test [nfc]: Simplify end-to-end ranking test with pure-m…
gnprice Jul 24, 2025
9e3907a
autocomplete test [nfc]: Use deepEquals and conditions for end-to-end…
gnprice Jul 24, 2025
e026fed
autocomplete test [nfc]: Apply ranking in debugCompareUsers
gnprice Jul 25, 2025
d589a01
autocomplete test [nfc]: Reorder mention sort/match tests to match impl
gnprice Jul 24, 2025
14b7fdf
autocomplete test [nfc]: Fix name for group that's not just about users
chrisbobbe Jul 30, 2025
a6055d5
autocomplete [nfc]: Renames/doc changes for explicitness about normal…
chrisbobbe Jul 25, 2025
00c0840
autocomplete: Rank user results by name-match quality
chrisbobbe Jul 24, 2025
7be6826
autocomplete: Match user results by email match (prefix match)
chrisbobbe Jul 29, 2025
d5dddb3
autocomplete: Add user-group results to mention autocomplete
chrisbobbe Jul 30, 2025
4d50b2d
action_sheet: Choose "Close" and "Cancel" consistently for bottom sheets
chrisbobbe Jul 9, 2025
f69eac9
icons: Add see_who_reacted, from Vlad on CZO
chrisbobbe Jul 9, 2025
b5c955b
action_sheet: Implement BottomSheetHeaderPlainText, following Figma
chrisbobbe Jul 24, 2025
538e5ae
inset_shadow test [nfc]: Pull PaintPatternPredicate helper outside it…
chrisbobbe Jul 24, 2025
6a429b1
inset_shadow: Implement start/end shadows, not just top/bottom
chrisbobbe Jul 24, 2025
1556946
emoji_reaction test [nfc]: Pull out some data for other tests to use
chrisbobbe Jul 25, 2025
025b0ce
emoji_reaction: Put "You" first in ReactionChip label; pull out helper
chrisbobbe Jul 31, 2025
b232183
emoji_reaction: Remove tooltip on ReactionChip; add semantics label
chrisbobbe Jul 31, 2025
41e3d57
emoji_reaction: Add labeled Semantics container node for reactions list
chrisbobbe Aug 1, 2025
e2c10ae
msglist: Support viewing who reacted to a message
chrisbobbe Jul 9, 2025
98b94bd
emoji_reaction: Refine scroll-into-view logic
chrisbobbe Jul 31, 2025
361ee16
dialog [nfc]: Rename checkNoErrorDialog to checkNoDialog
u7088495 Feb 11, 2025
bd112c2
dialog: Use Cupertino-flavored alert dialogs on iOS
u7088495 Nov 18, 2024
ec1baee
dialog [nfc]: Inline _materialDialogActionText in _adaptiveAction
u7088495 Oct 25, 2024
7e98ff1
theme: Set visualDensity to standard, even on desktop
gnprice Aug 3, 2025
609b490
dialog_checks: Make checkNoDialog describe the dialog it finds
chrisbobbe Jul 22, 2025
8d3c128
dialog: Remove no-op SingleChildScrollView on iOS
chrisbobbe Aug 4, 2025
766f071
action_sheet: Put mark-channel-as-read button at top of action sheet
chrisbobbe Aug 5, 2025
a55d8a9
dialog test [nfc]: Remove an unused import
chrisbobbe Aug 6, 2025
c67a4cc
login [nfc]: Tighten up some if-unmounted-returns; remove stale lint-…
chrisbobbe Jul 22, 2025
6d02f42
server_support [nfc]: Move some server-support logic out to this new …
chrisbobbe Aug 2, 2025
06f1b87
login test: Add happy-path test for AddAccountPage
chrisbobbe Aug 2, 2025
733bb88
login: Reject earlier (at get-server-settings) when server is too old
chrisbobbe Jul 22, 2025
e8928ae
api: Add routes subscribeToChannel, unsubscribeFromChannel
chrisbobbe Aug 5, 2025
2500040
action_sheet [nfc]: Support multiple button sections in action sheet
chrisbobbe Aug 5, 2025
81c2bb4
action_sheet [nfc]: Refactor showChannelActionSheet button sections
chrisbobbe Aug 5, 2025
e1d378c
icons: Add `circle_x`, from Figma
chrisbobbe Aug 5, 2025
7f7aa98
action_sheet: Add "Subscribe"/"Unsubscribe" buttons to channel action…
chrisbobbe Aug 5, 2025
2a163b2
l10n: Fix mismatch in descriptions of new strings
gnprice Aug 8, 2025
97b0082
l10n: Update translations from Weblate.
weblate Aug 9, 2025
1e118aa
api: Add InitialSnapshot.realmEnableReadReceipts
sm-sayedi Aug 2, 2025
3a39362
realm: Add RealmStore.realmEnableReadReceipts
sm-sayedi Aug 2, 2025
8ea919e
api: Add route getReadReceipts
sm-sayedi Jul 30, 2025
2a00838
icons: Add `check_check` icon, from Web Figma file
sm-sayedi Jul 14, 2025
b81158f
text: Introduce TextWithLink widget
gnprice Aug 1, 2025
ca3f54e
action_sheet [nfc]: Make BottomSheetHeaderPlainText more flexible; re…
chrisbobbe Aug 6, 2025
894d617
action_sheet: Implement BottomSheetEmptyContentPlaceholder, to use soon
chrisbobbe Aug 6, 2025
79c43cb
action_sheet: Add 'View read receipts' button
sm-sayedi Aug 5, 2025
618ed7a
msglist [nfc]: Allow passing `key` in `MessageListPage.buildRoute`
rajveermalviya Aug 1, 2025
5601d0e
subscription_list [nfc]: Allow disabling topic list button in channel…
rajveermalviya Aug 1, 2025
3531217
subscription_list [nfc]: Add a flag to hide channels where the user c…
rajveermalviya Aug 1, 2025
a851146
subscription_list [nfc]: Allow `onChannelSelect` callback
rajveermalviya Aug 1, 2025
87d4762
recent dms [nfc]: Add a flag to hide DMs where user can't post
rajveermalviya Aug 1, 2025
40d5a7d
recent dms [nfc]: Allow `onDmSelect` callback
rajveermalviya Aug 1, 2025
4d45945
compose [nfc]: Export and rename _File to FileToUpload
rajveermalviya Aug 1, 2025
e4deccb
compose [nfc]: Expose an uploadFiles method on ComposeBoxController
rajveermalviya Aug 1, 2025
fe42d20
subscription_list [nfc]: Handle bottom insets explicitly in subscript…
rajveermalviya Aug 3, 2025
4998340
recent dms [nfc]: Handle bottom insets explicitly in recent DMs page
rajveermalviya Aug 5, 2025
963f170
share: Support sharing content received from other apps on Android
rajveermalviya Aug 1, 2025
529e037
share: Use filename to guess mimetype, in addition to the header bytes
rajveermalviya Aug 13, 2025
565d2b6
changelog: Describe changes since 30.0.262
gnprice Aug 13, 2025
101071a
version: Bump version to 30.0.263
gnprice Aug 13, 2025
8c3cd76
mailmap: Use proper names for various users.
timabbott Aug 13, 2025
7549789
api [nfc]: Update TODO on User.isBillingAdmin
PIG208 Aug 23, 2024
d36f1f2
api: Cut User.isBillingAdmin, obsolete and gone in current servers
gnprice Jul 23, 2025
401d6f9
api: Drop is_cross_realm_bot fallback for User.isSystemBot, relying o…
PIG208 Aug 23, 2024
506b87a
server_support [nfc]: Explain why zulipMergeBase should remain nullable
gnprice Aug 14, 2025
1ac4431
api: Mark GetServerSettingsResult.zulipMergeBase as required
PIG208 Aug 23, 2024
5a50837
api: Mark InitialSnapshot.zulipMergeBase as required, relying on serv…
PIG208 Aug 23, 2024
0d2895b
api [nfc]: Further propagate InitialSnapshot.userSettings as required
PIG208 Aug 23, 2024
ebdab97
api: Mark WebAuthPayload.userId as required, relying on server 5+, FL…
PIG208 Aug 22, 2024
0a9b44e
api [nfc]: Remove TODO on UpdateMessageEvent.userId
PIG208 Jul 9, 2025
4a8de18
api: Mark UpdateMessageEvent.{renderingOnly,editTimestamp} as require…
PIG208 Aug 22, 2024
7f02888
api/notif [nfc]: Cut comment on FcmMessageChannelRecipient.streamId, …
PIG208 Aug 22, 2024
8a2ecca
api [nfc]: Cut comment on requiring stream_id from iOS APNs payload, …
PIG208 Jul 9, 2025
9f2cd3e
api: Mark GetServerSettingsResult.realmWebPublicAccessEnabled as requ…
PIG208 Aug 23, 2024
04eb961
api: Drop legacy support for prev_subject and topic from edit history…
PIG208 Aug 23, 2024
6a86822
api: Remove sender_id fallback for UnreadDmSnapshot.otherUserId, rely…
PIG208 Aug 23, 2024
36cfe99
api: Remove legacy getMessageCompat, relying on server 5+, FL 120+
PIG208 Jul 9, 2025
7249b33
compose [nfc]: Use ComposeBoxController.uploadFiles in _AttachUploads…
rajveermalviya Aug 14, 2025
f765840
deps: Update CocoaPods pods (tools/upgrade pod)
rajveermalviya Aug 4, 2025
2453ae7
deps: Upgrade Flutter to 3.33.0-1.0.pre-1285
rajveermalviya Aug 5, 2025
b6084e0
ios: Bump min iOS version to 15.0, as required by latest Firebase iOS…
rajveermalviya Aug 4, 2025
836f1d0
deps: Upgrade firebase_core, firebase_messaging to latest
rajveermalviya Aug 4, 2025
f09116a
deps: Update pigeon to 26.0.0, from 25.5.0
rajveermalviya Aug 4, 2025
7e791ac
deps: Upgrade packages within constraints (tools/upgrade pub)
rajveermalviya Aug 5, 2025
144a888
deps android: Upgrade Gradle to 9.0.0, from 8.14.3
rajveermalviya Aug 5, 2025
277fc97
deps android: Upgrade Kotlin to 2.2.0, from 2.1.20
rajveermalviya Aug 5, 2025
c6fcbf6
deps android: Upgrade Android Gradle Plugin to 8.12.0, from 8.10.1
rajveermalviya Aug 5, 2025
9f544cb
profile: Add a spacer between name/status and email/role
gnprice Jul 31, 2025
0d83579
presence: Log presence events in debug, like other events
gnprice Jul 31, 2025
11849c1
presence: Add userLastActive method
gnprice Jul 31, 2025
3fd0817
presence [nfc]: Expose a debugHandlePresenceResponse method for testing
gnprice Aug 8, 2025
6b7ba52
profile: Show last-active time
gnprice Jul 31, 2025
86a8ad9
compose_box [nfc]: Reorder two calls in edit-message "Save" tap handler
chrisbobbe Aug 6, 2025
11ee6e9
message [nfc]: Mention outbox-like logic in in editMessage dartdoc
chrisbobbe Aug 6, 2025
fffc6fc
message [nfc]: Have editMessage return Future<void> instead of void
chrisbobbe Aug 6, 2025
ef67a67
compose [nfc]: Pass PageRoot.contextOf to _Banner.buildTrailing
chrisbobbe Aug 6, 2025
e7cd777
compose: Show error dialog on failure of edit-message request
chrisbobbe Aug 6, 2025
385fb81
api: Use "channel" operator over the legacy "stream", where supported
sm-sayedi Aug 7, 2025
62b62dd
compose test [nfc]: Extract prepare helper
PIG208 Dec 24, 2024
61fe2c8
compose test: Set up compose box using enterContent
PIG208 Dec 24, 2024
fbdf3a9
compose: Support images from keyboard for Android
PIG208 Dec 24, 2024
db4e843
katex: Handle `nulldelimiter` class in spans
rajveermalviya Aug 11, 2025
9cc6700
katex: Handle `position` & `top` property in span inline styles
rajveermalviya Aug 11, 2025
802aa9a
reactions: Remove the touch feedback of "Cancel" button in emoji picker
sm-sayedi Aug 19, 2025
ab2a091
set-status: Change the text-input row's end margin from 10px to 8px
sm-sayedi Aug 16, 2025
d4df8f9
set-status: Remove the status-suggestion items touch feedback
sm-sayedi Aug 16, 2025
3326702
set-status: Fix content rendering in landscape mode
sm-sayedi Aug 16, 2025
06079a9
set-status: Remove shadow effect from the bottom of the page
sm-sayedi Aug 16, 2025
79061a8
set-status: Add a small space between emoji button and text input field
sm-sayedi Aug 16, 2025
e0793b4
test: Include eg.selfUser by default in eg.initialSnapshot
gnprice Aug 15, 2025
53fbf77
test: Take a selfUser parameter in eg.store
gnprice Aug 15, 2025
7770762
new-dms test: Include self-user in users list
gnprice Aug 19, 2025
c4f5256
autocomplete test: Ensure self-user in users list
gnprice Aug 15, 2025
042e10b
test: Include self-user in users lists
gnprice Aug 15, 2025
6bdbf1e
user [nfc]: Expose UserStoreImpl.userMapFromInitialSnapshot
gnprice Aug 15, 2025
90cb63a
store: Extract self-user up front; require to be present
gnprice Aug 15, 2025
edeb05d
user [nfc]: Assert up front that self-user is present
gnprice Aug 15, 2025
ffd96fe
msglist [nfc]: Add MessageListPage.maybeAncestorOf, alongside .ancest…
chrisbobbe Aug 7, 2025
9703379
action_sheet test: Remove `messages` in showFromAppBar channel-sheet …
chrisbobbe Aug 7, 2025
767d40c
action_sheet test: Also test showing channel sheet from topic list ap…
chrisbobbe Aug 7, 2025
8e32b3c
action_sheet: Add 'Channel feed' button to channel action sheet
chrisbobbe Aug 7, 2025
e12673a
topic_list: Don't show topic-list button in action sheet from app bar
chrisbobbe Aug 15, 2025
1d2fd9b
autocomplete [nfc]: Link to issue about space characters; add more TODOs
chrisbobbe Aug 14, 2025
e4299bb
autocomplete: Use cached lowercase query instead of computing on each…
chrisbobbe Aug 15, 2025
6d97331
autocomplete test [nfc]: Refactor some wildcard tests, to test more l…
chrisbobbe Aug 14, 2025
6e519d1
autocomplete: Make wildcard match on translated string case-insensitive
chrisbobbe Aug 14, 2025
6e305f7
autocomplete [nfc]: Use "normalize" where lowercase is meant
chrisbobbe Aug 14, 2025
171be6e
emoji: Make emoji autocomplete explicitly case-insensitive
chrisbobbe Aug 15, 2025
b342ec3
deps: Add unorm_dart, for matching insensitively to diacritics
chrisbobbe Aug 14, 2025
1af7a25
autocomplete: Match insensitively to diacritics
chrisbobbe Aug 14, 2025
bead286
new_dm_sheet test: Add a test user with a diacritic in their name
chrisbobbe Aug 15, 2025
0ade8a3
new_dm_sheet: Make searching insensitive to diacritics
chrisbobbe Aug 15, 2025
9884df7
inset_shadow [nfc]: Bring out a public helper, to use soon
chrisbobbe Aug 14, 2025
4c05735
code [nfc]: s/localizations/zulipLocalizations/g
chrisbobbe Aug 14, 2025
ee303d0
read_receipts [nfc]: Inline _ReadReceiptsUserList
chrisbobbe Aug 14, 2025
c79ffd3
read_receipts: Improve UX by making the sheet draggable-scrollable
chrisbobbe Aug 14, 2025
49a5a0d
emoji_reaction: Pass `explicitChildNodes: true` in a Semantics container
chrisbobbe Aug 14, 2025
d9ab075
emoji_reaction: Use DraggableScrollableModalBottomSheet for view-reac…
chrisbobbe Aug 14, 2025
70414d0
l10n: Update translations from Weblate.
weblate Aug 20, 2025
464af54
content test: Add ContentExample.deleted; use in new widget test
chrisbobbe Aug 19, 2025
711b2ed
content: Remove TextStyle merge in rendering unicode emoji
chrisbobbe Aug 19, 2025
5115ac7
content: Remove TextStyle merge in rendering bold spans
chrisbobbe Aug 19, 2025
dda72cb
content test: Remove test that's redundant with testContentSmoke test
chrisbobbe Aug 21, 2025
67ded9f
content test [nfc]: Use testContentSmoke shortcut for unsupported KaT…
chrisbobbe Aug 20, 2025
f3c86aa
content test [nfc]: Move an unsupported-KaTeX test into its group
chrisbobbe Aug 21, 2025
645ae8a
content test [nfc]: Get unsupported-katex HTML from ContentExample
chrisbobbe Aug 21, 2025
57dc8b5
content test [nfc]: Fix testFontWeight's return type
chrisbobbe Aug 21, 2025
3dc2669
content: Remove TextStyle merge in rendering inline code
chrisbobbe Aug 19, 2025
999b089
msglist: Separate messages after 10-min gap, with a sender row
rajveermalviya Aug 19, 2025
11e8226
changelog: Sync description of 0.0.34 release from beta-prelaunch branch
gnprice Aug 19, 2025
3baebd4
changelog: Describe changes since 30.0.263
gnprice Aug 21, 2025
e86e235
version: Bump version to 30.0.264
gnprice Aug 21, 2025
4333598
api: Add user-group memberships, and their events
gnprice Jul 29, 2025
a0cfecd
group: Maintain user-group membership on events
gnprice Jul 29, 2025
cd47dcc
api: Define type GroupSettingValue
gnprice Jul 29, 2025
7e387dc
group: Add selfInGroupSetting
gnprice Aug 19, 2025
11b09ff
group test: Test group membership, and handling events for it
gnprice Aug 19, 2025
1637dee
group [nfc]: Add HasUserGroupStore
gnprice Jul 30, 2025
65a0977
realm [nfc]: Give RealmStore a reference to UserGroupStore
gnprice Jul 30, 2025
f080dad
realm: Denormalize self-user role onto RealmStoreImpl
gnprice Jul 30, 2025
76aa6b5
api: Add SupportedPermissionSettings type, and fixture
gnprice Aug 21, 2025
1550173
realm test [nfc]: Reorder tests to match implementation
gnprice Aug 19, 2025
c6206a8
realm: Add selfHasPermissionForGroupSetting
gnprice Jul 30, 2025
8c3b11f
test: Add eg.nobodyGroup
gnprice Aug 19, 2025
c3be229
api: Add channel fields canSubscribeGroup, canAddSubscribersGroup
gnprice Jul 29, 2025
cf83c9e
channel: Add selfHasContentAccess, using canSubscribeGroup et al
gnprice Jul 30, 2025
0d4665d
msglist test: Avoid specifying explicit message-IDs in `eg.{*}Message()`
rajveermalviya Aug 21, 2025
65922be
msglist test [nfc]: Refactor `forcedShowSender` evaluation in `checkI…
rajveermalviya Aug 21, 2025
f304ec4
msglist test: Add test for `messagesCloseInTime`, and update a relate…
rajveermalviya Aug 21, 2025
313f8ca
emoji_reaction test: Use pumpAndSettle to let overscroll animation fi…
MTtankkeo Sep 2, 2025
b49ebf1
android build: Migrate to `kotlin.compilerOptions` from `kotlinOptions`
rajveermalviya Aug 25, 2025
d808699
msglist: Suppress bottom inset in top sliver, too
gnprice Sep 4, 2025
44c0ce3
db test [nfc]: Factor out BoolGlobalSettings tests in its own group
sm-sayedi Aug 9, 2025
ed75f19
settings: Avoid redundant updates in setBool
sm-sayedi Aug 19, 2025
331ed03
settings: Make general int global settings, so as to add without migr…
sm-sayedi Sep 5, 2025
f1a238c
notif test [nfc]: Remove a param that's effectively never used
chrisbobbe Aug 20, 2025
f1badd4
notif test: Decompose takeStartingRoutes
chrisbobbe Aug 20, 2025
c569596
settings: Add IntGlobalSetting.lastVisitedAccountId, and keep updated
sm-sayedi Sep 5, 2025
a26a469
test: Add eg.thirdAccount
sm-sayedi Sep 5, 2025
a9137f2
app: On launch, go to the last visited account
sm-sayedi Aug 28, 2025
4e4e26b
assets: Update Noto Color Emoji font to v2.048, for Unicode 16
rajveermalviya Sep 3, 2025
ff6dc79
katex [nfc]: Explain reason for ignoring .vlist-t2 and .vlist-s CSS c…
rajveermalviya Sep 1, 2025
2b39409
katex [nfc]: Rename a local to hasVlistT2
gnprice Sep 5, 2025
ce8802b
katex [nfc]: Clarify structure of "vlist" HTML and our reasoning abou…
gnprice Sep 5, 2025
1c10f9a
api: Add realm-level restrict-message-deleting fields to InitialSnapshot
chrisbobbe Aug 29, 2025
1225c09
channel: Add per-channel restrict-message-deleting fields
chrisbobbe Aug 29, 2025
772b71d
realm [nfc]: Order updatable realm-setting fields by realm/update_dic…
chrisbobbe Aug 29, 2025
dd70226
realm: Add realm-level restrict-message-deleting fields to RealmStore
chrisbobbe Aug 29, 2025
db5f9bd
channel: Add isArchived field
chrisbobbe Aug 29, 2025
9c37ed4
initial_snapshot: Fill in SupportedPermissionSettings.fixture.realm
chrisbobbe Aug 30, 2025
f978e51
channel [nfc]: Add HasChannelStore for other substores to use
chrisbobbe Sep 5, 2025
e5b43df
messages [nfc]: Provide ChannelStore to MessageStore
chrisbobbe Sep 5, 2025
536cbb7
message: Implement selfCanDeleteMessage
chrisbobbe Aug 29, 2025
34f56db
l10n: Update translations from Weblate.
weblate Sep 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ jobs:
# so that Flutter knows its version and sees the constraint in our
# pubspec is satisfied. It's uncommon for flutter/flutter to go
# more than 100 commits between tags. Fetch 1000 for good measure.
# TODO(upstream): Around 2025-05, Flutter upstream stopped making
# tags within the main/master branch. Get that fixed:
# https://github.com/zulip/zulip-flutter/issues/1710
# Pending that, fetch more than 1000 commits.
run: |
git clone --depth=1000 -b main https://github.com/flutter/flutter ~/flutter
git clone --depth=3000 -b main https://github.com/flutter/flutter ~/flutter
TZ=UTC git --git-dir ~/flutter/.git log -1 --format='%h | %ci | %s' --date=iso8601-local
echo ~/flutter/bin >> "$GITHUB_PATH"

Expand Down
37 changes: 36 additions & 1 deletion .github/workflows/update-translations.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,54 @@
name: Update translations from Weblate
permissions:
contents: write
pull-requests: write
on:
schedule:
- cron: "0 10 * * 1"
workflow_dispatch:

jobs:
update-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Fetch and merge from Weblate
# The commit message is generated in Weblate; see https://hosted.weblate.org/addon/17163/
run: |
git remote add weblate https://hosted.weblate.org/git/zulip/zulip-flutter/
git fetch weblate
git merge --ff-only weblate/main
# This may lag behind `main` if weblate is backlogged; this can
# theoretically cause the PR to not be able to auto-merged, though
# re-running the action once weblate has caught up should be
# sufficient to fix that.
git reset --hard weblate/main

- name: Clone Flutter SDK
# We can't do a depth-1 clone, because we need the most recent tag
# so that Flutter knows its version and sees the constraint in our
# pubspec is satisfied. It's uncommon for flutter/flutter to go
# more than 100 commits between tags. Fetch 1000 for good measure.
# TODO(upstream): See ci.yml for why we fetch more than 1000.
run: |
git clone --depth=3000 -b main https://github.com/flutter/flutter ~/flutter
TZ=UTC git --git-dir ~/flutter/.git log -1 --format='%h | %ci | %s' --date=iso8601-local
echo ~/flutter/bin >> "$GITHUB_PATH"

# The Flutter tool assumes the tip of tree is "origin/master"
# (or "upstream/master"):
# https://github.com/flutter/flutter/issues/160626
# TODO(upstream): make workaround unneeded
git --git-dir ~/flutter/.git update-ref refs/remotes/origin/master origin/main

- name: Update generated code
run: |
mkdir -p build
tools/check l10n --fix
git add lib/generated/l10n/
GIT_COMMITTER_NAME="Hosted Weblate" GIT_COMMITTER_EMAIL="[email protected]" \
git commit --amend -C HEAD

- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
Expand Down
7 changes: 6 additions & 1 deletion .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@
# # shows raw names/emails, filtered by mapped name:
# $ git log --format='%an %ae' --author=$NAME | uniq -c

Brynly Mitchell <[email protected]>
Chinmay Ajith <[email protected]>
Chris Bobbe <[email protected]> <[email protected]>
Greg Price <[email protected]> <[email protected]>
K Akhil <[email protected]>
Lakshya Goel <[email protected]>
Lalit Kumar Singh <[email protected]>
Rajesh Malviya <[email protected]>
Rajesh Malviya <[email protected]> <[email protected]>
Shu Chen <[email protected]> <[email protected]>
Tomlin7 <[email protected]>

# The goal when editing this file is to group all of a given person's
# contributions together, and under their preferred name and email
Expand Down
48 changes: 26 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
# Zulip Flutter (beta)
# Zulip Flutter

A Zulip client for Android and iOS, using Flutter.
The official Zulip app for Android and iOS, built with Flutter.

This app is currently [in beta][beta].
When it's ready, it [will become the new][] official mobile Zulip client.
To see what work is planned before that launch,
see the [milestones][] and the [project board][].

[beta]: https://chat.zulip.org/#narrow/stream/2-general/topic/Flutter/near/1708728
[will become the new]: https://chat.zulip.org/#narrow/stream/2-general/topic/Flutter/near/1582367
[milestones]: https://github.com/zulip/zulip-flutter/milestones?direction=asc&sort=title
[project board]: https://github.com/orgs/zulip/projects/5/views/4
This app [was launched][] as the main Zulip mobile app
in June 2025.
It replaced the [previous Zulip mobile app][] built with React Native.

[was launched]: https://blog.zulip.com/flutter-mobile-app-launch
[previous Zulip mobile app]: https://github.com/zulip/zulip-mobile#readme

## Using Zulip

To use Zulip on iOS or Android, install the [official mobile Zulip client][].
## Get the app

You can also [try out this beta app][beta].

[official mobile Zulip client]: https://github.com/zulip/zulip-mobile#readme
Release versions of the app are available here:
* [Zulip for iOS](https://apps.apple.com/app/zulip/id1203036395)
on Apple's App Store
* [Zulip for Android](https://play.google.com/store/apps/details?id=com.zulipmobile)
on the Google Play Store
* Or if you don't use Google Play, you can
[download an APK](https://github.com/zulip/zulip-flutter/releases/latest)
from the official build we post on GitHub.


## Contributing

Contributions to this app are welcome.

If you're looking to participate in Google Summer of Code with Zulip,
this is one of the projects we're [accepting GSoC 2024 applications][]
for.
this was among the projects we accepted [GSoC applications][gsoc] for
in 2024 and 2025.

[accepting GSoC 2024 applications]: https://zulip.readthedocs.io/en/latest/outreach/gsoc.html#mobile-app
[gsoc]: https://zulip.readthedocs.io/en/latest/outreach/gsoc.html#mobile-app


### Picking an issue to work on
Expand All @@ -42,7 +42,7 @@ browsing through recent commits and the codebase,
and the Zulip guide to Git.

To find possible issues to work on, see our [project board][].
Look for issues up through the "Launch" milestone,
Look for issues in the earliest milestone,
and that aren't already assigned.

Follow the Zulip guide to [picking an issue to work on][],
Expand All @@ -55,6 +55,7 @@ and describing your progress.

[your first codebase contribution]: https://zulip.readthedocs.io/en/latest/contributing/contributing.html#your-first-codebase-contribution
[what makes a great Zulip contributor]: https://zulip.readthedocs.io/en/latest/contributing/contributing.html#what-makes-a-great-zulip-contributor
[project board]: https://github.com/orgs/zulip/projects/5/views/4
[picking an issue to work on]: https://zulip.readthedocs.io/en/latest/contributing/contributing.html#picking-an-issue-to-work-on


Expand Down Expand Up @@ -96,6 +97,8 @@ Two specific points to expand on:
* Your changes will need to be organized into
[clear and coherent commits][commit-style],
following [Zulip's commit style guide][commit-style].
(Use Greg's ["secret" to using `git log -p`][git-log-p-secret]
and/or a graphical Git client to see examples of mergeable commits.)

This is always required before we can merge your PR. Depending on
your changes' complexity, it may also be required before we can
Expand All @@ -106,9 +109,10 @@ Two specific points to expand on:
[working on an issue]: https://zulip.readthedocs.io/en/latest/contributing/contributing.html#working-on-an-issue
[submitting a pull request]: https://zulip.readthedocs.io/en/latest/contributing/review-process.html
[commit-style]: https://zulip.readthedocs.io/en/latest/contributing/commit-discipline.html
[git-log-p-secret]: https://github.com/zulip/zulip-mobile/blob/main/docs/howto/git.md#git-log-secret


## Getting started in developing this beta app
## Getting started in developing

### Setting up

Expand Down Expand Up @@ -289,7 +293,7 @@ good time to [report them as issues][dart-test-tracker].

#### Server compatibility

We support Zulip Server 4.0 and later.
We support Zulip Server 7.0 and later.

For API features added in newer versions, use `TODO(server-N)`
comments (like those you see in the existing code.)
Expand Down
18 changes: 11 additions & 7 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,12 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = '1.8'
}

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

defaultConfig {
applicationId "com.zulip.flutter"
applicationId "com.zulipmobile"
minSdkVersion 28
targetSdkVersion flutter.targetSdkVersion
// These are synced to local.properties from pubspec.yaml by the flutter tool.
Expand Down Expand Up @@ -77,17 +73,25 @@ android {
// https://developer.android.com/reference/tools/gradle-api/8.5/com/android/build/api/dsl/Lint
checkAllWarnings = true
warningsAsErrors = true
baseline = file("lint-baseline.xml")
disable += ['AndroidGradlePluginVersion']
}
}

kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile).configureEach {
// Compile Kotlin with `-Werror`... but only in release builds, so that it
// doesn't get in the way of quick local experiments for debugging.
//
// The string-searching makes this a bit of a mess, but it works.
// Better would be if we can add this to android.buildTypes.release above;
// but on a first attempt that didn't work (it affected debug builds too).
kotlinOptions.allWarningsAsErrors = name.contains("Release")
compilerOptions.allWarningsAsErrors = name.contains("Release")
}

flutter {
Expand Down
12 changes: 12 additions & 0 deletions android/app/lint-baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.10.0" type="baseline" client="gradle" dependencies="false" name="AGP (8.10.0)" variant="all" version="8.10.0">

<!--TODO(#855) see if this is no longer needed-->
<issue
id="InvalidPackage"
message="Invalid package reference in library; not included in Android: `javax.xml.stream`. Referenced from `org.apache.tika.utils.XMLReaderUtils`.">
<location
file="$GRADLE_USER_HOME/caches/modules-2/files-2.1/org.apache.tika/tika-core/3.2.0/9232bb3c71f231e8228f570071c0e1ea29d40115/tika-core-3.2.0.jar"/>
</issue>

</issues>
12 changes: 11 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:label="Zulip beta"
android:label="Zulip"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
Expand Down Expand Up @@ -36,6 +36,16 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="zulip" android:host="login" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.zulip.flutter

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.OpenableColumns

class AndroidIntentEventListener : AndroidIntentEventsStreamHandler() {
private var eventSink: PigeonEventSink<AndroidIntentEvent>? = null
private val buffer = mutableListOf<AndroidIntentEvent>()

override fun onListen(p0: Any?, sink: PigeonEventSink<AndroidIntentEvent>) {
eventSink = sink
buffer.forEach { eventSink!!.success(it) }
}

private fun onEvent(event: AndroidIntentEvent) {
if (eventSink != null) {
eventSink?.success(event)
} else {
buffer.add(event)
}
}

fun handleSend(context: Context, intent: Intent) {
val intentAction = intent.action
assert(
intentAction == Intent.ACTION_SEND
|| intentAction == Intent.ACTION_SEND_MULTIPLE
)

// EXTRA_TEXT and EXTRA_STREAM are the text and file components of the
// content, respectively. The ACTION_SEND{,_MULTIPLE} docs say
// "either" / "or" will be present:
// https://developer.android.com/reference/android/content/Intent#ACTION_SEND
// But empirically both can be present, commonly, so we accept that form,
// interpreting it as an intent to share both kinds of data.
//
// Empirically, sometimes EXTRA_TEXT isn't something we think needs to be
// shared, like the URL of a file that's present in EXTRA_STREAM… but we
// shrug and include it anyway because we don't want to second-guess other
// apps' decisions about what to include; it's their responsibility.

val extraText = intent.getStringExtra(Intent.EXTRA_TEXT)
val extraStream = when (intentAction) {
Intent.ACTION_SEND -> {
var extraStream: List<IntentSharedFile>? = null
// TODO(android-sdk-33) Remove the use of deprecated API.
@Suppress("DEPRECATION") val url = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
if (url != null) {
extraStream = listOf(getIntentSharedFile(context, url))
}
extraStream
}

Intent.ACTION_SEND_MULTIPLE -> {
var extraStream: MutableList<IntentSharedFile>? = null
// TODO(android-sdk-33) Remove the use of deprecated API.
@Suppress("DEPRECATION") val urls =
intent.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM)
if (urls != null) {
extraStream = mutableListOf()
for (url in urls) {
val sharedFile = getIntentSharedFile(context, url)
extraStream.add(sharedFile)
}
}
extraStream
}

else -> throw IllegalArgumentException("Unexpected value for intent.action: $intentAction")
}

if (extraText == null && extraStream == null) {
throw Exception("Got unexpected ACTION_SEND* intent, with neither EXTRA_TEXT nor EXTRA_STREAM")
}

onEvent(
AndroidIntentSendEvent(
action = intentAction,
extraText = extraText,
extraStream = extraStream,
)
)
}
}

// A helper function to retrieve the shared file from the `content://` URL
// from the ACTION_SEND{_MULTIPLE} intent.
fun getIntentSharedFile(context: Context, url: Uri): IntentSharedFile {
val contentResolver = context.contentResolver
val mimeType = contentResolver.getType(url)
val name = contentResolver.query(url, null, null, null, null)?.use { cursor ->
cursor.moveToFirst()
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.getString(nameIndex)
}

class ResolverFailedException(msg: String) : RuntimeException(msg)

val bytes = (contentResolver.openInputStream(url)
?: throw ResolverFailedException("resolver.open… failed"))
.use { inputStream ->
inputStream.readBytes()
}

return IntentSharedFile(
name = name,
mimeType = mimeType,
bytes = bytes
)
}
Loading