Skip to content
Open

7.3.1 #3309

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e093f5c
Update CHANGELOG.md for 7.2.0 release
holmesworcester May 20, 2026
9640423
Publish
holmesworcester May 20, 2026
a90e889
Update packages CHANGELOG.md
holmesworcester May 20, 2026
ed29237
Revert iOS Tor.framework to 405.9.1 (Tor 0.4.5.9) on 7.2.0
holmesworcester May 20, 2026
75313d6
Publish
holmesworcester May 20, 2026
e59ae6e
Update packages CHANGELOG.md
holmesworcester May 20, 2026
f4d1907
fix(android): stop leave-community crash from missing Firebase config…
holmesworcester May 21, 2026
0623385
Publish
holmesworcester May 21, 2026
cc3e68c
Update packages CHANGELOG.md
holmesworcester May 21, 2026
78665f7
feat(mobile): dev/alpha-only "Share logs" + "Share all data" on Start…
holmesworcester May 21, 2026
6e2bff2
docs: complete 7.2.0 CHANGELOG with merged fixes since last alpha (#3…
holmesworcester May 26, 2026
a115b9a
test(mobile): refresh JoinCommunity/CreateCommunity snapshots for Spl…
holmesworcester May 26, 2026
a1da4b1
Publish
holmesworcester May 26, 2026
898fff1
Update packages CHANGELOG.md
holmesworcester May 26, 2026
8031bb5
Publish
islathehut May 28, 2026
c26b63a
Update packages CHANGELOG.md
islathehut May 28, 2026
4d8d486
Revert "Update packages CHANGELOG.md"
islathehut May 28, 2026
a3186ae
Revert "Publish"
islathehut May 28, 2026
9c7c53a
Merge branch '7.2.0' into 7.3.0
islathehut May 28, 2026
7118176
Publish
islathehut May 28, 2026
d7a4d28
Update packages CHANGELOG.md
islathehut May 28, 2026
d3ca17b
Update gitmodules
islathehut May 29, 2026
4e71eff
feat(3256): Make private channel creation and modification admin-only…
islathehut Jun 2, 2026
90534e0
Publish
islathehut Jun 2, 2026
f225014
Update packages CHANGELOG.md
islathehut Jun 2, 2026
8aeeffa
Fix Android Push Notification Cursor Race (#3264)
adrastaea Jun 3, 2026
b14c7a9
Publish
islathehut Jun 3, 2026
e3d252b
Update packages CHANGELOG.md
islathehut Jun 3, 2026
efd57d8
Android Foreground Notification Request (#3259)
adrastaea Jun 3, 2026
7ccc5a8
fix(3266): Mark IOS UI as needing compatibility updates to fix contra…
islathehut Jun 4, 2026
568f30a
Publish
islathehut Jun 4, 2026
a6bd1f2
Update packages CHANGELOG.md
islathehut Jun 4, 2026
38039f6
Publish
islathehut Jun 4, 2026
521b9f1
Update packages CHANGELOG.md
islathehut Jun 4, 2026
89f065c
Merge branch 'develop' into 7.3.0
islathehut Jun 4, 2026
f42ecd7
hide private channel ui
adrastaea Jun 20, 2026
bb96585
Publish
adrastaea Jun 20, 2026
10a689f
Update packages CHANGELOG.md
adrastaea Jun 20, 2026
a68d9d3
fix(ci): dedupe js-libp2p-noise deps to unbreak submodule build
adrastaea Jun 20, 2026
154905e
test: disable private-channel tests while private channels are hidden
adrastaea Jun 20, 2026
8e4b5ec
Publish
adrastaea Jun 20, 2026
6ac8743
Update packages CHANGELOG.md
adrastaea Jun 20, 2026
d70945d
Publish
holmesworcester Jun 20, 2026
ffaee1a
Update packages CHANGELOG.md
holmesworcester Jun 20, 2026
15ff076
Publish
holmesworcester Jun 20, 2026
03503d9
Update packages CHANGELOG.md
holmesworcester Jun 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 3rd-party/auth
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
# Changelog

## [unreleased]
## [7.3.1]

### Fixes

* Temporarily disabled private channels

## [7.3.0]

### Features

* Adds private channels with modifiable membership (no removals) to desktop [#3155](https://github.com/TryQuiet/quiet/issues/3155)
* Adds private channels with modifiable membership (no removals) to mobile [#3155](https://github.com/TryQuiet/quiet/issues/3155)
* Private channel creation and modification is limited to admins [#3256](https://github.com/TryQuiet/quiet/issues/3256)

### Fixes

* Fix: leaving a community now purges uploaded and downloaded files; if the leave is interrupted (process killed, OS-terminated, power loss), the purge is finished on the next app launch [#3225](https://github.com/TryQuiet/quiet/issues/3225)
* Fixed android not requesting permission for foreground push notifications [#3254](https://github.com/TryQuiet/quiet/issues/3254)
* Fixes race condition with android push notifications [#3255](https://github.com/TryQuiet/quiet/issues/3255)
* Mark IOS UI as needing compatibility updates to fix contrast problems on IOS 26 [#3266](https://github.com/TryQuiet/quiet/issues/3266)

## [7.2.0]

Expand Down
212 changes: 212 additions & 0 deletions android_crash_logs.txt

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"lint-staged": "lerna run lint-staged",
"pull:submodules": "git submodule update --init --recursive --remote",
"build:auth": "cd ./3rd-party/auth && pnpm install && pnpm build",
"build:noise": "cd ./3rd-party/js-libp2p-noise && npm i && npm run build",
"build:noise": "node scripts/patch-noise-overrides.js && cd ./3rd-party/js-libp2p-noise && npm i && npm run build",
"build:orbitdb": "cd ./3rd-party/orbitdb && npm i && npm run build:dist && npm run build:debug",
"applyPatches:qss": "patch -f -p0 < ./patch/qss.npmrc.patch || true",
"build:qss": "cd ./3rd-party/qss && pnpm run bootstrap",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('lockbox', () => {
expect(adminSigChain.context).toBeDefined()
expect(adminSigChain.team!.teamName).toBe('test')
expect(adminSigChain.user.userName).toBe('user')
expect(adminSigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(adminSigChain.roles.amIAdmin()).toBe(true)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
it('should create keys from seed and salt', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('invites', () => {
expect(adminSigChain.user).toBeDefined()
expect(adminSigChain.team!.teamName).toBe('test')
expect(adminSigChain.user.userName).toBe('user')
expect(adminSigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(adminSigChain.roles.amIAdmin()).toBe(true)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
it('admin should generate an invite and it be added to team graph', () => {
Expand Down Expand Up @@ -47,7 +47,7 @@ describe('invites', () => {
expect(newMemberSigChain.user.userName).toBe('user2')
expect(newMemberSigChain.user.userId).not.toBe(adminSigChain.user.userId)
expect(newMemberSigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(false)
expect(newMemberSigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(false)
expect(newMemberSigChain.roles.amIAdmin()).toBe(false)
expect(
adminSigChain.invites.admitMemberFromInvite(
inviteProof,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('devices', () => {
expect(adminSigChain.context).toBeDefined()
expect(adminSigChain.team!.teamName).toBe('test')
expect(adminSigChain.user.userName).toBe('user')
expect(adminSigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(adminSigChain.roles.amIAdmin()).toBe(true)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
it('sigchain should contain admin device', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('users', () => {
expect(adminSigChain.context).toBeDefined()
expect(adminSigChain.team!.teamName).toBe('test')
expect(adminSigChain.user.userName).toBe('user')
expect(adminSigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(adminSigChain.roles.amIAdmin()).toBe(true)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
it('should get keys', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('channels', () => {
expect(adminSigChain.context).toBeDefined()
expect(adminSigChain.team!.teamName).toBe(teamName)
expect(adminSigChain.user.userName).toBe(adminUsername)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(adminSigChain.roles.amIAdmin()).toBe(true)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
it('should create channel and admin should be added as member', () => {
Expand Down
16 changes: 16 additions & 0 deletions packages/backend/src/nest/auth/services/roles/channel.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ChainServiceBase } from '../chainServiceBase'
import { Member } from '@localfirst/auth'
import { createLogger } from '../../../common/logger'
import { hash } from '@localfirst/crypto'
import { NotAdminError, RoleName } from './roles'

const logger = createLogger('auth:channelService')

Expand All @@ -16,13 +17,19 @@ class ChannelService extends ChainServiceBase {
}

public create(channelId: string): string {
if (!this.sigChain.roles.amIAdmin()) {
throw new NotAdminError()
}
const roleName = this.generateChannelRoleName(channelId)
logger.info(`Adding new channel role with name ${roleName}`)
this.sigChain.roles.create(roleName)
return roleName
}

public createWithMembers(channelId: string, memberIdsForChannel: string[]): string {
if (!this.sigChain.roles.amIAdmin()) {
throw new NotAdminError()
}
const roleName = this.create(channelId)
for (const memberId of memberIdsForChannel) {
this.addMember(memberId, channelId)
Expand All @@ -31,6 +38,9 @@ class ChannelService extends ChainServiceBase {
}

public addMember(memberId: string, channelId: string) {
if (!this.sigChain.roles.amIAdmin()) {
throw new NotAdminError()
}
logger.info(`Adding member with ID ${memberId} to channel ${channelId}`)
const roleName = this.generateChannelRoleName(channelId)
this.sigChain.roles!.addMember(memberId, roleName)
Expand All @@ -52,12 +62,18 @@ class ChannelService extends ChainServiceBase {
}

public revokeMembership(memberId: string, channelId: string) {
if (!this.sigChain.roles.amIAdmin()) {
throw new NotAdminError()
}
logger.info(`Revoking membership of channel ${channelId} for member with ID ${memberId}`)
const roleName = this.generateChannelRoleName(channelId)
this.sigChain.roles.revokeMembership(memberId, roleName)
}

public delete(channelId: string) {
if (!this.sigChain.roles.amIAdmin()) {
throw new NotAdminError()
}
logger.info(`Removing role for channel ${channelId}`)
const roleName = this.generateChannelRoleName(channelId)
this.sigChain.roles.delete(roleName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('channels', () => {
expect(adminSigChain.context).toBeDefined()
expect(adminSigChain.team!.teamName).toBe(teamName)
expect(adminSigChain.user.userName).toBe(adminUsername)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(adminSigChain.roles.amIAdmin()).toBe(true)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
it('should create channel and admin should be added as member', () => {
Expand Down
8 changes: 8 additions & 0 deletions packages/backend/src/nest/auth/services/roles/role.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ class RoleService extends ChainServiceBase {
return this.memberHasRole(this.sigChain.user.userId, roleName)
}

public memberIsAdmin(memberId: string): boolean {
return this.sigChain.team!.memberIsAdmin(memberId)
}

public amIAdmin(): boolean {
return this.memberIsAdmin(this.sigChain.user.userId)
}

public getMembersForRole(roleName: RoleName | string): Member[] {
return this.sigChain.team!.membersInRole(roleName)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('roles', () => {
expect(adminSigChain.context).toBeDefined()
expect(adminSigChain.team!.teamName).toBe(teamName)
expect(adminSigChain.user.userName).toBe(adminUsername)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(adminSigChain.roles.amIAdmin()).toBe(true)
expect(adminSigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
it('should create an invite', () => {
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/nest/auth/services/roles/roles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ export type BaseChannel = {
export type Channel = QuietRole & BaseChannel

export type TruncatedChannel = TruncatedQuietRole & BaseChannel

export class NotAdminError extends Error {
constructor() {
super('User is not an admin on this community')
}
}
4 changes: 2 additions & 2 deletions packages/backend/src/nest/auth/sigchain.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('SigChain', () => {
expect(sigChain.context).toBeDefined()
expect(sigChain.team!.teamName).toBe('test')
expect(sigChain.user.userName).toBe('user')
expect(sigChain.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(sigChain.roles.amIAdmin()).toBe(true)
expect(sigChain.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
it('admin should not have a role that does not exist', () => {
Expand All @@ -30,7 +30,7 @@ describe('SigChain', () => {
const sigChain2 = SigChain.load(serializedChain, localUserContext, sigChain.team!.teamKeyring())
expect(sigChain2).toBeDefined()
expect(sigChain2.team!.teamName).toBe('test')
expect(sigChain2.roles.amIMemberOfRole(RoleName.ADMIN)).toBe(true)
expect(sigChain2.roles.amIAdmin()).toBe(true)
expect(sigChain2.roles.amIMemberOfRole(RoleName.MEMBER)).toBe(true)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import {
User,
UserProfilesUpdatedPayload,
UpdateCommunityPayload,
ChannelOperationStatus,
} from '@quiet/types'
import { CONFIG_OPTIONS, QSS_ALLOWED, QSS_ENDPOINT, SERVER_IO_PROVIDER, SOCKS_PROXY_AGENT } from '../const'
import { Libp2pService, Libp2pState } from '../libp2p/libp2p.service'
Expand Down Expand Up @@ -1115,7 +1116,17 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
this.socketService.on(
SocketActions.CREATE_CHANNEL,
async (payload: CreateChannelPayload, callback: (response?: CreateChannelResponse) => void) => {
callback(await this.storageService?.channels.handleCreateChannel(payload))
const _createChannel = async (payload: CreateChannelPayload): Promise<CreateChannelResponse> => {
try {
return await this.storageService?.channels.handleCreateChannel(payload)
} catch (e) {
this.logger.error('Error while creating channel', e)
return {
status: ChannelOperationStatus.FAILED,
}
}
}
callback(await _createChannel(payload))
}
)
this.socketService.on(
Expand Down
11 changes: 9 additions & 2 deletions packages/backend/src/nest/storage/channels/channels.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
DownloadStatus,
RemoveDownloadStatus,
CHANNEL_METADATA_STORE_NAME,
ChannelOperationStatus,
} from '@quiet/types'
import fs from 'fs'
import { IpfsFileManagerService } from '../../ipfs-file-manager/ipfs-file-manager.service'
Expand Down Expand Up @@ -473,7 +474,7 @@ export class ChannelsService extends EventEmitter {
if (!store) {
throw new Error('Failed to create channel')
}
return { channel: channelData }
return { channel: channelData, status: ChannelOperationStatus.SUCCESS }
}

/**
Expand Down Expand Up @@ -523,7 +524,7 @@ export class ChannelsService extends EventEmitter {
this.emit(StorageEvents.CHANNEL_SUBSCRIBED, {
channelId: channelData.id,
} as ChannelSubscribedPayload)
return { channel: channelData }
return { channel: channelData, status: ChannelOperationStatus.SUCCESS }
}

/**
Expand Down Expand Up @@ -616,6 +617,12 @@ export class ChannelsService extends EventEmitter {
return { channelId, status: AddMembersChannelStatus.NOT_MEMBER }
}

const isAdmin = this.sigchainService.activeChain.roles.amIAdmin()
if (!isAdmin) {
this.logger.error(`You are not an admin, cannot add members to private channel!`)
return { channelId, status: AddMembersChannelStatus.NOT_ADMIN }
}

const repo = this.channelsRepos.get(channelId)
const store = repo?.store
if (store == null) {
Expand Down
43 changes: 41 additions & 2 deletions packages/desktop/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,53 @@
# Changelog

## [7.3.1]

### Fixes

* Temporarily disabled private channels

## [7.3.0]

### Features

* Adds private channels with modifiable membership (no removals) to desktop [#3155](https://github.com/TryQuiet/quiet/issues/3155)
* Adds private channels with modifiable membership (no removals) to mobile [#3155](https://github.com/TryQuiet/quiet/issues/3155)
* Private channel creation and modification is limited to admins [#3256](https://github.com/TryQuiet/quiet/issues/3256)

### Fixes

* Fix: leaving a community now purges uploaded and downloaded files; if the leave is interrupted (process killed, OS-terminated, power loss), the purge is finished on the next app launch [#3225](https://github.com/TryQuiet/quiet/issues/3225)
* Fixed android not requesting permission for foreground push notifications [#3254](https://github.com/TryQuiet/quiet/issues/3254)
* Fixes race condition with android push notifications [#3255](https://github.com/TryQuiet/quiet/issues/3255)
* Mark IOS UI as needing compatibility updates to fix contrast problems on IOS 26 [#3266](https://github.com/TryQuiet/quiet/issues/3266)

## [7.2.0]

### Features

* Added background push notifications and background hibernation for android [#3156](https://github.com/TryQuiet/quiet/issues/3156)
* Extends the dev/alpha-only "Share logs" and "Share all data" actions to the "Starting backend" screen (mobile) [#3241](https://github.com/TryQuiet/quiet/pull/3241)

### Fixes

* The user profile tab at the bottom of the sidebar now has the correct opacity and layout, and the faint horizontal stripe that appeared on some platforms and window sizes is gone now. [#3184](https://github.com/TryQuiet/quiet/pull/3184)
* Improved tor lifecycle handling [#3233](https://github.com/TryQuiet/quiet/issues/3233)
* Fixed Android crash on leaving a community when `google-services.json` was missing from the build [#3238](https://github.com/TryQuiet/quiet/pull/3238)
* Fixed broken privacy policy link on the Terms of Service / Privacy Policy acceptance screen (desktop + mobile) [#3186](https://github.com/TryQuiet/quiet/pull/3186)
* Fixed Android build failure under product flavors where react-native-config didn't load the matching `.env` file [#3197](https://github.com/TryQuiet/quiet/pull/3197)

### Chores

* Refactored syncing data with QSS for modularity [#3235](https://github.com/TryQuiet/quiet/issues/3235)
* Upgraded Electron to v32 (desktop) [#3119](https://github.com/TryQuiet/quiet/pull/3119)

## [7.1.0]

### Features

* Adds ios push notification support [#3087](https://github.com/TryQuiet/quiet/issues/3087)
* Adds dev/alpha-only "Share logs" and "Share all data" actions on joining screen and menu (mobile) [#3213](https://github.com/TryQuiet/quiet/issues/3213)

### Fixes

### Chores

## [7.0.1]
Expand Down
4 changes: 2 additions & 2 deletions packages/desktop/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
},
"homepage": "https://github.com/TryQuiet",
"@comment version": "To build new version for specific platform, just replace platform in version tag to one of following linux, mac, windows",
"version": "7.1.0",
"version": "7.3.4",
"description": "Decentralized team chat",
"main": "dist/main/main.js",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const args: CreateChannelProps = {
createChannel: function (name: string): void {
logger.info('creating channel: ', name)
},
isAdmin: true,
handleClose: function (): void {},
clearErrorsDispatch: function (): void {},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ describe('Add new channel', () => {
createChannel={() => {}}
handleClose={() => {}}
clearErrorsDispatch={() => {}}
isAdmin={true}
/>
)

Expand Down Expand Up @@ -130,6 +131,7 @@ describe('Add new channel', () => {
createChannel={() => {}}
handleClose={() => {}}
clearErrorsDispatch={() => {}}
isAdmin={true}
/>
)

Expand Down
Loading
Loading