diff --git a/Dockerfile b/Dockerfile index 3b3f911236..fa3ba1d00f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM ubuntu:22.04 as builder SHELL ["bash", "-c"] ARG git_commit_id -ARG rust_version=1.73.0 +ARG rust_version=1.75.0 ENV GIT_COMMIT_ID=$git_commit_id ENV TZ=UTC diff --git a/backend/canisters/community/CHANGELOG.md b/backend/canisters/community/CHANGELOG.md index c035d81d8a..b6f1196b66 100644 --- a/backend/canisters/community/CHANGELOG.md +++ b/backend/canisters/community/CHANGELOG.md @@ -9,6 +9,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Show proposal payloads for NNS proposals ([#5072](https://github.com/open-chat-labs/open-chat/pull/5072)) +### Changed + +- Add `subtype` to channel search results ([#5084](https://github.com/open-chat-labs/open-chat/pull/5084)) + +### Fixed + +- Prevent latest messages of payment gated groups from being public ([#5080](https://github.com/open-chat-labs/open-chat/pull/5080)) + ## [[2.0.985](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.985-community)] - 2023-12-19 ### Added diff --git a/backend/canisters/community/impl/src/jobs/make_pending_payments.rs b/backend/canisters/community/impl/src/jobs/make_pending_payments.rs index 7e868cca1a..22acb3f953 100644 --- a/backend/canisters/community/impl/src/jobs/make_pending_payments.rs +++ b/backend/canisters/community/impl/src/jobs/make_pending_payments.rs @@ -94,6 +94,6 @@ async fn make_payment(ledger_canister: CanisterId, transfer_args: TransferArg) - fn memo(reason: PendingPaymentReason) -> Memo { match reason { - PendingPaymentReason::AccessGate => MEMO_JOINING_FEE.to_vec().try_into().unwrap(), + PendingPaymentReason::AccessGate => MEMO_JOINING_FEE.to_vec().into(), } } diff --git a/backend/canisters/community/impl/src/model/channels.rs b/backend/canisters/community/impl/src/model/channels.rs index 8a33e6b414..26fadda3ea 100644 --- a/backend/canisters/community/impl/src/model/channels.rs +++ b/backend/canisters/community/impl/src/model/channels.rs @@ -370,7 +370,8 @@ impl Channel { } fn can_view_latest_message(&self, is_channel_member: bool, is_community_member: bool, is_community_public: bool) -> bool { - is_channel_member || (self.chat.is_public.value && (is_community_member || is_community_public)) + is_channel_member + || (self.chat.is_public.value && !self.chat.has_payment_gate() && (is_community_member || is_community_public)) } } @@ -388,6 +389,7 @@ impl From<&Channel> for ChannelMatch { avatar_id: types::Document::id(&channel.chat.avatar), member_count: channel.chat.members.len(), gate: channel.chat.gate.value.clone(), + subtype: channel.chat.subtype.value.clone(), } } } diff --git a/backend/canisters/cycles_dispenser/api/src/lib.rs b/backend/canisters/cycles_dispenser/api/src/lib.rs index 048db36a9f..9550e16025 100644 --- a/backend/canisters/cycles_dispenser/api/src/lib.rs +++ b/backend/canisters/cycles_dispenser/api/src/lib.rs @@ -1,7 +1,5 @@ mod lifecycle; -mod queries; mod updates; pub use lifecycle::*; -pub use queries::*; pub use updates::*; diff --git a/backend/canisters/cycles_dispenser/api/src/queries/mod.rs b/backend/canisters/cycles_dispenser/api/src/queries/mod.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/backend/canisters/cycles_dispenser/api/src/queries/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/backend/canisters/escrow/api/src/lib.rs b/backend/canisters/escrow/api/src/lib.rs index 074f4e9207..912a18a451 100644 --- a/backend/canisters/escrow/api/src/lib.rs +++ b/backend/canisters/escrow/api/src/lib.rs @@ -4,11 +4,9 @@ use sha256::sha256; use types::UserId; mod lifecycle; -mod queries; mod updates; pub use lifecycle::*; -pub use queries::*; pub use updates::*; pub fn deposit_subaccount(user_id: UserId, offer_id: u32) -> Subaccount { diff --git a/backend/canisters/escrow/api/src/queries/mod.rs b/backend/canisters/escrow/api/src/queries/mod.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/backend/canisters/escrow/api/src/queries/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/backend/canisters/group/CHANGELOG.md b/backend/canisters/group/CHANGELOG.md index a63acc50ba..2457505e6f 100644 --- a/backend/canisters/group/CHANGELOG.md +++ b/backend/canisters/group/CHANGELOG.md @@ -9,6 +9,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Show proposal payloads for NNS proposals ([#5072](https://github.com/open-chat-labs/open-chat/pull/5072)) +### Fixed + +- Prevent latest messages of payment gated groups from being public ([#5080](https://github.com/open-chat-labs/open-chat/pull/5080)) + ## [[2.0.986](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.986-group)] - 2023-12-19 ### Added diff --git a/backend/canisters/group/impl/src/jobs/make_pending_payments.rs b/backend/canisters/group/impl/src/jobs/make_pending_payments.rs index 7e868cca1a..22acb3f953 100644 --- a/backend/canisters/group/impl/src/jobs/make_pending_payments.rs +++ b/backend/canisters/group/impl/src/jobs/make_pending_payments.rs @@ -94,6 +94,6 @@ async fn make_payment(ledger_canister: CanisterId, transfer_args: TransferArg) - fn memo(reason: PendingPaymentReason) -> Memo { match reason { - PendingPaymentReason::AccessGate => MEMO_JOINING_FEE.to_vec().try_into().unwrap(), + PendingPaymentReason::AccessGate => MEMO_JOINING_FEE.to_vec().into(), } } diff --git a/backend/canisters/group/impl/src/queries/public_summary.rs b/backend/canisters/group/impl/src/queries/public_summary.rs index 7a362f1919..fe8cb814a7 100644 --- a/backend/canisters/group/impl/src/queries/public_summary.rs +++ b/backend/canisters/group/impl/src/queries/public_summary.rs @@ -23,7 +23,7 @@ fn public_summary_impl(args: Args, state: &RuntimeState) -> Response { let events_ttl = data.chat.events.get_events_time_to_live(); // You can't see private group messages unless you are a member of the group - let latest_message = if is_public || state.data.get_member(caller).is_some() { + let latest_message = if (is_public && !data.chat.has_payment_gate()) || state.data.get_member(caller).is_some() { events_reader.latest_message_event(None) } else { None diff --git a/backend/canisters/group_index/CHANGELOG.md b/backend/canisters/group_index/CHANGELOG.md index 92027eb632..3386b115e9 100644 --- a/backend/canisters/group_index/CHANGELOG.md +++ b/backend/canisters/group_index/CHANGELOG.md @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] +### Changed + +- Add `subtype` to group search results ([#5084](https://github.com/open-chat-labs/open-chat/pull/5084)) + ## [[2.0.979](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.979-group_index)] - 2023-12-19 ### Changed diff --git a/backend/canisters/group_index/impl/src/model/public_groups.rs b/backend/canisters/group_index/impl/src/model/public_groups.rs index 1f0d33104e..014389583a 100644 --- a/backend/canisters/group_index/impl/src/model/public_groups.rs +++ b/backend/canisters/group_index/impl/src/model/public_groups.rs @@ -262,6 +262,7 @@ impl From<&PublicGroupInfo> for GroupMatch { avatar_id: group.avatar_id, member_count: group.activity.member_count, gate: group.gate.clone(), + subtype: group.subtype.clone(), } } } diff --git a/backend/canisters/neuron_controller/api/src/lib.rs b/backend/canisters/neuron_controller/api/src/lib.rs index 048db36a9f..9550e16025 100644 --- a/backend/canisters/neuron_controller/api/src/lib.rs +++ b/backend/canisters/neuron_controller/api/src/lib.rs @@ -1,7 +1,5 @@ mod lifecycle; -mod queries; mod updates; pub use lifecycle::*; -pub use queries::*; pub use updates::*; diff --git a/backend/canisters/neuron_controller/api/src/queries/mod.rs b/backend/canisters/neuron_controller/api/src/queries/mod.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/backend/canisters/neuron_controller/api/src/queries/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/backend/canisters/proposals_bot/impl/src/lib.rs b/backend/canisters/proposals_bot/impl/src/lib.rs index c490562299..53f4d0355f 100644 --- a/backend/canisters/proposals_bot/impl/src/lib.rs +++ b/backend/canisters/proposals_bot/impl/src/lib.rs @@ -160,7 +160,7 @@ fn generate_message_id(governance_canister_id: CanisterId, proposal_id: Proposal hash.update(b"proposals_bot"); hash.update(governance_canister_id.as_slice()); hash.update(proposal_id.to_ne_bytes()); - let array32: [u8; 32] = hash.finalize().try_into().unwrap(); + let array32: [u8; 32] = hash.finalize().into(); let array16: [u8; 16] = array32[..16].try_into().unwrap(); u128::from_ne_bytes(array16).into() } diff --git a/backend/canisters/user/CHANGELOG.md b/backend/canisters/user/CHANGELOG.md index 3529c50b67..86554518e7 100644 --- a/backend/canisters/user/CHANGELOG.md +++ b/backend/canisters/user/CHANGELOG.md @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] +### Changed + +- Add `local_user_index_canister_id` to `initial_state` response ([#5083](https://github.com/open-chat-labs/open-chat/pull/5083)) + ### Removed - Remove group summary cache ([#5067](https://github.com/open-chat-labs/open-chat/pull/5067)) diff --git a/backend/canisters/user/api/can.did b/backend/canisters/user/api/can.did index 60e90e3849..c5039a29f7 100644 --- a/backend/canisters/user/api/can.did +++ b/backend/canisters/user/api/can.did @@ -747,6 +747,7 @@ type InitialStateResponse = variant { avatar_id : opt nat; blocked_users : vec UserId; suspended : bool; + local_user_index_canister_id : CanisterId; }; }; diff --git a/backend/canisters/user/api/src/queries/initial_state.rs b/backend/canisters/user/api/src/queries/initial_state.rs index 1c95ad482c..bacab1e15c 100644 --- a/backend/canisters/user/api/src/queries/initial_state.rs +++ b/backend/canisters/user/api/src/queries/initial_state.rs @@ -1,6 +1,6 @@ use candid::CandidType; use serde::{Deserialize, Serialize}; -use types::{Chat, ChatId, DirectChatSummary, Empty, GroupChatSummary, TimestampMillis, UserId}; +use types::{CanisterId, Chat, ChatId, DirectChatSummary, Empty, GroupChatSummary, TimestampMillis, UserId}; pub type Args = Empty; @@ -19,6 +19,7 @@ pub struct SuccessResult { pub avatar_id: Option, pub blocked_users: Vec, pub suspended: bool, + pub local_user_index_canister_id: CanisterId, } #[derive(CandidType, Serialize, Deserialize, Debug)] diff --git a/backend/canisters/user/impl/src/queries/initial_state.rs b/backend/canisters/user/impl/src/queries/initial_state.rs index 593a643d09..92f118fa65 100644 --- a/backend/canisters/user/impl/src/queries/initial_state.rs +++ b/backend/canisters/user/impl/src/queries/initial_state.rs @@ -44,5 +44,6 @@ fn initial_state_impl(state: &RuntimeState) -> Response { avatar_id, blocked_users, suspended: state.data.suspended.value, + local_user_index_canister_id: state.data.local_user_index_canister_id, }) } diff --git a/backend/canisters/user_index/impl/src/jobs/make_pending_payments.rs b/backend/canisters/user_index/impl/src/jobs/make_pending_payments.rs index 0492af24b0..dbaacd346f 100644 --- a/backend/canisters/user_index/impl/src/jobs/make_pending_payments.rs +++ b/backend/canisters/user_index/impl/src/jobs/make_pending_payments.rs @@ -66,7 +66,7 @@ async fn make_payment(pending_payment: &PendingPayment) -> Result TokenStream { } fn get_method_attribute(inputs: Vec) -> MethodAttribute { - let first_arg = inputs.get(0).unwrap(); + let first_arg = inputs.first().unwrap(); let second_arg = inputs.get(1).unwrap(); let third_arg = inputs.get(2).unwrap(); diff --git a/backend/libraries/canister_api_macros/src/lib.rs b/backend/libraries/canister_api_macros/src/lib.rs index d93a625689..6ce8e03fc7 100644 --- a/backend/libraries/canister_api_macros/src/lib.rs +++ b/backend/libraries/canister_api_macros/src/lib.rs @@ -180,7 +180,7 @@ fn get_arg_names(signature: &Signature) -> Vec { } fn get_validation_method_attribute(inputs: Vec) -> ValidationMethodAttribute { - let service_name = inputs.get(0).unwrap().to_string(); + let service_name = inputs.first().unwrap().to_string(); let function_name = inputs.get(1).unwrap().to_string(); ValidationMethodAttribute { diff --git a/backend/libraries/group_chat_core/src/lib.rs b/backend/libraries/group_chat_core/src/lib.rs index ef1e4e8b20..c0b1ec8e1d 100644 --- a/backend/libraries/group_chat_core/src/lib.rs +++ b/backend/libraries/group_chat_core/src/lib.rs @@ -1731,12 +1731,8 @@ impl GroupChatCore { }) } - fn has_payment_gate(&self) -> bool { - self.gate - .value - .as_ref() - .map(|g| matches!(g, AccessGate::Payment(_))) - .unwrap_or_default() + pub fn has_payment_gate(&self) -> bool { + self.gate.value.as_ref().map(|g| g.is_payment_gate()).unwrap_or_default() } } diff --git a/backend/libraries/types/can.did b/backend/libraries/types/can.did index 135808d2d2..7868dababf 100644 --- a/backend/libraries/types/can.did +++ b/backend/libraries/types/can.did @@ -1590,6 +1590,7 @@ type GroupMatch = record { avatar_id : opt nat; member_count : nat32; gate : opt AccessGate; + subtype : opt GroupSubtype; }; type ChannelMatch = record { @@ -1599,6 +1600,7 @@ type ChannelMatch = record { avatar_id : opt nat; member_count : nat32; gate : opt AccessGate; + subtype : opt GroupSubtype; }; type ThreadPreview = record { diff --git a/backend/libraries/types/src/gated_groups.rs b/backend/libraries/types/src/gated_groups.rs index f3f61a4441..2ff3fe18cd 100644 --- a/backend/libraries/types/src/gated_groups.rs +++ b/backend/libraries/types/src/gated_groups.rs @@ -17,6 +17,10 @@ impl AccessGate { pub fn synchronous(&self) -> bool { matches!(self, AccessGate::DiamondMember) } + + pub fn is_payment_gate(&self) -> bool { + matches!(self, AccessGate::Payment(_)) + } } #[derive(CandidType, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] diff --git a/backend/libraries/types/src/group_match.rs b/backend/libraries/types/src/group_match.rs index e3354156be..f1773264c4 100644 --- a/backend/libraries/types/src/group_match.rs +++ b/backend/libraries/types/src/group_match.rs @@ -1,4 +1,4 @@ -use crate::{AccessGate, ChannelId, ChatId, CommunityId}; +use crate::{AccessGate, ChannelId, ChatId, CommunityId, GroupSubtype}; use candid::CandidType; use serde::{Deserialize, Serialize}; @@ -10,6 +10,7 @@ pub struct GroupMatch { pub avatar_id: Option, pub member_count: u32, pub gate: Option, + pub subtype: Option, } #[derive(CandidType, Serialize, Deserialize, Debug)] @@ -35,4 +36,5 @@ pub struct ChannelMatch { pub avatar_id: Option, pub member_count: u32, pub gate: Option, + pub subtype: Option, } diff --git a/frontend/app/src/components/Panel.svelte b/frontend/app/src/components/Panel.svelte deleted file mode 100644 index 62fd9cb421..0000000000 --- a/frontend/app/src/components/Panel.svelte +++ /dev/null @@ -1,163 +0,0 @@ - - -
- -
- - diff --git a/frontend/app/src/components/Resizable.svelte b/frontend/app/src/components/Resizable.svelte new file mode 100644 index 0000000000..537b478a6d --- /dev/null +++ b/frontend/app/src/components/Resizable.svelte @@ -0,0 +1,90 @@ + + + + +{#if !$mobileWidth} + + +{/if} + + diff --git a/frontend/app/src/components/SelectChatModal.svelte b/frontend/app/src/components/SelectChatModal.svelte index 52c6ea4d3a..5f81ff33bf 100644 --- a/frontend/app/src/components/SelectChatModal.svelte +++ b/frontend/app/src/components/SelectChatModal.svelte @@ -15,7 +15,6 @@ import Avatar from "./Avatar.svelte"; import CollapsibleCard from "./CollapsibleCard.svelte"; import { AvatarSize, chatIdentifiersEqual } from "openchat-client"; - import Panel from "./Panel.svelte"; import { iconSize } from "../stores/iconSize"; import HoverIcon from "./HoverIcon.svelte"; import AccountMultiple from "svelte-material-icons/AccountMultiple.svelte"; @@ -250,7 +249,7 @@ } - +
@@ -419,7 +418,7 @@ {/each} {/if} - +
diff --git a/frontend/app/src/components/home/LeftPanel.svelte b/frontend/app/src/components/home/LeftPanel.svelte index a827abd793..bc0a2a2c2d 100644 --- a/frontend/app/src/components/home/LeftPanel.svelte +++ b/frontend/app/src/components/home/LeftPanel.svelte @@ -1,9 +1,14 @@ - +
- +
diff --git a/frontend/app/src/components/home/MessageEntry.svelte b/frontend/app/src/components/home/MessageEntry.svelte index a13ca8a6e8..fa49c7acb9 100644 --- a/frontend/app/src/components/home/MessageEntry.svelte +++ b/frontend/app/src/components/home/MessageEntry.svelte @@ -68,7 +68,7 @@ let emojiQuery: string | undefined; let messageEntryHeight: number; let messageActions: MessageActions; - let rangeToReplace: [number, number] | undefined = undefined; + let rangeToReplace: [Node, number, number] | undefined = undefined; let previousChatId = chat.id; // Update this to force a new textbox instance to be created @@ -172,23 +172,26 @@ function uptoCaret( inputContent: string | null, - fn: (slice: string, pos: number) => void, + fn: (slice: string, node: Node, pos: number) => void, ): void { if (inputContent === null) return; - const pos = window.getSelection()?.anchorOffset; - if (pos === undefined) return; + const selection = window.getSelection(); + if (selection === null) return; + const anchorNode = selection.anchorNode; + if (anchorNode?.textContent == null) return; + const text = anchorNode.textContent; - const slice = inputContent.slice(0, pos); - fn(slice, pos); + const slice = text.slice(0, selection.anchorOffset); + fn(slice, anchorNode, selection.anchorOffset); } function triggerEmojiLookup(inputContent: string | null): void { - uptoCaret(inputContent, (slice: string, pos: number) => { + uptoCaret(inputContent, (slice: string, node: Node, pos: number) => { const matches = slice.match(emojiRegex); if (matches !== null) { if (matches.index !== undefined) { - rangeToReplace = [matches.index, pos]; + rangeToReplace = [node, matches.index, pos]; emojiQuery = matches[1].toLowerCase() || undefined; showEmojiSearch = true; } @@ -201,11 +204,11 @@ function triggerMentionLookup(inputContent: string | null): void { if (chat.kind === "direct_chat" || chat.memberCount <= 1) return; - uptoCaret(inputContent, (slice: string, pos: number) => { + uptoCaret(inputContent, (slice: string, node: Node, pos: number) => { const matches = slice.match(mentionRegex); if (matches !== null) { if (matches.index !== undefined) { - rangeToReplace = [matches.index, pos]; + rangeToReplace = [node, matches.index, pos]; mentionPrefix = matches[1].toLowerCase() || undefined; showMentionPicker = true; } @@ -436,10 +439,10 @@ sel?.addRange(range); } - function setCaretTo(pos: number) { + function setCaretTo(node: Node, pos: number) { const range = document.createRange(); - range.selectNodeContents(inp); - range.setStart(inp.childNodes[0], pos); + range.selectNodeContents(node); + range.setStart(node, pos); range.collapse(true); const sel = window.getSelection(); sel?.removeAllRanges(); @@ -454,18 +457,18 @@ function replaceTextWith(replacement: string) { if (rangeToReplace === undefined) return; - const start = rangeToReplace[0]; + const [node, start, end] = rangeToReplace; - const replaced = `${inp.textContent?.slice( + const replaced = `${node.textContent?.slice( 0, - rangeToReplace[0], - )}${replacement} ${inp.textContent?.slice(rangeToReplace[1])}`; - inp.textContent = replaced; + start, + )}${replacement} ${node.textContent?.slice(end)}`; + node.textContent = replaced; dispatch("setTextContent", inp.textContent || undefined); tick().then(() => { - setCaretTo(start + replacement.length); + setCaretTo(node, start + replacement.length + 1); }); rangeToReplace = undefined; diff --git a/frontend/app/src/components/home/MiddlePanel.svelte b/frontend/app/src/components/home/MiddlePanel.svelte index eda00e5c88..c483c99c6c 100644 --- a/frontend/app/src/components/home/MiddlePanel.svelte +++ b/frontend/app/src/components/home/MiddlePanel.svelte @@ -1,5 +1,4 @@ - +
{#if $pathParams.kind === "explore_groups_route"} {:else if $pathParams.kind === "communities_route"} @@ -68,10 +71,37 @@ on:forward /> {/if} - +
diff --git a/frontend/app/src/components/home/RightPanel.svelte b/frontend/app/src/components/home/RightPanel.svelte index 1c0a2b0530..a88344cc09 100644 --- a/frontend/app/src/components/home/RightPanel.svelte +++ b/frontend/app/src/components/home/RightPanel.svelte @@ -1,5 +1,4 @@ - +
{#if lastState.kind === "group_details" && $selectedChatId !== undefined && $multiUserChat !== undefined} {/if} - + + +
+ + diff --git a/frontend/app/src/components/home/RightPanelWrapper.svelte b/frontend/app/src/components/home/RightPanelWrapper.svelte new file mode 100644 index 0000000000..a4807bc915 --- /dev/null +++ b/frontend/app/src/components/home/RightPanelWrapper.svelte @@ -0,0 +1,71 @@ + + +{#if $layoutStore.rightPanel === "inline"} + +{/if} + +{#if $layoutStore.rightPanel === "floating"} + + +
+ +
+
+{/if} + + diff --git a/frontend/app/src/components/home/nav/LeftNav.svelte b/frontend/app/src/components/home/nav/LeftNav.svelte index 8ae4cadc67..d9107f7b0f 100644 --- a/frontend/app/src/components/home/nav/LeftNav.svelte +++ b/frontend/app/src/components/home/nav/LeftNav.svelte @@ -1,6 +1,5 @@