core, ui: require update for public groups (#7009)

This commit is contained in:
spaced4ndy
2026-05-26 09:03:41 +00:00
committed by GitHub
parent ff36d401ce
commit 12fbf61f32
12 changed files with 97 additions and 15 deletions
+1
View File
@@ -1404,6 +1404,7 @@ enum GroupLinkPlan: Decodable, Hashable {
case connectingProhibit(groupInfo_: GroupInfo?)
case known(groupInfo: GroupInfo)
case noRelays(groupSLinkData_: GroupShortLinkData?)
case updateRequired(groupSLinkData_: GroupShortLinkData?)
}
struct ChatTagData: Encodable {
@@ -1559,6 +1559,33 @@ func planAndConnect(
cleanup?()
}
}
case let .updateRequired(groupSLinkData_):
logger.debug("planAndConnect, .groupLink, .updateRequired")
await MainActor.run {
if let groupSLinkData = groupSLinkData_ {
showOpenChatAlert(
profileName: groupSLinkData.groupProfile.displayName,
profileFullName: groupSLinkData.groupProfile.fullName,
profileImage:
ProfileImage(
imageStr: groupSLinkData.groupProfile.image,
iconName: "person.2.circle.fill",
size: alertProfileImageSize
),
theme: theme,
subtitle: NSLocalizedString("This group requires a newer version of the app. Please update the app to join.", comment: "alert subtitle"),
cancelTitle: NSLocalizedString("OK", comment: "alert button"),
confirmTitle: nil,
onCancel: { cleanup?() }
)
} else {
showAlert(
NSLocalizedString("App update required", comment: "alert title"),
message: NSLocalizedString("This group requires a newer version of the app. Please update the app to join.", comment: "alert message")
)
cleanup?()
}
}
}
case let .error(chatError):
logger.debug("planAndConnect, .error \(chatErrorString(chatError))")
@@ -6993,6 +6993,7 @@ sealed class GroupLinkPlan {
@Serializable @SerialName("connectingProhibit") class ConnectingProhibit(val groupInfo_: GroupInfo? = null): GroupLinkPlan()
@Serializable @SerialName("known") class Known(val groupInfo: GroupInfo): GroupLinkPlan()
@Serializable @SerialName("noRelays") class NoRelays(val groupSLinkData_: GroupShortLinkData? = null): GroupLinkPlan()
@Serializable @SerialName("updateRequired") class UpdateRequired(val groupSLinkData_: GroupShortLinkData? = null): GroupLinkPlan()
}
abstract class TerminalItem {
@@ -316,6 +316,33 @@ private suspend fun planAndConnectTask(
cleanup()
}
}
is GroupLinkPlan.UpdateRequired -> {
Log.d(TAG, "planAndConnect, .GroupLink, .UpdateRequired")
val groupSLinkData = connectionPlan.groupLinkPlan.groupSLinkData_
if (groupSLinkData != null) {
AlertManager.privacySensitive.showOpenChatAlert(
profileName = groupSLinkData.groupProfile.displayName,
profileFullName = groupSLinkData.groupProfile.fullName,
profileImage = {
ProfileImage(
size = alertProfileImageSize,
image = groupSLinkData.groupProfile.image,
icon = MR.images.ic_supervised_user_circle_filled
)
},
subtitle = generalGetString(MR.strings.group_link_requires_newer_version),
confirmText = null,
dismissText = generalGetString(MR.strings.ok),
onDismiss = { cleanup() }
)
} else {
AlertManager.privacySensitive.showAlertMsg(
generalGetString(MR.strings.app_update_required),
generalGetString(MR.strings.group_link_requires_newer_version)
)
cleanup()
}
}
}
is ConnectionPlan.Error -> {
Log.d(TAG, "planAndConnect, error ${connectionPlan.chatError}")
@@ -196,6 +196,8 @@
<string name="link_requires_newer_app_version_please_upgrade">This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link.</string>
<string name="channel_temporarily_unavailable">Channel temporarily unavailable</string>
<string name="channel_no_active_relays_try_later">Channel has no active relays. Please try to join later.</string>
<string name="app_update_required">App update required</string>
<string name="group_link_requires_newer_version">This group requires a newer version of the app. Please update the app to join.</string>
<string name="connection_error_auth">Connection error (AUTH)</string>
<string name="connection_error_auth_desc">Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection.</string>
<string name="connection_error_blocked">Connection blocked</string>
@@ -970,6 +970,7 @@ directoryServiceEvent st opts@DirectoryOpts {adminUsers, superUsers, serviceName
GLPConnectingProhibit _ -> sendMessage cc ct $ "Already connecting to this " <> gt <> "."
GLPConnectingConfirmReconnect -> sendMessage cc ct $ "Already connecting to this " <> gt <> "."
GLPNoRelays _ -> sendMessage cc ct $ T.toTitle gt <> " has no active relays. Please try again later."
GLPUpdateRequired _ -> sendMessage cc ct $ T.toTitle gt <> " requires a newer version."
GLPOwnLink _ -> sendMessage cc ct "Unexpected error. Please report it to directory admins."
_ -> sendMessage cc ct "Unexpected error. Please report it to directory admins."
+4
View File
@@ -2331,6 +2331,10 @@ NoRelays:
- type: "noRelays"
- groupSLinkData_: [GroupShortLinkData](#groupshortlinkdata)?
UpdateRequired:
- type: "updateRequired"
- groupSLinkData_: [GroupShortLinkData](#groupshortlinkdata)?
---
@@ -2602,6 +2602,7 @@ export type GroupLinkPlan =
| GroupLinkPlan.ConnectingProhibit
| GroupLinkPlan.Known
| GroupLinkPlan.NoRelays
| GroupLinkPlan.UpdateRequired
export namespace GroupLinkPlan {
export type Tag =
@@ -2611,6 +2612,7 @@ export namespace GroupLinkPlan {
| "connectingProhibit"
| "known"
| "noRelays"
| "updateRequired"
interface Interface {
type: Tag
@@ -2649,6 +2651,11 @@ export namespace GroupLinkPlan {
type: "noRelays"
groupSLinkData_?: GroupShortLinkData
}
export interface UpdateRequired extends Interface {
type: "updateRequired"
groupSLinkData_?: GroupShortLinkData
}
}
export interface GroupMember {
@@ -1854,6 +1854,10 @@ class GroupLinkPlan_noRelays(TypedDict):
type: Literal["noRelays"]
groupSLinkData_: NotRequired["GroupShortLinkData"]
class GroupLinkPlan_updateRequired(TypedDict):
type: Literal["updateRequired"]
groupSLinkData_: NotRequired["GroupShortLinkData"]
GroupLinkPlan = (
GroupLinkPlan_ok
| GroupLinkPlan_ownLink
@@ -1861,9 +1865,10 @@ GroupLinkPlan = (
| GroupLinkPlan_connectingProhibit
| GroupLinkPlan_known
| GroupLinkPlan_noRelays
| GroupLinkPlan_updateRequired
)
GroupLinkPlan_Tag = Literal["ok", "ownLink", "connectingConfirmReconnect", "connectingProhibit", "known", "noRelays"]
GroupLinkPlan_Tag = Literal["ok", "ownLink", "connectingConfirmReconnect", "connectingProhibit", "known", "noRelays", "updateRequired"]
class GroupMember(TypedDict):
groupMemberId: int # int64
+2
View File
@@ -1051,6 +1051,7 @@ data GroupLinkPlan
| GLPConnectingProhibit {groupInfo_ :: Maybe GroupInfo}
| GLPKnown {groupInfo :: GroupInfo, groupUpdated :: BoolDef, ownerVerification :: Maybe OwnerVerification, linkOwners :: ListDef GroupLinkOwner}
| GLPNoRelays {groupSLinkData_ :: Maybe GroupShortLinkData}
| GLPUpdateRequired {groupSLinkData_ :: Maybe GroupShortLinkData}
deriving (Show)
data GroupLinkOwner = GroupLinkOwner
@@ -1096,6 +1097,7 @@ connectionPlanProceed = \case
GLPOwnLink _ -> True
GLPConnectingConfirmReconnect -> True
GLPNoRelays _ -> False
GLPUpdateRequired _ -> False
_ -> False
CPError _ -> True
+18 -14
View File
@@ -4120,21 +4120,25 @@ processChatCommand vr nm = \case
Nothing -> do
(fd, cData@(ContactLinkData _ UserContactData {direct, owners, relays})) <- getShortLinkConnReq' nm user l'
groupSLinkData_ <- liftIO $ decodeLinkUserData cData
if not direct && null relays
then pure (con (linkConnReq fd), CPGroupLink (GLPNoRelays groupSLinkData_))
else do
let FixedLinkData {linkConnReq = cReq, linkEntityId, rootKey} = fd
linkInfo = GroupShortLinkInfo {direct, groupRelays = relays, publicGroupId = B64UrlByteString <$> linkEntityId}
let profilePGId = groupSLinkData_ >>= \GroupShortLinkData {groupProfile = GroupProfile {publicGroup}} ->
fmap (\PublicGroupProfile {publicGroupId} -> publicGroupId) publicGroup
case (B64UrlByteString <$> linkEntityId, profilePGId) of
(Just entityId, Just publicGroupId) | entityId == publicGroupId -> pure ()
(Nothing, Nothing) -> pure ()
_ -> throwChatError CEInvalidConnReq
let ov = verifyLinkOwner rootKey owners l' sig_
plan <- groupJoinRequestPlan user cReq (Just linkInfo) groupSLinkData_ ov
pure (con cReq, plan)
if
| not direct && unsupportedGroupType groupSLinkData_ -> pure (con (linkConnReq fd), CPGroupLink (GLPUpdateRequired groupSLinkData_))
| not direct && null relays -> pure (con (linkConnReq fd), CPGroupLink (GLPNoRelays groupSLinkData_))
| otherwise -> do
let FixedLinkData {linkConnReq = cReq, linkEntityId, rootKey} = fd
linkInfo = GroupShortLinkInfo {direct, groupRelays = relays, publicGroupId = B64UrlByteString <$> linkEntityId}
let profilePGId = groupSLinkData_ >>= \GroupShortLinkData {groupProfile = GroupProfile {publicGroup}} ->
fmap (\PublicGroupProfile {publicGroupId} -> publicGroupId) publicGroup
case (B64UrlByteString <$> linkEntityId, profilePGId) of
(Just entityId, Just publicGroupId) | entityId == publicGroupId -> pure ()
(Nothing, Nothing) -> pure ()
_ -> throwChatError CEInvalidConnReq
let ov = verifyLinkOwner rootKey owners l' sig_
plan <- groupJoinRequestPlan user cReq (Just linkInfo) groupSLinkData_ ov
pure (con cReq, plan)
where
unsupportedGroupType = \case
Just GroupShortLinkData {groupProfile = GroupProfile {publicGroup = Just PublicGroupProfile {groupType}}} -> groupType /= GTChannel
_ -> False
knownLinkPlans = withFastStore $ \db ->
liftIO (getGroupInfoViaUserShortLink db vr user l') >>= \case
Just (cReq, g) -> pure $ Just (con cReq, CPGroupLink (GLPOwnLink g))
+1
View File
@@ -2138,6 +2138,7 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
]
knownGroup prepared = grpOrBizLink g <> ": known " <> prepared <> grpOrBiz g <> " " <> ttyGroup' g
GLPNoRelays _ -> [grpLink "channel has no active relays, please try to join later"]
GLPUpdateRequired _ -> [grpLink "this group requires a newer version of the app, please upgrade"]
where
connecting g = [grpOrBizLink g <> ": connecting to " <> grpOrBiz g <> " " <> ttyGroup' g]
grpLink = ("group link: " <>)