From df5ea3d4603f8bb6d6825fd9823ce21f45be5280 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Fri, 22 May 2026 12:45:02 +0100 Subject: [PATCH] android, desktop: new settings section design (#6777) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * android, desktop: new settings section design * Section facelift: LIGHT canvas swap, equal padding, 2dp item dividers - LIGHT canvas (themedBackground) now paints the off-white formula (bg.mixWith(onBackground, 0.95f)) so white cards read as raised. DARK/BLACK keep palette bg (cards already raised via founder's formula in Section.kt). SIMPLEX keeps its gradient. - Section cards in LIGHT switch from formula to pure white via Color.White. DARK/BLACK keep the formula, unchanged. - Section card horizontal padding equalized to 16dp on outer + inner for clean canvas-edge alignment. extraPadding (icon-indented rows) keeps DEFAULT_PADDING * 1.7f. - 2dp dividers between rows inside section cards, color matches the per-theme canvas (SIMPLEX uses gradient bottom stop). Implemented via Modifier.drawBehind on each SectionItemView, gated by a private LocalInSectionCard CompositionLocal set true only by SectionView's inner Column — standalone SectionItemView usage (alerts, pickers) stays unaffected. Single canvas helper canvasColorForCurrentTheme() in Theme.kt is the source of truth for both canvas paint and divider color. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: paint item divider on top of clickable's hover indication Previously sectionItemDivider() was inside the modifier val before clickable, so the hover background drew over it inconsistently — on hover the row's content area got a tinted overlay while the 2dp divider area stayed at canvas color, creating visible contrast that read as a "dark line below hovered row". Moving the modifier to the end of the chain (after clickable+padding) makes drawBehind paint after the hover indication, so the divider color is consistently #F2F2F2-ish regardless of hover state. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: trim section item horizontal padding to 15dp CARD_PADDING (16dp) still drives outer card margin from screen edge. Item content inside the card now uses CARD_ITEM_PADDING = CARD_PADDING - 1.dp, giving the row text a slightly tighter horizontal inset that reads better at the current card width. Co-Authored-By: Claude Opus 4.7 (1M context) * Appearance: drop redundant 10dp spacer between Apply-to row and wallpaper preview Before section facelift the spacer separated the Apply-to row from the wallpaper preview block visually. With the new 2dp item divider drawing under the Apply-to row that separation is already provided, and the spacer leaves an awkward white gap between the divider and the preview. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: repurpose SectionDivider() as explicit 2dp canvas-color line; use in Appearance themes card SectionDivider() composable had 0 callsites and used Material Divider with horizontal inset (unused legacy). Repurposed to draw a 2dp canvas-color Box matching the auto-divider style used by SectionItemView, gated by LocalInSectionCard so it no-ops outside a section card. Use it in Appearance themes card between WallpaperPresetSelector (custom composable, not a SectionItemView, so no auto-divider) and the following content (Remove image / Color mode / Dark mode), providing the visual separator the user expects between the theme grid and the rows below it. Co-Authored-By: Claude Opus 4.7 (1M context) * Appearance: symmetric vertical padding around profile avatar row ProfileImageSection's Row had Modifier.padding(top = 10.dp), giving 10dp above the avatar and 0dp below — visibly asymmetric inside the card. Changed to vertical = 10.dp so top and bottom padding match. Co-Authored-By: Claude Opus 4.7 (1M context) * NetworkAndServers: move messages card footer/spacer out of SectionView Before PR #6777 SectionView had no card chrome, so SectionTextFooter and SectionDividerSpaced placed inside its content lambda rendered as plain inline content. After the card chrome was added, the same code rendered the footer caption and the spacer INSIDE the white card area, producing an unwanted gap (and visible auto-divider tail) under Advanced network settings. Move both out of the SectionView lambda so the footer reads as a caption below the card (iOS-style) and the spacer separates this card from the next one. Co-Authored-By: Claude Opus 4.7 (1M context) * DeveloperView: move card footer/bottom-spacer out of SectionView lambdas Same pre-card-chrome pattern as NetworkAndServers: SectionTextFooter ("Show: Database IDs and Transport isolation...") and SectionBottomSpacer were inside SectionView lambdas, so after PR #6777 added card chrome they rendered inside the white card area — the footer caption sat inside the first card and the 48dp bottom spacer appeared as an empty row at the end of the deprecated-options card (after SimpleX links). Move both out of the SectionView lambda so the footer reads as a caption below the first card and the bottom spacer adds safe-area room after the deprecated-options card (not inside it). Co-Authored-By: Claude Opus 4.7 (1M context) * ChatInfoView: move chat-ttl footer caption out of SectionView lambda Same pre-card-chrome pattern: SectionTextFooter("Delete chat messages from your device.") was inside the ChatTTLOption SectionView lambda, so after PR #6777 added card chrome it rendered inside the card. Move it out so the caption sits below the card iOS-style. Co-Authored-By: Claude Opus 4.7 (1M context) * ChatWallpaperEditor: wrap loose params in SectionView cards In ChatInfo > Chat theme screen the wallpaper preset selector, the wallpaper setup controls, the reset/set-default buttons and the "Apply to" mode dropdown were rendered as loose composables on a gray canvas — no card chrome, inconsistent with the rest of Appearance. Wrap them in SectionView so they read as raised iOS-style cards: - wallpaper preset selector + setup view → one card - reset-to-global + set-default buttons → one card - (advanced mode) Apply-to dropdown → one card - (collapsed mode) Advanced-settings button → one card CustomizeThemeColorsSection and ImportExportThemeSection were already SectionView-wrapped and remain unchanged. UserWallpaperEditor (sister function with similar layout, lines 28-220) is intentionally left alone — user reported only the chat-theme entry point. Co-Authored-By: Claude Opus 4.7 (1M context) * GroupChatInfoView: render group members inside the same SectionView card as owner Previously the members card showed only the current user (owner) and the add-members button — the actual group members were rendered as separate LazyColumn items() OUTSIDE the SectionView, so they sat on the gray canvas without card chrome. Visually inconsistent: owner in a card, everyone else floating. Move filteredMembers.value.forEach { ... } INSIDE the SectionView lambda so every member row is part of the same card as the owner. Drop the explicit Divider() call (auto-divider handles it now). Move remember key to member.groupMemberId so per-member state survives reorders. Trade-off: lazy rendering of member rows is replaced with eager composition inside a Column. For typical groups (<100 members) this is imperceptible; very large groups may compose slower on open. Watching for reports. Co-Authored-By: Claude Opus 4.7 (1M context) * ChatInfoView: move E2E encryption card spacer out of SectionView lambda Same pre-card-chrome pattern: SectionDividerSpaced was inside the single-row SectionView around the InfoRow, so after PR #6777 added card chrome it rendered as a white gap inside the card (under the auto-divider on the InfoRow), producing the "extra divider + gap" the user reported. Co-Authored-By: Claude Opus 4.7 (1M context) * ServersSummaryView: wrap Message reception sections in SectionView card SubscriptionsSectionView and SMPSubscriptionsSection both rendered their InfoRows + control item in a plain Column without card chrome — so on the Servers info screen the "Message reception" section title sat above loose rows on the gray canvas (no card), inconsistent with the rest of the screen. Wrap the inner Column in SectionView so the rows get the raised iOS-style card look. The custom header Row (title + subscription status indicator) stays outside the card so the icon stays inline with the title text. Co-Authored-By: Claude Opus 4.7 (1M context) * Appearance: add missing SectionDivider import f922d8fc introduced SectionDivider() call in the themes card but forgot to add the per-symbol import. SectionView/SectionDividerSpaced etc. in this codebase are imported individually (Section.kt declares them at top level, not inside a package), so SectionDivider needs its own import line. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: fix item divider position — paint via drawWithContent at full row bottom 8050676b moved sectionItemDivider() AFTER clickable.padding() in the modifier chain to make the line paint on top of clickable's hover indication. Side effect: drawBehind then saw the size of the padding-reduced content area, not the full row, so dividers rendered 15dp ABOVE the actual row bottom (in the middle of the row's bottom padding zone) instead of at the row edge between adjacent items. Fix: keep sectionItemDivider() in the modifier val BEFORE clickable/ padding (so size = full row outer bounds) AND switch from drawBehind to drawWithContent { drawContent(); drawLine(...) } so the line is painted AFTER the chain's content + hover indication draw. Both goals satisfied: divider sits at the true row bottom AND paints on top of hover overlay. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: bump hover ripple alpha to 0.08 on LIGHT theme for visibility against canvas Default Compose Material 1 RippleTheme uses hoveredAlpha=0.04 for LIGHT, producing a Black·0.04 overlay (~#F5F5F5) on white cards — visually 3 units per channel away from the off-white canvas (~#F2F2F2), so the hover state blends into the canvas and the row looks unfocused. Add a section-local SectionRippleTheme that mirrors Material's defaults for everything except hoveredAlpha on LIGHT (raised to 0.08 → ~#EBEBEB overlay, ~7 units delta from canvas — visibly distinct). Dark themes keep Material defaults since their hover contrast is already adequate. Provided via CompositionLocalProvider in all three SectionView variants alongside LocalInSectionCard, so it scopes only to section card items. Co-Authored-By: Claude Opus 4.7 (1M context) * ProtocolServerView: pad CustomServer address field inside its card The TextEditor (144dp tall input) sat flush against the top and bottom edges of its containing SectionView card on the New server screen. Pass padding = PaddingValues(vertical = DEFAULT_PADDING_HALF) to the SectionView so the field gets 10dp of breathing room top and bottom inside the card. Co-Authored-By: Claude Opus 4.7 (1M context) * NetworkAndServers: move ConditionsButton into operators card; wrap Save servers in its own card - "Review conditions" (ConditionsButton — a bare SectionItemView) was rendered between the operators card and the messages card on the canvas without card chrome. Move it inside the operators SectionView lambda after the operator rows, so it shares the card and gets a 2dp auto-divider above it separating it from the operator list. - "Save servers" (a bare SectionItemView further down) is now wrapped in its own SectionView so it reads as a single-item card matching the iOS-style facelift of the rest of the screen. Co-Authored-By: Claude Opus 4.7 (1M context) * Appearance: fix Transparency truncation and SettingsActionItem horizontal padding Two layout regressions from earlier facelift commits where slider/item math assumed DEFAULT_PADDING (20dp) for inner card padding, but the facelift uses CARD_PADDING (16dp outer) + CARD_ITEM_PADDING (15dp inner) = 31dp per side instead of 20dp. - Slider widthIn calc in AppToolbarsSection and MessageShapeSection used (maxWidth - DEFAULT_PADDING * 2) so the slider was ~22dp wider than it should be, shrinking the label Box (weight 1f) and clipping "Transparency" to "Transparenc". Switched to (CARD_PADDING + CARD_ITEM_PADDING) * 2. - SettingsActionItemWithContent explicitly passed PaddingValues(horizontal = DEFAULT_PADDING) to its SectionItemView, overriding the new CARD_ITEM_PADDING default. That made any row using SettingsPreferenceItem/SettingsActionItem sit 5dp further inset than rows using plain SectionItemViewWithoutMinPadding — visible as a left indent on "Tail" relative to "Corner". Replaced with CARD_ITEM_PADDING so it matches. Removed `private` from CARD_PADDING and CARD_ITEM_PADDING in Section.kt to allow imports from other files (used the same way as SectionView etc. are imported individually). Co-Authored-By: Claude Opus 4.7 (1M context) * Appearance + Customize theme: bring loose items into cards, drop spurious spacer Four small fixes on the same theme-related screens: - Move "Customize theme" SectionItemView INSIDE the THEMES SectionView in AppearanceView so it sits in the same card as Color mode / Dark mode colors with an auto-divider above it. - Wrap WallpaperPresetSelector (theme slots + chat preview) and the conditional Remove-image button in CustomizeThemeView with a SectionView so they read as a card, matching the Appearance themes card pattern. Add a SectionDividerSpaced after. - Drop SectionSpacer() that sat between the Wallpaper tint row and the Sent message row inside WallpaperSetupView — auto-divider on the Wallpaper tint SectionItemView already provides separation; the 30dp spacer rendered as extra empty padding inside the card. - Wrap the Reset colors action in a single-item SectionView so it reads as its own card, matching the export/import card below. Co-Authored-By: Claude Opus 4.7 (1M context) * ServersSummaryView: wrap "Showing info for" dropdown in SectionView card The user-selection ExposedDropDownSettingRow at the top of the servers info screen was rendered loose on the canvas with no card chrome. Wrap in SectionView so it reads as a card matching the rest of the screen. Co-Authored-By: Claude Opus 4.7 (1M context) * GroupChatInfoView: move chat-ttl footer caption out of SectionView lambda Same pre-card-chrome pattern as ChatInfoView (fixed in b1a1dad8): SectionTextFooter("Delete chat messages from your device.") sat inside the SectionView around ChatTTLOption, so it rendered inside the white card after PR #6777 added card chrome. Move it out so the caption sits below the card iOS-style. Co-Authored-By: Claude Opus 4.7 (1M context) * NewChatSheet: render filtered contact list inside SectionView card The "Contacts" header was a SectionView with empty content lambda, and the actual contact rows were rendered as separate LazyColumn items OUTSIDE the SectionView — so they sat on canvas without card chrome. Move filteredContactChats.forEachIndexed { ContactListNavLinkView } INSIDE the SectionView lambda in both OneHandLazyColumn and NonOneHandLazyColumn so the contacts read as a single card matching the iOS-style facelift. Same trade-off as GroupChatInfoView members fix (fa29bb7a): lazy rendering of contact rows replaced with eager composition inside a Column. For typical contact lists (<100) imperceptible; very long lists may compose slower on open. Co-Authored-By: Claude Opus 4.7 (1M context) * AddGroupView/AddChannelView: wrap action buttons + toggles in SectionView card In Create group and Create public channel screens the action buttons (Create / Configure relays) and incognito toggle were rendered as loose SectionItemViews on the gray canvas with no card chrome. Wrap them in SectionView so they read as a single card matching the iOS-style facelift. The display-name input above and the descriptive footer below stay outside the card (text input keeps its own padding, footer reads as caption). Added missing `import SectionView` in AddGroupView. Co-Authored-By: Claude Opus 4.7 (1M context) * TagListView: wrap Add/Save list button in SectionView card The "Add to list" / "Save list" action button in TagListEditor (opened from chatlist "+" Add list) was a loose SectionItemView on the canvas with no card chrome. Wrap in SectionView so it reads as a single-item card. ChatTagInput stays as a form field above. Added missing `import SectionView`. Co-Authored-By: Claude Opus 4.7 (1M context) * UserAddressView: move "contacts remain connected" footer out; pad welcome message field; wrap Save in card Three SimpleX address fixes: - "Your contacts will remain connected" SectionTextFooter moved out of the DeleteAddressButton SectionView (was rendering inside the card). - Address settings > welcome message field gets 10dp vertical contentPadding on its SectionView so the TextEditor doesn't sit flush against the card top/bottom. - Address settings > Save action wrapped in its own SectionView so it reads as a single-item card. Co-Authored-By: Claude Opus 4.7 (1M context) * WelcomeView: wrap Create profile action button in SectionView card The Create profile action SettingsActionItem at the bottom of the Create profile screen was loose on canvas. Wrap in SectionView so it reads as a single-item card matching the iOS-style facelift. The two SectionTextFooter captions below stay outside the card. Added missing `import SectionView`. Co-Authored-By: Claude Opus 4.7 (1M context) * ConnectMobileView: move footer + spacer out of "this device name" SectionView lambda Same pre-card-chrome pattern: SectionTextFooter and SectionDividerSpaced were inside the SectionView around DeviceNameField + multicast toggle, so they rendered inside the white card after PR #6777 — visible as an extra empty padding below the "Discoverable via local network" toggle (the SectionDividerSpaced 10dp Spacer inside the card). Move both outside the SectionView so the footer reads as caption below the card and the spacer separates this card from the next. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: suppress RippleTheme deprecation warnings (build was treating warnings as errors) `androidx.compose.material.ripple.RippleTheme` and `LocalRippleTheme` were deprecated in newer Compose Material in favor of the modern Indication APIs. Our SectionRippleTheme override (a5b199660) hit those deprecations and the project's Kotlin compiler flags treat warnings as errors, breaking the build. Add `@file:Suppress("DEPRECATION")` to Section.kt — narrow file-level scope. Modern Indication-based ripple migration is a separate, larger concern; suppress for now so the section hover-alpha override keeps working. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: also suppress DEPRECATION_ERROR — RippleTheme is @Deprecated(level=ERROR) Previous attempt (4bf981a6b) suppressed DEPRECATION but the Compose library deprecated RippleTheme with level=DeprecationLevel.ERROR, which requires the DEPRECATION_ERROR suppression key instead. Add both so either severity is covered. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: replace deprecated RippleTheme override with modern Modifier.hoverable + background Drop SectionRippleTheme/RippleAlpha/LocalRippleTheme machinery (deprecated in newer Compose Material, would not compile with the project's warnings- as-errors policy without DEPRECATION_ERROR suppress, which is a code smell). Replace with a Modifier.hoverable + Modifier.background pattern — the modern Compose-native way to apply a hover overlay: - New private @Composable Modifier.sectionItemHover() that: - returns Modifier as-is outside SectionView card (LocalInSectionCard = false) - inside a card, attaches its own MutableInteractionSource via .hoverable() and paints a transparent or onBackground@0.08-alpha background based on collectIsHoveredAsState - Applied alongside .sectionItemDivider() in each SectionItemView modifier chain. Click ripple keeps coming from Modifier.clickable's own indication (default ripple, no changes there). - Drop @file:Suppress deprecation lines; drop SectionRippleTheme object; drop ripple imports; drop LocalRippleTheme from CompositionLocalProvider calls in three SectionView variants. Visual result identical to the previous attempt (hovered row gets a visible gray overlay on LIGHT canvas), no deprecated APIs, no warnings-as-errors fight. Click ripple unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: suppress sectionItemHover on disabled SectionItemView sectionItemHover was applied unconditionally inside section cards, so a disabled row would still show the hover overlay on mouseover — misleading: the visible interactive feedback contradicts the disabled state (no click reaction). Add `enabled: Boolean = true` parameter; the helper now returns `this` unchanged when `enabled = false`. The 3 SectionItemView family functions that own a modifier chain pass `enabled = !disabled`. SectionItemViewWithoutMinPadding inherits through SectionItemView delegation. Non-clickable info rows (click == null but disabled = false) still get the hover overlay — that's intentional cursor feedback matching iOS Settings behavior. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: lighten section item hover overlay from 0.08 to 0.05 alpha 0.08 read as too dark on white cards. Original Compose default 0.04 blended with the off-white canvas (#F2F2F2 vs ~#F5F5F5). 0.05 is the midpoint — still visibly distinct from canvas (~#F2F2F2 canvas vs ~#F3F3F3 hover on white card) but no longer reads as a heavy box. Co-Authored-By: Claude Opus 4.7 (1M context) * RTCServers: wrap Configure ICE servers toggle in SectionView card Your ICE servers screen had its Configure-ICE toggle and the description text / editor / read-only display all directly in a raw Column with no card chrome. Wrap the toggle row in SectionView so it reads as a card matching the iOS-style facelift. The description text and the TextEditor / read-only Surface stay in the same loose Column below (they're a form/display block, not a settings row). Removed the explicit `padding = PaddingValues()` on the SectionItemViewSpaceBetween — inside SectionView it inherits CARD_ITEM_PADDING by default which is what we want now. Co-Authored-By: Claude Opus 4.7 (1M context) * NetworkAndServers: rewrite UseSocksProxySwitch via SettingsActionItemWithContent UseSocksProxySwitch was a custom Row with hard-coded horizontal padding of DEFAULT_PADDING (20dp) — but its neighbours on the messages card are SettingsActionItem rows that go through SectionItemView with the new CARD_ITEM_PADDING (15dp). 5dp icon misalignment between the SOCKS toggle row and the rest, plus no auto-divider underneath since it wasn't a SectionItemView. Replace the custom Row with SettingsActionItemWithContent — same icon + label + DefaultSwitch shape, now wrapped in SectionItemView so it shares padding and auto-divider with siblings. Co-Authored-By: Claude Opus 4.7 (1M context) * SocksProxySettings: move section text footers out of SectionView lambdas Same pre-card-chrome pattern as elsewhere: two SectionTextFooter calls ("Disable onion hosts when not supported" and the proxy-auth footer) were inside their SectionView lambdas in SocksProxySettings, so after the card chrome was added they rendered inside the white cards as inline content. Move both out so they read as captions below the corresponding cards. Co-Authored-By: Claude Opus 4.7 (1M context) * SocksProxySettings: split UseOnionHosts so the dynamic description footer renders outside the card UseOnionHosts wrapped its ExposedDropDownSettingRow and a dynamic SectionTextFooter ("Onion hosts will be used when available." / similar) in a Column, so when UseOnionHosts was called inside a SectionView lambda the footer rendered inside the white card. Split into two composables: - UseOnionHosts — only the dropdown row (no longer wraps in Column) - UseOnionHostsDescription — only the dynamic SectionTextFooter, called separately by the caller Shared `onionHostsValues` is now a private @Composable val accessible to both. In SocksProxySettings, UseOnionHostsDescription is now placed AFTER the SectionView block (alongside the existing "Disable onion hosts when not supported" caption) so the dynamic description reads as a caption below the card. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: suppress hover on rows whose action is an inline control (switch/dropdown) sectionItemHover used to show on every row inside a section card. But rows where the action is an inline control (switch via PreferenceToggle, dropdown via ExposedDropDownSettingRow) are not "interactive as a row" — the user has to hit the actual control, not the whole row. Showing hover on the whole row was misleading. Add `clickable: Boolean = true` param to sectionItemHover; suppress when false. SectionItemView and SectionItemViewSpaceBetween pass `clickable = click != null`. SectionItemViewLongClickable keeps the default (its click is non-nullable, always interactive). Co-Authored-By: Claude Opus 4.7 (1M context) * Section + Theme: lighten LIGHT canvas to 0.97; revert custom hover overlay User feedback: the off-white canvas at 0.95 (#F2F2F2) read as too dark. Two coordinated changes: - canvasColorForCurrentTheme LIGHT branch: 0.95f → 0.97f. Canvas now #F7F7F7 (3% darker than white, was 5%). Still distinct from pure white card but lighter. - Drop the custom sectionItemHover Modifier helper (and its hoverable + InteractionSource + background machinery). The reason for the custom hover was that the default Material 0.04-alpha ripple hover (#F5F5F5 on white card) blended with the old #F2F2F2 canvas. With the lighter canvas at #F7F7F7 the default hover #F5F5F5 is now visibly darker than canvas (2 units delta) — visible enough at Material default without our custom override. Removed unused MutableInteractionSource and collectIsHoveredAsState imports. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: bump section item minHeight by 6dp (50 → 56) User asked for taller settings rows. Bump the default minHeight in all four SectionItemView family functions from DEFAULT_MIN_SECTION_ITEM_HEIGHT (50dp) to DEFAULT_MIN_SECTION_ITEM_HEIGHT + 6.dp (56dp). Scoped to SectionItemView callers only — does not touch the global DEFAULT_MIN_SECTION_ITEM_HEIGHT constant, so non-section callers (ChatItemInfoView, ComposeContextProfilePicker, TagListView, UserPicker) keep the 50dp baseline. Callers that pass explicit minHeight (e.g. 54dp in GroupChatInfoView members) are unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) * Move SectionTextFooter / Spacer out of cards in 5 screens Fixes from the user's verified list of misplaced footers/spacers: - ChatInfoView: SimpleX address footer ("You can share this address with your contacts to let them connect with you.") moved out of the address SectionView lambda. - GroupMemberInfoView: same string for member address. - Appearance: SectionSpacer in the Image-wallpaper branch (after "Remove image" button) removed — it created 30dp empty padding inside the THEMES card only when a custom image was selected. - NotificationsSettingsView: Xiaomi battery-optimization footer ("Xiaomi devices: please enable Autostart...") moved out of the notifications SectionView lambda (visible only on Xiaomi devices in Periodic/Service notification mode). - ConnectMobileView: dropped the 20dp Spacer that sat inside the QR SectionView after the developer-tools "Share link" row — visible as extra padding below Share link inside the card. Same pre-card-chrome pattern as other moves: helpers placed inside SectionView lambdas before PR #6777 rendered fine when SectionView was a plain Column; after card chrome they render inside the white card. Moved them outside so footers read as captions and spacers actually separate cards. Co-Authored-By: Claude Opus 4.7 (1M context) * Migrate views: move all SectionTextFooter / SectionSpacer out of SectionView lambdas Same pre-card-chrome pattern as elsewhere. MigrateToDevice (4 footers) and MigrateFromDevice (9 footers + 1 SectionSpacer in error view) historically wrote captions and inter-card spacers inside their SectionView content lambdas. After PR #6777 added card chrome these rendered inside the white cards. MigrateToDevice fixes (4 footers, one per sub-view): - Confirm network settings footer - Database init failed retry footer - Archive import failed retry footer - Passphrase entering dynamic footer MigrateFromDevice fixes (9 footers + 1 SectionSpacer): - ChatStopFailed view footer - Passphrase confirmation footer - Upload confirmation footer - Upload failed retry footer - Link shown view: archive-will-be-deleted + choose-migrate footers - Finished view: 2 warning footers (must-not-use-two-devices, using-on-two-devices-breaks-encryption) - Implicit SectionSpacer at ChatStopFailed view also moved out Co-Authored-By: Claude Opus 4.7 (1M context) * Section + ChatListNavLink.android: align in-card chat row divider with desktop; canvas to 0.94 Two changes: 1) Theme.kt LIGHT canvas: 0.97f → 0.94f (#F0F0F0). User wants more contrast against cards. With Material's default 0.04-alpha hover (#F5F5F5) this puts hover LIGHTER than canvas by 5 units — unusual direction but it's the user's call; they'll evaluate visually. 2) ChatListNavLinkView.android: when rendered inside a SectionView card (e.g. contact list inside NewChatSheet after the forEach-into-card refactor), use SectionDivider() — same 2dp full-width canvas-color divider as desktop. Outside a card (main chat list), fall back to the original Material `Divider(Modifier.padding(horizontal = 8.dp))` so unchanged for that context. 3) LocalInSectionCard made `internal` so the android-specific file can read it. Same pattern as LocalAppColors etc. Co-Authored-By: Claude Opus 4.7 (1M context) * Section: bump section item minHeight by 2dp more (56 → 58) * GroupWelcomeView: wrap message editor/preview and buttons in SectionView cards * GroupLinkView: wrap action items below QR in SectionView card * Section: align InfoRow / IndentedInfoRow horizontal padding with CARD_ITEM_PADDING InfoRow defaulted to DEFAULT_PADDING (20dp), but card chrome adopted CARD_ITEM_PADDING (15dp) for SectionItemView and InfoRowTwoValues. Inside a card, rows of different kinds visibly jumped left/right. Bring InfoRow and its IndentedInfoRow variant onto the same baseline. * ServersSummaryView: align Message reception header indent with other section headers * ServersSummaryView: split SMP/XFTP server summary into separate top-level cards The summary layouts wrapped Stats / Subscriptions / Sessions inside the outer Server address SectionView, which produced nested cards and pushed the Statistics 'Starting from...' footer inside a card. Unnest them so each section is its own card with proper spacing and the footer renders outside. * CreateProfile: add vertical gap between profile fields and Create profile action card * UserPicker: wrap menu options in SectionView cards (SecondSection + GlobalSettingsSection) * UserPicker: gate SectionView card wrap on Android only Desktop UserPicker doesn't have a canvas background, so white cards on the white surface were invisible and the existing desktop divider above inactive users looked stray next to the SectionItemView mini-dividers. * Revert "UserPicker: gate SectionView card wrap on Android only" This reverts commit be365e55aea25489d8812c8fb5f650db0b340ce6. * UserPicker: use canvas color on desktop and split SecondSection around inactive-users grid Desktop background was MaterialTheme.colors.surface (white) so the SectionView cards introduced earlier were invisible. Switch to canvasColorForCurrentTheme() to match Android. Drop the explicit Divider above the inactive-users grid: split SecondSection into two SectionView cards with the avatar grid between them so the section dividers come from the cards themselves. * ChatListNavLinkView.android: fix LocalInSectionCard import path LocalInSectionCard is declared in Section.kt which has no package (root package), so it must be imported as 'import LocalInSectionCard', not as 'chat.simplex.common.views.helpers.LocalInSectionCard'. * UserPicker: merge SecondSection + GlobalSettings into one card on portrait Both Android and desktop portrait now show address, preferences, (desktop: inactive-users grid), profiles, link mobile / use from desktop, and settings inside a single SectionView card. Desktop landscape keeps the side-by-side two-card layout. * ChatInfoImage: default placeholder icon color to secondary secondaryVariant is near-white (#F1F2F6) and disappears against the gray canvas. Use the visible secondary tone instead so default avatars without a photo are legible on both card and canvas backgrounds. * UserPicker: align item padding with Settings, add divider after inactive-users grid UserPickerOptionRow no longer applies extraPadding on desktop, and the Settings row uses default SectionItemView padding instead of its own. Both now match the CARD_ITEM_PADDING used in Settings screens. After the inactive-users avatar grid in the unified card, paint a SectionDivider so it visually separates from Your chat profiles. * ChatInfoImage: place default avatar one canvas-shade darker than the canvas secondary (#8B8786) was too dark. Use background mixed with onBackground at 0.88 — same darkening recipe as canvasColorForCurrentTheme uses with 0.94, applied a step further. On LIGHT this lands near #E1E1E1: 15 units darker than the canvas, matching how the canvas sits 15 darker than white. * Appearance: symmetric vertical padding around Font size and Zoom preview tiles Both rows used Modifier.padding(top = 10.dp) so the tile hugged the bottom of the SectionView card. Switch to padding(vertical = 10.dp) to match the symmetric padding used by ProfileImageSection. * ChatInfoImage: dark themes use secondaryVariant for default avatar to match UserPicker The mixWith canvas-darkening formula only lands well in LIGHT. For DARK / BLACK / SIMPLEX, fall back to secondaryVariant, which UserPicker already uses for the active profile avatar — keeps placeholder avatars consistent across the app on dark themes. * Section: tighten icon-to-text spacing in TextIconSpaced by 2dp * ChatInfoImage: lighten LIGHT default avatar to halfway between white and canvas * ChatInfoView: hide Servers section header when there is no server content When both chatSubStatus and cStats are null, the SectionView body rendered as empty (zero-height card) but the SERVERS title still appeared, leaving an orphan header between E2E encryption and Clear chat. Gate the whole section on having at least one of the two. * GroupLink / WelcomeMessage: use SectionDividerSpaced between adjacent cards Three places had adjacent SectionView cards with no spacer (GroupLinkView QR + actions, WelcomeMessageView non-owner preview + copy), or used a one-off Spacer(8.dp) instead of the conventional helper (owner mode-button card). Replace with SectionDividerSpaced() so all between-card gaps live behind one helper. * Chat info / Group info: use full spacing between two title-less cards ChatInfoView (Contact prefs/Send receipts/Chat theme → Delete messages) and GroupChatInfoView (Member reports → Edit group profile) both used SectionDividerSpaced(maxBottomPadding = false) = 10dp between two cards that have neither header nor footer touching the gap, so the tight variant wasn't justified. Switch to the default 20dp. * remove diff noise * Sections: drop .uppercase() from all section / header titles Source string resources are already in sentence case (e.g. "Profile images", "Message reception"). The .uppercase() calls forced them to ALL CAPS, which is the Android settings convention but conflicts with the iOS-style facelift. Remove the call everywhere so headers render as in the source. * Section: shrink icon-to-text spacing to 5dp (-3dp from previous 8dp) * Appearance: shrink ColorModeSwitcher tap target to keep UserPicker Settings row at standard 58dp height * UserPicker.android: align profile boxes with menu card left edge (CARD_PADDING) * ChatListNavLinkView.desktop: restore chat list dividers outside SectionView Commit 633e0f414 made SectionDivider() a no-op outside SectionView card, which removed the desktop chat list dividers (the list is not wrapped in a SectionView). Mirror the Android conditional: SectionDivider in-card, padded Divider otherwise. * UserPicker: restore SectionView wrap around desktop active-profile row Commit 3a7118235 extracted the profile out of its original SectionView when wrapping the menu in its own card. Without the card chrome the profile shifted to the screen edge instead of sitting at CARD_PADDING like the menu below. Wrap it back in SectionView and add SectionDividerSpaced before the menu card. * Strings: convert section-title resources from ALL CAPS to sentence case 26 section header strings used as SectionView titles (SETTINGS, CHAT DATABASE, HELP, SERVERS, etc.) were stored ALL CAPS in source. The .uppercase() removal commit did nothing for them. Convert the source values to sentence case with proper-noun preservation (SimpleX, SOCKS). LIVE and OK stay all-caps (status badge and button). * UserPicker: add top spacer above active profile card and tighten its left padding Card was flush against the sheet's top edge; add DEFAULT_PADDING spacer above. Left padding inside the card was 16dp while the avatar (60dp) sat in an 80dp minHeight row so visual top/bottom were ~10dp — bring start down to 10dp so the photo sits equidistant from card top, bottom and left. * Section: bump card-title font size from 12sp to 14sp across all 3 SectionView variants * ServersSummaryView: bump Message reception custom header to 14sp to match other card titles * Sections: add SemiBold weight to card titles across all 4 places * Sections: drop card-title weight from SemiBold to Medium (W500) * ServersSummaryView: Message reception header bottom padding 5dp -> 8dp to match SectionView default * Strings: convert group_info_section_title_num_members to sentence case * Strings: convert settings_section_title_interface to sentence case (Interface) * Revert UserPicker to pre-card-wraps state per founder's request Restore UserPicker.kt and UserPicker.android.kt to their state at 43855ae07 (before commit 3a7118235 introduced SectionView wraps). The founder asked in chat to keep UserPicker out of the cards facelift — undo all of our changes to it, including the followup tweaks (avatar padding, divider above grid, active-profile wrap, etc.) and the founder's own followup cleanup 23b0e41d8 which only existed to refactor our wraps. * Section / Theme: extract sectionCardColor() helper Three SectionView overloads were each computing the same cardColor inline: if (CurrentColors.value.base == DefaultTheme.LIGHT) Color.White else MaterialTheme.colors.background.mixWith(...). DRY violation paired with the canvasColorForCurrentTheme() helper that already covers the canvas side of the same theme split. Add a sectionCardColor() function in Theme.kt and collapse the 3 inline formulas to one call. * Theme: document why canvasColorForCurrentTheme reads CurrentColors.value directly Reviewer asked why this helper uses CurrentColors.value.base instead of the Compose MaterialTheme/CompositionLocal route. Reason is that the helper is intentionally callable from both @Composable bodies and DrawScope (inside sectionItemDivider's drawWithContent), and DrawScope can't invoke @Composable getters. Add a paragraph to the doc-comment so future readers don't try to 'fix' it back to MaterialTheme.colors and break the divider draw path. * ConnectMobileView: collapse double blank line left over from move-footer edit * Sections: normalize redundant SectionDividerSpaced flag combinations After founder simplified SectionDividerSpaced to one Spacer height (any flag true -> DEFAULT_PADDING; both false -> DEFAULT_PADDING_HALF), many call sites still pass combinations like (maxTopPadding = true) or (maxTopPadding = true, maxBottomPadding = false) that all produce the same 20dp gap as the default. The flag names no longer match what they do — reviewer flagged this as misleading. Collapse all call sites to two canonical forms: SectionDividerSpaced() for the 20dp gap, SectionDividerSpaced(maxBottomPadding = false) for the 10dp tight gap. Behavior identical. Function signature kept (founder's API). * NewChatSheet: render filtered contacts in search mode (regression fix) Commit 3a9ece8d1 moved contacts forEach inside the if-branch and made the else-branch fall back to NoFilteredContactsItem. That broke search: when the user typed text and the filter returned non-empty results, the if-condition (filtered.isNotEmpty() && searchText.isEmpty()) was false, the else ran NoFilteredContactsItem, NoFilteredContactsItem's internal guard saw a non-empty filter and rendered nothing — search results disappeared. Restore three-way branching with when{}: header + contacts in card when no search; contacts in plain card when search has matches; NoFilteredContactsItem when filter is empty. Applied at both OneHandLazyColumn and the regular layout. * GroupChatInfoView: keep Invite + owner in card, render members as lazy items fa29bb7a7 put filteredMembers.value.forEach inside the same SectionView as the Invite button and the owner row to get a unified card visual. That sacrificed lazy rendering — all members composed at once, hurting big-group scroll perf. Founder asked to bring lazy back. Compromise: keep Invite + (search row) + owner row inside the SectionView card (the 'hero' rows). Move the rest of the members out to a sibling items(filteredMembers.value, key = { it.groupMemberId }) call in the parent LazyColumn — bare SectionItemViewLongClickable rows below the card, lazy-composed by LazyColumn. * ChatInfoImage: LIGHT default avatar at midpoint of white card and gray canvas Was at 0.91 mix (~#E8) — designed to sit 'below' the white card, but on the ~#F0 canvas it nearly blended (delta ~8). Switch to 0.97 mix (~#F7), which is the geometric midpoint between #FF (white card) and ~#F0 (canvas) and so sits at equal absolute contrast against either background. * MemberProfileImage: use defaultProfileIconColor instead of secondaryVariant MemberProfileImage hard-coded color = MaterialTheme.colors.secondaryVariant as default, which is LightGray (#F1F2F6) on LIGHT — slightly bluish and nearly invisible against the ~#F0F0F0 canvas. Reuse the defaultProfileIconColor() helper so the LIGHT default matches the rest of the app (midpoint between canvas and white card), and DARK themes keep their palette secondaryVariant. defaultProfileIconColor() in ChatInfoImage.kt promoted from private to file- level visibility so it can be referenced from GroupMemberInfoView. * ProfileImage colors: split into card vs canvas variants Revert defaultProfileIconColor back to 0.91 mix (~#E8) — that's the right amount of contrast against a white SectionView card. Add a sibling helper defaultProfileIconColorOnCanvas() at 0.85 mix (~#D9), which sits 23 units below the ~#F0 canvas — same absolute contrast as the card variant achieves on white. Switch MemberProfileImage default from defaultProfileIconColor to the canvas variant. Member avatars almost always render on canvas (chat list rows, chat-bubble author avatar, group members list outside the card, channel members, channel relays). Callers that need the card variant pass an explicit color. * GroupChatInfoView: move owner row out of the members card into the lazy list Per review #1: card holds only Invite + (optional) search; the user-as-owner row joins the same lazy column as the rest of the members, picking up the canvas-variant avatar color through MemberProfileImage's updated default. * Revert "ProfileImage colors: split into card vs canvas variants" This reverts commit 379f84a4aeb86ace5b1cb9fcac084915d8868146. * Revert "MemberProfileImage: use defaultProfileIconColor instead of secondaryVariant" This reverts commit bea3f246644b410c939aee00a0978a004b1d2bed. * Revert "ChatInfoImage: LIGHT default avatar at midpoint of white card and gray canvas" This reverts commit 05fbd6e0b1bfc959f8e883c3b04065af40d763dc. * Theme: darken LightColorPalette.secondaryVariant from #F1F2F6 (LightGray) to #E0E0E0 Old value (LightGray = #F1F2F6) was nearly invisible against the ~#F0F0F0 canvas — slightly bluish hue, ~1-2 units of contrast. The new #E0E0E0 sits ~16 units below canvas and ~31 below white card, visible on both. Affects all LIGHT-theme avatar placeholders, UserPicker icons, DevicePill borders and a handful of subtle UI surfaces using secondaryVariant. * Card-less screens: paint background with Material surface Form-only and link/QR screens have no card sections — the off-white canvas under them just adds an extra visual layer with nothing to lift. Switch their background to MaterialTheme.colors.surface (white on LIGHT, palette surface on DARK/BLACK/SIMPLEX) so the screen reads as a single sheet. Two patterns by container: - 11 ModalView callsites get background = MaterialTheme.colors.surface. - 4 screens rendered inside someone else's ModalView (GroupLinkView, HiddenProfileView, TagListView, UserProfilesView) wrap their root ColumnWithScrollBar in Box(Modifier.fillMaxSize().background(...)) so they own their background regardless of caller. - 1 BottomSheet root (CreateProfile in WelcomeView) gets background on the fillMaxSize Box. Touched screens: Create profile, Create first profile (mobile/desktop), Create group, Create channel (3 wizard steps), Edit group profile, Group link, Add welcome message / Welcome message, Edit own profile, Hide profile, Tag list editor, Your chat profiles, Add server, Add chat relay (new variant only — Edit relay stays settings-style). * NewServerView: add missing MaterialTheme import after previous commit * Revert "GroupLink / WelcomeMessage: use SectionDividerSpaced between adjacent cards" This reverts commit 29be15404f8965c98f46a441534c9c45c44caef8. * Revert "CreateProfile: add vertical gap between profile fields and Create profile action card" This reverts commit 43855ae07d7a6c492e2ae5d5477d07de6e997a80. * Revert "WelcomeView: wrap Create profile action button in SectionView card" This reverts commit c61ea0109250e1a75d9c3efd6f8b72d1a67db752. * Revert "AddGroupView/AddChannelView: wrap action buttons + toggles in SectionView card" This reverts commit 4d9319d12af6eebb2b344b1d8d627b4510c644ab. * Revert "GroupLinkView: wrap action items below QR in SectionView card" This reverts commit f2ef38092a5375dd19971dfe399eb1a768856ca0. * Revert "GroupWelcomeView: wrap message editor/preview and buttons in SectionView cards" This reverts commit edb3495a8f04f249145c6a0ca8a6d15aaf6aabda. * Revert "TagListView: wrap Add/Save list button in SectionView card" This reverts commit c25f36a90045c9a5da77f3fccd73e113779d9d9b. * UserProfilesView: drop SectionView wraps to remove card chrome The Your-chat-profiles screen is now on white surface bg; the SectionView cards (founder's original from PR #6777) painted white-on-white and only contributed padding. Unwrap the two SectionViews (hidden-profile reveal button + main profiles list) so the rows render directly inside the ColumnWithScrollBar without card chrome. * NewChatSheet: use standard 20dp gap between cards instead of tight 10dp * WelcomeMessageView/GroupChatInfoView: unify owner button row, restore member dividers WelcomeMessageView: drop SectionView wrap on SaveButton so all three owner-mode action rows (Edit/Preview, Copy, Save) render uniformly as loose rows on canvas, matching the post-revert direction of the card-chrome cleanup. GroupChatInfoView: restore per-item Divider() in the members lazy list (lost during card-chrome experimentation). Owner row stays attached to the "N members" card by design; divider appears between owner and first lazy member, and between each subsequent member. Co-Authored-By: Claude Opus 4.7 (1M context) * Strings: sentence case for 29 section-title keys across all locales Base file was converted in 8292a815f / de36f1f40 / 314384b69 but other locales still rendered titles like SETTINGS, НАСТРОЙКИ, EINSTELLUNGEN, PARAMÈTRES, USTAWIENIA, ÎMPOSTAZIONI in ALL CAPS. Bring every locale to sentence case with a single sweep. Implementation: Python script (/tmp/fix_uppercase_locales.py) walks every non-base locale dir, finds the 29 key strings, and rewrites them when the value is entirely uppercase (no lowercase letter). Placeholders like %1$s are preserved as-is; SimpleX and SOCKS are kept as proper nouns after the lowercase pass. Values already in sentence case, empty, or in scripts with no case distinction are left alone. 540 string changes across 33 locales (ar, bg, ca, cs, da, de, el, es, fa, fi, fr, hr, hu, in, it, iw, ja, ko, ku, lt, nb-rNO, nl, pl, pt, pt-rBR, ro, ru, th, tr, uk, vi, zh-rCN, zh-rTW). Locales bn, hi, ml, sv, lv had nothing to change. * UserProfilesView: use Divider() between rows (SectionDivider no-op outside SectionView) * ShareListView: use MaterialTheme.colors.surface background (Forward picker) * ChatItemInfoView: white surface background + drop SectionView card wraps Message info screen (right-click → Info on desktop) had off-white themedBackground canvas with white SectionView cards inside. Switch to MaterialTheme.colors.surface background and replace 7 SectionView wraps with plain Column (preserving the contentPadding the SectionViews had) — content reads as a single sheet, no ghost card edges on white-on-white. * Card-less screens batch 2: surface bg for conditions + how-to-use + about + version Six more screens get white surface background to match the form-screen visual: - UsageConditionsView (Network & servers → Review conditions): root ColumnWithScrollBar gets .background(surface). - SingleOperatorUsageConditionsView (operator-conditions modal opened from enabling an operator): same. - HowItWorks (Settings → How to use it): root Column gets .background(surface). - WhatsNewView (Settings → What's new): ModalView gets background = surface. - SimpleXInfoLayout (Settings → About SimpleX Chat): conditional on onboardingStage == null so the onboarding entry keeps its themedBackground while the settings entry switches to surface. - VersionInfoView (Settings → App version): root ColumnWithScrollBar gets .background(surface). * fix language strings * fix contact list to be lazy * more language fixes * fix greek * fix indentation * refactor and simplify * remove dividers * background for settings pages with cards * fix section titles * remove footers outside of section cards * move footers out of cards * fix appearance etc * fix members lists, add background * appearance * reduce paddings inside cards * paddings * more paddings * card item paddings * fix paddings * toolbar color * more toolbar color * fix toolbar * add padding * refactor modals hierarchy * more cards * more cards * fix theme * split walpaper settings to two sections * better grid * grid --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> Co-authored-by: another-simple-pixel Co-authored-by: Claude Opus 4.7 (1M context) --- .../views/usersettings/Appearance.android.kt | 7 +- .../chat/simplex/common/ui/theme/Theme.kt | 32 +- .../simplex/common/views/chat/ChatInfoView.kt | 25 +- .../simplex/common/views/chat/ChatView.kt | 10 +- .../common/views/chat/ContactPreferences.kt | 18 +- .../views/chat/group/AddGroupMembersView.kt | 7 +- .../views/chat/group/AddGroupRelayView.kt | 5 +- .../views/chat/group/ChannelMembersView.kt | 2 +- .../views/chat/group/ChannelRelaysView.kt | 2 +- .../views/chat/group/GroupChatInfoView.kt | 92 +++--- .../common/views/chat/group/GroupLinkView.kt | 110 ++++--- .../views/chat/group/GroupMemberInfoView.kt | 16 +- .../views/chat/group/GroupPreferences.kt | 37 ++- .../views/chat/group/MemberAdmission.kt | 6 +- .../views/chat/group/MemberSupportChatView.kt | 2 +- .../views/chatlist/ChatListNavLinkView.kt | 2 +- .../common/views/chatlist/ChatListView.kt | 7 +- .../views/chatlist/ServersSummaryView.kt | 59 ++-- .../common/views/chatlist/TagListView.kt | 3 +- .../common/views/chatlist/UserPicker.kt | 2 +- .../views/database/DatabaseEncryptionView.kt | 2 +- .../common/views/database/DatabaseView.kt | 11 +- .../simplex/common/views/helpers/ModalView.kt | 15 +- .../simplex/common/views/helpers/Section.kt | 135 ++++++-- .../common/views/helpers/ThemeModeEditor.kt | 270 ++++++++------- .../views/migration/MigrateFromDevice.kt | 46 +-- .../common/views/migration/MigrateToDevice.kt | 33 +- .../common/views/newchat/AddChannelView.kt | 4 +- .../common/views/newchat/AddGroupView.kt | 4 +- .../newchat/ContactConnectionInfoView.kt | 5 +- .../common/views/newchat/NewChatSheet.kt | 4 +- .../common/views/newchat/NewChatView.kt | 8 +- .../views/onboarding/ChooseServerOperators.kt | 8 +- .../views/onboarding/LinkAMobileView.kt | 2 +- .../common/views/remote/ConnectDesktopView.kt | 55 ++-- .../common/views/remote/ConnectMobileView.kt | 8 +- .../common/views/usersettings/Appearance.kt | 307 +++++++++--------- .../views/usersettings/DeveloperView.kt | 21 +- .../views/usersettings/HiddenProfileView.kt | 2 +- .../usersettings/NotificationsSettingsView.kt | 9 +- .../common/views/usersettings/Preferences.kt | 15 +- .../views/usersettings/PrivacySettings.kt | 9 +- .../common/views/usersettings/SettingsView.kt | 10 +- .../views/usersettings/UserAddressView.kt | 34 +- .../views/usersettings/UserProfilesView.kt | 3 +- .../AdvancedNetworkSettings.kt | 14 +- .../networkAndServers/ChatRelayView.kt | 11 +- .../networkAndServers/NetworkAndServers.kt | 25 +- .../networkAndServers/OperatorView.kt | 21 +- .../networkAndServers/ProtocolServerView.kt | 14 +- .../networkAndServers/ProtocolServersView.kt | 12 +- .../commonMain/resources/MR/ar/strings.xml | 2 +- .../commonMain/resources/MR/base/strings.xml | 64 ++-- .../commonMain/resources/MR/bg/strings.xml | 48 +-- .../commonMain/resources/MR/ca/strings.xml | 52 +-- .../commonMain/resources/MR/cs/strings.xml | 48 +-- .../commonMain/resources/MR/da/strings.xml | 2 +- .../commonMain/resources/MR/de/strings.xml | 58 ++-- .../commonMain/resources/MR/el/strings.xml | 46 +-- .../commonMain/resources/MR/es/strings.xml | 56 ++-- .../commonMain/resources/MR/fa/strings.xml | 2 +- .../commonMain/resources/MR/fi/strings.xml | 40 +-- .../commonMain/resources/MR/fr/strings.xml | 50 +-- .../commonMain/resources/MR/hr/strings.xml | 36 +- .../commonMain/resources/MR/hu/strings.xml | 56 ++-- .../commonMain/resources/MR/in/strings.xml | 48 +-- .../commonMain/resources/MR/it/strings.xml | 56 ++-- .../commonMain/resources/MR/iw/strings.xml | 2 +- .../commonMain/resources/MR/ja/strings.xml | 2 +- .../commonMain/resources/MR/ko/strings.xml | 2 +- .../commonMain/resources/MR/ku/strings.xml | 24 +- .../commonMain/resources/MR/lt/strings.xml | 40 +-- .../resources/MR/nb-rNO/strings.xml | 2 +- .../commonMain/resources/MR/nl/strings.xml | 46 +-- .../commonMain/resources/MR/pl/strings.xml | 48 +-- .../resources/MR/pt-rBR/strings.xml | 46 +-- .../commonMain/resources/MR/pt/strings.xml | 28 +- .../commonMain/resources/MR/ro/strings.xml | 48 +-- .../commonMain/resources/MR/ru/strings.xml | 56 ++-- .../commonMain/resources/MR/th/strings.xml | 2 +- .../commonMain/resources/MR/tr/strings.xml | 46 +-- .../commonMain/resources/MR/uk/strings.xml | 48 +-- .../commonMain/resources/MR/vi/strings.xml | 46 +-- .../resources/MR/zh-rCN/strings.xml | 2 +- .../resources/MR/zh-rTW/strings.xml | 2 +- .../chatlist/ChatListNavLinkView.desktop.kt | 3 +- .../views/usersettings/Appearance.desktop.kt | 13 +- 87 files changed, 1463 insertions(+), 1268 deletions(-) diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt index 47506d9532..c16d1ea90d 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/Appearance.android.kt @@ -2,7 +2,6 @@ package chat.simplex.common.views.usersettings import SectionBottomSpacer import SectionDividerSpaced -import SectionSpacer import SectionView import android.app.Activity import android.content.ComponentName @@ -126,9 +125,9 @@ fun AppearanceScope.AppearanceLayout( SectionDividerSpaced() ProfileImageSection() - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() - SectionView(stringResource(MR.strings.settings_section_title_icon), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING_HALF)) { + SectionView(stringResource(MR.strings.settings_section_title_icon), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING_HALF, vertical = DEFAULT_PADDING_HALF)) { LazyRow { items(AppIcon.values().size, { index -> AppIcon.values()[index] }) { index -> val item = AppIcon.values()[index] @@ -152,7 +151,7 @@ fun AppearanceScope.AppearanceLayout( } } - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() FontScaleSection() SectionBottomSpacer() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt index 1de47df7ce..b8dc9ff6d8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/ui/theme/Theme.kt @@ -596,10 +596,38 @@ data class ThemeModeOverride ( } } -fun Modifier.themedBackground(baseTheme: DefaultTheme = CurrentColors.value.base, bgLayerSize: MutableState?, bgLayer: GraphicsLayer?/*, shape: Shape = RectangleShape*/): Modifier { +// Canvas color for settings/info screens (drawn behind cards by themedBackground) +// and for the 2dp item divider inside section cards (matches canvas so dividers +// read as gaps showing the screen behind). +// LIGHT: formula derives off-white from palette bg + onBackground — lifts white +// cards above. DARK/BLACK: palette bg (cards already raised via founder's +// formula in Section.kt). SIMPLEX: gradient bottom stop (darker), since the +// canvas itself is a gradient drawn by themedBackgroundBrush. +fun canvasColorForCurrentTheme(): Color { + val theme = CurrentColors.value + val c = theme.colors + return when (theme.base) { + DefaultTheme.LIGHT -> c.background.mixWith(c.onBackground, 0.94f) + DefaultTheme.SIMPLEX -> c.background.darker(0.4f) + else -> c.background + } +} + +// Card background color for SectionView. LIGHT: pure white (raised above the +// off-white canvas). DARK/BLACK/SIMPLEX: founder's mixWith formula (lifts cards +// above palette bg using onBackground tint). +fun sectionCardColor(): Color { + val theme = CurrentColors.value + return if (theme.base == DefaultTheme.LIGHT) Color.White + else theme.colors.background.mixWith(theme.colors.onBackground, 0.95f) +} + +fun Modifier.themedBackground(baseTheme: DefaultTheme = CurrentColors.value.base, bgLayerSize: MutableState?, bgLayer: GraphicsLayer?, overrideColor: Color? = null): Modifier { return drawBehind { copyBackgroundToAppBar(bgLayerSize, bgLayer) { - if (baseTheme == DefaultTheme.SIMPLEX) { + if (overrideColor != null) { + drawRect(overrideColor) + } else if (baseTheme == DefaultTheme.SIMPLEX) { drawRect(brush = themedBackgroundBrush()) } else { drawRect(CurrentColors.value.colors.background) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt index 061ea71016..a063477f84 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatInfoView.kt @@ -3,10 +3,9 @@ package chat.simplex.common.views.chat import InfoRow import InfoRowEllipsis import SectionBottomSpacer -import SectionDividerSpaced import SectionItemView import SectionItemViewSpaceBetween -import SectionSpacer +import SectionDividerSpaced import SectionTextFooter import SectionView import androidx.compose.desktop.ui.tooling.preview.Preview @@ -553,7 +552,7 @@ fun ChatInfoLayout( LocalAliasEditor(chat.id, localAlias, updateValue = onLocalAliasChanged) - SectionSpacer() + SectionDividerSpaced() Box( Modifier.fillMaxWidth(), @@ -573,10 +572,10 @@ fun ChatInfoLayout( } } - SectionSpacer() + SectionDividerSpaced() if (customUserProfile != null) { - SectionView(generalGetString(MR.strings.incognito).uppercase()) { + SectionView(generalGetString(MR.strings.incognito)) { SectionItemViewSpaceBetween { Text(generalGetString(MR.strings.incognito_random_profile)) Text(customUserProfile.chatViewName, color = Indigo) @@ -601,7 +600,7 @@ fun ChatInfoLayout( } WallpaperButton { - ModalManager.end.showModal { + ModalManager.end.showModal(cardScreen = true) { val chat = remember { derivedStateOf { chatModel.chats.value.firstOrNull { it.id == chat.id } } } val c = chat.value if (c != null) { @@ -610,13 +609,13 @@ fun ChatInfoLayout( } } } - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() SectionView { ChatTTLOption(chatItemTTL, setChatItemTTL, deletingItems) - SectionTextFooter(stringResource(MR.strings.chat_ttl_options_footer)) } - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionTextFooter(stringResource(MR.strings.chat_ttl_options_footer)) + SectionDividerSpaced() val conn = contact.activeConn if (conn != null) { @@ -627,13 +626,13 @@ fun ChatInfoLayout( } if (contact.contactLink != null) { - SectionView(stringResource(MR.strings.address_section_title).uppercase()) { + SectionView(stringResource(MR.strings.address_section_title)) { SimpleXLinkQRCode(contact.contactLink) val clipboard = LocalClipboardManager.current ShareAddressButton { clipboard.shareText(simplexChatLink(contact.contactLink)) } - SectionTextFooter(stringResource(MR.strings.you_can_share_this_address_with_your_contacts).format(contact.displayName)) } - SectionDividerSpaced(maxTopPadding = true) + SectionTextFooter(stringResource(MR.strings.you_can_share_this_address_with_your_contacts).format(contact.displayName)) + SectionDividerSpaced() } if (contact.ready && contact.active) { @@ -670,7 +669,7 @@ fun ChatInfoLayout( } } } - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() } SectionView { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index f42969a73f..5299a5e686 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -406,7 +406,7 @@ fun ChatView( val selectedItems: MutableState?> = mutableStateOf(null) ModalManager.end.showCustomModal { close -> val appBar = remember { mutableStateOf(null as @Composable (BoxScope.() -> Unit)?) } - ModalView(close, appBar = appBar.value) { + ModalView(close, cardScreen = true, appBar = appBar.value) { val chatInfo = remember { activeChat }.value?.chatInfo if (chatInfo is ChatInfo.Direct) { var contactInfo: Pair? by remember { mutableStateOf(preloadedContactInfo) } @@ -509,7 +509,7 @@ fun ChatView( if (chatsCtx.secondaryContextFilter == null) { ModalManager.end.closeModals() } - ModalManager.end.showModalCloseable(true) { close -> + ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { close -> remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem -> GroupMemberInfoView(chatRh, groupInfo, mem, scrollToItemId, stats, code, chatModel, openedFromSupportChat = false, close = close, closeAll = close) } @@ -801,7 +801,7 @@ fun ChatView( } is ChatInfo.ContactConnection -> { val close = { chatModel.chatId.value = null } - ModalView(close, showClose = appPlatform.isAndroid, content = { + ModalView(close, showClose = appPlatform.isAndroid, cardScreen = true, content = { ContactConnectionInfoView(chatModel, chatRh, chatInfo.contactConnection.connLinkInv, chatInfo.contactConnection, false, close) }) LaunchedEffect(chatInfo.id) { @@ -3193,7 +3193,7 @@ fun addGroupMembers(groupInfo: GroupInfo, rhId: Long?, view: Any? = null, close: withBGApi { setGroupMembers(rhId, groupInfo, chatModel) close?.invoke() - ModalManager.end.showModalCloseable(true) { close -> + ModalManager.end.showModalCloseable(showClose = true) { close -> AddGroupMembersView(rhId, groupInfo, false, chatModel, close) } } @@ -3204,7 +3204,7 @@ fun openGroupLink(groupInfo: GroupInfo, rhId: Long?, view: Any? = null, close: ( withBGApi { val link = chatModel.controller.apiGetGroupLink(rhId, groupInfo.groupId) close?.invoke() - ModalManager.end.showModalCloseable(true) { + ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { GroupLinkView(chatModel, rhId, groupInfo, link, onGroupLinkUpdated = null, isChannel = groupInfo.useRelays, shareGroupInfo = groupInfo) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContactPreferences.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContactPreferences.kt index 7c04c30f67..0276727ccc 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContactPreferences.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ContactPreferences.kt @@ -2,12 +2,13 @@ package chat.simplex.common.views.chat import InfoRow import SectionBottomSpacer -import SectionDividerSpaced import SectionItemView +import SectionDividerSpaced import SectionTextFooter import SectionView import androidx.compose.foundation.* import androidx.compose.foundation.layout.* +import androidx.compose.ui.Modifier import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.* @@ -54,6 +55,7 @@ fun ContactPreferencesView( if (featuresAllowed == currentFeaturesAllowed) close() else showUnsavedChangesAlert({ savePrefs(close) }, close) }, + cardScreen = true, ) { ContactPreferencesLayout( featuresAllowed, @@ -90,27 +92,27 @@ private fun ContactPreferencesLayout( TimedMessagesFeatureSection(featuresAllowed, contact.mergedPreferences.timedMessages, timedMessages, onTTLUpdated) { allowed, ttl -> applyPrefs(featuresAllowed.copy(timedMessagesAllowed = allowed, timedMessagesTTL = ttl ?: currentFeaturesAllowed.timedMessagesTTL)) } - SectionDividerSpaced(true) + SectionDividerSpaced() val allowFullDeletion: MutableState = remember(featuresAllowed) { mutableStateOf(featuresAllowed.fullDelete) } FeatureSection(ChatFeature.FullDelete, user.fullPreferences.fullDelete.allow, contact.mergedPreferences.fullDelete, allowFullDeletion) { applyPrefs(featuresAllowed.copy(fullDelete = it)) } - SectionDividerSpaced(true) + SectionDividerSpaced() val allowReactions: MutableState = remember(featuresAllowed) { mutableStateOf(featuresAllowed.reactions) } FeatureSection(ChatFeature.Reactions, user.fullPreferences.reactions.allow, contact.mergedPreferences.reactions, allowReactions) { applyPrefs(featuresAllowed.copy(reactions = it)) } - SectionDividerSpaced(true) + SectionDividerSpaced() val allowVoice: MutableState = remember(featuresAllowed) { mutableStateOf(featuresAllowed.voice) } FeatureSection(ChatFeature.Voice, user.fullPreferences.voice.allow, contact.mergedPreferences.voice, allowVoice) { applyPrefs(featuresAllowed.copy(voice = it)) } - SectionDividerSpaced(true) + SectionDividerSpaced() val allowCalls: MutableState = remember(featuresAllowed) { mutableStateOf(featuresAllowed.calls) } FeatureSection(ChatFeature.Calls, user.fullPreferences.calls.allow, contact.mergedPreferences.calls, allowCalls) { applyPrefs(featuresAllowed.copy(calls = it)) } - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() ResetSaveButtons( reset = reset, save = savePrefs, @@ -135,7 +137,7 @@ private fun FeatureSection( ) SectionView( - feature.text.uppercase(), + feature.text, icon = feature.iconFilled(), iconTint = if (enabled.forUser) SimplexGreen else if (enabled.forContact) WarningYellow else Color.Red, leadingIcon = true, @@ -170,7 +172,7 @@ private fun TimedMessagesFeatureSection( ) SectionView( - ChatFeature.TimedMessages.text.uppercase(), + ChatFeature.TimedMessages.text, icon = ChatFeature.TimedMessages.iconFilled(), iconTint = if (enabled.forUser) SimplexGreen else if (enabled.forContact) WarningYellow else Color.Red, leadingIcon = true, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt index 9298b600e9..0749df7775 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupMembersView.kt @@ -5,7 +5,6 @@ import SectionCustomFooter import SectionDividerSpaced import SectionItemView import SectionItemViewWithoutMinPadding -import SectionSpacer import SectionView import androidx.compose.foundation.* import androidx.compose.foundation.layout.* @@ -161,7 +160,7 @@ fun AddGroupMembersLayout( iconColor = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight ) } - SectionSpacer() + SectionDividerSpaced() if (contactsToAdd.isEmpty() && searchText.value.text.isEmpty()) { Row( @@ -195,8 +194,8 @@ fun AddGroupMembersLayout( SectionCustomFooter { InviteSectionFooter(selectedContactsCount = selectedContacts.size, allowModifyMembers, clearSelection) } - SectionDividerSpaced(maxTopPadding = true) - SectionView(stringResource(MR.strings.select_contacts).uppercase()) { + SectionDividerSpaced() + SectionView(stringResource(MR.strings.select_contacts)) { SectionItemView(padding = PaddingValues(start = DEFAULT_PADDING, end = DEFAULT_PADDING_HALF)) { SearchRowView(searchText) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupRelayView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupRelayView.kt index d0c2486069..1ed75bd2a2 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupRelayView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupRelayView.kt @@ -5,6 +5,7 @@ import SectionCustomFooter import SectionDividerSpaced import SectionItemView import SectionView +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* @@ -131,8 +132,8 @@ private fun AddGroupRelayLayout( fontSize = 14.sp ) } - SectionDividerSpaced(maxTopPadding = true) - SectionView(generalGetString(MR.strings.select_relays).uppercase()) { + SectionDividerSpaced() + SectionView(generalGetString(MR.strings.select_relays)) { availableRelays.forEach { item -> val selected = item.relayId in selectedRelayIds SectionItemView( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelMembersView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelMembersView.kt index 0cf3a3c96f..bcf8048971 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelMembersView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelMembersView.kt @@ -44,7 +44,7 @@ fun ChannelMembersView( if (groupInfo.isOwner) { val subscriberCount = groupInfo.groupSummary.publicMemberCount ?: (members.size + 1).toLong() - SectionView(title = subscriberCountStr(subscriberCount).uppercase()) { + SectionView(title = subscriberCountStr(subscriberCount)) { SectionItemView(minHeight = 54.dp, padding = PaddingValues(horizontal = DEFAULT_PADDING)) { ChannelMemberRow(groupInfo.membership, user = true, showRole = true) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelRelaysView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelRelaysView.kt index cfe9f0472d..d99e16d15f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelRelaysView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelRelaysView.kt @@ -117,7 +117,7 @@ private fun ChannelRelaysLayout( // Backend gate (APIAddGroupRelays) rejects any chatRelayId already in group_relays // regardless of relayStatus, so all current rows must be excluded from the add list. val existingRelayIds = groupRelays.mapNotNull { it.userChatRelay.chatRelayId }.toSet() - ModalManager.end.showModalCloseable(true) { close -> + ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { close -> AddGroupRelayView( groupInfo = groupInfo, existingRelayIds = existingRelayIds, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt index 0f64479359..10eec7b62f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt @@ -1,20 +1,24 @@ package chat.simplex.common.views.chat.group +import CARD_PADDING import InfoRow import SectionBottomSpacer -import SectionDividerSpaced import SectionItemView import SectionItemViewLongClickable import SectionItemViewSpaceBetween -import SectionSpacer +import SectionDividerSpaced import SectionTextFooter import SectionView import androidx.compose.animation.* import androidx.compose.animation.core.animateDpAsState import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.RectangleShape import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable @@ -111,7 +115,7 @@ fun ModalData.GroupChatInfoView( setGroupMembers(rhId, groupInfo, chatModel) if (!isActive) return@launch - ModalManager.end.showModalCloseable(true) { close -> + ModalManager.end.showModalCloseable(showClose = true) { close -> AddGroupMembersView(rhId, groupInfo, false, chatModel, close) } } @@ -126,7 +130,7 @@ fun ModalData.GroupChatInfoView( } else { member to null } - ModalManager.end.showModalCloseable(true) { closeCurrent -> + ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { closeCurrent -> remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem -> GroupMemberInfoView(rhId, groupInfo, mem, scrollToItemId, stats, code, chatModel, openedFromSupportChat = false, groupRelay = groupRelay, close = closeCurrent) { closeCurrent() @@ -167,7 +171,7 @@ fun ModalData.GroupChatInfoView( clearChat = { clearChatDialog(chat, close) }, leaveGroup = { leaveGroupDialog(rhId, groupInfo, chatModel, close) }, manageGroupLink = { - ModalManager.end.showModal { GroupLinkView(chatModel, rhId, groupInfo, groupLink, onGroupLinkUpdated, isChannel = groupInfo.useRelays, shareGroupInfo = groupInfo) } + ModalManager.end.showModal(cardScreen = true) { GroupLinkView(chatModel, rhId, groupInfo, groupLink, onGroupLinkUpdated, isChannel = groupInfo.useRelays, shareGroupInfo = groupInfo) } }, onSearchClicked = onSearchClicked, deletingItems = deletingItems @@ -552,7 +556,7 @@ fun ModalData.GroupChatInfoLayout( LocalAliasEditor(chat.id, groupInfo.localAlias, isContact = false, updateValue = onLocalAliasChanged) - SectionSpacer() + SectionDividerSpaced() Box( Modifier.fillMaxWidth(), @@ -581,10 +585,10 @@ fun ModalData.GroupChatInfoLayout( } } - SectionSpacer() + SectionDividerSpaced() if (groupInfo.useRelays && groupInfo.membership.memberIncognito) { - SectionView(generalGetString(MR.strings.incognito).uppercase()) { + SectionView(generalGetString(MR.strings.incognito)) { SectionItemViewSpaceBetween { Text(generalGetString(MR.strings.incognito_random_profile)) Text(groupInfo.membership.chatViewName, color = Indigo) @@ -658,7 +662,7 @@ fun ModalData.GroupChatInfoLayout( } } if (anyTopSectionRowShow) { - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() } SectionView { if (groupInfo.isOwner && groupInfo.businessChat?.chatType == null) { @@ -677,7 +681,7 @@ fun ModalData.GroupChatInfoLayout( else if (groupInfo.businessChat == null) MR.strings.only_group_owners_can_change_prefs else MR.strings.only_chat_owners_can_change_prefs SectionTextFooter(stringResource(footerId)) - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() SectionView { if (!groupInfo.useRelays) { @@ -688,7 +692,7 @@ fun ModalData.GroupChatInfoLayout( } } WallpaperButton { - ModalManager.end.showModal { + ModalManager.end.showModal(cardScreen = true) { val chat = remember { derivedStateOf { chatModel.chats.value.firstOrNull { it.id == chat.id } } } val c = chat.value if (c != null) { @@ -697,12 +701,12 @@ fun ModalData.GroupChatInfoLayout( } } ChatTTLOption(chatItemTTL, setChatItemTTL, deletingItems) - SectionTextFooter(stringResource(MR.strings.chat_ttl_options_footer)) } - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = true) + SectionTextFooter(stringResource(MR.strings.chat_ttl_options_footer)) + SectionDividerSpaced() if (!groupInfo.nextConnectPrepared && !groupInfo.useRelays) { - SectionView(title = String.format(generalGetString(MR.strings.group_info_section_title_num_members), activeSortedMembers.count() + 1)) { + SectionView(title = String.format(generalGetString(MR.strings.group_info_section_title_num_members), activeSortedMembers.count() + 1), cardShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)) { if (groupInfo.canAddMembers) { val onAddMembersClick = if (chat.chatInfo.incognito) ::cantInviteIncognitoAlert else addMembers val tint = if (chat.chatInfo.incognito) MaterialTheme.colors.secondary else MaterialTheme.colors.primary @@ -725,32 +729,36 @@ fun ModalData.GroupChatInfoLayout( } } if (!groupInfo.nextConnectPrepared && !groupInfo.useRelays) { - items(filteredMembers.value, key = { it.groupMemberId }) { member -> - Divider() - val showMenu = remember { mutableStateOf(false) } - val canBeSelected = groupInfo.membership.memberRole >= member.memberRole && member.memberRole < GroupMemberRole.Moderator - SectionItemViewLongClickable( - click = { - if (selectedItems.value != null) { - if (canBeSelected) { - toggleItemSelection(member.groupMemberId, selectedItems) + itemsIndexed(filteredMembers.value, key = { _, m -> m.groupMemberId }) { index, member -> + val isLast = index == filteredMembers.value.lastIndex + val shape = if (isLast) RoundedCornerShape(bottomStart = 16.dp, bottomEnd = 16.dp) else RectangleShape + Column(Modifier.padding(horizontal = CARD_PADDING).fillMaxWidth().clip(shape).background(sectionCardColor())) { + Divider() + val showMenu = remember { mutableStateOf(false) } + val canBeSelected = groupInfo.membership.memberRole >= member.memberRole && member.memberRole < GroupMemberRole.Moderator + SectionItemViewLongClickable( + click = { + if (selectedItems.value != null) { + if (canBeSelected) { + toggleItemSelection(member.groupMemberId, selectedItems) + } + } else { + showMemberInfo(member, null) + } + }, + longClick = { showMenu.value = true }, + minHeight = 54.dp, + padding = PaddingValues(horizontal = DEFAULT_PADDING) + ) { + Box(contentAlignment = Alignment.CenterStart) { + androidx.compose.animation.AnimatedVisibility(selectedItems.value != null, enter = fadeIn(), exit = fadeOut()) { + SelectedListItem(Modifier.alpha(if (canBeSelected) 1f else 0f).padding(start = 2.dp), member.groupMemberId, selectedItems) + } + val selectionOffset by animateDpAsState(if (selectedItems.value != null) 20.dp + 22.dp * fontSizeMultiplier else 0.dp) + DropDownMenuForMember(chat.remoteHostId, member, groupInfo, selectedItems, showMenu) + Box(Modifier.padding(start = selectionOffset)) { + MemberRow(member) } - } else { - showMemberInfo(member, null) - } - }, - longClick = { showMenu.value = true }, - minHeight = 54.dp, - padding = PaddingValues(horizontal = DEFAULT_PADDING) - ) { - Box(contentAlignment = Alignment.CenterStart) { - androidx.compose.animation.AnimatedVisibility(selectedItems.value != null, enter = fadeIn(), exit = fadeOut()) { - SelectedListItem(Modifier.alpha(if (canBeSelected) 1f else 0f).padding(start = 2.dp), member.groupMemberId, selectedItems) - } - val selectionOffset by animateDpAsState(if (selectedItems.value != null) 20.dp + 22.dp * fontSizeMultiplier else 0.dp) - DropDownMenuForMember(chat.remoteHostId, member, groupInfo, selectedItems, showMenu) - Box(Modifier.padding(start = selectionOffset)) { - MemberRow(member) } } } @@ -758,7 +766,7 @@ fun ModalData.GroupChatInfoLayout( } item { if (!groupInfo.nextConnectPrepared && !groupInfo.useRelays) { - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() } SectionView { if (groupInfo.useRelays && (groupInfo.isOwner || activeSortedMembers.any { it.memberRole == GroupMemberRole.Relay })) { @@ -1186,7 +1194,9 @@ private fun ChannelLinkButton(onClick: () -> Unit) { @Composable private fun ChannelLinkQRCodeSection(groupLink: String) { val clipboard = LocalClipboardManager.current - SimpleXLinkQRCode(connReq = groupLink) + Box(Modifier.padding(vertical = DEFAULT_PADDING_HALF)) { + SimpleXLinkQRCode(connReq = groupLink) + } SectionItemView({ clipboard.shareText(simplexChatLink(groupLink)) }) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupLinkView.kt index 673f72bb4e..b68f0efaf5 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupLinkView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupLinkView.kt @@ -1,7 +1,9 @@ package chat.simplex.common.views.chat.group import SectionBottomSpacer +import SectionDividerSpaced import SectionItemView +import SectionView import SectionViewWithButton import androidx.compose.foundation.layout.* import androidx.compose.material.* @@ -215,7 +217,10 @@ fun GroupLinkLayout( } } else { if (!isChannel) { - RoleSelectionRow(groupInfo, groupLinkMemberRole) + SectionView { + RoleSelectionRow(groupInfo, groupLinkMemberRole) + } + SectionDividerSpaced() } var initialLaunch by remember { mutableStateOf(true) } LaunchedEffect(groupLinkMemberRole.value) { @@ -225,69 +230,70 @@ fun GroupLinkLayout( initialLaunch = false } val showShortLink = remember { mutableStateOf(true) } - Spacer(Modifier.height(DEFAULT_PADDING_HALF)) SectionViewWithButton( titleButton = if (!isChannel && groupLink.connLinkContact.connShortLink != null) { { ToggleShortLinkButton(showShortLink) } } else null) { - SimpleXCreatedLinkQRCode(groupLink.connLinkContact, short = showShortLink.value) - } - if (!isChannel && groupLink.shouldBeUpgraded) { + Box(Modifier.padding(vertical = DEFAULT_PADDING_HALF)) { + SimpleXCreatedLinkQRCode(groupLink.connLinkContact, short = showShortLink.value) + } + if (!isChannel && groupLink.shouldBeUpgraded) { + SettingsActionItem( + painterResource(MR.images.ic_add), + stringResource(MR.strings.upgrade_group_link), + click = { showAddShortLinkAlert(null) }, + iconColor = MaterialTheme.colors.primary, + textColor = MaterialTheme.colors.primary, + ) + } + val clipboard = LocalClipboardManager.current SettingsActionItem( - painterResource(MR.images.ic_add), - stringResource(MR.strings.upgrade_group_link), - click = { showAddShortLinkAlert(null) }, - iconColor = MaterialTheme.colors.primary, - textColor = MaterialTheme.colors.primary, - ) - } - val clipboard = LocalClipboardManager.current - SettingsActionItem( - painterResource(MR.images.ic_share), - stringResource(MR.strings.share_link), - click = { - if (!isChannel && groupLink.shouldBeUpgraded) { - showAddShortLinkAlert { + painterResource(MR.images.ic_share), + stringResource(MR.strings.share_link), + click = { + if (!isChannel && groupLink.shouldBeUpgraded) { + showAddShortLinkAlert { + clipboard.shareText(groupLink.connLinkContact.simplexChatUri(short = showShortLink.value)) + } + } else { clipboard.shareText(groupLink.connLinkContact.simplexChatUri(short = showShortLink.value)) } - } else { - clipboard.shareText(groupLink.connLinkContact.simplexChatUri(short = showShortLink.value)) - } - }, - iconColor = MaterialTheme.colors.primary, - textColor = MaterialTheme.colors.primary, - ) - if (shareGroupInfo != null && isChannel) { - SettingsActionItem( - painterResource(MR.images.ic_forward), - stringResource(MR.strings.share_via_chat), - click = { - chatModel.sharedContent.value = SharedContent.ChatLink(shareGroupInfo) - chatModel.chatId.value = null - ModalManager.closeAllModalsEverywhere() }, iconColor = MaterialTheme.colors.primary, textColor = MaterialTheme.colors.primary, ) - } - if (!creatingGroup && !isChannel) { - SettingsActionItem( - painterResource(MR.images.ic_delete), - stringResource(MR.strings.delete_link), - click = deleteLink, - iconColor = Color.Red, - textColor = Color.Red, - ) - } - if (creatingGroup && close != null) { - SettingsActionItem( - painterResource(MR.images.ic_check), - stringResource(MR.strings.continue_to_next_step), - click = close, - iconColor = MaterialTheme.colors.primary, - textColor = MaterialTheme.colors.primary, - ) + if (shareGroupInfo != null && isChannel) { + SettingsActionItem( + painterResource(MR.images.ic_forward), + stringResource(MR.strings.share_via_chat), + click = { + chatModel.sharedContent.value = SharedContent.ChatLink(shareGroupInfo) + chatModel.chatId.value = null + ModalManager.closeAllModalsEverywhere() + }, + iconColor = MaterialTheme.colors.primary, + textColor = MaterialTheme.colors.primary, + ) + } + if (!creatingGroup && !isChannel) { + SettingsActionItem( + painterResource(MR.images.ic_delete), + stringResource(MR.strings.delete_link), + click = deleteLink, + iconColor = Color.Red, + textColor = Color.Red, + ) + } + if (creatingGroup && close != null) { + SettingsActionItem( + painterResource(MR.images.ic_check), + stringResource(MR.strings.continue_to_next_step), + click = close, + iconColor = MaterialTheme.colors.primary, + textColor = MaterialTheme.colors.primary, + ) + } } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt index 8677609863..8117f674f6 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt @@ -2,12 +2,12 @@ package chat.simplex.common.views.chat.group import InfoRow import SectionBottomSpacer -import SectionDividerSpaced import SectionItemView -import SectionSpacer +import SectionDividerSpaced import SectionTextFooter import SectionView import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.InlineTextContent @@ -423,7 +423,7 @@ fun GroupMemberInfoLayout( // TODO [relays] re-enable when relay management ships val canRemove = member.canBeRemoved(groupInfo) && member.memberRole != GroupMemberRole.Relay if (canBlockForAll || canRemove) { - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() SectionView { if (canBlockForAll) { if (member.blockedByAdmin) { @@ -445,7 +445,7 @@ fun GroupMemberInfoLayout( @Composable fun NonAdminBlockSection() { - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() SectionView { if (member.blockedByAdmin) { SettingsActionItem( @@ -469,7 +469,7 @@ fun GroupMemberInfoLayout( ) { GroupMemberInfoHeader(member) } - SectionSpacer() + SectionDividerSpaced() val contactId = member.memberContactId @@ -533,7 +533,7 @@ fun GroupMemberInfoLayout( } } - SectionSpacer() + SectionDividerSpaced() } val showMemberSupportChat = !openedFromSupportChat && @@ -566,7 +566,7 @@ fun GroupMemberInfoLayout( } if (member.contactLink != null) { - SectionView(stringResource(MR.strings.address_section_title).uppercase()) { + SectionView(stringResource(MR.strings.address_section_title)) { SimpleXLinkQRCode(member.contactLink) val clipboard = LocalClipboardManager.current ShareAddressButton { clipboard.shareText(simplexChatLink(member.contactLink)) } @@ -577,8 +577,8 @@ fun GroupMemberInfoLayout( } else { ConnectViaAddressButton(onClick = { connectViaAddress(member.contactLink) }) } - SectionTextFooter(stringResource(MR.strings.you_can_share_this_address_with_your_contacts).format(member.displayName)) } + SectionTextFooter(stringResource(MR.strings.you_can_share_this_address_with_your_contacts).format(member.displayName)) SectionDividerSpaced() } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt index 740349eaea..d8be4998be 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt @@ -6,9 +6,11 @@ import SectionDividerSpaced import SectionItemView import SectionTextFooter import SectionView +import androidx.compose.foundation.background import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.* +import androidx.compose.ui.Modifier import androidx.compose.runtime.saveable.rememberSaveable import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.compose.stringResource @@ -64,6 +66,7 @@ fun GroupPreferencesView(m: ChatModel, rhId: Long?, chatId: String, close: () -> if (preferences == currentPreferences) close() else showUnsavedChangesAlert({ savePrefs(close) }, close, saveTextId) }, + cardScreen = true, ) { GroupPreferencesLayout( preferences, @@ -182,37 +185,39 @@ private fun GroupPreferencesLayout( AppBarTitle(stringResource(titleId)) if (!groupInfo.useRelays) { if (groupInfo.businessChat == null) { - MemberAdmissionButton(openMemberAdmission) - SectionDividerSpaced(maxBottomPadding = false) + SectionView { + MemberAdmissionButton(openMemberAdmission) + } + SectionDividerSpaced() } TimedMessagesPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() DirectMessagesPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() FullDeletePreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() ReactionsPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() VoicePreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() FilesPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() SimplexLinksPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() ReportsPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() HistoryPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() SupportPreference(disabled = true) } else { TimedMessagesPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() FullDeletePreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() ReactionsPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() HistoryPreference() - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() SupportPreference(notice = generalGetString(MR.strings.chat_with_admins_relay_note), onEnable = { revert -> AlertManager.shared.showAlertDialog( title = generalGetString(MR.strings.enable_chats_with_admins_question), @@ -225,7 +230,7 @@ private fun GroupPreferencesLayout( }) } if (groupInfo.isOwner) { - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() val saveTextId = if (groupInfo.useRelays) MR.strings.save_and_notify_channel_subscribers else MR.strings.save_and_notify_group_members ResetSaveButtons( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/MemberAdmission.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/MemberAdmission.kt index 7c9db58316..544af8ed7e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/MemberAdmission.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/MemberAdmission.kt @@ -6,7 +6,10 @@ import SectionDividerSpaced import SectionItemView import SectionTextFooter import SectionView +import androidx.compose.foundation.background import androidx.compose.material.MaterialTheme +import androidx.compose.ui.Modifier +import chat.simplex.common.ui.theme.* import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable @@ -49,6 +52,7 @@ fun MemberAdmissionView(m: ChatModel, rhId: Long?, chatId: String, close: () -> if (admission == currentAdmission) close() else showUnsavedChangesAlert({ saveAdmission(close) }, close) }, + cardScreen = true, ) { MemberAdmissionLayout( admission, @@ -85,7 +89,7 @@ private fun MemberAdmissionLayout( } } if (groupInfo.isOwner) { - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() ResetSaveButtons( reset = reset, save = saveAdmission, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/MemberSupportChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/MemberSupportChatView.kt index 6680ef99bc..180c9f9d23 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/MemberSupportChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/MemberSupportChatView.kt @@ -85,7 +85,7 @@ fun MemberSupportChatAppBar( } else { null } - ModalManager.end.showModalCloseable(true) { closeCurrent -> + ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { closeCurrent -> remember { derivedStateOf { chatModel.getGroupMember(scopeMember_.groupMemberId) } }.value?.let { mem -> GroupMemberInfoView(rhId, groupInfo, mem, scrollToItemId, stats, code, chatModel, openedFromSupportChat = true, close = closeCurrent) { closeCurrent() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt index 0cec9ab773..d3533bbd02 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt @@ -583,7 +583,7 @@ fun ContactConnectionMenuItems(rhId: Long?, chatInfo: ChatInfo.ContactConnection onClick = { ModalManager.center.closeModals() ModalManager.end.closeModals() - ModalManager.center.showModalCloseable(true, showClose = appPlatform.isAndroid) { close -> + ModalManager.center.showModalCloseable(settings = true, showClose = appPlatform.isAndroid, cardScreen = true) { close -> ContactConnectionInfoView(chatModel, rhId, chatInfo.contactConnection.connLinkInv, chatInfo.contactConnection, true, close) } showMenu.value = false diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt index 01dcd021f7..94b13a8270 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt @@ -1,5 +1,6 @@ package chat.simplex.common.views.chatlist +import LocalCardScreen import androidx.compose.foundation.* import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsHoveredAsState @@ -572,7 +573,7 @@ private fun ChatListToolbar(userPickerState: MutableStateFlow navigationButton = { if (chatModel.users.isEmpty() && !chatModel.desktopNoUserNoRemote) { NavigationButtonMenu { - ModalManager.start.showModalCloseable { close -> + ModalManager.start.showModalCloseable(cardScreen = true) { close -> SettingsView(chatModel, setPerformLA, close) } } @@ -854,8 +855,8 @@ enum class ScrollDirection { @Composable fun BoxScope.StatusBarBackground() { if (appPlatform.isAndroid) { - val finalColor = MaterialTheme.colors.background.copy(0.88f) - Box(Modifier.fillMaxWidth().windowInsetsTopHeight(WindowInsets.statusBars).background(finalColor)) + val bg = if (LocalCardScreen.current) canvasColorForCurrentTheme() else MaterialTheme.colors.background + Box(Modifier.fillMaxWidth().windowInsetsTopHeight(WindowInsets.statusBars).background(bg.copy(0.88f))) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ServersSummaryView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ServersSummaryView.kt index ed1c7116e6..5d94b9c2d6 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ServersSummaryView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ServersSummaryView.kt @@ -10,6 +10,7 @@ import SectionView import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.background import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -151,7 +152,7 @@ enum class PresentedServerType { @Composable private fun ServerSessionsView(sess: ServerSessions) { - SectionView(generalGetString(MR.strings.servers_info_transport_sessions_section_header).uppercase()) { + SectionView(generalGetString(MR.strings.servers_info_transport_sessions_section_header)) { InfoRow( generalGetString(MR.strings.servers_info_sessions_connected), numOrDash(sess.ssConnected) @@ -293,7 +294,7 @@ private fun XFTPServersListView(servers: List, statsStartedAt @Composable private fun SMPStatsView(stats: AgentSMPServerStatsData, statsStartedAt: Instant, remoteHostInfo: RemoteHostInfo?) { - SectionView(generalGetString(MR.strings.servers_info_statistics_section_header).uppercase()) { + SectionView(generalGetString(MR.strings.servers_info_statistics_section_header)) { InfoRow( generalGetString(MR.strings.servers_info_messages_sent), numOrDash(stats._sentDirect + stats._sentViaProxy) @@ -329,7 +330,7 @@ private fun SMPSubscriptionsSection(totals: SMPTotals) { horizontalArrangement = Arrangement.spacedBy(DEFAULT_SPACE_AFTER_ICON * 2) ) { Text( - generalGetString(MR.strings.servers_info_subscriptions_section_header).uppercase(), + generalGetString(MR.strings.servers_info_subscriptions_section_header), color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = 12.sp @@ -359,7 +360,7 @@ private fun SMPSubscriptionsSection(subs: SMPServerSubs, summary: SMPServerSumma horizontalArrangement = Arrangement.spacedBy(DEFAULT_SPACE_AFTER_ICON * 2) ) { Text( - generalGetString(MR.strings.servers_info_subscriptions_section_header).uppercase(), + generalGetString(MR.strings.servers_info_subscriptions_section_header), color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = 12.sp @@ -415,7 +416,7 @@ private fun reconnectServerAlert(rh: RemoteHostInfo?, server: String) { @Composable fun XFTPStatsView(stats: AgentXFTPServerStatsData, statsStartedAt: Instant, rh: RemoteHostInfo?) { - SectionView(generalGetString(MR.strings.servers_info_statistics_section_header).uppercase()) { + SectionView(generalGetString(MR.strings.servers_info_statistics_section_header)) { InfoRow( generalGetString(MR.strings.servers_info_uploaded), prettySize(stats._uploadsSize) @@ -449,7 +450,7 @@ private fun IndentedInfoRow(title: String, desc: String) { @Composable fun DetailedSMPStatsLayout(stats: AgentSMPServerStatsData, statsStartedAt: Instant) { - SectionView(generalGetString(MR.strings.servers_info_detailed_statistics_sent_messages_header).uppercase()) { + SectionView(generalGetString(MR.strings.servers_info_detailed_statistics_sent_messages_header)) { InfoRow(generalGetString(MR.strings.servers_info_detailed_statistics_sent_messages_total), numOrDash(stats._sentDirect + stats._sentViaProxy)) InfoRowTwoValues(generalGetString(MR.strings.sent_directly), generalGetString(MR.strings.attempts_label), stats._sentDirect, stats._sentDirectAttempts) InfoRowTwoValues(generalGetString(MR.strings.sent_via_proxy), generalGetString(MR.strings.attempts_label), stats._sentViaProxy, stats._sentViaProxyAttempts) @@ -465,7 +466,7 @@ fun DetailedSMPStatsLayout(stats: AgentSMPServerStatsData, statsStartedAt: Insta SectionDividerSpaced() - SectionView(generalGetString(MR.strings.servers_info_detailed_statistics_received_messages_header).uppercase()) { + SectionView(generalGetString(MR.strings.servers_info_detailed_statistics_received_messages_header)) { InfoRow(generalGetString(MR.strings.servers_info_detailed_statistics_received_total), numOrDash(stats._recvMsgs)) SectionItemView { Text(generalGetString(MR.strings.servers_info_detailed_statistics_receive_errors), color = MaterialTheme.colors.onBackground) @@ -483,7 +484,7 @@ fun DetailedSMPStatsLayout(stats: AgentSMPServerStatsData, statsStartedAt: Insta SectionDividerSpaced() - SectionView(generalGetString(MR.strings.connections).uppercase()) { + SectionView(generalGetString(MR.strings.connections)) { InfoRow(generalGetString(MR.strings.created), numOrDash(stats._connCreated)) InfoRow(generalGetString(MR.strings.secured), numOrDash(stats._connSecured)) InfoRow(generalGetString(MR.strings.completed), numOrDash(stats._connCompleted)) @@ -502,7 +503,7 @@ fun DetailedSMPStatsLayout(stats: AgentSMPServerStatsData, statsStartedAt: Insta @Composable fun DetailedXFTPStatsLayout(stats: AgentXFTPServerStatsData, statsStartedAt: Instant) { - SectionView(generalGetString(MR.strings.uploaded_files).uppercase()) { + SectionView(generalGetString(MR.strings.uploaded_files)) { InfoRow(generalGetString(MR.strings.size), prettySize(stats._uploadsSize)) InfoRowTwoValues(generalGetString(MR.strings.chunks_uploaded), generalGetString(MR.strings.attempts_label), stats._uploads, stats._uploadAttempts) InfoRow(generalGetString(MR.strings.upload_errors), numOrDash(stats._uploadErrs)) @@ -510,7 +511,7 @@ fun DetailedXFTPStatsLayout(stats: AgentXFTPServerStatsData, statsStartedAt: Ins InfoRow(generalGetString(MR.strings.deletion_errors), numOrDash(stats._deleteErrs)) } SectionDividerSpaced() - SectionView(generalGetString(MR.strings.downloaded_files).uppercase()) { + SectionView(generalGetString(MR.strings.downloaded_files)) { InfoRow(generalGetString(MR.strings.size), prettySize(stats._downloadsSize)) InfoRowTwoValues(generalGetString(MR.strings.chunks_downloaded), generalGetString(MR.strings.attempts_label), stats._downloads, stats._downloadAttempts) SectionItemView { @@ -528,7 +529,7 @@ fun DetailedXFTPStatsLayout(stats: AgentXFTPServerStatsData, statsStartedAt: Ins @Composable fun XFTPServerSummaryLayout(summary: XFTPServerSummary, statsStartedAt: Instant, rh: RemoteHostInfo?) { - SectionView(generalGetString(MR.strings.server_address).uppercase()) { + SectionView(generalGetString(MR.strings.server_address)) { SelectionContainer { Text( summary.xftpServer, @@ -546,7 +547,7 @@ fun XFTPServerSummaryLayout(summary: XFTPServerSummary, statsStartedAt: Instant, if (summary.stats != null) { XFTPStatsView(stats = summary.stats, rh = rh, statsStartedAt = statsStartedAt) if (summary.sessions != null) { - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() } } @@ -560,7 +561,7 @@ fun XFTPServerSummaryLayout(summary: XFTPServerSummary, statsStartedAt: Instant, @Composable fun SMPServerSummaryLayout(summary: SMPServerSummary, statsStartedAt: Instant, rh: RemoteHostInfo?) { - SectionView(generalGetString(MR.strings.server_address).uppercase()) { + SectionView(generalGetString(MR.strings.server_address)) { SelectionContainer { Text( summary.smpServer, @@ -578,7 +579,7 @@ fun SMPServerSummaryLayout(summary: SMPServerSummary, statsStartedAt: Instant, r if (summary.stats != null) { SMPStatsView(stats = summary.stats, remoteHostInfo = rh, statsStartedAt = statsStartedAt) if (summary.subs != null || summary.sessions != null) { - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() } } @@ -605,7 +606,8 @@ fun ModalData.SMPServerSummaryView( statsStartedAt: Instant ) { ModalView( - close = close + close = close, + cardScreen = true, ) { ColumnWithScrollBar { val bottomPadding = DEFAULT_PADDING @@ -628,7 +630,8 @@ fun ModalData.DetailedXFTPStatsView( statsStartedAt: Instant ) { ModalView( - close = close + close = close, + cardScreen = true, ) { ColumnWithScrollBar { Box(contentAlignment = Alignment.Center) { @@ -652,7 +655,8 @@ fun ModalData.DetailedSMPStatsView( statsStartedAt: Instant ) { ModalView( - close = close + close = close, + cardScreen = true, ) { ColumnWithScrollBar { Box(contentAlignment = Alignment.Center) { @@ -676,7 +680,8 @@ fun ModalData.XFTPServerSummaryView( statsStartedAt: Instant ) { ModalView( - close = close + close = close, + cardScreen = true, ) { ColumnWithScrollBar { Box(contentAlignment = Alignment.Center) { @@ -839,7 +844,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta val statsStartedAt = it.statsStartedAt SMPStatsView(totals.stats, statsStartedAt, rh) - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() SMPSubscriptionsSection(totals) SectionDividerSpaced() @@ -847,7 +852,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta SMPServersListView( servers = currentlyUsedSMPServers, statsStartedAt = statsStartedAt, - header = generalGetString(MR.strings.servers_info_connected_servers_section_header).uppercase(), + header = generalGetString(MR.strings.servers_info_connected_servers_section_header), rh = rh ) SectionDividerSpaced() @@ -857,7 +862,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta SMPServersListView( servers = previouslyUsedSMPServers, statsStartedAt = statsStartedAt, - header = generalGetString(MR.strings.servers_info_previously_connected_servers_section_header).uppercase(), + header = generalGetString(MR.strings.servers_info_previously_connected_servers_section_header), rh = rh ) SectionDividerSpaced() @@ -867,11 +872,11 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta SMPServersListView( servers = proxySMPServers, statsStartedAt = statsStartedAt, - header = generalGetString(MR.strings.servers_info_proxied_servers_section_header).uppercase(), + header = generalGetString(MR.strings.servers_info_proxied_servers_section_header), footer = generalGetString(MR.strings.servers_info_proxied_servers_section_footer), rh = rh ) - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() } ServerSessionsView(totals.sessions) @@ -888,13 +893,13 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta val previouslyUsedXFTPServers = xftpSummary.previouslyUsedXFTPServers XFTPStatsView(totals.stats, statsStartedAt, rh) - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() if (currentlyUsedXFTPServers.isNotEmpty()) { XFTPServersListView( currentlyUsedXFTPServers, statsStartedAt, - generalGetString(MR.strings.servers_info_connected_servers_section_header).uppercase(), + generalGetString(MR.strings.servers_info_connected_servers_section_header), rh ) SectionDividerSpaced() @@ -904,7 +909,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta XFTPServersListView( previouslyUsedXFTPServers, statsStartedAt, - generalGetString(MR.strings.servers_info_previously_connected_servers_section_header).uppercase(), + generalGetString(MR.strings.servers_info_previously_connected_servers_section_header), rh ) SectionDividerSpaced() @@ -915,7 +920,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta } } - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() SectionView { ReconnectAllServersButton(rh) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/TagListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/TagListView.kt index c6cc887655..fe61859937 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/TagListView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/TagListView.kt @@ -1,7 +1,6 @@ package chat.simplex.common.views.chatlist import SectionCustomFooter -import SectionDivider import SectionItemView import TextIconSpaced import androidx.compose.animation.core.animateDpAsState @@ -157,7 +156,7 @@ fun TagListView(rhId: Long?, chat: Chat? = null, close: () -> Unit, reorderMode: Icon(painterResource(MR.images.ic_drag_handle), null, Modifier.size(20.dp), tint = MaterialTheme.colors.secondary) } } - SectionDivider() + Divider(Modifier.padding(horizontal = 8.dp)) } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt index a02e0dc768..5cf7d9325f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt @@ -380,7 +380,7 @@ private fun GlobalSettingsSection( SectionItemView( click = { - ModalManager.start.showModalCloseable { close -> + ModalManager.start.showModalCloseable(cardScreen = true) { close -> SettingsView(chatModel, setPerformLA, close) } }, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt index 1c1c37b7ac..b656b8b8da 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseEncryptionView.kt @@ -119,7 +119,7 @@ fun DatabaseEncryptionLayout( ChatStoppedView() SectionSpacer() } - SectionView(if (migration) generalGetString(MR.strings.database_passphrase).uppercase() else null) { + SectionView(if (migration) generalGetString(MR.strings.database_passphrase) else null) { SavePassphraseSetting( useKeychain.value, initialRandomDBPassphrase.value, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt index d55d89f26b..648a0eb8e7 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment +import androidx.compose.foundation.background import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter @@ -170,7 +171,7 @@ fun DatabaseLayout( AppBarTitle(stringResource(MR.strings.your_chat_database)) if (!chatModel.desktopNoUserNoRemote) { - SectionView(stringResource(MR.strings.messages_section_title).uppercase()) { + SectionView(stringResource(MR.strings.messages_section_title)) { TtlOptions(chatItemTTL, enabled = rememberUpdatedState(!stopped && !progressIndicator), onChatItemTTLSelected) } SectionTextFooter( @@ -184,7 +185,7 @@ fun DatabaseLayout( } } ) - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() } val toggleEnabled = remember { chatModel.remoteHosts }.none { it.sessionState is RemoteHostSessionState.Connected } if (chatModel.localUserCreated.value == true) { @@ -200,7 +201,7 @@ fun DatabaseLayout( RunChatSetting(stopped, toggleEnabled && !progressIndicator, startChat, stopChatAlert) } if (stopped) SectionTextFooter(stringResource(MR.strings.you_must_use_the_most_recent_version_of_database)) - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() } SectionView(stringResource(MR.strings.chat_database_section)) { @@ -214,7 +215,7 @@ fun DatabaseLayout( if (unencrypted) painterResource(MR.images.ic_lock_open_right) else if (useKeyChain) painterResource(MR.images.ic_vpn_key_filled) else painterResource(MR.images.ic_lock), stringResource(MR.strings.database_passphrase), - click = { ModalManager.start.showModal { DatabaseEncryptionView(chatModel, false) } }, + click = { ModalManager.start.showModal(cardScreen = true) { DatabaseEncryptionView(chatModel, false) } }, iconColor = if (unencrypted || (appPlatform.isDesktop && passphraseSaved)) WarningOrange else MaterialTheme.colors.secondary, disabled = operationsDisabled ) @@ -262,7 +263,7 @@ fun DatabaseLayout( } SectionDividerSpaced() - SectionView(stringResource(MR.strings.files_and_media_section).uppercase()) { + SectionView(stringResource(MR.strings.files_and_media_section)) { val deleteFilesDisabled = operationsDisabled || appFilesCountAndSize.value.first == 0 SectionItemView( deleteAppFilesAndMedia, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt index 28c81fbf56..02c0b45de4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.graphics.Color import chat.simplex.common.model.ChatController.appPrefs import chat.simplex.common.model.ChatModel import chat.simplex.common.platform.* +import LocalCardScreen import chat.simplex.common.ui.theme.* import chat.simplex.common.views.chatlist.StatusBarBackground import chat.simplex.common.views.onboarding.OnboardingStage @@ -27,6 +28,7 @@ fun ModalView( showAppBar: Boolean = true, enableClose: Boolean = true, background: Color = Color.Unspecified, + cardScreen: Boolean = false, modifier: Modifier = Modifier, showSearch: Boolean = false, searchAlwaysVisible: Boolean = false, @@ -40,7 +42,9 @@ fun ModalView( } val oneHandUI = remember { derivedStateOf { if (appPrefs.onboardingStage.state.value == OnboardingStage.OnboardingComplete) appPrefs.oneHandUI.state.value else false } } Surface(Modifier.fillMaxSize(), contentColor = LocalContentColor.current) { - Box(if (background != Color.Unspecified) Modifier.background(background) else Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer)) { + val bgOverride = if (cardScreen) canvasColorForCurrentTheme() else if (background != Color.Unspecified) background else null + CompositionLocalProvider(LocalCardScreen provides cardScreen) { + Box(Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer, overrideColor = bgOverride)) { Box(modifier = modifier) { content() } @@ -66,6 +70,7 @@ fun ModalView( } } } + } } } @@ -111,15 +116,15 @@ class ModalManager(private val placement: ModalPlacement? = null) { fun isLastModalOpen(id: ModalViewId): Boolean = modalViews.lastOrNull()?.id == id - fun showModal(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, forceAnimated: Boolean = false, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.() -> Unit) { + fun showModal(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, forceAnimated: Boolean = false, cardScreen: Boolean = false, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.() -> Unit) { showCustomModal(id = id, forceAnimated = forceAnimated) { close -> - ModalView(close, showClose = showClose, endButtons = endButtons, content = { content() }) + ModalView(close, showClose = showClose, cardScreen = cardScreen, endButtons = endButtons, content = { content() }) } } - fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.(close: () -> Unit) -> Unit) { + fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, cardScreen: Boolean = false, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.(close: () -> Unit) -> Unit) { showCustomModal(id = id) { close -> - ModalView(close, showClose = showClose, endButtons = endButtons, content = { content(close) }) + ModalView(close, showClose = showClose, cardScreen = cardScreen, endButtons = endButtons, content = { content(close) }) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt index 7ee52af784..9afcdd0b94 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Section.kt @@ -1,9 +1,15 @@ import androidx.compose.foundation.* import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.layout.Layout import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalDensity @@ -12,6 +18,7 @@ import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.* +import androidx.compose.ui.text.font.FontWeight import chat.simplex.common.platform.onRightClick import chat.simplex.common.platform.windowWidth import chat.simplex.common.ui.theme.* @@ -20,16 +27,82 @@ import chat.simplex.common.views.onboarding.SelectableCard import chat.simplex.common.views.usersettings.SettingsActionItemWithContent import chat.simplex.res.MR +private val SectionCardShape = RoundedCornerShape(16.dp) +val CARD_PADDING = 18.dp +val ICON_TEXT_SPACING = 8.dp + +val LocalCardScreen = staticCompositionLocalOf { false } + +val itemHPadding: Dp + @Composable get() = if (LocalCardScreen.current) CARD_PADDING else DEFAULT_PADDING + @Composable -fun SectionView(title: String? = null, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = DEFAULT_PADDING, content: (@Composable ColumnScope.() -> Unit)) { +private fun CardColumnLayout( + contentPadding: PaddingValues = PaddingValues(), + cardShape: Shape = SectionCardShape, + content: @Composable () -> Unit +) { + val dividerColor = canvasColorForCurrentTheme() + val dividerPx = with(LocalDensity.current) { 2.dp.toPx() } + val childBottoms = remember { mutableListOf() } + Layout( + content = content, + modifier = Modifier + .padding(horizontal = CARD_PADDING) + .fillMaxWidth() + .clip(cardShape) + .background(sectionCardColor()) + .padding(contentPadding) + .drawBehind { + for (i in 0 until childBottoms.size - 1) { + val y = childBottoms[i] + drawLine(dividerColor, Offset(0f, y), Offset(size.width, y), strokeWidth = dividerPx) + } + } + ) { measurables, constraints -> + val placeables = measurables.map { it.measure(constraints) } + childBottoms.clear() + var y = 0f + placeables.forEach { p -> + y += p.height + childBottoms.add(y) + } + layout(constraints.maxWidth, y.toInt()) { + var yPos = 0 + placeables.forEach { p -> + p.placeRelative(0, yPos) + yPos += p.height + } + } + } +} + +@Composable +private fun CardColumn( + contentPadding: PaddingValues = PaddingValues(), + cardShape: Shape = SectionCardShape, + content: @Composable () -> Unit +) { + if (LocalCardScreen.current) { + CardColumnLayout(contentPadding, cardShape, content) + } else { + Column(Modifier.padding(contentPadding).fillMaxWidth()) { content() } + } +} + +@Composable +fun SectionView(title: String? = null, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = DEFAULT_PADDING, cardShape: Shape = SectionCardShape, content: (@Composable ColumnScope.() -> Unit)) { + val card = LocalCardScreen.current Column { if (title != null) { Text( title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, - modifier = Modifier.padding(start = DEFAULT_PADDING, bottom = headerBottomPadding), fontSize = 12.sp + modifier = Modifier.padding(start = if (card) DEFAULT_PADDING + DEFAULT_PADDING_HALF else DEFAULT_PADDING, bottom = if (card) 8.dp else headerBottomPadding), + fontSize = if (card) 14.sp else 12.sp, + fontWeight = if (card) FontWeight.Medium else FontWeight.Normal ) } - Column(Modifier.padding(contentPadding).fillMaxWidth()) { content() } + CardColumn(contentPadding, cardShape) { content() } } } @@ -42,24 +115,27 @@ fun SectionView( padding: PaddingValues = PaddingValues(), content: (@Composable ColumnScope.() -> Unit) ) { + val card = LocalCardScreen.current Column { val iconSize = with(LocalDensity.current) { 21.sp.toDp() } - Row(Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically) { + Row(Modifier.padding(start = if (card) DEFAULT_PADDING + DEFAULT_PADDING_HALF else DEFAULT_PADDING, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically) { if (leadingIcon) Icon(icon, null, Modifier.padding(end = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint) - Text(title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = 12.sp) + Text(title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = if (card) 14.sp else 12.sp, fontWeight = if (card) FontWeight.Medium else FontWeight.Normal) if (!leadingIcon) Icon(icon, null, Modifier.padding(start = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint) } - Column(Modifier.padding(padding).fillMaxWidth()) { content() } + CardColumn(padding) { content() } } } @Composable fun SectionViewWithButton(title: String? = null, titleButton: (@Composable () -> Unit)?, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = DEFAULT_PADDING, content: (@Composable ColumnScope.() -> Unit)) { + val card = LocalCardScreen.current Column { if (title != null || titleButton != null) { - Row(modifier = Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, bottom = headerBottomPadding).fillMaxWidth()) { + val hPadding = if (card) DEFAULT_PADDING + DEFAULT_PADDING_HALF else DEFAULT_PADDING + Row(modifier = Modifier.padding(start = hPadding, end = hPadding, bottom = if (card) 8.dp else headerBottomPadding).fillMaxWidth()) { if (title != null) { - Text(title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = 12.sp) + Text(title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = if (card) 14.sp else 12.sp, fontWeight = if (card) FontWeight.Medium else FontWeight.Normal) } if (titleButton != null) { Spacer(modifier = Modifier.weight(1f)) @@ -67,7 +143,7 @@ fun SectionViewWithButton(title: String? = null, titleButton: (@Composable () -> } } } - Column(Modifier.padding(contentPadding).fillMaxWidth()) { content() } + CardColumn(contentPadding) { content() } } } @@ -121,9 +197,9 @@ fun SectionItemView( disabled: Boolean = false, extraPadding: Boolean = false, padding: PaddingValues = if (extraPadding) - PaddingValues(start = DEFAULT_PADDING * 1.7f, end = DEFAULT_PADDING, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL) + PaddingValues(start = DEFAULT_PADDING * 1.7f, end = itemHPadding, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL) else - PaddingValues(horizontal = DEFAULT_PADDING, vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL), + PaddingValues(horizontal = itemHPadding, vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL), content: (@Composable RowScope.() -> Unit) ) { val modifier = Modifier @@ -144,9 +220,9 @@ fun SectionItemViewWithoutMinPadding( disabled: Boolean = false, extraPadding: Boolean = false, padding: PaddingValues = if (extraPadding) - PaddingValues(start = DEFAULT_PADDING * 1.7f, end = DEFAULT_PADDING) + PaddingValues(start = DEFAULT_PADDING * 1.7f, end = itemHPadding) else - PaddingValues(horizontal = DEFAULT_PADDING), + PaddingValues(horizontal = itemHPadding), content: (@Composable RowScope.() -> Unit) ) { SectionItemView(click, minHeight, disabled, extraPadding, padding, content) @@ -160,9 +236,9 @@ fun SectionItemViewLongClickable( disabled: Boolean = false, extraPadding: Boolean = false, padding: PaddingValues = if (extraPadding) - PaddingValues(start = DEFAULT_PADDING * 1.7f, end = DEFAULT_PADDING, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL) + PaddingValues(start = DEFAULT_PADDING * 1.7f, end = itemHPadding, top = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL, bottom = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL) else - PaddingValues(horizontal = DEFAULT_PADDING, vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL), + PaddingValues(horizontal = itemHPadding, vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL), content: (@Composable RowScope.() -> Unit) ) { val modifier = Modifier @@ -185,7 +261,7 @@ fun SectionItemViewSpaceBetween( click: (() -> Unit)? = null, onLongClick: (() -> Unit)? = null, minHeight: Dp = DEFAULT_MIN_SECTION_ITEM_HEIGHT, - padding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING), + padding: PaddingValues = PaddingValues(horizontal = itemHPadding), disabled: Boolean = false, content: (@Composable RowScope.() -> Unit) ) { @@ -256,20 +332,19 @@ fun SectionCustomFooter(padding: PaddingValues = PaddingValues(start = DEFAULT_P } } -@Composable -fun SectionDivider() { - Divider(Modifier.padding(horizontal = 8.dp)) -} - @Composable fun SectionDividerSpaced(maxTopPadding: Boolean = false, maxBottomPadding: Boolean = true) { - Divider( - Modifier.padding( - start = DEFAULT_PADDING_HALF, - top = if (maxTopPadding) DEFAULT_PADDING + 18.dp else DEFAULT_PADDING + 2.dp, - end = DEFAULT_PADDING_HALF, - bottom = if (maxBottomPadding) DEFAULT_PADDING + 18.dp else DEFAULT_PADDING + 2.dp) - ) + if (LocalCardScreen.current) { + Spacer(Modifier.height(30.dp)) + } else { + Divider( + Modifier.padding( + start = DEFAULT_PADDING_HALF, + top = if (maxTopPadding) DEFAULT_PADDING + 18.dp else DEFAULT_PADDING + 2.dp, + end = DEFAULT_PADDING_HALF, + bottom = if (maxBottomPadding) DEFAULT_PADDING + 18.dp else DEFAULT_PADDING + 2.dp) + ) + } } @Composable @@ -284,11 +359,11 @@ fun SectionBottomSpacer() { @Composable fun TextIconSpaced(extraPadding: Boolean = false) { - Spacer(Modifier.padding(horizontal = if (extraPadding) 17.dp else DEFAULT_PADDING_HALF)) + Spacer(Modifier.padding(horizontal = if (extraPadding) 17.dp else if (LocalCardScreen.current) ICON_TEXT_SPACING else DEFAULT_PADDING_HALF)) } @Composable -fun InfoRow(title: String, value: String, icon: Painter? = null, iconTint: Color? = null, textColor: Color = MaterialTheme.colors.onBackground, padding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING)) { +fun InfoRow(title: String, value: String, icon: Painter? = null, iconTint: Color? = null, textColor: Color = MaterialTheme.colors.onBackground, padding: PaddingValues = PaddingValues(horizontal = itemHPadding)) { SectionItemViewSpaceBetween(padding = padding) { Row { val iconSize = with(LocalDensity.current) { 21.sp.toDp() } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt index d7cdf0e2e3..c8c24d918a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ThemeModeEditor.kt @@ -3,8 +3,8 @@ package chat.simplex.common.views.helpers import SectionBottomSpacer import SectionDividerSpaced import SectionItemView -import SectionSpacer import SectionView +import androidx.compose.foundation.background import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme.colors @@ -108,18 +108,22 @@ fun ModalData.UserWallpaperEditor( ) } - WallpaperPresetSelector( - selectedWallpaper = wallpaperType, - baseTheme = currentTheme.base, - currentColors = { type -> - // If applying for : - // - all themes: no overrides needed - // - specific user: only user overrides for currently selected theme are needed, because they will NOT be copied when other wallpaper is selected - val perUserOverride = if (wallpaperType.sameType(type)) chatModel.currentUser.value?.uiThemes else null - ThemeManager.currentColors(type, null, perUserOverride, appPrefs.themeOverrides.get()) - }, - onChooseType = onChooseType - ) + SectionView { + WallpaperPresetSelector( + selectedWallpaper = wallpaperType, + baseTheme = currentTheme.base, + currentColors = { type -> + // If applying for : + // - all themes: no overrides needed + // - specific user: only user overrides for currently selected theme are needed, because they will NOT be copied when other wallpaper is selected + val perUserOverride = if (wallpaperType.sameType(type)) chatModel.currentUser.value?.uiThemes else null + ThemeManager.currentColors(type, null, perUserOverride, appPrefs.themeOverrides.get()) + }, + onChooseType = onChooseType + ) + } + + SectionDividerSpaced() WallpaperSetupView( themeModeOverride.value.type, @@ -133,29 +137,30 @@ fun ModalData.UserWallpaperEditor( onTypeChange = onTypeChange, ) - SectionSpacer() + SectionDividerSpaced() - if (!globalThemeUsed.value) { - ResetToGlobalThemeButton(true) { - themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) - globalThemeUsed.value = true - withBGApi { save(applyToMode.value, null) } - } - } - - SetDefaultThemeButton { - globalThemeUsed.value = false - val lightBase = DefaultTheme.LIGHT - val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX - val mode = themeModeOverride.value.mode - withBGApi { - // Saving for both modes in one place by changing mode once per save - if (applyToMode.value == null) { - val oppositeMode = if (mode == DefaultThemeMode.LIGHT) DefaultThemeMode.DARK else DefaultThemeMode.LIGHT - save(oppositeMode, ThemeModeOverride.withFilledAppDefaults(oppositeMode, if (oppositeMode == DefaultThemeMode.LIGHT) lightBase else darkBase)) + SectionView { + if (!globalThemeUsed.value) { + ResetToGlobalThemeButton(true) { + themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + globalThemeUsed.value = true + withBGApi { save(applyToMode.value, null) } + } + } + SetDefaultThemeButton { + globalThemeUsed.value = false + val lightBase = DefaultTheme.LIGHT + val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX + val mode = themeModeOverride.value.mode + withBGApi { + // Saving for both modes in one place by changing mode once per save + if (applyToMode.value == null) { + val oppositeMode = if (mode == DefaultThemeMode.LIGHT) DefaultThemeMode.DARK else DefaultThemeMode.LIGHT + save(oppositeMode, ThemeModeOverride.withFilledAppDefaults(oppositeMode, if (oppositeMode == DefaultThemeMode.LIGHT) lightBase else darkBase)) + } + themeModeOverride.value = ThemeModeOverride.withFilledAppDefaults(mode, if (mode == DefaultThemeMode.LIGHT) lightBase else darkBase) + save(themeModeOverride.value.mode, themeModeOverride.value) } - themeModeOverride.value = ThemeModeOverride.withFilledAppDefaults(mode, if (mode == DefaultThemeMode.LIGHT) lightBase else darkBase) - save(themeModeOverride.value.mode, themeModeOverride.value) } } @@ -174,38 +179,40 @@ fun ModalData.UserWallpaperEditor( } } - SectionSpacer() + SectionDividerSpaced() if (showMore) { - val values by remember { mutableStateOf( - listOf( - null to generalGetString(MR.strings.chat_theme_apply_to_all_modes), - DefaultThemeMode.LIGHT to generalGetString(MR.strings.chat_theme_apply_to_light_mode), - DefaultThemeMode.DARK to generalGetString(MR.strings.chat_theme_apply_to_dark_mode), + SectionView { + val values by remember { mutableStateOf( + listOf( + null to generalGetString(MR.strings.chat_theme_apply_to_all_modes), + DefaultThemeMode.LIGHT to generalGetString(MR.strings.chat_theme_apply_to_light_mode), + DefaultThemeMode.DARK to generalGetString(MR.strings.chat_theme_apply_to_dark_mode), + ) ) - ) - } - ExposedDropDownSettingRow( - generalGetString(MR.strings.chat_theme_apply_to_mode), - values, - applyToMode, - icon = null, - enabled = remember { mutableStateOf(true) }, - onSelected = { - applyToMode.value = it - if (it != null && it != CurrentColors.value.base.mode) { - val lightBase = DefaultTheme.LIGHT - val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX - ThemeManager.applyTheme(if (it == DefaultThemeMode.LIGHT) lightBase.themeName else darkBase.themeName) - } } - ) + ExposedDropDownSettingRow( + generalGetString(MR.strings.chat_theme_apply_to_mode), + values, + applyToMode, + icon = null, + enabled = remember { mutableStateOf(true) }, + onSelected = { + applyToMode.value = it + if (it != null && it != CurrentColors.value.base.mode) { + val lightBase = DefaultTheme.LIGHT + val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX + ThemeManager.applyTheme(if (it == DefaultThemeMode.LIGHT) lightBase.themeName else darkBase.themeName) + } + } + ) + } SectionDividerSpaced() AppearanceScope.CustomizeThemeColorsSection(currentTheme, editColor = editColor) - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() ImportExportThemeSection(null, remember { chatModel.currentUser }.value?.uiThemes) { withBGApi { @@ -214,7 +221,9 @@ fun ModalData.UserWallpaperEditor( } } } else { - AdvancedSettingsButton { showMore = true } + SectionView { + AdvancedSettingsButton { showMore = true } + } } SectionBottomSpacer() @@ -329,32 +338,36 @@ fun ModalData.ChatWallpaperEditor( ThemeManager.currentColors(type, if (type?.sameType(themeModeOverride.value.type) == true) themeModeOverride.value else null, chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) } - WallpaperPresetSelector( - selectedWallpaper = currentTheme.wallpaper.type, - activeBackgroundColor = currentTheme.wallpaper.background, - activeTintColor = currentTheme.wallpaper.tint, - baseTheme = CurrentColors.collectAsState().value.base, - currentColors = { type -> currentColors(type) }, - onChooseType = { type -> - when { - type is WallpaperType.Image && chatModel.remoteHostId() != null -> { /* do nothing */ } - type is WallpaperType.Image && ((themeModeOverride.value.type is WallpaperType.Image && !globalThemeUsed.value) || currentColors(type).wallpaper.type.image == null) -> { - withLongRunningApi { importWallpaperLauncher.launch("image/*") } - } - type is WallpaperType.Image -> { - if (!onTypeCopyFromSameTheme(currentColors(type).wallpaper.type)) { + SectionView { + WallpaperPresetSelector( + selectedWallpaper = currentTheme.wallpaper.type, + activeBackgroundColor = currentTheme.wallpaper.background, + activeTintColor = currentTheme.wallpaper.tint, + baseTheme = CurrentColors.collectAsState().value.base, + currentColors = { type -> currentColors(type) }, + onChooseType = { type -> + when { + type is WallpaperType.Image && chatModel.remoteHostId() != null -> { /* do nothing */ } + type is WallpaperType.Image && ((themeModeOverride.value.type is WallpaperType.Image && !globalThemeUsed.value) || currentColors(type).wallpaper.type.image == null) -> { withLongRunningApi { importWallpaperLauncher.launch("image/*") } } + type is WallpaperType.Image -> { + if (!onTypeCopyFromSameTheme(currentColors(type).wallpaper.type)) { + withLongRunningApi { importWallpaperLauncher.launch("image/*") } + } + } + globalThemeUsed.value || themeModeOverride.value.type != type -> { + onTypeCopyFromSameTheme(type) + } + else -> { + onTypeChange(type) + } } - globalThemeUsed.value || themeModeOverride.value.type != type -> { - onTypeCopyFromSameTheme(type) - } - else -> { - onTypeChange(type) - } - } - }, - ) + }, + ) + } + + SectionDividerSpaced() WallpaperSetupView( themeModeOverride.value.type, @@ -368,29 +381,30 @@ fun ModalData.ChatWallpaperEditor( onTypeChange = onTypeChange, ) - SectionSpacer() + SectionDividerSpaced() - if (!globalThemeUsed.value) { - ResetToGlobalThemeButton(remember { chatModel.currentUser }.value?.uiThemes?.preferredMode(isInDarkTheme()) == null) { - themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) - globalThemeUsed.value = true - withBGApi { save(applyToMode.value, null) } - } - } - - SetDefaultThemeButton { - globalThemeUsed.value = false - val lightBase = DefaultTheme.LIGHT - val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX - val mode = themeModeOverride.value.mode - withBGApi { - // Saving for both modes in one place by changing mode once per save - if (applyToMode.value == null) { - val oppositeMode = if (mode == DefaultThemeMode.LIGHT) DefaultThemeMode.DARK else DefaultThemeMode.LIGHT - save(oppositeMode, ThemeModeOverride.withFilledAppDefaults(oppositeMode, if (oppositeMode == DefaultThemeMode.LIGHT) lightBase else darkBase)) + SectionView { + if (!globalThemeUsed.value) { + ResetToGlobalThemeButton(remember { chatModel.currentUser }.value?.uiThemes?.preferredMode(isInDarkTheme()) == null) { + themeModeOverride.value = ThemeManager.defaultActiveTheme(chatModel.currentUser.value?.uiThemes, appPrefs.themeOverrides.get()) + globalThemeUsed.value = true + withBGApi { save(applyToMode.value, null) } + } + } + SetDefaultThemeButton { + globalThemeUsed.value = false + val lightBase = DefaultTheme.LIGHT + val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX + val mode = themeModeOverride.value.mode + withBGApi { + // Saving for both modes in one place by changing mode once per save + if (applyToMode.value == null) { + val oppositeMode = if (mode == DefaultThemeMode.LIGHT) DefaultThemeMode.DARK else DefaultThemeMode.LIGHT + save(oppositeMode, ThemeModeOverride.withFilledAppDefaults(oppositeMode, if (oppositeMode == DefaultThemeMode.LIGHT) lightBase else darkBase)) + } + themeModeOverride.value = ThemeModeOverride.withFilledAppDefaults(mode, if (mode == DefaultThemeMode.LIGHT) lightBase else darkBase) + save(themeModeOverride.value.mode, themeModeOverride.value) } - themeModeOverride.value = ThemeModeOverride.withFilledAppDefaults(mode, if (mode == DefaultThemeMode.LIGHT) lightBase else darkBase) - save(themeModeOverride.value.mode, themeModeOverride.value) } } @@ -409,38 +423,40 @@ fun ModalData.ChatWallpaperEditor( } } - SectionSpacer() + SectionDividerSpaced() if (showMore) { - val values by remember { mutableStateOf( - listOf( - null to generalGetString(MR.strings.chat_theme_apply_to_all_modes), - DefaultThemeMode.LIGHT to generalGetString(MR.strings.chat_theme_apply_to_light_mode), - DefaultThemeMode.DARK to generalGetString(MR.strings.chat_theme_apply_to_dark_mode), + SectionView { + val values by remember { mutableStateOf( + listOf( + null to generalGetString(MR.strings.chat_theme_apply_to_all_modes), + DefaultThemeMode.LIGHT to generalGetString(MR.strings.chat_theme_apply_to_light_mode), + DefaultThemeMode.DARK to generalGetString(MR.strings.chat_theme_apply_to_dark_mode), + ) ) - ) - } - ExposedDropDownSettingRow( - generalGetString(MR.strings.chat_theme_apply_to_mode), - values, - applyToMode, - icon = null, - enabled = remember { mutableStateOf(true) }, - onSelected = { - applyToMode.value = it - if (it != null && it != CurrentColors.value.base.mode) { - val lightBase = DefaultTheme.LIGHT - val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX - ThemeManager.applyTheme(if (it == DefaultThemeMode.LIGHT) lightBase.themeName else darkBase.themeName) - } } - ) + ExposedDropDownSettingRow( + generalGetString(MR.strings.chat_theme_apply_to_mode), + values, + applyToMode, + icon = null, + enabled = remember { mutableStateOf(true) }, + onSelected = { + applyToMode.value = it + if (it != null && it != CurrentColors.value.base.mode) { + val lightBase = DefaultTheme.LIGHT + val darkBase = if (CurrentColors.value.base != DefaultTheme.LIGHT) CurrentColors.value.base else if (appPrefs.systemDarkTheme.get() == DefaultTheme.DARK.themeName) DefaultTheme.DARK else if (appPrefs.systemDarkTheme.get() == DefaultTheme.BLACK.themeName) DefaultTheme.BLACK else DefaultTheme.SIMPLEX + ThemeManager.applyTheme(if (it == DefaultThemeMode.LIGHT) lightBase.themeName else darkBase.themeName) + } + } + ) + } SectionDividerSpaced() AppearanceScope.CustomizeThemeColorsSection(currentTheme, editColor = editColor) - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() ImportExportThemeSection(themeModeOverride.value, remember { chatModel.currentUser }.value?.uiThemes) { withBGApi { themeModeOverride.value = it @@ -448,7 +464,9 @@ fun ModalData.ChatWallpaperEditor( } } } else { - AdvancedSettingsButton { showMore = true } + SectionView { + AdvancedSettingsButton { showMore = true } + } } SectionBottomSpacer() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt index 03542ca8af..39c4cb0b7f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt @@ -1,7 +1,7 @@ package chat.simplex.common.views.migration import SectionBottomSpacer -import SectionSpacer +import SectionDividerSpaced import SectionTextFooter import SectionView import androidx.compose.foundation.layout.* @@ -11,6 +11,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate +import androidx.compose.foundation.background import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @@ -134,6 +135,7 @@ fun MigrateFromDeviceView(close: () -> Unit) { } close() }, + cardScreen = true, ) { MigrateFromDeviceLayout( migrationState = migrationState, @@ -182,7 +184,7 @@ private fun SectionByState( @Composable private fun MutableState.ChatStopInProgressView() { Box { - SectionView(stringResource(MR.strings.migrate_from_device_stopping_chat).uppercase()) {} + SectionView(stringResource(MR.strings.migrate_from_device_stopping_chat)) {} ProgressView() } LaunchedEffect(Unit) { @@ -192,9 +194,9 @@ private fun MutableState.ChatStopInProgressView() { @Composable private fun MutableState.ChatStopFailedView(reason: String) { - SectionView(stringResource(MR.strings.error_stopping_chat).uppercase()) { + SectionView(stringResource(MR.strings.error_stopping_chat)) { Text(reason) - SectionSpacer() + SectionDividerSpaced() SettingsActionItemWithContent( icon = painterResource(MR.images.ic_report_filled), text = stringResource(MR.strings.auth_stop_chat), @@ -224,9 +226,9 @@ private fun MutableState.PassphraseConfirmationView() { val view = LocalMultiplatformView() Column { ChatStoppedView() - SectionSpacer() + SectionDividerSpaced() - SectionView(stringResource(MR.strings.migrate_from_device_verify_database_passphrase).uppercase()) { + SectionView(stringResource(MR.strings.migrate_from_device_verify_database_passphrase)) { PassphraseField(currentKey, placeholder = stringResource(MR.strings.current_passphrase), Modifier.padding(horizontal = DEFAULT_PADDING), isValid = ::validKey, requestFocus = true) SettingsActionItemWithContent( @@ -243,8 +245,8 @@ private fun MutableState.PassphraseConfirmationView() { } } ) {} - SectionTextFooter(stringResource(MR.strings.migrate_from_device_confirm_you_remember_passphrase)) } + SectionTextFooter(stringResource(MR.strings.migrate_from_device_confirm_you_remember_passphrase)) } if (verifyingPassphrase.value) { ProgressView() @@ -254,7 +256,7 @@ private fun MutableState.PassphraseConfirmationView() { @Composable private fun MutableState.UploadConfirmationView() { - SectionView(stringResource(MR.strings.migrate_from_device_confirm_upload).uppercase()) { + SectionView(stringResource(MR.strings.migrate_from_device_confirm_upload)) { SettingsActionItemWithContent( icon = painterResource(MR.images.ic_ios_share), text = stringResource(MR.strings.migrate_from_device_archive_and_upload), @@ -268,7 +270,7 @@ private fun MutableState.UploadConfirmationView() { @Composable private fun MutableState.ArchivingView() { Box { - SectionView(stringResource(MR.strings.migrate_from_device_archiving_database).uppercase()) {} + SectionView(stringResource(MR.strings.migrate_from_device_archiving_database)) {} ProgressView() } LaunchedEffect(Unit) { @@ -279,7 +281,7 @@ private fun MutableState.ArchivingView() { @Composable private fun MutableState.DatabaseInitView(tempDatabaseFile: File, totalBytes: Long, archivePath: String) { Box { - SectionView(stringResource(MR.strings.migrate_from_device_database_init).uppercase()) {} + SectionView(stringResource(MR.strings.migrate_from_device_database_init)) {} ProgressView() } LaunchedEffect(Unit) { @@ -298,7 +300,7 @@ private fun MutableState.UploadProgressView( archivePath: String, ) { Box { - SectionView(stringResource(MR.strings.migrate_from_device_uploading_archive).uppercase()) { + SectionView(stringResource(MR.strings.migrate_from_device_uploading_archive)) { val ratio = uploadedBytes.toFloat() / max(totalBytes, 1) LargeProgressView(ratio, "${(ratio * 100).toInt()}%", stringResource(MR.strings.migrate_from_device_bytes_uploaded).format(formatBytes(uploadedBytes))) } @@ -310,7 +312,7 @@ private fun MutableState.UploadProgressView( @Composable private fun MutableState.UploadFailedView(totalBytes: Long, archivePath: String, chatReceiver: MigrationFromChatReceiver?) { - SectionView(stringResource(MR.strings.migrate_from_device_upload_failed).uppercase()) { + SectionView(stringResource(MR.strings.migrate_from_device_upload_failed)) { SettingsActionItemWithContent( icon = painterResource(MR.images.ic_ios_share), text = stringResource(MR.strings.migrate_from_device_repeat_upload), @@ -329,7 +331,7 @@ private fun MutableState.UploadFailedView(totalBytes: Long, @Composable private fun LinkCreationView() { Box { - SectionView(stringResource(MR.strings.migrate_from_device_creating_archive_link).uppercase()) {} + SectionView(stringResource(MR.strings.migrate_from_device_creating_archive_link)) {} ProgressView() } } @@ -361,15 +363,15 @@ private fun MutableState.LinkShownView(fileId: Long, link: S ) } ) {} - SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_archive_will_be_deleted)) - SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_choose_migrate_from_another_device)) } - SectionSpacer() - SectionView(stringResource(MR.strings.show_QR_code).uppercase()) { + SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_archive_will_be_deleted)) + SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_choose_migrate_from_another_device)) + SectionDividerSpaced() + SectionView(stringResource(MR.strings.show_QR_code)) { SimpleXLinkQRCode(link, onShare = {}) } - SectionSpacer() - SectionView(stringResource(MR.strings.migrate_from_device_or_share_this_file_link).uppercase()) { + SectionDividerSpaced() + SectionView(stringResource(MR.strings.migrate_from_device_or_share_this_file_link)) { LinkTextView(link, true) } } @@ -377,7 +379,7 @@ private fun MutableState.LinkShownView(fileId: Long, link: S @Composable private fun MutableState.FinishedView(chatDeletion: Boolean) { Box { - SectionView(stringResource(MR.strings.migrate_from_device_migration_complete).uppercase()) { + SectionView(stringResource(MR.strings.migrate_from_device_migration_complete)) { SettingsActionItemWithContent( icon = painterResource(MR.images.ic_play_arrow_filled), text = stringResource(MR.strings.migrate_from_device_start_chat), @@ -410,9 +412,9 @@ private fun MutableState.FinishedView(chatDeletion: Boolean) ) } ) {} - SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_you_must_not_start_database_on_two_device)) - SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_using_on_two_device_breaks_encryption)) } + SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_you_must_not_start_database_on_two_device)) + SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_using_on_two_device_breaks_encryption)) if (chatDeletion) { ProgressView() } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt index cabfbf031e..f92a5e0ce4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt @@ -2,6 +2,7 @@ package chat.simplex.common.views.migration import SectionBottomSpacer import SectionItemView +import SectionDividerSpaced import SectionSpacer import SectionTextFooter import SectionView @@ -9,6 +10,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.foundation.background import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalClipboardManager import chat.simplex.common.model.* @@ -148,6 +150,7 @@ fun ModalData.MigrateToDeviceView(close: () -> Unit) { close() } }, + cardScreen = true, ) { MigrateToDeviceLayout( migrationState = migrationState, @@ -201,7 +204,7 @@ private fun MutableState.PasteOrScanLinkView(close: () -> Uni val progressIndicator = remember { mutableStateOf(false) } Column { if (appPlatform.isAndroid) { - SectionView(stringResource(MR.strings.scan_QR_code).replace('\n', ' ').uppercase()) { + SectionView(stringResource(MR.strings.scan_QR_code).replace('\n', ' ')) { QRCodeScanner(showQRCodeScanner = remember { mutableStateOf(true) }) { text -> checkUserLink(text) } @@ -209,12 +212,12 @@ private fun MutableState.PasteOrScanLinkView(close: () -> Uni SectionSpacer() } - SectionView(stringResource(if (appPlatform.isAndroid) MR.strings.or_paste_archive_link else MR.strings.paste_archive_link).uppercase()) { + SectionView(stringResource(if (appPlatform.isAndroid) MR.strings.or_paste_archive_link else MR.strings.paste_archive_link)) { PasteLinkView() } SectionSpacer() - SectionView(stringResource(MR.strings.chat_archive).uppercase()) { + SectionView(stringResource(MR.strings.chat_archive)) { ArchiveImportView(progressIndicator, close) } } @@ -280,7 +283,7 @@ private fun ModalData.OnionView(link: String, legacyLinkSocksProxy: String?, lin mutableStateOf(getNetCfg().withOnionHosts(onionHosts.value).copy(socksProxy = linkNetworkProxy?.toProxyString() ?: legacyLinkSocksProxy, sessionMode = sessionMode.value)) } - SectionView(stringResource(MR.strings.migrate_to_device_confirm_network_settings).uppercase()) { + SectionView(stringResource(MR.strings.migrate_to_device_confirm_network_settings)) { SettingsActionItemWithContent( icon = painterResource(MR.images.ic_check), text = stringResource(MR.strings.migrate_to_device_apply_onion), @@ -305,7 +308,7 @@ private fun ModalData.OnionView(link: String, legacyLinkSocksProxy: String?, lin val networkProxyPref = SharedPreference(get = { networkProxy.value }, set = { networkProxy.value = it }) - SectionView(stringResource(MR.strings.network_settings_title).uppercase()) { + SectionView(stringResource(MR.strings.network_settings_title)) { OnionRelatedLayout( appPreferences.developerTools.get(), networkUseSocksProxy, @@ -325,7 +328,7 @@ private fun ModalData.OnionView(link: String, legacyLinkSocksProxy: String?, lin @Composable private fun MutableState.DatabaseInitView(link: String, tempDatabaseFile: File, netCfg: NetCfg, networkProxy: NetworkProxy?) { Box { - SectionView(stringResource(MR.strings.migrate_to_device_database_init).uppercase()) {} + SectionView(stringResource(MR.strings.migrate_to_device_database_init)) {} ProgressView() } LaunchedEffect(Unit) { @@ -345,7 +348,7 @@ private fun MutableState.LinkDownloadingView( networkProxy: NetworkProxy? ) { Box { - SectionView(stringResource(MR.strings.migrate_to_device_downloading_details).uppercase()) {} + SectionView(stringResource(MR.strings.migrate_to_device_downloading_details)) {} ProgressView() } LaunchedEffect(Unit) { @@ -356,7 +359,7 @@ private fun MutableState.LinkDownloadingView( @Composable private fun DownloadProgressView(downloadedBytes: Long, totalBytes: Long) { Box { - SectionView(stringResource(MR.strings.migrate_to_device_downloading_archive).uppercase()) { + SectionView(stringResource(MR.strings.migrate_to_device_downloading_archive)) { val ratio = downloadedBytes.toFloat() / max(totalBytes, 1) LargeProgressView(ratio, "${(ratio * 100).toInt()}%", stringResource(MR.strings.migrate_to_device_bytes_downloaded).format(formatBytes(downloadedBytes))) } @@ -365,7 +368,7 @@ private fun DownloadProgressView(downloadedBytes: Long, totalBytes: Long) { @Composable private fun MutableState.DownloadFailedView(link: String, chatReceiver: MigrationToChatReceiver?, archivePath: String, netCfg: NetCfg, networkProxy: NetworkProxy?) { - SectionView(stringResource(MR.strings.migrate_to_device_download_failed).uppercase()) { + SectionView(stringResource(MR.strings.migrate_to_device_download_failed)) { SettingsActionItemWithContent( icon = painterResource(MR.images.ic_download), text = stringResource(MR.strings.migrate_to_device_repeat_download), @@ -386,7 +389,7 @@ private fun MutableState.DownloadFailedView(link: String, cha @Composable private fun MutableState.ArchiveImportView(archivePath: String, netCfg: NetCfg, networkProxy: NetworkProxy?) { Box { - SectionView(stringResource(MR.strings.migrate_to_device_importing_archive).uppercase()) {} + SectionView(stringResource(MR.strings.migrate_to_device_importing_archive)) {} ProgressView() } LaunchedEffect(Unit) { @@ -396,7 +399,7 @@ private fun MutableState.ArchiveImportView(archivePath: Strin @Composable private fun MutableState.ArchiveImportFailedView(archivePath: String, netCfg: NetCfg, networkProxy: NetworkProxy?) { - SectionView(stringResource(MR.strings.migrate_to_device_import_failed).uppercase()) { + SectionView(stringResource(MR.strings.migrate_to_device_import_failed)) { SettingsActionItemWithContent( icon = painterResource(MR.images.ic_download), text = stringResource(MR.strings.migrate_to_device_repeat_import), @@ -417,7 +420,7 @@ private fun MutableState.PassphraseEnteringView(currentKey: S Box { val view = LocalMultiplatformView() - SectionView(stringResource(MR.strings.migrate_to_device_enter_passphrase).uppercase()) { + SectionView(stringResource(MR.strings.migrate_to_device_enter_passphrase)) { SavePassphraseSetting( useKeychain.value, false, @@ -489,7 +492,7 @@ private fun MutableState.MigrationConfirmationView(status: DB } else -> Tuple4(generalGetString(MR.strings.error), null, generalGetString(MR.strings.unknown_error), null) } - SectionView(header.uppercase()) { + SectionView(header) { if (button != null && confirmation != null) { SettingsActionItemWithContent( icon = painterResource(MR.images.ic_download), @@ -500,14 +503,14 @@ private fun MutableState.MigrationConfirmationView(status: DB } ) {} } - SectionTextFooter(footer) } + SectionTextFooter(footer) } @Composable private fun MigrationView(passphrase: String, confirmation: MigrationConfirmation, useKeychain: Boolean, netCfg: NetCfg, networkProxy: NetworkProxy?, close: () -> Unit) { Box { - SectionView(stringResource(MR.strings.migrate_to_device_migrating).uppercase()) {} + SectionView(stringResource(MR.strings.migrate_to_device_migrating)) {} ProgressView() } LaunchedEffect(Unit) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddChannelView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddChannelView.kt index 93bb4f49db..b5188178fa 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddChannelView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddChannelView.kt @@ -66,7 +66,7 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit closeAll() withBGApi { openGroupChat(null, gInfo.groupId) - ModalManager.end.showModalCloseable(true) { close -> + ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { close -> GroupLinkView(chatModel, rhId = null, groupInfo = gInfo, groupLink = groupLink.value, onGroupLinkUpdated = null, creatingGroup = true, isChannel = true, shareGroupInfo = gInfo, close = close) } } @@ -567,7 +567,7 @@ private fun LinkStepView( } } } - ModalView(close = close, showClose = false) { + ModalView(close = close, showClose = false, cardScreen = true) { GroupLinkView( chatModel = chatModel, rhId = null, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt index a54d2e42e7..1d8da1690c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt @@ -53,11 +53,11 @@ fun AddGroupView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit, c closeAll.invoke() if (!groupInfo.incognito) { - ModalManager.end.showModalCloseable(true) { close -> + ModalManager.end.showModalCloseable(showClose = true) { close -> AddGroupMembersView(rhId, groupInfo, creatingGroup = true, chatModel, close) } } else { - ModalManager.end.showModalCloseable(true) { close -> + ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { close -> GroupLinkView(chatModel, rhId, groupInfo, groupLink = null, onGroupLinkUpdated = null, creatingGroup = true, close = close) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt index 0f299b5187..f1bd732d87 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt @@ -7,6 +7,7 @@ import SectionView import SectionViewWithButton import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.foundation.layout.* +import androidx.compose.foundation.background import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -130,7 +131,7 @@ private fun ContactConnectionInfoLayout( if (connLink != null && connLink.connFullLink.isNotEmpty() && contactConnection.initiated) { Spacer(Modifier.height(DEFAULT_PADDING)) SectionViewWithButton( - stringResource(MR.strings.one_time_link).uppercase(), + stringResource(MR.strings.one_time_link), titleButton = if (connLink.connShortLink == null) null else {{ ToggleShortLinkButton(showShortLink) }} ) { SimpleXCreatedLinkQRCode(connLink, short = showShortLink.value) @@ -146,7 +147,7 @@ private fun ContactConnectionInfoLayout( } SectionTextFooter(sharedProfileInfo(chatModel, contactConnection.incognito)) - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() DeleteButton(deleteConnection) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt index 1eceaf4158..993e1fca01 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt @@ -325,7 +325,7 @@ private fun ModalData.NewChatSheetLayout( item { if (filteredContactChats.isNotEmpty() && searchText.value.text.isEmpty()) { SectionDividerSpaced(maxTopPadding = false, maxBottomPadding = false) - SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {} + SectionView(stringResource(MR.strings.contact_list_header_title), headerBottomPadding = DEFAULT_PADDING_HALF) {} Spacer(Modifier.height(DEFAULT_PADDING_HALF)) } } @@ -410,7 +410,7 @@ private fun ModalData.NewChatSheetLayout( item { if (filteredContactChats.isNotEmpty() && searchText.value.text.isEmpty()) { SectionDividerSpaced() - SectionView(stringResource(MR.strings.contact_list_header_title).uppercase(), headerBottomPadding = DEFAULT_PADDING_HALF) {} + SectionView(stringResource(MR.strings.contact_list_header_title), headerBottomPadding = DEFAULT_PADDING_HALF) {} } } item { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt index 72311cd7fe..5b3fd34c22 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt @@ -495,7 +495,7 @@ private fun InviteView(rhId: Long?, connLinkInvitation: CreatedConnLink, contact ) SimpleXCreatedLinkQRCode(connLinkInvitation, short = showShortLink.value, onShare = { chatModel.markShowingInvitationUsed() }) } else { - SectionView(stringResource(MR.strings.share_this_1_time_link).uppercase(), headerBottomPadding = 5.dp) { + SectionView(stringResource(MR.strings.share_this_1_time_link), headerBottomPadding = 5.dp) { LinkTextView(connLinkInvitation.simplexChatUri(short = showShortLink.value), true) } @@ -519,7 +519,7 @@ private fun InviteView(rhId: Long?, connLinkInvitation: CreatedConnLink, contact val currentUser = remember { chatModel.currentUser }.value if (currentUser != null) { - SectionView(stringResource(MR.strings.new_chat_share_profile).uppercase(), headerBottomPadding = 5.dp) { + SectionView(stringResource(MR.strings.new_chat_share_profile), headerBottomPadding = 5.dp) { SectionItemView( padding = PaddingValues( top = 0.dp, @@ -643,14 +643,14 @@ private fun ConnectView(rhId: Long?, showQRCodeScanner: MutableState, p ) } - SectionView(stringResource(MR.strings.paste_the_link_you_received).uppercase(), headerBottomPadding = 5.dp) { + SectionView(stringResource(MR.strings.paste_the_link_you_received), headerBottomPadding = 5.dp) { PasteLinkView(rhId, pastedLink, showQRCodeScanner, close) } if (appPlatform.isAndroid) { Spacer(Modifier.height(10.dp)) - SectionView(stringResource(MR.strings.or_scan_qr_code).uppercase(), headerBottomPadding = 5.dp) { + SectionView(stringResource(MR.strings.or_scan_qr_code), headerBottomPadding = 5.dp) { QRCodeScanner(showQRCodeScanner) { text -> val linkVerified = verifyOnly(text) if (!linkVerified) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/ChooseServerOperators.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/ChooseServerOperators.kt index 2fd77b46a1..d11e396388 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/ChooseServerOperators.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/ChooseServerOperators.kt @@ -55,7 +55,7 @@ fun OnboardingConditionsView(chatModel: ChatModel) { OnboardingConditionsDesktop(selectedOperatorIds) } else { CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) { - ModalView({}, showClose = false, showAppBar = false) { + ModalView({}, showClose = false, showAppBar = false, cardScreen = true) { OnboardingShrinkingLayout( modifier = Modifier.fillMaxSize().themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer) .systemBarsPadding() @@ -133,7 +133,7 @@ fun OnboardingConditionsView(chatModel: ChatModel) { @Composable private fun OnboardingConditionsDesktop(selectedOperatorIds: MutableState>) { CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) { - ModalView({}, showClose = false) { + ModalView({}, showClose = false, cardScreen = true) { ColumnWithScrollBar(horizontalAlignment = Alignment.CenterHorizontally) { Column(Modifier.widthIn(max = 600.dp).fillMaxHeight().padding(horizontal = DEFAULT_PADDING).align(Alignment.CenterHorizontally), horizontalAlignment = Alignment.CenterHorizontally) { Box(Modifier.align(Alignment.CenterHorizontally)) { @@ -184,7 +184,7 @@ fun ModalData.ChooseServerOperators( prepareChatBeforeFinishingOnboarding() } CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) { - ModalView(close, enableClose = selectedOperatorIds.value.isNotEmpty()) { + ModalView(close, enableClose = selectedOperatorIds.value.isNotEmpty(), cardScreen = true) { ColumnWithScrollBar( Modifier .themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer), @@ -373,7 +373,7 @@ private fun ChooseServerOperatorsInfoView() { SectionDividerSpaced() - SectionView(title = stringResource(MR.strings.onboarding_network_about_operators).uppercase()) { + SectionView(title = stringResource(MR.strings.onboarding_network_about_operators)) { chatModel.conditions.value.serverOperators.forEach { op -> ServerOperatorRow(op) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/LinkAMobileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/LinkAMobileView.kt index e902b7947e..97dfcd34b9 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/LinkAMobileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/LinkAMobileView.kt @@ -65,7 +65,7 @@ private fun LinkAMobileLayout( Modifier.weight(0.3f), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - SectionView(generalGetString(MR.strings.this_device_name).uppercase()) { + SectionView(generalGetString(MR.strings.this_device_name)) { DeviceNameField(deviceName.value ?: "") { updateDeviceName(it) } SectionTextFooter(generalGetString(MR.strings.this_device_name_shared_with_mobile)) PreferenceToggle(stringResource(MR.strings.multicast_discoverable_via_local_network), checked = remember { ChatModel.controller.appPrefs.offerRemoteMulticast.state }.value) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt index 8bb84060c2..81e1afd22c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt @@ -4,10 +4,10 @@ import SectionBottomSpacer import SectionDividerSpaced import SectionItemView import SectionItemViewLongClickable -import SectionSpacer import SectionView import TextIconSpaced import androidx.compose.foundation.layout.* +import androidx.compose.foundation.background import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material.* import androidx.compose.runtime.* @@ -29,8 +29,7 @@ import chat.simplex.common.model.ChatController.switchToLocalSession import chat.simplex.common.model.ChatModel.connectedToRemote import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.platform.* -import chat.simplex.common.ui.theme.DEFAULT_PADDING -import chat.simplex.common.ui.theme.DEFAULT_PADDING_HALF +import chat.simplex.common.ui.theme.* import chat.simplex.common.views.chat.item.ItemAction import chat.simplex.common.views.helpers.* import chat.simplex.common.views.newchat.QRCodeScanner @@ -53,7 +52,7 @@ fun ConnectDesktopView(close: () -> Unit) { showDisconnectDesktopAlert(close) } } - ModalView(close = closeWithAlert) { + ModalView(close = closeWithAlert, cardScreen = true) { ConnectDesktopLayout( deviceName = deviceName.value!!, close @@ -128,7 +127,7 @@ private fun ConnectDesktopLayout(deviceName: String, close: () -> Unit) { @Composable private fun ConnectDesktop(deviceName: String, remoteCtrls: SnapshotStateList, sessionAddress: MutableState) { AppBarTitle(stringResource(MR.strings.connect_to_desktop)) - SectionView(stringResource(MR.strings.this_device_name).uppercase()) { + SectionView(stringResource(MR.strings.this_device_name)) { DevicesView(deviceName, remoteCtrls) { if (it != "") { setDeviceName(it) @@ -139,7 +138,7 @@ private fun ConnectDesktop(deviceName: String, remoteCtrls: SnapshotStateList) { AppBarTitle(stringResource(MR.strings.connecting_to_desktop)) - SectionView(stringResource(MR.strings.this_device_name).uppercase()) { + SectionView(stringResource(MR.strings.this_device_name)) { DevicesView(deviceName, remoteCtrls) { if (it != "") { setDeviceName(it) @@ -197,10 +196,10 @@ private fun SearchingDesktop(deviceName: String, remoteCtrls: SnapshotStateList< } } SectionDividerSpaced() - SectionView(stringResource(MR.strings.found_desktop).uppercase(), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { + SectionView(stringResource(MR.strings.found_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { Text(stringResource(MR.strings.waiting_for_desktop), fontStyle = FontStyle.Italic) } - SectionSpacer() + SectionDividerSpaced() DisconnectButton(stringResource(MR.strings.scan_QR_code).replace('\n', ' '), MR.images.ic_qr_code, ::disconnectDesktop) } @@ -215,7 +214,7 @@ private fun FoundDesktop( sessionAddress: MutableState, ) { AppBarTitle(stringResource(MR.strings.found_desktop)) - SectionView(stringResource(MR.strings.this_device_name).uppercase()) { + SectionView(stringResource(MR.strings.this_device_name)) { DevicesView(deviceName, remoteCtrls) { if (it != "") { setDeviceName(it) @@ -224,7 +223,7 @@ private fun FoundDesktop( } } SectionDividerSpaced() - SectionView(stringResource(MR.strings.found_desktop).uppercase(), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { + SectionView(stringResource(MR.strings.found_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { CtrlDeviceNameText(session, rc) CtrlDeviceVersionText(session) if (!compatible) { @@ -232,7 +231,7 @@ private fun FoundDesktop( } } - SectionSpacer() + SectionDividerSpaced() if (compatible) { SectionItemView({ withBGApi { confirmKnownDesktop(sessionAddress, rc) } }) { @@ -256,19 +255,19 @@ private fun FoundDesktop( @Composable private fun VerifySession(session: RemoteCtrlSession, rc: RemoteCtrlInfo?, sessCode: String, remoteCtrls: SnapshotStateList) { AppBarTitle(stringResource(MR.strings.verify_connection)) - SectionView(stringResource(MR.strings.connected_to_desktop).uppercase(), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { + SectionView(stringResource(MR.strings.connected_to_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { CtrlDeviceNameText(session, rc) Spacer(Modifier.height(DEFAULT_PADDING_HALF)) CtrlDeviceVersionText(session) } - SectionSpacer() + SectionDividerSpaced() - SectionView(stringResource(MR.strings.verify_code_with_desktop).uppercase()) { + SectionView(stringResource(MR.strings.verify_code_with_desktop)) { SessionCodeText(sessCode) } - SectionSpacer() + SectionDividerSpaced() SectionItemView({ verifyDesktopSessionCode(remoteCtrls, sessCode) }) { Icon(painterResource(MR.images.ic_check), generalGetString(MR.strings.confirm_verb), tint = MaterialTheme.colors.secondary) @@ -311,20 +310,20 @@ private fun CtrlDeviceVersionText(session: RemoteCtrlSession) { @Composable private fun ActiveSession(session: RemoteCtrlSession, rc: RemoteCtrlInfo, close: () -> Unit) { AppBarTitle(stringResource(MR.strings.connected_to_desktop)) - SectionView(stringResource(MR.strings.connected_desktop).uppercase(), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { + SectionView(stringResource(MR.strings.connected_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { Text(rc.deviceViewName) Spacer(Modifier.height(DEFAULT_PADDING_HALF)) CtrlDeviceVersionText(session) } if (session.sessionCode != null) { - SectionSpacer() - SectionView(stringResource(MR.strings.session_code).uppercase()) { + SectionDividerSpaced() + SectionView(stringResource(MR.strings.session_code)) { SessionCodeText(session.sessionCode!!) } } - SectionSpacer() + SectionDividerSpaced() SectionView { DisconnectButton { disconnectDesktop(close) } @@ -355,7 +354,7 @@ private fun DevicesView(deviceName: String, remoteCtrls: SnapshotStateList) { - SectionView(stringResource(MR.strings.scan_qr_code_from_desktop).uppercase()) { + SectionView(stringResource(MR.strings.scan_qr_code_from_desktop)) { QRCodeScanner { text -> sessionAddress.value = text connectDesktopAddress(sessionAddress, text) @@ -366,7 +365,7 @@ private fun ScanDesktopAddressView(sessionAddress: MutableState) { @Composable private fun DesktopAddressView(sessionAddress: MutableState) { val clipboard = LocalClipboardManager.current - SectionView(stringResource(MR.strings.desktop_address).uppercase()) { + SectionView(stringResource(MR.strings.desktop_address)) { if (sessionAddress.value.isEmpty()) { SettingsActionItem( painterResource(MR.images.ic_content_paste), @@ -410,7 +409,7 @@ private fun DesktopAddressView(sessionAddress: MutableState) { private fun LinkedDesktopsView(remoteCtrls: SnapshotStateList) { ColumnWithScrollBar { AppBarTitle(stringResource(MR.strings.linked_desktops)) - SectionView(stringResource(MR.strings.desktop_devices).uppercase()) { + SectionView(stringResource(MR.strings.desktop_devices)) { remoteCtrls.forEach { rc -> val showMenu = rememberSaveable { mutableStateOf(false) } SectionItemViewLongClickable(click = {}, longClick = { showMenu.value = true }) { @@ -427,7 +426,7 @@ private fun LinkedDesktopsView(remoteCtrls: SnapshotStateList) { } SectionDividerSpaced() - SectionView(stringResource(MR.strings.linked_desktop_options).uppercase()) { + SectionView(stringResource(MR.strings.linked_desktop_options)) { PreferenceToggle(stringResource(MR.strings.verify_connections), checked = remember { controller.appPrefs.confirmRemoteSessions.state }.value) { controller.appPrefs.confirmRemoteSessions.set(it) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt index 1d01ab11ff..8caf038481 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt @@ -92,7 +92,7 @@ fun ConnectMobileLayout( ) { ColumnWithScrollBar { AppBarTitle(stringResource(if (remember { chatModel.remoteHosts }.isEmpty()) MR.strings.link_a_mobile else MR.strings.linked_mobiles)) - SectionView(generalGetString(MR.strings.this_device_name).uppercase()) { + SectionView(generalGetString(MR.strings.this_device_name)) { DeviceNameField(deviceName.value ?: "") { updateDeviceName(it) } SectionTextFooter(generalGetString(MR.strings.this_device_name_shared_with_mobile)) PreferenceToggle(stringResource(MR.strings.multicast_discoverable_via_local_network), checked = remember { controller.appPrefs.offerRemoteMulticast.state }.value) { @@ -100,7 +100,7 @@ fun ConnectMobileLayout( } SectionDividerSpaced() } - SectionView(stringResource(MR.strings.devices).uppercase()) { + SectionView(stringResource(MR.strings.devices)) { if (chatModel.localUserCreated.value == true) { SettingsActionItemWithContent(text = stringResource(MR.strings.this_device), icon = painterResource(MR.images.ic_desktop), click = connectDesktop) { if (connectedHost.value == null) { @@ -215,7 +215,7 @@ private fun ConnectMobileViewLayout( Spacer(Modifier.height(DEFAULT_PADDING)) } if (deviceName != null || sessionCode != null) { - SectionView(stringResource(MR.strings.connected_mobile).uppercase()) { + SectionView(stringResource(MR.strings.connected_mobile)) { SelectionContainer { Text( deviceName ?: stringResource(MR.strings.new_mobile_device), @@ -228,7 +228,7 @@ private fun ConnectMobileViewLayout( } if (sessionCode != null) { - SectionView(stringResource(MR.strings.verify_code_on_mobile).uppercase()) { + SectionView(stringResource(MR.strings.verify_code_on_mobile)) { SelectionContainer { Text( sessionCode.substring(0, 23), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt index e24c09afd0..1c9e602f1b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Appearance.kt @@ -1,11 +1,13 @@ package chat.simplex.common.views.usersettings +import CARD_PADDING +import LocalCardScreen import SectionBottomSpacer import SectionDividerSpaced import SectionItemView +import itemHPadding import SectionItemViewSpaceBetween import SectionItemViewWithoutMinPadding -import SectionSpacer import SectionView import androidx.compose.foundation.* import androidx.compose.foundation.interaction.MutableInteractionSource @@ -58,9 +60,9 @@ expect fun AppearanceView(m: ChatModel) object AppearanceScope { @Composable fun ProfileImageSection() { - SectionView(stringResource(MR.strings.settings_section_title_profile_images).uppercase(), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { + SectionView(stringResource(MR.strings.settings_section_title_profile_images), contentPadding = PaddingValues(horizontal = CARD_PADDING)) { val image = remember { chatModel.currentUser }.value?.image - Row(Modifier.padding(top = 10.dp), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) { + Row(Modifier.padding(vertical = 10.dp), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) { val size = 60 Box(Modifier.offset(x = -(size / 12).dp)) { if (!image.isNullOrEmpty()) { @@ -91,9 +93,10 @@ object AppearanceScope { @Composable fun AppToolbarsSection() { BoxWithConstraints { - SectionView(stringResource(MR.strings.appearance_app_toolbars).uppercase()) { + SectionView(stringResource(MR.strings.appearance_app_toolbars)) { SectionItemViewWithoutMinPadding { Box(Modifier.weight(1f)) { + var fontScale by remember { mutableStateOf(1f) } Text( stringResource(MR.strings.appearance_in_app_bars_alpha), Modifier.clickable( @@ -102,7 +105,9 @@ object AppearanceScope { ) { appPrefs.inAppBarsAlpha.set(appPrefs.inAppBarsDefaultAlpha) }, - maxLines = 1 + maxLines = 1, + fontSize = MaterialTheme.typography.body1.fontSize * fontScale, + onTextLayout = { if (it.hasVisualOverflow && fontScale > 0.5f) fontScale -= 0.05f } ) } Spacer(Modifier.padding(end = 10.dp)) @@ -175,7 +180,7 @@ object AppearanceScope { @Composable fun MessageShapeSection() { BoxWithConstraints { - SectionView(stringResource(MR.strings.settings_section_title_message_shape).uppercase()) { + SectionView(stringResource(MR.strings.settings_section_title_message_shape)) { SectionItemViewWithoutMinPadding { Text(stringResource(MR.strings.settings_message_shape_corner), Modifier.weight(1f)) Spacer(Modifier.width(10.dp)) @@ -205,8 +210,8 @@ object AppearanceScope { @Composable fun FontScaleSection() { val localFontScale = remember { mutableStateOf(appPrefs.fontScale.get()) } - SectionView(stringResource(MR.strings.appearance_font_size).uppercase(), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { - Row(Modifier.padding(top = 10.dp), verticalAlignment = Alignment.CenterVertically) { + SectionView(stringResource(MR.strings.appearance_font_size), contentPadding = PaddingValues(horizontal = CARD_PADDING)) { + Row(Modifier.padding(vertical = 10.dp), verticalAlignment = Alignment.CenterVertically) { Box(Modifier.size(50.dp) .background(MaterialTheme.colors.surface, RoundedCornerShape(percent = 22)) .clip(RoundedCornerShape(percent = 22)) @@ -409,26 +414,29 @@ object AppearanceScope { } if (appPlatform.isDesktop) { - val itemWidth = (DEFAULT_START_MODAL_WIDTH * fontSizeSqrtMultiplier - DEFAULT_PADDING * 2 - DEFAULT_PADDING_HALF * 3) / 4 - val itemHeight = (DEFAULT_START_MODAL_WIDTH * fontSizeSqrtMultiplier - DEFAULT_PADDING * 2) / 4 + val gridPadding = 12.dp + val cardPadding = if (LocalCardScreen.current) CARD_PADDING * 2 else 0.dp + val itemSize = (DEFAULT_START_MODAL_WIDTH * fontSizeSqrtMultiplier - cardPadding - gridPadding * 5) / 4 val rows = ceil((PresetWallpaper.entries.size + 2) / 4f).roundToInt() LazyVerticalGrid( columns = GridCells.Fixed(4), - Modifier.height(itemHeight * rows + DEFAULT_PADDING_HALF * (rows - 1) + DEFAULT_PADDING * 2), - contentPadding = PaddingValues(DEFAULT_PADDING), - verticalArrangement = Arrangement.spacedBy(DEFAULT_PADDING_HALF), - horizontalArrangement = Arrangement.spacedBy(DEFAULT_PADDING_HALF), + Modifier.height(itemSize * rows + gridPadding * (rows + 1)), + contentPadding = PaddingValues(gridPadding), + verticalArrangement = Arrangement.spacedBy(gridPadding), + horizontalArrangement = Arrangement.spacedBy(gridPadding), ) { - gridContent(itemWidth, itemHeight) + gridContent(itemSize, itemSize) } } else { - LazyHorizontalGrid( + val gridPadding = 14.dp + val itemSize = 81.dp + LazyHorizontalGrid( rows = GridCells.Fixed(1), - Modifier.height(80.dp + DEFAULT_PADDING * 2), - contentPadding = PaddingValues(DEFAULT_PADDING), - horizontalArrangement = Arrangement.spacedBy(DEFAULT_PADDING_HALF), + Modifier.height(itemSize + gridPadding * 2), + contentPadding = PaddingValues(gridPadding), + horizontalArrangement = Arrangement.spacedBy(gridPadding), ) { - gridContent(80.dp, 80.dp) + gridContent(itemSize, itemSize) } } } @@ -521,9 +529,7 @@ object AppearanceScope { } SectionView(stringResource(MR.strings.settings_section_title_themes)) { - Spacer(Modifier.height(DEFAULT_PADDING_HALF)) ThemeDestinationPicker(themeUserDestination) - Spacer(Modifier.height(DEFAULT_PADDING_HALF)) val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> if (to != null) onImport(to) @@ -555,7 +561,7 @@ object AppearanceScope { color = if (chatModel.remoteHostId != null && themeUserDestination.value != null) MaterialTheme.colors.secondary else MaterialTheme.colors.primary ) } - SectionSpacer() + SectionDividerSpaced() } val state: State = remember(appPrefs.currentTheme.get()) { @@ -584,23 +590,23 @@ object AppearanceScope { } saveThemeToDatabase(null) } - } - SectionItemView(click = { - val user = themeUserDestination.value - if (user == null) { - ModalManager.start.showModal { - val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> - if (to != null) onImport(to) + SectionItemView(click = { + val user = themeUserDestination.value + if (user == null) { + ModalManager.start.showModal(cardScreen = true) { + val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? -> + if (to != null) onImport(to) + } + CustomizeThemeView { onChooseType(it, importWallpaperLauncher) } + } + } else { + ModalManager.start.showModalCloseable(cardScreen = true) { close -> + UserWallpaperEditorModal(chatModel.remoteHostId(), user.first, close) } - CustomizeThemeView { onChooseType(it, importWallpaperLauncher) } - } - } else { - ModalManager.start.showModalCloseable { close -> - UserWallpaperEditorModal(chatModel.remoteHostId(), user.first, close) } + }) { + Text(stringResource(MR.strings.customize_theme_title)) } - }) { - Text(stringResource(MR.strings.customize_theme_title)) } } @@ -626,68 +632,70 @@ object AppearanceScope { ) } - WallpaperPresetSelector( - selectedWallpaper = wallpaperType, - baseTheme = currentTheme.base, - currentColors = { type -> - ThemeManager.currentColors(type, null, null, appPrefs.themeOverrides.get()) - }, - onChooseType = onChooseType - ) - - val type = MaterialTheme.wallpaper.type - if (type is WallpaperType.Image) { - SectionItemView(disabled = chatModel.remoteHostId != null, click = { - val defaultActiveTheme = ThemeManager.defaultActiveTheme(appPrefs.themeOverrides.get()) - ThemeManager.saveAndApplyWallpaper(baseTheme, null) - ThemeManager.removeTheme(defaultActiveTheme?.themeId) - removeWallpaperFile(type.filename) - saveThemeToDatabase(null) - }) { - Text( - stringResource(MR.strings.theme_remove_image), - color = if (chatModel.remoteHostId == null) MaterialTheme.colors.primary else MaterialTheme.colors.secondary - ) - } - SectionSpacer() - } - - SectionView(stringResource(MR.strings.settings_section_title_chat_colors).uppercase()) { - WallpaperSetupView( - wallpaperType, - baseTheme, - MaterialTheme.wallpaper, - MaterialTheme.appColors.sentMessage, - MaterialTheme.appColors.sentQuote, - MaterialTheme.appColors.receivedMessage, - MaterialTheme.appColors.receivedQuote, - editColor = { name -> - editColor(name) - }, - onTypeChange = { type -> - ThemeManager.saveAndApplyWallpaper(baseTheme, type) - saveThemeToDatabase(null) + SectionView { + WallpaperPresetSelector( + selectedWallpaper = wallpaperType, + baseTheme = currentTheme.base, + currentColors = { type -> + ThemeManager.currentColors(type, null, null, appPrefs.themeOverrides.get()) }, + onChooseType = onChooseType ) + val type = MaterialTheme.wallpaper.type + if (type is WallpaperType.Image) { + SectionItemView(disabled = chatModel.remoteHostId != null, click = { + val defaultActiveTheme = ThemeManager.defaultActiveTheme(appPrefs.themeOverrides.get()) + ThemeManager.saveAndApplyWallpaper(baseTheme, null) + ThemeManager.removeTheme(defaultActiveTheme?.themeId) + removeWallpaperFile(type.filename) + saveThemeToDatabase(null) + }) { + Text( + stringResource(MR.strings.theme_remove_image), + color = if (chatModel.remoteHostId == null) MaterialTheme.colors.primary else MaterialTheme.colors.secondary + ) + } + } } SectionDividerSpaced() + WallpaperSetupView( + wallpaperType, + baseTheme, + MaterialTheme.wallpaper, + MaterialTheme.appColors.sentMessage, + MaterialTheme.appColors.sentQuote, + MaterialTheme.appColors.receivedMessage, + MaterialTheme.appColors.receivedQuote, + editColor = { name -> + editColor(name) + }, + onTypeChange = { type -> + ThemeManager.saveAndApplyWallpaper(baseTheme, type) + saveThemeToDatabase(null) + }, + firstSectionTitle = stringResource(MR.strings.settings_section_title_chat_colors), + ) + SectionDividerSpaced() + CustomizeThemeColorsSection(currentTheme) { name -> editColor(name) } - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() val currentOverrides = remember(currentTheme) { ThemeManager.defaultActiveTheme(appPrefs.themeOverrides.get()) } val canResetColors = currentTheme.base.hasChangedAnyColor(currentOverrides) if (canResetColors) { - SectionItemView({ - ThemeManager.resetAllThemeColors() - saveThemeToDatabase(null) - }) { - Text(generalGetString(MR.strings.reset_color), color = colors.primary) + SectionView { + SectionItemView({ + ThemeManager.resetAllThemeColors() + saveThemeToDatabase(null) + }) { + Text(generalGetString(MR.strings.reset_color), color = colors.primary) + } } - SectionSpacer() + SectionDividerSpaced() } SectionView { @@ -1007,7 +1015,7 @@ object AppearanceScope { SimpleXThemeOverride(currentColors()) { ChatThemePreview(theme, wallpaperImage, wallpaperType, previewBackgroundColor, previewTintColor) } - SectionSpacer() + SectionDividerSpaced() } var currentColor by remember { mutableStateOf(initialColor) } @@ -1084,7 +1092,7 @@ object AppearanceScope { }) { Text(generalGetString(MR.strings.reset_single_color), color = colors.primary) } - SectionSpacer() + SectionDividerSpaced() } } @@ -1188,75 +1196,82 @@ fun WallpaperSetupView( initialReceivedQuoteColor: Color, editColor: (ThemeColor) -> Unit, onTypeChange: (WallpaperType?) -> Unit, + firstSectionTitle: String? = null, ) { - if (wallpaperType is WallpaperType.Image) { - val state = remember(wallpaperType.scaleType, initialWallpaper?.type) { mutableStateOf(wallpaperType.scaleType ?: (initialWallpaper?.type as? WallpaperType.Image)?.scaleType ?: WallpaperScaleType.FILL) } - val values = remember { - WallpaperScaleType.entries.map { it to generalGetString(it.text) } - } - ExposedDropDownSettingRow( - stringResource(MR.strings.wallpaper_scale), - values, - state, - onSelected = { scaleType -> - onTypeChange(wallpaperType.copy(scaleType = scaleType)) - } - ) - } + val hasWallpaperSettings = wallpaperType is WallpaperType.Preset || wallpaperType is WallpaperType.Image - if (wallpaperType is WallpaperType.Preset || (wallpaperType is WallpaperType.Image && wallpaperType.scaleType == WallpaperScaleType.REPEAT)) { - val state = remember(wallpaperType, initialWallpaper?.type?.scale) { mutableStateOf(wallpaperType.scale ?: initialWallpaper?.type?.scale ?: 1f) } - Row(Modifier.padding(horizontal = DEFAULT_PADDING), verticalAlignment = Alignment.CenterVertically) { - Text("${state.value}".substring(0, min("${state.value}".length, 4)), Modifier.width(50.dp)) - Slider( - state.value, - valueRange = 0.5f..2f, - onValueChange = { - if (wallpaperType is WallpaperType.Preset) { - onTypeChange(wallpaperType.copy(scale = it)) - } else if (wallpaperType is WallpaperType.Image) { - onTypeChange(wallpaperType.copy(scale = it)) - } + if (hasWallpaperSettings) { + SectionView(firstSectionTitle) { + if (wallpaperType is WallpaperType.Image) { + val state = remember(wallpaperType.scaleType, initialWallpaper?.type) { mutableStateOf(wallpaperType.scaleType ?: (initialWallpaper?.type as? WallpaperType.Image)?.scaleType ?: WallpaperScaleType.FILL) } + val values = remember { + WallpaperScaleType.entries.map { it to generalGetString(it.text) } } - ) + ExposedDropDownSettingRow( + stringResource(MR.strings.wallpaper_scale), + values, + state, + onSelected = { scaleType -> + onTypeChange(wallpaperType.copy(scaleType = scaleType)) + } + ) + } + + if (wallpaperType is WallpaperType.Preset || (wallpaperType is WallpaperType.Image && wallpaperType.scaleType == WallpaperScaleType.REPEAT)) { + val state = remember(wallpaperType, initialWallpaper?.type?.scale) { mutableStateOf(wallpaperType.scale ?: initialWallpaper?.type?.scale ?: 1f) } + Row(Modifier.padding(horizontal = DEFAULT_PADDING), verticalAlignment = Alignment.CenterVertically) { + Text("${state.value}".substring(0, min("${state.value}".length, 4)), Modifier.width(50.dp)) + Slider( + state.value, + valueRange = 0.5f..2f, + onValueChange = { + if (wallpaperType is WallpaperType.Preset) { + onTypeChange(wallpaperType.copy(scale = it)) + } else if (wallpaperType is WallpaperType.Image) { + onTypeChange(wallpaperType.copy(scale = it)) + } + } + ) + } + } + + val wallpaperBackgroundColor = initialWallpaper?.background ?: wallpaperType.defaultBackgroundColor(theme, MaterialTheme.colors.background) + SectionItemViewSpaceBetween({ editColor(ThemeColor.WALLPAPER_BACKGROUND) }) { + val title = generalGetString(MR.strings.color_wallpaper_background) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = wallpaperBackgroundColor) + } + val wallpaperTintColor = initialWallpaper?.tint ?: wallpaperType.defaultTintColor(theme) + SectionItemViewSpaceBetween({ editColor(ThemeColor.WALLPAPER_TINT) }) { + val title = generalGetString(MR.strings.color_wallpaper_tint) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = wallpaperTintColor) + } } + SectionDividerSpaced() } - if (wallpaperType is WallpaperType.Preset || wallpaperType is WallpaperType.Image) { - val wallpaperBackgroundColor = initialWallpaper?.background ?: wallpaperType.defaultBackgroundColor(theme, MaterialTheme.colors.background) - SectionItemViewSpaceBetween({ editColor(ThemeColor.WALLPAPER_BACKGROUND) }) { - val title = generalGetString(MR.strings.color_wallpaper_background) + SectionView(if (!hasWallpaperSettings) firstSectionTitle else null) { + SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_MESSAGE) }) { + val title = generalGetString(MR.strings.color_sent_message) Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = wallpaperBackgroundColor) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialSentColor) } - val wallpaperTintColor = initialWallpaper?.tint ?: wallpaperType.defaultTintColor(theme) - SectionItemViewSpaceBetween({ editColor(ThemeColor.WALLPAPER_TINT) }) { - val title = generalGetString(MR.strings.color_wallpaper_tint) + SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_QUOTE) }) { + val title = generalGetString(MR.strings.color_sent_quote) Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = wallpaperTintColor) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialSentQuoteColor) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.RECEIVED_MESSAGE) }) { + val title = generalGetString(MR.strings.color_received_message) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialReceivedColor) + } + SectionItemViewSpaceBetween({ editColor(ThemeColor.RECEIVED_QUOTE) }) { + val title = generalGetString(MR.strings.color_received_quote) + Text(title) + Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialReceivedQuoteColor) } - SectionSpacer() - } - - SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_MESSAGE) }) { - val title = generalGetString(MR.strings.color_sent_message) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialSentColor) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_QUOTE) }) { - val title = generalGetString(MR.strings.color_sent_quote) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialSentQuoteColor) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.RECEIVED_MESSAGE) }) { - val title = generalGetString(MR.strings.color_received_message) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialReceivedColor) - } - SectionItemViewSpaceBetween({ editColor(ThemeColor.RECEIVED_QUOTE) }) { - val title = generalGetString(MR.strings.color_received_quote) - Text(title) - Icon(painterResource(MR.images.ic_circle_filled), title, tint = initialReceivedQuoteColor) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt index dcb71a552d..2c729149d0 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/DeveloperView.kt @@ -4,9 +4,12 @@ import SectionBottomSpacer import SectionDividerSpaced import SectionTextFooter import SectionView +import androidx.compose.foundation.background import androidx.compose.runtime.* +import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler import chat.simplex.common.model.ChatController.appPrefs +import chat.simplex.common.ui.theme.* import chat.simplex.common.platform.* import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource @@ -29,14 +32,14 @@ fun DeveloperView(withAuth: (title: String, desc: String, block: () -> Unit) -> ChatConsoleItem { withAuth(generalGetString(MR.strings.auth_open_chat_console), generalGetString(MR.strings.auth_log_in_using_credential)) { ModalManager.start.showModalCloseable { TerminalView(false) } } } ResetHintsItem(unchangedHints) SettingsPreferenceItem(painterResource(MR.images.ic_code), stringResource(MR.strings.show_developer_options), developerTools) - SectionTextFooter( - generalGetString(if (devTools.value) MR.strings.show_dev_options else MR.strings.hide_dev_options) + " " + - generalGetString(MR.strings.developer_options) - ) } + SectionTextFooter( + generalGetString(if (devTools.value) MR.strings.show_dev_options else MR.strings.hide_dev_options) + " " + + generalGetString(MR.strings.developer_options) + ) if (devTools.value) { - SectionDividerSpaced(maxTopPadding = true) - SectionView(stringResource(MR.strings.developer_options_section).uppercase()) { + SectionDividerSpaced() + SectionView(stringResource(MR.strings.developer_options_section)) { SettingsActionItemWithContent(painterResource(MR.images.ic_breaking_news), stringResource(MR.strings.debug_logs)) { DefaultSwitch( checked = remember { appPrefs.logLevel.state }.value <= LogLevel.DEBUG, @@ -59,15 +62,15 @@ fun DeveloperView(withAuth: (title: String, desc: String, block: () -> Unit) -> SettingsPreferenceItem(painterResource(MR.images.ic_avg_pace), stringResource(MR.strings.show_slow_api_calls), appPreferences.showSlowApiCalls) } } - SectionDividerSpaced(maxTopPadding = true) - SectionView(stringResource(MR.strings.deprecated_options_section).uppercase()) { + SectionDividerSpaced() + SectionView(stringResource(MR.strings.deprecated_options_section)) { val simplexLinkMode = chatModel.controller.appPrefs.simplexLinkMode SimpleXLinkOptions(chatModel.simplexLinkMode, onSelected = { simplexLinkMode.set(it) chatModel.simplexLinkMode.value = it }) - SectionBottomSpacer() } + SectionBottomSpacer() } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HiddenProfileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HiddenProfileView.kt index 55bd796a3b..4a3806ab89 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HiddenProfileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HiddenProfileView.kt @@ -68,7 +68,7 @@ private fun HiddenProfileLayout( val passwordValid by remember { derivedStateOf { hidePassword.value == hidePassword.value.trim() } } val confirmValid by remember { derivedStateOf { confirmHidePassword.value == "" || hidePassword.value == confirmHidePassword.value } } val saveDisabled by remember { derivedStateOf { hidePassword.value == "" || !passwordValid || confirmHidePassword.value == "" || !confirmValid } } - SectionView(stringResource(MR.strings.hidden_profile_password).uppercase()) { + SectionView(stringResource(MR.strings.hidden_profile_password)) { SectionItemViewWithoutMinPadding { PassphraseField(hidePassword, generalGetString(MR.strings.password_to_show), isValid = { passwordValid }, showStrength = true) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NotificationsSettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NotificationsSettingsView.kt index 2fc427cd2e..150b2a38e0 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NotificationsSettingsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NotificationsSettingsView.kt @@ -4,8 +4,11 @@ import SectionBottomSpacer import SectionTextFooter import SectionView import SectionViewSelectable +import androidx.compose.foundation.background import androidx.compose.material.* import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import chat.simplex.common.ui.theme.* import androidx.compose.ui.text.AnnotatedString import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.text.capitalize @@ -74,9 +77,9 @@ fun NotificationsSettingsLayout( color = MaterialTheme.colors.secondary ) } - if (platform.androidIsXiaomiDevice() && (notificationsMode.value == NotificationsMode.PERIODIC || notificationsMode.value == NotificationsMode.SERVICE)) { - SectionTextFooter(annotatedStringResource(MR.strings.xiaomi_ignore_battery_optimization)) - } + } + if (platform.androidIsXiaomiDevice() && (notificationsMode.value == NotificationsMode.PERIODIC || notificationsMode.value == NotificationsMode.SERVICE)) { + SectionTextFooter(annotatedStringResource(MR.strings.xiaomi_ignore_battery_optimization)) } SectionBottomSpacer() } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Preferences.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Preferences.kt index fe9137ee35..63f3491d80 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Preferences.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/Preferences.kt @@ -1,13 +1,15 @@ package chat.simplex.common.views.usersettings import SectionBottomSpacer -import SectionDividerSpaced import SectionItemView +import SectionDividerSpaced import SectionTextFooter import SectionView import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme +import androidx.compose.ui.Modifier +import chat.simplex.common.ui.theme.* import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable @@ -47,6 +49,7 @@ fun PreferencesView(m: ChatModel, user: User, close: () -> Unit,) { if (preferences == currentPreferences) close() else showUnsavedChangesAlert({ savePrefs(close) }, close) }, + cardScreen = true, ) { PreferencesLayout( preferences, @@ -81,27 +84,27 @@ private fun PreferencesLayout( onTTLUpdated = onTTLUpdated ) - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() val allowFullDeletion = remember(preferences) { mutableStateOf(preferences.fullDelete.allow) } FeatureSection(ChatFeature.FullDelete, allowFullDeletion) { applyPrefs(preferences.copy(fullDelete = SimpleChatPreference(allow = it))) } - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() val allowReactions = remember(preferences) { mutableStateOf(preferences.reactions.allow) } FeatureSection(ChatFeature.Reactions, allowReactions) { applyPrefs(preferences.copy(reactions = SimpleChatPreference(allow = it))) } - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() val allowVoice = remember(preferences) { mutableStateOf(preferences.voice.allow) } FeatureSection(ChatFeature.Voice, allowVoice) { applyPrefs(preferences.copy(voice = SimpleChatPreference(allow = it))) } - SectionDividerSpaced(true, maxBottomPadding = false) + SectionDividerSpaced() val allowCalls = remember(preferences) { mutableStateOf(preferences.calls.allow) } FeatureSection(ChatFeature.Calls, allowCalls) { applyPrefs(preferences.copy(calls = SimpleChatPreference(allow = it))) } - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() ResetSaveButtons( reset = reset, save = savePrefs, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt index 2771b5ac62..7316c9bd82 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt @@ -1,10 +1,11 @@ package chat.simplex.common.views.usersettings import SectionBottomSpacer -import SectionDividerSpaced import SectionItemView +import SectionDividerSpaced import SectionTextFooter import SectionView +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* @@ -171,7 +172,7 @@ fun PrivacySettingsView( } if (!chatModel.desktopNoUserNoRemote) { - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() ContacRequestsFromGroupsSection( currentUser = currentUser, setAutoAcceptGrpDirectInvs = { enable -> @@ -179,7 +180,7 @@ fun PrivacySettingsView( } ) - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() DeliveryReceiptsSection( currentUser = currentUser, setOrAskSendReceiptsContacts = { enable -> @@ -619,7 +620,7 @@ fun SimplexLockView( } if (performLA.value && laMode.value == LAMode.PASSCODE) { SectionDividerSpaced() - SectionView(stringResource(MR.strings.self_destruct_passcode).uppercase()) { + SectionView(stringResource(MR.strings.self_destruct_passcode)) { val openInfo = { ModalManager.start.showModal { SelfDestructInfoView() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt index a02d67265d..f17d3a6e4b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt @@ -1,8 +1,9 @@ package chat.simplex.common.views.usersettings import SectionBottomSpacer -import SectionDividerSpaced +import itemHPadding import SectionItemView +import SectionDividerSpaced import SectionView import TextIconSpaced import androidx.compose.desktop.ui.tooling.preview.Preview @@ -46,12 +47,13 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, close: ( user?.displayName, setPerformLA = setPerformLA, showModal = { modalView -> { ModalManager.start.showModal { modalView(chatModel) } } }, - showSettingsModal = { modalView -> { ModalManager.start.showModal(true) { modalView(chatModel) } } }, + showSettingsModal = { modalView -> { ModalManager.start.showModal(settings = true, cardScreen = true) { modalView(chatModel) } } }, showSettingsModalWithSearch = { modalView -> ModalManager.start.showCustomModal { close -> val search = rememberSaveable { mutableStateOf("") } ModalView( { close() }, + cardScreen = true, showSearch = true, searchAlwaysVisible = true, onSearchValueChanged = { search.value = it }, @@ -348,9 +350,9 @@ fun SettingsActionItemWithContent(icon: Painter?, text: String? = null, click: ( click, extraPadding = extraPadding, padding = if (extraPadding && icon != null) - PaddingValues(start = DEFAULT_PADDING * 1.7f, end = DEFAULT_PADDING) + PaddingValues(start = DEFAULT_PADDING * 1.7f, end = itemHPadding) else - PaddingValues(horizontal = DEFAULT_PADDING), + PaddingValues(horizontal = itemHPadding), disabled = disabled ) { if (icon != null) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt index e5c731f3b2..c55eaf6c10 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt @@ -8,6 +8,7 @@ import SectionView import SectionViewWithButton import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.ui.layout.ContentScale import androidx.compose.foundation.shape.RoundedCornerShape @@ -171,7 +172,7 @@ fun UserAddressView( ) } - ModalView(close = close) { + ModalView(close = close, cardScreen = true) { showLayout() } @@ -301,16 +302,16 @@ private fun UserAddressLayout( ) { if (userAddress == null) { if (!onboarding) { - SectionView(generalGetString(MR.strings.for_social_media).uppercase()) { + SectionView(generalGetString(MR.strings.for_social_media)) { CreateAddressButton(createAddress) } SectionDividerSpaced() - SectionView(generalGetString(MR.strings.or_to_share_privately).uppercase()) { + SectionView(generalGetString(MR.strings.or_to_share_privately)) { CreateOneTimeLinkButton() } - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() SectionView { LearnMoreButton(learnMore) } @@ -336,7 +337,7 @@ private fun UserAddressLayout( val savedAddressSettingsState = remember { mutableStateOf(addressSettingsState.value) } SectionViewWithButton( - stringResource(MR.strings.for_social_media).uppercase(), + stringResource(MR.strings.for_social_media), titleButton = if (userAddress.connLinkContact.connShortLink != null) {{ ToggleShortLinkButton(showShortLink) }} else null ) { SimpleXCreatedLinkQRCode(userAddress.connLinkContact, short = showShortLink.value) @@ -353,26 +354,25 @@ private fun UserAddressLayout( // ShareViaEmailButton { sendEmail(userAddress) } BusinessAddressToggle(addressSettingsState) { saveAddressSettings(addressSettingsState.value, savedAddressSettingsState) } AddressSettingsButton(user, userAddress, shareViaProfile, setProfileAddress, saveAddressSettings) - - if (addressSettingsState.value.businessAddress) { - SectionTextFooter(stringResource(MR.strings.add_your_team_members_to_conversations)) - } + } + if (addressSettingsState.value.businessAddress) { + SectionTextFooter(stringResource(MR.strings.add_your_team_members_to_conversations)) } - SectionDividerSpaced(maxTopPadding = addressSettingsState.value.businessAddress) - SectionView(generalGetString(MR.strings.or_to_share_privately).uppercase()) { + SectionDividerSpaced() + SectionView(generalGetString(MR.strings.or_to_share_privately)) { CreateOneTimeLinkButton() } - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() SectionView { LearnMoreButton(learnMore) } - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() SectionView { DeleteAddressButton(deleteAddress) - SectionTextFooter(stringResource(MR.strings.your_contacts_will_remain_connected)) } + SectionTextFooter(stringResource(MR.strings.your_contacts_will_remain_connected)) } } } @@ -495,7 +495,7 @@ private fun ModalData.UserAddressSettings( } } - ModalView(close = { onClose(close) }) { + ModalView(close = { onClose(close) }, cardScreen = true) { ColumnWithScrollBar { AppBarTitle(stringResource(MR.strings.address_settings), hostDevice(user?.remoteHostId)) Column( @@ -512,10 +512,10 @@ private fun ModalData.UserAddressSettings( } SectionDividerSpaced() - SectionView(stringResource(MR.strings.address_welcome_message).uppercase()) { + SectionView(stringResource(MR.strings.address_welcome_message)) { AutoReplyEditor(addressSettingsState) } - SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false) + SectionDividerSpaced() saveAddressSettingsButton(addressSettingsState.value == savedAddressSettingsState.value) { saveAddressSettings(addressSettingsState.value, savedAddressSettingsState) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt index d7ddb6b950..ac21fb6b23 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserProfilesView.kt @@ -1,7 +1,6 @@ package chat.simplex.common.views.usersettings import SectionBottomSpacer -import SectionDivider import SectionItemView import SectionItemViewSpaceBetween import SectionItemViewWithoutMinPadding @@ -177,7 +176,7 @@ private fun UserProfilesLayout( SectionView { for (user in filteredUsers) { UserView(user, visibleUsersCount, activateUser, removeUser, unhideUser, muteUser, unmuteUser, showHiddenProfile) - SectionDivider() + Divider(Modifier.padding(horizontal = 8.dp)) } if (searchTextOrPassword.value.trim().isEmpty()) { SectionItemView(addUser, minHeight = 68.dp) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/AdvancedNetworkSettings.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/AdvancedNetworkSettings.kt index 8c38070c98..42746006a3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/AdvancedNetworkSettings.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/AdvancedNetworkSettings.kt @@ -8,6 +8,7 @@ import SectionTextFooter import SectionView import SectionViewSelectableCards import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* @@ -158,6 +159,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() - }, close) } }, + cardScreen = true, ) { AdvancedNetworkSettingsLayout( currentRemoteHost = currentRemoteHost, @@ -234,13 +236,13 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() - SettingsPreferenceItem(painterResource(MR.images.ic_arrow_forward), stringResource(MR.strings.private_routing_show_message_status), chatModel.controller.appPrefs.showSentViaProxy) } SectionTextFooter(stringResource(MR.strings.private_routing_explanation)) - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() - SectionView(stringResource(MR.strings.network_session_mode_transport_isolation).uppercase()) { + SectionView(stringResource(MR.strings.network_session_mode_transport_isolation)) { SessionModePicker(sessionMode, showModal, updateSessionMode) } SectionDividerSpaced() - SectionView(stringResource(MR.strings.network_smp_web_port_section_title).uppercase()) { + SectionView(stringResource(MR.strings.network_smp_web_port_section_title)) { ExposedDropDownSettingRow( stringResource(MR.strings.network_smp_web_port_toggle), SMPWebPortServers.entries.map { it to stringResource(it.text) }, @@ -251,9 +253,9 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() - if (smpWebPortServers.value == SMPWebPortServers.Preset) stringResource(MR.strings.network_smp_web_port_preset_footer) else String.format(stringResource(MR.strings.network_smp_web_port_footer), if (smpWebPortServers.value == SMPWebPortServers.All) "443" else "5223") ) - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() - SectionView(stringResource(MR.strings.network_option_tcp_connection).uppercase()) { + SectionView(stringResource(MR.strings.network_option_tcp_connection)) { SectionItemView { TimeoutSettingRow( stringResource(MR.strings.network_option_tcp_connection_timeout), networkTCPConnectTimeoutInteractive, @@ -330,7 +332,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() - } } - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() SectionView { SectionItemView(reset, disabled = resetDisabled) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt index 1c68e780dc..ab63067226 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt @@ -149,7 +149,8 @@ fun ChatRelayView( text = generalGetString(MR.strings.check_relay_address) ) } - } + }, + cardScreen = true, ) { ChatRelayLayout( relayToEdit, @@ -182,7 +183,7 @@ private fun ChatRelayLayout( @Composable private fun PresetRelay(relay: MutableState, testing: MutableState) { - SectionView(stringResource(MR.strings.preset_relay_address).uppercase()) { + SectionView(stringResource(MR.strings.preset_relay_address)) { SelectionContainer { Text( relay.value.address, @@ -192,7 +193,7 @@ private fun PresetRelay(relay: MutableState, testing: MutableStat } } SectionDividerSpaced() - SectionView(stringResource(MR.strings.preset_relay_name).uppercase()) { + SectionView(stringResource(MR.strings.preset_relay_name)) { SectionItemView { Text(relay.value.displayName) } @@ -291,7 +292,7 @@ private fun UseRelaySection( testing: MutableState ) { val scope = rememberCoroutineScope() - SectionView(stringResource(MR.strings.use_relay).uppercase()) { + SectionView(stringResource(MR.strings.use_relay)) { SectionItemViewSpaceBetween( click = { testing.value = true @@ -377,7 +378,7 @@ fun ModalData.NewChatRelayView( ModalView(close = { addChatRelay(relayToEdit.value, userServers, serverErrors, serverWarnings, rhId, close) - }) { + }, cardScreen = true) { NewChatRelayLayout(relayToEdit) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/NetworkAndServers.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/NetworkAndServers.kt index a62a58cb10..892a252a9d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/NetworkAndServers.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/NetworkAndServers.kt @@ -9,6 +9,7 @@ import SectionTextFooter import SectionView import SectionViewSelectable import TextIconSpaced +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material.* @@ -84,7 +85,7 @@ fun ModalData.NetworkAndServersView(closeNetworkAndServers: () -> Unit) { onClose(close = { ModalManager.start.closeModals() }) } } - ModalView(close = { onClose(closeNetworkAndServers) }) { + ModalView(close = { onClose(closeNetworkAndServers) }, cardScreen = true) { NetworkAndServersLayout( currentRemoteHost = currentRemoteHost, networkUseSocksProxy = networkUseSocksProxy, @@ -210,7 +211,7 @@ fun ModalData.NetworkAndServersView(closeNetworkAndServers: () -> Unit) { AppBarTitle(stringResource(MR.strings.network_and_servers)) // TODO: Review this and socks. if (!chatModel.desktopNoUserNoRemote) { - SectionView(generalGetString(MR.strings.network_preset_servers_title).uppercase()) { + SectionView(generalGetString(MR.strings.network_preset_servers_title)) { userServers.value.forEachIndexed { index, srv -> srv.operator?.let { ServerOperatorRow(index, it, currUserServers, userServers, serverErrors, serverWarnings, currentRemoteHost?.remoteHostId) } } @@ -262,14 +263,11 @@ fun ModalData.NetworkAndServersView(closeNetworkAndServers: () -> Unit) { UseSocksProxySwitch(networkUseSocksProxy, toggleSocksProxy) SettingsActionItem(painterResource(MR.images.ic_settings_ethernet), stringResource(MR.strings.network_socks_proxy_settings), { showCustomModal { SocksProxySettings(networkUseSocksProxy.value, appPrefs.networkProxy, onionHosts, sessionMode = appPrefs.networkSessionMode.get(), false, it) } }) SettingsActionItem(painterResource(MR.images.ic_cable), stringResource(MR.strings.network_settings), { ModalManager.start.showCustomModal { AdvancedNetworkSettingsView(showModal, it) } }) - if (networkUseSocksProxy.value) { - SectionTextFooter(annotatedStringResource(MR.strings.socks_proxy_setting_limitations)) - SectionDividerSpaced(maxTopPadding = true) - } else { - SectionDividerSpaced(maxBottomPadding = false) - } } } + if (currentRemoteHost == null && networkUseSocksProxy.value) { + SectionTextFooter(annotatedStringResource(MR.strings.socks_proxy_setting_limitations)) + } val saveDisabled = !serversCanBeSaved(currUserServers.value, userServers.value, serverErrors.value) SectionItemView( @@ -303,7 +301,7 @@ fun ModalData.NetworkAndServersView(closeNetworkAndServers: () -> Unit) { if (appPlatform.isAndroid) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.settings_section_title_network_connection).uppercase()) { + SectionView(generalGetString(MR.strings.settings_section_title_network_connection)) { val info = remember { chatModel.networkInfo }.value SettingsActionItemWithContent(icon = null, info.networkType.text) { Icon(painterResource(MR.images.ic_circle_filled), stringResource(MR.strings.icon_descr_server_status_connected), tint = if (info.online) Color.Green else MaterialTheme.colors.error) @@ -466,10 +464,11 @@ fun SocksProxySettings( ) } }, + cardScreen = true, ) { ColumnWithScrollBar { AppBarTitle(generalGetString(MR.strings.network_socks_proxy_settings)) - SectionView(stringResource(MR.strings.network_socks_proxy).uppercase()) { + SectionView(stringResource(MR.strings.network_socks_proxy)) { Column(Modifier.padding(horizontal = DEFAULT_PADDING)) { DefaultConfigurableTextField( hostUnsaved, @@ -495,9 +494,9 @@ fun SocksProxySettings( SectionTextFooter(annotatedStringResource(MR.strings.disable_onion_hosts_when_not_supported)) } - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() - SectionView(stringResource(MR.strings.network_proxy_auth).uppercase()) { + SectionView(stringResource(MR.strings.network_proxy_auth)) { PreferenceToggle( stringResource(MR.strings.network_proxy_random_credentials), checked = proxyAuthRandomUnsaved.value, @@ -526,7 +525,7 @@ fun SocksProxySettings( SectionTextFooter(proxyAuthFooter(usernameUnsaved.value.text, passwordUnsaved.value.text, proxyAuthModeUnsaved.value, sessionMode)) } - SectionDividerSpaced(maxBottomPadding = false, maxTopPadding = true) + SectionDividerSpaced() SectionView { SectionItemView({ diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/OperatorView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/OperatorView.kt index 9e11b9a932..f5bceabbf1 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/OperatorView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/OperatorView.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* +import androidx.compose.foundation.background import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -181,7 +182,7 @@ fun OperatorViewLayout( val duplicateHosts = findDuplicateHosts(serverErrors.value) Column { - SectionView(generalGetString(MR.strings.operator).uppercase()) { + SectionView(generalGetString(MR.strings.operator)) { SectionItemView({ ModalManager.start.showModalCloseable { _ -> OperatorInfoView(operator) } }) { Row( Modifier.fillMaxWidth(), @@ -238,7 +239,7 @@ fun OperatorViewLayout( if (userServers.value[operatorIndex].chatRelays.any { !it.deleted }) { val duplicateRelayAddresses = findDuplicateRelayAddresses(serverErrors.value) SectionDividerSpaced() - SectionView(generalGetString(MR.strings.chat_relays).uppercase()) { + SectionView(generalGetString(MR.strings.chat_relays)) { userServers.value[operatorIndex].chatRelays.forEachIndexed { index, relay -> if (!relay.deleted) { ChatRelayViewLink(relay, duplicateRelayAddresses) { @@ -252,7 +253,7 @@ fun OperatorViewLayout( if (userServers.value[operatorIndex].smpServers.any { !it.deleted }) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.operator_use_for_messages).uppercase()) { + SectionView(generalGetString(MR.strings.operator_use_for_messages)) { SectionItemView(padding = PaddingValues(horizontal = DEFAULT_PADDING)) { Text( stringResource(MR.strings.operator_use_for_messages_receiving), @@ -306,7 +307,7 @@ fun OperatorViewLayout( // Preset servers can't be deleted if (userServers.value[operatorIndex].smpServers.any { it.preset }) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.message_servers).uppercase()) { + SectionView(generalGetString(MR.strings.message_servers)) { userServers.value[operatorIndex].smpServers.forEachIndexed { i, server -> if (!server.preset) return@forEachIndexed SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.SMP) }) { @@ -340,7 +341,7 @@ fun OperatorViewLayout( if (userServers.value[operatorIndex].smpServers.any { !it.preset && !it.deleted }) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.operator_added_message_servers).uppercase()) { + SectionView(generalGetString(MR.strings.operator_added_message_servers)) { userServers.value[operatorIndex].smpServers.forEachIndexed { i, server -> if (server.deleted || server.preset) return@forEachIndexed SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.SMP) }) { @@ -356,7 +357,7 @@ fun OperatorViewLayout( if (userServers.value[operatorIndex].xftpServers.any { !it.deleted }) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.operator_use_for_files).uppercase()) { + SectionView(generalGetString(MR.strings.operator_use_for_files)) { SectionItemView(padding = PaddingValues(horizontal = DEFAULT_PADDING)) { Text( stringResource(MR.strings.operator_use_for_sending), @@ -389,7 +390,7 @@ fun OperatorViewLayout( // Preset servers can't be deleted if (userServers.value[operatorIndex].xftpServers.any { it.preset }) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.media_and_file_servers).uppercase()) { + SectionView(generalGetString(MR.strings.media_and_file_servers)) { userServers.value[operatorIndex].xftpServers.forEachIndexed { i, server -> if (!server.preset) return@forEachIndexed SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.XFTP) }) { @@ -423,7 +424,7 @@ fun OperatorViewLayout( if (userServers.value[operatorIndex].xftpServers.any { !it.preset && !it.deleted}) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.operator_added_xftp_servers).uppercase()) { + SectionView(generalGetString(MR.strings.operator_added_xftp_servers)) { userServers.value[operatorIndex].xftpServers.forEachIndexed { i, server -> if (server.deleted || server.preset) return@forEachIndexed SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.XFTP) }) { @@ -490,7 +491,7 @@ fun OperatorInfoView(serverOperator: ServerOperator) { } } - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() val uriHandler = LocalUriHandler.current SectionView { @@ -507,7 +508,7 @@ fun OperatorInfoView(serverOperator: ServerOperator) { val selfhost = serverOperator.info.selfhost if (selfhost != null) { - SectionDividerSpaced(maxBottomPadding = false) + SectionDividerSpaced() SectionView { SectionItemView { val (text, link) = selfhost diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServerView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServerView.kt index 01630a2b52..b3326bd2e9 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServerView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServerView.kt @@ -5,6 +5,7 @@ import SectionDividerSpaced import SectionItemView import SectionItemViewSpaceBetween import SectionView +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material.* @@ -80,7 +81,8 @@ fun ProtocolServerView( ) } } - } + }, + cardScreen = true, ) { Box { ProtocolServerLayout( @@ -140,7 +142,7 @@ private fun PresetServer( testing: Boolean, testServer: () -> Unit ) { - SectionView(stringResource(MR.strings.smp_servers_preset_address).uppercase()) { + SectionView(stringResource(MR.strings.smp_servers_preset_address)) { SelectionContainer { Text( server.value.server, @@ -172,7 +174,7 @@ fun CustomServer( } } SectionView( - stringResource(MR.strings.smp_servers_your_server_address).uppercase(), + stringResource(MR.strings.smp_servers_your_server_address), icon = painterResource(MR.images.ic_error), iconTint = if (!valid.value) MaterialTheme.colors.error else Color.Transparent, ) { @@ -190,13 +192,13 @@ fun CustomServer( } } } - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() UseServerSection(server, valid.value, testing, testServer, onDelete) if (valid.value) { SectionDividerSpaced() - SectionView(stringResource(MR.strings.smp_servers_add_to_another_device).uppercase()) { + SectionView(stringResource(MR.strings.smp_servers_add_to_another_device)) { QRCode(serverAddress.value, small = true) } } @@ -210,7 +212,7 @@ private fun UseServerSection( testServer: () -> Unit, onDelete: (() -> Unit)? = null, ) { - SectionView(stringResource(MR.strings.smp_servers_use_server).uppercase()) { + SectionView(stringResource(MR.strings.smp_servers_use_server)) { SectionItemViewSpaceBetween(testServer, disabled = !valid || testing) { Text(stringResource(MR.strings.smp_servers_test_server), color = if (valid && !testing) MaterialTheme.colors.onBackground else MaterialTheme.colors.secondary) ShowTestStatus(server.value) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServersView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServersView.kt index 3be2456b72..280cd7bedb 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServersView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ProtocolServersView.kt @@ -7,9 +7,11 @@ import SectionItemView import SectionTextFooter import SectionView import androidx.compose.foundation.layout.* +import androidx.compose.foundation.background import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import chat.simplex.common.ui.theme.* import androidx.compose.ui.platform.LocalUriHandler import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource @@ -86,7 +88,7 @@ fun YourServersViewLayout( Column { if (userServers.value[operatorIndex].chatRelays.any { !it.deleted }) { val duplicateRelayAddresses = findDuplicateRelayAddresses(serverErrors.value) - SectionView(generalGetString(MR.strings.chat_relays).uppercase()) { + SectionView(generalGetString(MR.strings.chat_relays)) { userServers.value[operatorIndex].chatRelays.forEachIndexed { i, relay -> if (relay.deleted) return@forEachIndexed ChatRelayViewLink(relay, duplicateRelayAddresses) { @@ -99,7 +101,7 @@ fun YourServersViewLayout( if (userServers.value[operatorIndex].smpServers.any { !it.deleted }) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.message_servers).uppercase()) { + SectionView(generalGetString(MR.strings.message_servers)) { userServers.value[operatorIndex].smpServers.forEachIndexed { i, server -> if (server.deleted) return@forEachIndexed SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.SMP) }) { @@ -133,7 +135,7 @@ fun YourServersViewLayout( if (userServers.value[operatorIndex].xftpServers.any { !it.deleted }) { SectionDividerSpaced() - SectionView(generalGetString(MR.strings.media_and_file_servers).uppercase()) { + SectionView(generalGetString(MR.strings.media_and_file_servers)) { userServers.value[operatorIndex].xftpServers.forEachIndexed { i, server -> if (server.deleted) return@forEachIndexed SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.XFTP) }) { @@ -170,7 +172,7 @@ fun YourServersViewLayout( userServers.value[operatorIndex].xftpServers.any { !it.deleted } || userServers.value[operatorIndex].chatRelays.any { !it.deleted } ) { - SectionDividerSpaced(maxTopPadding = false, maxBottomPadding = false) + SectionDividerSpaced() } SectionView { @@ -195,7 +197,7 @@ fun YourServersViewLayout( ServersWarningFooter(serversWarn) } } - SectionDividerSpaced(maxTopPadding = false, maxBottomPadding = false) + SectionDividerSpaced() SectionView { TestServersButton( diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml index 95ec53287a..36744ad503 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml @@ -1091,7 +1091,7 @@ للاتصال، يمكن لجهة الاتصال مسح رمز QR أو استخدام الرابط في التطبيق. اختبر الخوادم لا معرّفات مُستخدم - دعم SIMPLEX CHAT + دعم SimpleX Chat بدِّل العنوان الرئيسي سيتم وضع علامة على الرسالة على أنها تحت الإشراف لجميع الأعضاء. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index 375edecd44..e5d313e9ed 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -1101,7 +1101,7 @@ Off Appearance Customize theme - INTERFACE COLORS + Interface colors App version App version: v%s App build: %s @@ -1537,26 +1537,26 @@ Open clean link - YOU - SETTINGS - CHAT DATABASE - HELP - SUPPORT SIMPLEX CHAT - APP - DEVICE - CHATS - FILES - SEND DELIVERY RECEIPTS TO - CONTACT REQUESTS FROM GROUPS + You + Settings + Chat database + Help + Support SimpleX Chat + App + Device + Chats + Files + Send delivery receipts to + Contact requests from groups Restart Shutdown Developer tools Experimental features - SOCKS PROXY - INTERFACE + SOCKS proxy + Interface LANGUAGE - APP ICON - THEMES + App icon + Themes Profile images Message shape Corner @@ -1564,21 +1564,21 @@ Chat theme Profile theme Chat colors - MESSAGES AND FILES - PRIVATE MESSAGE ROUTING - CALLS + Messages and files + Private message routing + Calls Network connection Incognito mode - EXPERIMENTAL + Experimental Use from desktop Your chat database - RUN CHAT + Run chat Remote mobiles Chat is running Chat is stopped - CHAT DATABASE + Chat database Database passphrase Export database Import database @@ -1887,7 +1887,7 @@ Invite members Add team members Add friends - %1$s MEMBERS + %1$s members you: %1$s Delete group Delete channel @@ -1940,7 +1940,7 @@ Chat relays - FOR CONSOLE + For console Local name Database ID Debug delivery @@ -2010,7 +2010,7 @@ disabled failed inactive - MEMBER + Member Role Change role Change @@ -2027,7 +2027,7 @@ Group Chat Connection - CONNECTION FAILED + Connection failed direct indirect (%1$s) Message queue info @@ -2056,7 +2056,7 @@ Message too large - SERVERS + Servers Receiving via Sending via Network status @@ -3020,9 +3020,9 @@ Waiting for channel owner to add relays. - RELAY - OWNER - SUBSCRIBER + Relay + Owner + Subscriber Channel Relay link Relay address @@ -3096,6 +3096,6 @@ Quit SimpleX SimpleX SimpleX — %d unread - Minimize to tray when closing window - Keep SimpleX running in the background to receive messages. + Close to tray + Runs in background to receive messages \ No newline at end of file diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml index c691447b32..890720a727 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/bg/strings.xml @@ -83,7 +83,7 @@ Android Keystore се използва за сигурно съхраняване на паролата - тоа позволява на услугата за известия да работи. Създаен беше празен профил за чат с предоставеното име и приложението се отвари както обикновено. Приложението може да получава известия само когато работи, няма да се стартира услуга във фонов режим - ИКОНА НА ПРИЛОЖЕНИЕТО + Икона на приложението Идентифицирай Оптимизацията на батерията е активна, изключват се фоновата услуга и периодичните заявки за нови съобщения. Можете да ги активирате отново през настройките. за всеки чат профил, който имате в приложението.]]> @@ -169,13 +169,13 @@ чрез реле видео разговор Вашите обаждания - ПРИЛОЖЕНИЕ + Приложение Резервно копие на данните от приложението Кода за достъп до приложение се заменя с код за самоунищожение. Автоматично приемане на изображения Идентификацията е отменена Изпрати визуализация на линковете - ОБАЖДАНИЯ + Обаждания Android Keystore ще се използва за сигурно съхраняване на паролата, след като рестартирате приложението или промените паролата - това ще позволи получаването на известия. Промяна на паролата на базата данни\? променена ролята от %s на %s @@ -223,7 +223,7 @@ Базата данни е изтрита Чатът работи Чатът е спрян - БАЗА ДАННИ + База данни Базата данни е импортирана Потвърди новата парола… Потвърди актуализаациите на базата данни @@ -314,13 +314,13 @@ Промяна на режима на заключване Промени режима на самоунищожение Промени кода за достъп за самоунищожение - ЧАТОВЕ + Чатове промяна на адреса… В момента максималният поддържан размер на файла е %1$s. ID в базата данни ID в базата данни: %d Контакти - ТЕМИ + Теми Базата данни е криптирана с автоматично генерирана парола. Моля, променете я преди експортиране. Парола за базата данни Изтрий базата данни @@ -406,7 +406,7 @@ Идентификатори в базата данни и опция за изолация на транспорта. Изтрий адрес Изтрий адрес\? - ЦВЕТОВЕ НА ИНТЕРФЕЙСА + Цветове на интерфейса Създай Създай профил Изтрий изображение @@ -446,7 +446,7 @@ Активирай потвърждениeто\? Изпращането на потвърждениe за доставка е деактивирано за %d контакта Изпращането на потвърждениe е активирано за %d контакта - УСТРОЙСТВО + Устройство Деактивиране (запазване на промените) %d файл(а) с общ размер от %s Криптирай @@ -485,7 +485,7 @@ Те могат да бъдат променени в настройките за всеки контакт и група. Инструменти за разработчици Деактивиране за всички - ИЗПРАЩАЙТЕ ПОТВЪРЖДЕНИE ЗА ДОСТАВКА НА + Изпращайте потвърждениe за доставка на Изтрий съобщенията след %s секунда(и) Изтрий съобщенията @@ -622,7 +622,7 @@ Пълно име: Изход без запазване Парола за скрит профил - ЕКСПЕРИМЕНТАЛЕН + Експериментален Файл: %s Разшири избора на роля Поправи връзката\? @@ -632,7 +632,7 @@ Изпратените съобщения ще бъдат изтрити след зададеното време. Групов линк Файлове и медия - ЗА КОНЗОЛАТА + За конзолата Групови настройки Файл Файлът не е намерен @@ -643,7 +643,7 @@ Филтрирайте непрочетените и любимите чатове. Членовете могат да изпращат лични съобщения. помощ - ПОМОЩ + Помощ Здравей, \nСвържи се с мен през SimpleX Chat: %s Членовете могат да добавят реакции към съобщенията. @@ -805,7 +805,7 @@ Когато приложението работи Периодично Постави получения линк - СЪОБЩЕНИЯ И ФАЙЛОВЕ + Съобщения и файлове Няма получени или изпратени файлове Известията ще се доставят само докато приложението не е спряно! Премахване на парола от Keystore\? @@ -987,7 +987,7 @@ Режим на заключване Моля, докладвайте го на разработчиците. Защити екрана на приложението - ЧЛЕН + Член Премахване PING бройка Само вашият контакт може да добавя реакции на съобщенията. @@ -1042,8 +1042,8 @@ Сподели с контактите Спри споделянето Спри споделянето на адреса\? - НАСТРОЙКИ - СТАРТИРАНЕ НА ЧАТ + Настройки + Стартиране на чат Задай име на контакт… Няма информация за доставката Отзови файл\? @@ -1067,7 +1067,7 @@ Изпращането на потвърждениe за доставка е разрешено за %d групи Рестартирайте приложението, за да използвате импортирана база данни. Тази група има над %1$d членове, потвърждениeто за доставка няма да се изпраща. - СЪРВЪРИ + Сървъри %s: %s Доставка Активиране (запазване на груповите промени) @@ -1093,7 +1093,7 @@ Сподели медия… SimpleX адрес Сигурността на SimpleX Chat беше одитирана от Trail of Bits. - SOCKS ПРОКСИ + SOCKS прокси Рестартиране Изключване Рестартирайте приложението, за да създадете нов чат профил. @@ -1152,7 +1152,7 @@ Заглавие (за споделяне с вашия контакт) Тази група вече не съществува. - ПОДКРЕПЕТЕ SIMPLEX CHAT + Подкрепете SimpleX Chat Вашият контакт изпрати файл, който е по-голям от поддържания в момента максимален размер (%1$s). Тази функция все още не се поддържа. Опитайте следващата версия. Докосни за започване на нов чат @@ -1231,7 +1231,7 @@ адреса за получаване е променен Можете да споделите този адрес с вашите контакти, за да им позволите да се свържат с %s. Премахни от любимите - ВИЕ + Вие Вашата база данни Изчаква се получаването на изображението Изчаква се получаването на изображението @@ -1775,7 +1775,7 @@ За да защити вашия IP адрес, поверително рутиране използва вашите SMP сървъри за доставяне на съобщения. Препращане на съобщенията без файловете? Неизвестни сървъри - ФАЙЛОВЕ + Файлове Показване на списъка на чатовете в нов прозорец Системна Тъмна @@ -1800,7 +1800,7 @@ Препращащ сървър: %1$s\nГрешка: %2$s Версията на сървъра е несъвместима с мрежовите настройки. Защити IP адреса - ПОВЕРИТЕЛНО РУТИРАНЕ НА СЪОБЩЕНИЯ + Поверително рутиране на съобщения Приложението ще поиска потвърждение за изтегляния от неизвестни файлови сървъри (с изключение на .onion сървъри или когато SOCKS прокси е активирано). Грешка: %1$s Изтегляне @@ -2038,7 +2038,7 @@ Изтегли %s (%s) Пропусни тази версия Провери за актуализации - БАЗА ДАННИ + База данни Можете да изпращате съобщения до %1$s от архивираните контакти. Достъпен панел Изпращането на съобщения на груповия член не е налично @@ -2501,7 +2501,7 @@ Сподели стар линк Линкът ще бъде кратък и профилът на групата ще бъде споделен чрез него. Обнови групов линк - ЗАЯВКИ ЗА КОНТАКТ ОТ ГРУПИ + Заявки за контакт от групи Членът е изтрит - не може да се приеме заявката заявка за връзка от група %1$s Тази настройка е за текущия профил diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ca/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ca/strings.xml index 7ab3f5a381..c53247853f 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ca/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ca/strings.xml @@ -126,10 +126,10 @@ S\'eliminaran totes les dades de l\'aplicació. Es crea un perfil de xat buit amb el nom proporcionat i l\'aplicació s\'obre com de costum. La contrasenya de l\'aplicació es substitueix per una contrasenya d\'autodestrucció. - APLICACIÓ - ICONA APLICACIÓ + Aplicació + Icona aplicació Desenfocar els mitjans - TRUCADES + Trucades Android Keystore s\'utilitza per emmagatzemar de manera segura la frase de contrasenya: permet que el servei de notificacions funcioni. Android Keystore s\'utilitzarà per emmagatzemar de manera segura la frase de contrasenya després de reiniciar l\'aplicació o canviar la frase de contrasenya; permetrà rebre notificacions. No es pot accedir a Keystore per desar la contrasenya de la base de dades @@ -383,7 +383,7 @@ Desactivar rebuts? Desactivar rebuts per a grups? Eines per a desenvolupadors - DISPOSITIU + Dispositiu La base de dades es xifra amb una contrasenya aleatòria. Si us plau, canvieu-la abans d\'exportar. Contrasenya de la base de dades Voleu suprimir el perfil? @@ -514,8 +514,8 @@ Canvia el mode l\'autodestrucció Canvia el codi d\'autodestrucció Confirmeu el codi d\'accés - BASE DE DADES DELS XATS - XATS + Base de dades dels xats + Xats Tema del xat Colors del xat Base de dades suprimida @@ -551,7 +551,7 @@ Obre a l\'aplicació mòbil.]]> Error en desar els servidors ICE Error en desar el servidor intermediari - BASE DE DADES DELS XATS + Base de dades dels xats El xat s\'està executant El xat està aturat Error: %s @@ -742,7 +742,7 @@ s\'està connectant… Les condicions s\'acceptaran per als operadors habilitats després de 30 dies. SimpleX no pot funcionar en segon pla. Només rebreu les notificacions quan obriu l\'aplicació. - Trucades de SimpleX chat + Trucades de SimpleX Chat Missatges de xat de SimpleX enviat per llegir @@ -781,7 +781,7 @@ Mostra: Amaga: SimpleX - La seguretat de SimpleX chat ha estat auditada per Trail of Bits. + La seguretat de SimpleX Chat ha estat auditada per Trail of Bits. Parlem a SimpleX Chat El nom no és vàlid! cursiva @@ -794,7 +794,7 @@ inactiu Mode clar Grups d\'incògnit - MEMBRE + Membre Voleu unir-vos al grup? Surt Voleu sortir del xat? @@ -966,8 +966,8 @@ Activar els rebuts? Activar autodestrucció Activar els rebuts per a grups? - FITXERS - EXPERIMENTAL + Fitxers + Experimental Exportar base de dades Xifrar Fitxer: %s @@ -981,7 +981,7 @@ Grup no trobat! es requereix renegociar el xifratge grup esborrat - PER A CONSOLA + Per a consola Arreglar connexió? Correcció no suportada per membre del grup Nom complet del grup: @@ -1055,7 +1055,7 @@ Donar permís(os) per fer trucades Auriculars Xifra fitxers locals - AJUT + Ajut Arxius i mitjans Xifrar base de dades? Base de dades xifrada @@ -1109,7 +1109,7 @@ Missatge El missatge és massa llarg! missatge - MISSATGES I FITXERS + Missatges i fitxers Missatges Estat del missatge Estat del missatge: %s @@ -1266,15 +1266,15 @@ L\'enviament de rebuts està desactivat per a %d contactes L\'enviament de rebuts està habilitat per a %d contactes L\'enviament de rebuts està habilitat per a %d grups - ENVIAR ELS REBUS DE LLIURAMENT A + Enviar els rebus de lliurament a L\'enviament de rebuts està desactivat per a %d grups Reiniciar - SERVIDOR INTERMEDIARI SOCKS + Servidor intermediari SOCKS Imatges de perfil - TEMES + Temes Cua Forma del missatge - EXECUTAR SIMPLEX + Executar SimpleX Usar des d\'ordinador Base de dades de xat Importar base de dades @@ -1899,7 +1899,7 @@ Utilitzar servidor intermediari SOCKS? Si disponibles Les vostres credencials es podrien enviar sense xifrar. - COLORS DE LA INTERFÍCIE + Colors de la interfície Alternativa d\'encaminament de missatges Mode d\'encaminament de missatges Obrir ubicació del fitxer @@ -1949,12 +1949,12 @@ Aquesta configuració és per al vostre perfil actual Es pot canviar a la configuració de contacte i grup. No - CONFIGURACIÓ + Configuració Tou Fort - SUPORT SIMPLEX XAT + Suport SimpleX Chat Connexió a la xarxa - ENCAMINAMENT DE MISSATGES PRIVAT + Encaminament de missatges privat mai No s\'han rebut ni enviats fitxers Reinicieu l\'aplicació per crear un perfil de xat nou. @@ -2024,7 +2024,7 @@ Vista prèvia Rebent via Desa i actualitza el perfil del grup - SERVIDORS + Servidors Missatge de benvinguda El missatge de benvinguda és massa llarg Els teus servidors @@ -2183,7 +2183,7 @@ Servidors SMP Servidors XFTP Altaveu - VÓS + Vós %s segon(s) "Heu estat convidat a un grup" %s connectat @@ -2474,7 +2474,7 @@ Compartir l\'enllaç antic L\'enllaç serà curt i el perfil del grup es compartirà a través d\'ell. Actualitzar l\'enllaç del grup - SOL·LICITUDS DE CONTACTE DE GRUPS + Sol·licituds de contacte de grups Membre eliminat(da); no es pot acceptar la sol·licitud. connexió sol·licitada del grup %1$s Aquesta configuració és per al perfil actual diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml index df4907885c..3a97c594b1 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml @@ -40,11 +40,11 @@ Vytvořit odkaz Smazat odkaz\? Odeslat přímou zprávu - ČLEN + Člen Změnit roli ve skupině\? Připoj nepřímé (%1$s) - SERVERY + Servery Příjímáno přes Vytvoření tajné skupiny Zadejte název skupiny: @@ -259,16 +259,16 @@ Reproduktor zapnut Probíhající hovor Automaticky přijímat obrázky - NASTAVENÍ - NÁPOVĚDA - ZAŘÍZENÍ - KONVERZACE + Nastavení + Nápověda + Zařízení + Konverzace Experimentální funkce - SOCKS PROXY - IKONA APLIKACE - TÉMATA - ZPRÁVY A SOUBORY - VOLÁNÍ + SOCKS proxy + Ikona aplikace + Témata + Zprávy a soubory + Volání Export databáze Import databáze Smazat databázi @@ -700,15 +700,15 @@ \n1. Zprávy vypršely v odesílajícím klientovi po 2 dnech nebo na serveru po 30 dnech. \n2. Dešifrování zprávy se nezdařilo, protože vy nebo váš kontakt jste použili starou zálohu databáze. \n3. Spojení je kompromitováno. - VY - PODPOŘIT SIMPLEX CHAT + Vy + Podpořit SimpleX Chat Nástroje pro vývojáře Inkognito mód Vaše chat databáze - SPUSTIT CHAT + Spustit chat Chat je spuštěn Chat je zastaven - DATABÁZE CHATU + Databáze chatu přístupová fráze k databázi Archiv nové databáze Archiv staré databáze @@ -836,7 +836,7 @@ Chyba při vytváření odkazu skupiny Chyba při odstraňování odkazu skupiny Předvolby skupiny mohou měnit pouze vlastníci skupiny. - PRO KONSOLE + Pro konsole Místní název ID databáze Odstranit člena @@ -991,7 +991,7 @@ Zvýšit a otevřít chat Skrýt: Zobrazit možnosti vývojáře - POKUSNÝ + Pokusný Obrázek bude přijat, až kontakt dokončí jeho nahrání. Zobrazit: ID databáze a možnost Izolace přenosu. @@ -1164,7 +1164,7 @@ Když někdo požádá o připojení, můžete žádost přijmout nebo odmítnout. Uživatelské příručce.]]> Adresa SimpleX - BARVY MOTIVU + Barvy motivu Přizpůsobit motiv Aktualizace profilu bude zaslána vašim kontaktům. Sdílet adresu s kontakty? @@ -1301,7 +1301,7 @@ V odpovědi na Žádná historie Časový limit protokolu na KB - ZASLAT POTVRZENÍ O DORUČENÍ NA + Zaslat potvrzení o doručení na Druhé zaškrtnutí jsme přehlédli! ✅ Přijímací adresa bude změněna na jiný server. Změna adresy bude dokončena po připojení odesílatele. Vybrat soubor @@ -1803,8 +1803,8 @@ \nProsím sdělte jakékoli další problémy vývojářům. Ne NEposílejte zprávy přímo, i když váš nebo cílový server nepodporuje soukromé směrování. - SOUBORY - SOUKROMÉ SMĚROVÁNÍ ZPRÁV + Soubory + Soukromé směrování zpráv Téma profilu Přijata odpověď Obnovit barvu @@ -1878,7 +1878,7 @@ Připomenout později Zkontrolovat aktualizace Vypnuto - CHAT DATABÁZE + Chat databáze vypnut info fronty serveru: %1$s\n\nposlední obdržená zpráva: %2$s Uložit a připojit znovu @@ -2362,7 +2362,7 @@ Členové budou odstraněny ze skupiny - toto nelze zvrátit! Odebrat členy? Členové budou odstraněny z chatu - toto nelze zvrátit! - Použitím SimpleX chatu souhlasíte že:\n- ve veřejných skupinách budete zasílat pouze legální obsah.\n- budete respektovat ostatní uživatele – žádný spam. + Použitím SimpleX Chatu souhlasíte že:\n- ve veřejných skupinách budete zasílat pouze legální obsah.\n- budete respektovat ostatní uživatele – žádný spam. Přijmout Zásady ochrany soukromí a podmínky používání. Soukromé konverzace, skupiny a kontakty nejsou přístupné provozovatelům serverů. @@ -2430,7 +2430,7 @@ Otevřít novou skupinu Připojit Připojte se rychleji! 🚀 - POŽADAVKY NA PŘIPOJENÍ ZE SKUPIN + Požadavky na připojení ze skupin kontakt by měl přijmout… Vytvořit vaši adresu Popis příliš dlouhý diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/da/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/da/strings.xml index 38507cc228..9487b85cb3 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/da/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/da/strings.xml @@ -157,7 +157,7 @@ En anden grund Svaropkald Alle kan være vært for servere. - APP + App App løber altid i baggrunden App Build: %s App kan kun modtage meddelelser, når den kører, ingen baggrundstjeneste startes diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml index 8700ade74e..ebe38b2dc7 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml @@ -549,26 +549,26 @@ Linkvorschau senden App-Datensicherung - MEINE DATEN - EINSTELLUNGEN - HILFE - UNTERSTÜTZUNG VON SIMPLEX CHAT - GERÄT - CHATS + Meine Daten + Einstellungen + Hilfe + Unterstützung von SimpleX Chat + Gerät + Chats Entwicklertools Experimentelle Funktionen - SOCKS-PROXY - APP-ICON - DESIGN - NACHRICHTEN und DATEIEN - CALLS + SOCKS-Proxy + App-Icon + Design + Nachrichten und Dateien + Calls Inkognito-Modus Chat-Datenbank - CHAT STARTEN + Chat starten Der Chat läuft Der Chat ist beendet - CHAT-DATENBANK + Chat-Datenbank Datenbank-Passwort Datenbank exportieren Datenbank importieren @@ -747,7 +747,7 @@ Sie versuchen, einen Kontakt, mit dem Sie ein Inkognito-Profil geteilt haben, in die Gruppe einzuladen, in der Sie Ihr Hauptprofil verwenden. Mitglieder einladen - %1$s MITGLIEDER + %1$s Mitglieder Sie: %1$s Gruppe löschen Gruppe löschen? @@ -765,7 +765,7 @@ Fehler beim Löschen des Gruppen-Links Gruppen-Präferenzen können nur von Gruppen-Eigentümern geändert werden. - FÜR KONSOLE + Für Konsole Lokaler Name Datenbank-ID @@ -773,7 +773,7 @@ Direktnachricht senden Das Mitglied wird aus der Gruppe entfernt. Dies kann nicht rückgängig gemacht werden! Entfernen - MITGLIED + Mitglied Rolle Rolle ändern Ändern @@ -788,7 +788,7 @@ direkt indirekt (%1$s) - SERVER + Server Empfangen über Senden über Netzwerkstatus @@ -1065,7 +1065,7 @@ Datenbank-Aktualisierungen bestätigen Anzeigen: Entwickleroptionen anzeigen - EXPERIMENTELL + Experimentell Datenbank-Aktualisierung Unterschiedlicher Migrationsstand in der App/Datenbank: %s / %s Datenbank herabstufen und den Chat öffnen @@ -1189,7 +1189,7 @@ Wenn Personen eine Verbindung anfordern, können Sie diese annehmen oder ablehnen. Sie werden Ihre damit verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen. Design anpassen - INTERFACE-FARBEN + Interface-Farben Fügen Sie die Adresse Ihrem Profil hinzu, damit Ihre SimpleX-Kontakte sie mit anderen Personen teilen können. Es wird eine Profilaktualisierung an Ihre SimpleX-Kontakte gesendet. Alle Ihre Kontakte bleiben verbunden. Es wird eine Profilaktualisierung an Ihre Kontakte gesendet. Erstellen Sie eine Adresse, damit sich Personen mit Ihnen verbinden können. @@ -1309,7 +1309,7 @@ Während des Imports sind nicht schwerwiegende Fehler aufgetreten: Herunterfahren\? Bis zum Neustart der App erhalten Sie keine Benachrichtigungen mehr - APP + App Neustart Herunterfahren Fehler beim Beenden des Adresswechsels @@ -1372,7 +1372,7 @@ Bestätigungen aktivieren\? Das Senden von Bestätigungen an %d Kontakte ist aktiviert Für alle aktivieren - EMPFANGSBESTÄTIGUNGEN SENDEN AN + Empfangsbestätigungen senden an Deaktivieren (vorgenommene Einstellungen bleiben erhalten) Bestätigungen senden Ihre Verbindungen beibehalten @@ -1851,13 +1851,13 @@ Herabstufung erlauben Sie nutzen immer privates Routing. Nachrichten werden nicht direkt versendet, selbst wenn Ihr oder der Ziel-Server kein privates Routing unterstützt. - PRIVATES NACHRICHTEN-ROUTING + Privates Nachrichten-Routing Nachrichten werden direkt versendet, wenn die IP-Adresse geschützt ist, und Ihr oder der Ziel-Server kein privates Routing unterstützt. Nachrichten werden direkt versendet, wenn Ihr oder der Ziel-Server kein privates Routing unterstützt. Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Server genutzt. Sie nutzen privates Routing mit unbekannten Servern, wenn Ihre IP-Adresse nicht geschützt ist. IP-Adresse schützen - DATEIEN + Dateien Die App wird bei unbekannten Datei-Servern nach einer Download-Bestätigung fragen (außer bei .onion oder wenn ein SOCKS-Proxy aktiviert ist). Unbekannte Server! Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für Datei-Server sichtbar sein. @@ -2126,7 +2126,7 @@ Neue Nachricht Bitte überprüfen Sie, ob der SimpleX-Link korrekt ist. Ungültiger Link - CHAT-DATENBANK + Chat-Datenbank Fehler beim Wechseln des Profils Die Nachrichten werden gelöscht. Dies kann nicht rückgängig gemacht werden! Profil teilen @@ -2583,7 +2583,7 @@ Alten Link teilen Der Link wird gekürzt sein, und das Gruppen-Profil wird über den Link geteilt. Gruppen-Link aktualisieren - KONTAKTANFRAGEN VON GRUPPEN + Kontaktanfragen von Gruppen Mitglied ist gelöscht - Anfrage kann nicht angenommen werden Angefragte Verbindung von Gruppe %1$s Diese Einstellung gilt für Ihr aktuelles Profil @@ -2626,7 +2626,7 @@ Sprachnachrichten suchen Videos Sprachnachrichten - VERBINDUNG FEHLGESCHLAGEN + Verbindung fehlgeschlagen Fehlgeschlagen Kanäle, welche Sie erstellt haben oder denen Sie beigetreten sind, werden dauerhaft deaktiviert. %1$d/%2$d Relais aktiv @@ -2695,12 +2695,12 @@ Es sind nicht alle Relais verbunden Kanal öffnen Neuen Kanal öffnen - EIGENTÜMER + Eigentümer Eigentümer Voreingestellte Relais-Adresse Voreingestellter Relais-Name Relais - RELAIS + Relais Relais-Adresse Relais-Adresse Relais-Verbindung fehlgeschlagen @@ -2711,7 +2711,7 @@ Der Server erfordert eine Autorisierung, um eine Verbindung zum Relais herzustellen. Bitte Passwort überprüfen. Serverwarnung Relais-Adresse teilen - ABONNENT + Abonnent Abonnenten Abonnenten verbinden sich über den Relais‑Link mit dem Kanal.\nDie Relais-Adresse wurde zur Einrichtung dieses Relais für diesen Kanal verwendet. Abonnent wird aus dem Kanal entfernt. Dies kann nicht rückgängig gemacht werden! diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/el/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/el/strings.xml index 47cfd90ad6..390913c5f7 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/el/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/el/strings.xml @@ -86,7 +86,7 @@ Ο ΙCE διακομιστής σου Κωδικός πρόσβασης εφαρμογής Αίτημα σύνδεσης θα σταλεί σε αυτό το μέλος της ομάδας. - ΟΙΚΟΝΑ ΕΦΑΡΜΟΓΗΣ + Εικόνα εφαρμογής Εφαρμογή Οι ρυθμίσεις σου Έκδοση εφαρμογής: v%s @@ -105,7 +105,7 @@ Άλλαξε \nΔιαθέσιμο στην έκδοση 5.1 Τέλος κλήσης - ΚΛΗΣΕΙΣ + Κλήσεις Αυτόματη αποδοχή %1$d αποτυχία κρυπτογράφησης μηνύματος αλλαγή διεύθυνσης για %s… @@ -252,7 +252,7 @@ Eνεργοποίηση ήχου Κακό μήνυμα hash Θάμπωση των μέσων - ΒΑΣΗ ΔΕΔΟΜΕΝΩΝ ΣΥΝΟΜΙΛΙΑΣ + Βάση δεδομένων συνομιλίας Το Android Keystore χρησιμοποιείται για την ασφαλή αποθήκευση της φράσης πρόσβασης - επιτρέπει την υπηρεσία ειδοποιήσεων να λειτουργεί. αποκλεισμένος Αποκλεισμένος από τον διαχειριστή @@ -288,7 +288,7 @@ Αρχειοθετημένες επαφές Ακύρωση μεταφοράς Χρώματα συνομιλίας - ΒΑΣΗ ΔΕΔΟΜΕΝΩΝ ΣΥΝΟΜΙΛΙΑΣ + Βάση δεδομένων συνομιλίας Η συνομιλία εκτελείται Παρακαλώ σημείωσε: ΔΕΝ θα μπορείς να ανακτήσεις ή να αλλάξεις τη φράση πρόσβασης εάν τη χάσεις.]]> Αποκλεισμός για όλους @@ -377,7 +377,7 @@ κακό αναγνωριστικό μηνύματος Απάντηση κλήσης Κακό αναγνωριστικό μηνύματος - ΣΥΝΟΜΙΛΙΕΣ + Συνομιλίες Η βάση δεδεδομένων της συνομιλίας εισάχθηκε συμφωνία κρυπτογράφησης για %s… Να επιτραπούν οι κλήσεις; @@ -600,7 +600,7 @@ Κρυμμένη επαφή: Η επαφή διαγράφηκε. η επαφή δεν είναι έτοιμη - ΑΙΤΗΣΕΙΣ ΕΠΑΦΩΝ ΑΠΟ ΟΜΑΔΕΣ + Αιτήσεις επαφών από ομάδες Επαφές η επαφή πρέπει να αποδεχτεί… Η επαφή θα διαγραφεί – αυτή η ενέργεια δεν μπορεί να αναιρεθεί! @@ -759,7 +759,7 @@ Λεπτομέρειες Επιλογές προγραμματιστή Εργαλεία προγραμματιστή - ΣΥΣΚΕΥΗ + Συσκευή Η επαλήθευση συσκευής είναι απενεργοποιημένη. Απενεργοποιείται το SimpleX Lock. Η επαλήθευση συσκευής δεν είναι ενεργοποιημένη. Μπορείς να ενεργοποιήσεις το SimpleX Lock από τις Ρυθμίσεις, αφού πρώτα ενεργοποιήσεις την επαλήθευση συσκευής. Συσκευές @@ -927,7 +927,7 @@ Για όλους τους διαχειριστές για καλύτερη ιδιωτικότητα μεταδεδομένων Για το προφίλ συνομιλίας %s: - ΓΙΑ ΚΟΝΣΟΛΑ + Για κονσόλα Για όλους Για παράδειγμα, αν η επαφή σου λαμβάνει μηνύματα μέσω κάποιου SimpleX Chat διακομιιστή, η εφαρμογή σου θα τα παραδίδει μέσω ενός Flux διακομιστή. Για μένα @@ -986,7 +986,7 @@ Τερματισμός κλήσης Ακουστικά βοήθεια - ΒΟΗΘΕΙΑ + Βοήθεια Βοήθησε τους διαχειριστές να διαχειρίζονται τις ομάδες τους. Γεια σου!\nΣυνδέσου μαζί μου μέσω SimpleX Chat: %s Κρυφό @@ -1069,7 +1069,7 @@ Άμεσες ειδοποιήσεις Άμεσες ειδοποιήσεις! Οι άμεσες ειδοποιήσεις είναι απενεργοποιημένες! - ΧΡΩΜΑΤΑ ΔΙΕΠΑΦΗΣ + Χρώματα διεπαφής Εσωτερικό σφάλμα μη έγκυρη συνομιλία Μη έγκυρος σύνδεσμος @@ -1175,7 +1175,7 @@ Διακομιστές πολυμέσων & αρχείων Μεσαίο μέλος - ΜΕΛΟΣ + Μέλος Μέλος %1$s το μέλος %1$s άλλαξε σε %2$s Εγγραφή μέλους @@ -1219,7 +1219,7 @@ Εναλλακτική δρομολόγηση μηνυμάτων Λειτουργία δρομολόγησης μηνυμάτων Μηνύματα - ΜΗΝΥΜΑΤΑ ΚΑΙ ΑΡΧΕΙΑ + Μηνύματα και αρχεία Διακομιστές μηνυμάτων Θα εμφανιστούν τα μηνύματα από το %s! Θα εμφανιστούν τα μηνύματα από αυτά τα μέλη! @@ -1332,7 +1332,7 @@ Η εικόνα δεν μπορεί να αποκωδικοποιηθεί. Δοκίμασε μια άλλη εικόνα ή επικοινώνησε με τους προγραμματιστές. Ο σύνδεσμος θα είναι σύντομος και το προφίλ της ομάδας θα κοινοποιηθεί μέσω αυτού. Θέμα - ΘΕΜΑΤΑ + Θέματα Τα μηνύματα θα διαγραφούν για όλα τα μέλη. Τα μηνύματα θα επισημαίνονται ως ελεγχόμενα για όλα τα μέλη. Το μήνυμα θα διαγραφεί για όλα τα μέλη. @@ -1582,7 +1582,7 @@ Έξοδος χωρίς αποθήκευση Επέκτεινε Επέκταση επιλογής ρόλου - ΠΕΙΡΑΜΑΤΙΚΟ + Πειραματικό Πειραματικά χαρακτηριστικά έληξε Εξαγωγή της βάσης δεδομένων @@ -1604,7 +1604,7 @@ Το αρχείο δεν βρέθηκε - πιθανότατα το αρχείο διαγράφηκε ή ακυρώθηκε. Αρχείο: %s Αρχεία - ΑΡΧΕΙΑ + Αρχεία Αρχεία και πολυμέσα Απαγορεύονται τα αρχεία και τα πολυμέσα. Τα αρχεία και τα πολυμέσα, απαγορεύονται σε αυτήν τη συνομιλία. @@ -1863,7 +1863,7 @@ Ιδιωτικά ονόματα αρχείων Ιδιωτικά ονόματα αρχείων πολυμέσων. Δρομολόγηση ιδιωτικών μηνυμάτων 🚀 - ΔΡΟΜΟΛΟΓΗΣΗ ΙΔΙΩΤΙΚΩΝ ΜΗΝΥΜΑΤΩΝ + Δρομολόγηση ιδιωτικών μηνυμάτων Ιδιωτικές σημειώσεις Ιδιωτικές σημειώσεις Ιδιωτικές ειδοποιήσεις @@ -2032,7 +2032,7 @@ Ανάκληση αρχείου Ανάκληση αρχείου; Ρόλος - ΕΚΚΙΝΗΣΗ ΣΥΝΟΜΙΛΙΑΣ + Εκκίνηση συνομιλίας Εκτελείται όταν η εφαρμογή είναι ανοιχτή Ασφαλής λήψη αρχείων Ασφαλέστερες ομάδες @@ -2098,7 +2098,7 @@ Απέστειλε Στείλε ένα ζωντανό μήνυμα - θα ενημερώνεται για τον παραλήπτη ή τους παραλήπτες καθώς το πληκτρολογείς. Αποστολή αιτήματος επαφής; - ΑΠΟΣΤΟΛΗ ΑΝΑΦΟΡΩΝ ΠΑΡΑΔΟΣΗΣ ΣΕ + Αποστολή αναφορών παράδοσης σε Αποστολή άμεσου μηνύματος Στείλε άμεσο μήνυμα για να συνδεθείς Αποστολή μηνύματος που εξαφανίζεται @@ -2153,7 +2153,7 @@ πληροφορίες ουράς διακομιστή: %1$s\n\nτελευταίο ληφθέν μήνυμα: %2$s Ο διακομιστής απαιτεί εξουσιοδότηση για τη δημιουργία ουρών, έλεγξε τον κωδικό. Ο διακομιστής απαιτεί εξουσιοδότηση για ανέβασμα αρχείων, έλεγξε τον κωδικό. - ΔΙΑΚΟΜΙΣΤΕΣ + Διακομιστές Πληροφορίες διακομιστών Θα γίνει επαναφορά στα στατιστικά στοιχεία των διακομιστών - αυτή η ενέργεια δεν μπορεί να αναιρεθεί! Η δοκιμή του διακομιστή απέτυχε! @@ -2179,7 +2179,7 @@ Όρισε το εμφανιζόμενο μήνυμα για τα νέα μέλη! Ρυθμίσεις Ρυθμίσεις - ΡΥΘΜΙΣΕΙΣ + Ρυθμίσεις Όρισε τη φράση πρόσβασης της βάσης δεδομένων Διαμόρφωση εικόνων προφίλ Διαμοίρασε @@ -2260,7 +2260,7 @@ Διακομιστής SMP Διακομιστές SMP Διακομιστής μεσολάβησης SOCKS - ΔΙΑΚΟΜΙΣΤΗΣ ΜΕΣΟΛΑΒΗΣΗΣ SOCKS + Διακομιστής μεσολάβησης SOCKS Ρυθμίσεις διακομιστή μεσολάβησης SOCKS Απαλό Κάποιο/α αρχείο/α δεν εξήχθησαν @@ -2309,7 +2309,7 @@ Η εγγραφή αγνοήθηκε %s ανεβασμένα Υποστήριξη bluetooth και άλλων βελτιώσεων. - ΥΠΟΣΤΗΡΙΞΗ SIMPLEX CHAT + Υποστήριξη SimpleX Chat Ενάλλαξε Εναλλαγή ήχου και βίντεο κατά τη διάρκεια της κλήσης. Αλλαγή προφίλ συνομιλίας για προσκλήσεις 1-χρήσης. @@ -2414,7 +2414,7 @@ Ναι Ναι εσύ - ΕΣΥ + Εσύ εσύ: %1$s Αποδέχθηκες τη σύνδεση αποδέχθηκες αυτό το μέλος diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml index 7088c54d9b..6b02074b7d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml @@ -20,7 +20,7 @@ Permites que tus contactos envien mensajes de voz. siempre La aplicación sólo puede recibir notificaciones cuando se está ejecutando. No se iniciará ningún servicio en segundo plano. - ICONO DE LA APLICACIÓN + Icono de la aplicación La optimización de la batería está activa, desactivando el servicio en segundo plano y las solicitudes periódicas de nuevos mensajes. Puedes volver a activarlos en Configuración. El servicio está siempre en funcionamiento en segundo plano. Las notificaciones se muestran en cuanto haya mensajes nuevos. Se puede desactivar en la configuración. En ese caso las notificaciones se seguirán mostrando mientras la aplicación esté en funcionamiento.]]> @@ -200,7 +200,7 @@ Eliminar servidor Introduce tu nombre: conectado - DISPOSITIVO + Dispositivo Contraseña base de datos Eliminar base de datos Eliminar todos los archivos @@ -243,7 +243,7 @@ Core versión: v%s Eliminar imagen Editar imagen - CHATS + Chats Cambiar Se realizan comprobaciones de mensajes nuevos periódicas de hasta un minuto de duración cada 10 minutos Limpiar @@ -274,7 +274,7 @@ Preferencias generales cancelado %s SimpleX está parado - LLAMADAS + Llamadas SimpleX está en ejecución está cambiando de servidor… habla con los desarrolladores @@ -295,7 +295,7 @@ Llamadas en la ventana de bloqueo ¡No se pueden invitar contactos! Consola de Chat - BASE DE DATOS DE SIMPLEX + Base de datos de SimpleX Base de datos eliminada Base de datos importada Comprueba la dirección del servidor e inténtalo de nuevo. @@ -393,15 +393,15 @@ Archivo no encontrado Guía de uso finalizado - AYUDA + Ayuda Exportar base de datos Error al exportar base de datos Error al iniciar Chat se ha unido mediante tu enlace de grupo Error al actualizar enlace de grupo - PARA CONSOLA + Para consola Error al cambiar rol - SERVIDORES + Servidores Nombre del grupo: Preferencias del grupo Los miembros pueden enviar mensajes directos. @@ -455,7 +455,7 @@ \n2. El descifrado ha fallado porque tu o tu contacto estáis usando una copia de seguridad antigua de la base de datos. \n3. La conexión ha sido comprometida. Contacto y texto - MIEMBRO + Miembro nunca No se usarán hosts .onion Vista previa de notificaciones @@ -524,7 +524,7 @@ videollamada (sin cifrar) sin cifrar Importar base de datos - MENSAJES Y ARCHIVOS + Mensajes y archivos ¿Importar base de datos\? Sin archivos recibidos o enviados Mensajes @@ -661,7 +661,7 @@ No se permiten mensajes temporales. Sólo tú puedes enviar mensajes de voz. Sólo tu contacto puede enviar mensajes de voz. - EJECUTAR SIMPLEX + Ejecutar SimpleX Reinicia la aplicación para poder usar la base de datos importada. Introduce la contraseña actual correcta. recepción no permitida @@ -703,8 +703,8 @@ Aislamiento de transporte tachado Abrir SimpleX - PROXY SOCKS - TEMAS + Proxy SOCKS + Temas Parar Esta acción es irreversible. Tu perfil, contactos, mensajes y archivos se perderán. Omitir invitación a miembros @@ -786,7 +786,7 @@ El perfil sólo se comparte con tus contactos. inicializando… Mensajes omitidos - CONFIGURACIÓN + Configuración ¿Parar SimpleX? %s segundo(s) Pulsa para unirte @@ -794,7 +794,7 @@ Timeout de la conexión TCP Tema Establece preferencias de grupo - SOPORTE SIMPLEX CHAT + Soporte SimpleX Chat Escribe la contraseña para exportar Actualizar Actualizar contraseña base de datos @@ -899,7 +899,7 @@ Llamadas Servidores ICE Privacidad - MIS DATOS + Mis datos Base de datos Puedes iniciar el chat en Configuración / Base de datos o reiniciando la aplicación. Has enviado una invitación de grupo @@ -990,7 +990,7 @@ Versión de base de datos incompatible Confirmar actualizaciones de la bases de datos la versión de la base de datos es más reciente que la aplicación, pero no hay migración hacia versión anterior para: %s - EXPERIMENTAL + Experimental IDs de la base de datos y opciones de aislamiento de transporte. El archivo se recibirá cuando el contacto termine de subirlo. La imagen se recibirá cuando el contacto termine de subirla. @@ -1142,7 +1142,7 @@ Mensaje enviado Dejar de compartir ¿Dejar de compartir la dirección\? - COLORES DE LA INTERFAZ + Colores de la interfaz Puedes crearla más tarde ¿Compartir la dirección con los contactos SimpleX? Compartir con contactos SimpleX @@ -1229,7 +1229,7 @@ sin texto Han ocurrido algunos errores no críticos durante la importación: ¿Salir de SimpleX? - APLICACIÓN + Aplicación Reiniciar Salir Las notificaciones dejarán de funcionar hasta que vuelvas a iniciar la aplicación @@ -1291,7 +1291,7 @@ Activar para todos Activar (conservar anulaciones) Desactivar para todos - ENVIAR CONFIRMACIONES DE ENTREGA A + Enviar confirmaciones de entrega a ¡Las confirmaciones de entrega están desactivadas! No activar ¡Error al activar confirmaciones de entrega! @@ -1776,7 +1776,7 @@ Usar siempre enrutamiento privado. Aviso de entrega de mensaje Nunca - ENRUTAMIENTO PRIVADO DE MENSAJES + Enrutamiento privado de mensajes La dirección del servidor es incompatible con la configuración de la red. Con IP desprotegida Clave incorrecta o conexión desconocida - probablemente esta conexión fue eliminada @@ -1787,7 +1787,7 @@ \n%1$s. Proteger dirección IP Sin Tor o VPN, tu dirección IP será visible para los servidores de archivos. - ARCHIVOS + Archivos La aplicación pedirá que confirmes las descargas desde servidores de archivos desconocidos (excepto si son .onion o cuando esté habilitado el proxy SOCKS). Colores del chat Tema del chat @@ -2053,7 +2053,7 @@ Por favor, comprueba que el enlace SimpleX es correcto. %1$d archivo(s) se está(n) descargando todavía. %1$d otro(s) error(es) de archivo. - BASE DE DATOS + Base de datos Error en reenvío de mensajes ¿Reenviar %1$s mensaje(s)? Reenviar mensajes… @@ -2508,7 +2508,7 @@ Compartir enlace antiguo El enlace será corto y el perfil del grupo se compartirá mediante el enlace. Actualizar enlace de grupo - SOLICITUDES DE CONTACTO EN GRUPOS + Solicitudes de contacto en grupos conexión solicitada desde el grupo %1$s Esta configuración se aplica al perfil actual Miembro eliminado, no puede aceptar solicitudes @@ -2597,7 +2597,7 @@ perfil del canal actualizado El canal será eliminado para todos los suscriptores. ¡No puede deshacerse! El canal será eliminado para tí. ¡No puede deshacerse! - CONEXIÓN FALLIDA + Conexión fallida Crear canal público Crear canal público Crear canal público (BETA) @@ -2631,12 +2631,12 @@ Hay servidores no conectados Abrir canal Abrir canal nuevo - PROPIETARIO + Propietario Propietarios Direcciones predefinidas Nombres predefinidos servidor - SERVIDOR + Servidor Dirección servidor Dirección del servidor Enlace servidor @@ -2647,7 +2647,7 @@ El servidor requiere autorización para conectar con el servidor, comprueba la contraseña. Alerta del servidor Compartir dirección del servidor - SUSCRIPTOR + Suscriptor Suscriptores Los suscriptores usan el enlace del servidor para conectarse a los canales.\nLa dirección del servidor se usó para establecer el servidor para el canal. El suscriptor será eliminado del canal. ¡No puede deshacerse! diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml index 3f7d4ff025..a3da005ac6 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fa/strings.xml @@ -781,7 +781,7 @@ خاموش ارسال رسید برای %d گروه فعال است ارسال رسید برای %d گروه غیرفعال است - حمایت از SIMPLEX CHAT + حمایت از SimpleX Chat پروکسی SOCKS استفاده از کامپیوتر آرشیو پایگاه داده جدید diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml index 24634192ec..4753cdb9cf 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fi/strings.xml @@ -39,9 +39,9 @@ Salli lähetettyjen viestien peruuttamaton poistaminen. Salli katoavien viestien lähettäminen. Kaikki tiedot poistetaan, kun se syötetään. - SOVELLUKSEN KUVAKE + Sovelluksen kuvake Sovelluksen tietojen varmuuskopiointi - PUHELUT + Puhelut Pyydettiin videon vastaanottamista Tunnistaudu Tunnistautuminen ei ole käytettävissä @@ -54,7 +54,7 @@ Tietokannan salauksen tunnuslause päivitetään ja tallennetaan Keystoreen. Poista keskusteluprofiili käyttäjälle poistettu - LAITE + Laite %dh Yhteysvirhe Tiedostoa ei voi vastaanottaa @@ -153,7 +153,7 @@ Vaihda itsetuhotilaa Vaihda itsetuhoutuva pääsykoodi Sovelluksen salasana korvataan itsetuhoutuvalla pääsykoodilla. - KESKUSTELUJEN TIETOKANTA + Keskustelujen tietokanta Kehittäjän työkalut Ei pääsyä Keystoreen tietokannan salasanan tallentamiseksi Tietokannan tunnus: %d @@ -308,7 +308,7 @@ Hyväksy kuvat automaattisesti Virheellinen viestin tunniste Vaihda lukitustilaa - KESKUSTELUT + Keskustelut Kaikki ryhmän jäsenet pysyvät yhteydessä. Kontaktia ei voi kutsua! valmis @@ -453,7 +453,7 @@ Virhe käynnistettäessä keskustelua Virhe keskustelun lopettamisessa Virhe asetuksen muuttamisessa - KOKEELLINEN + Kokeellinen Piilota: Kuinka se toimii e2e-salattu videopuhelu @@ -526,7 +526,7 @@ Kuva tallennettu galleriaan Kuva vastaanotetaan, kun kontaktisi on ladannut sen. Tiedosto - APUA + Apua Virhe tietokannan salauksessa Alenna ja avaa chat Ei-aktiivinen ryhmä @@ -576,7 +576,7 @@ Immuuni roskapostille ja väärinkäytöksille Virhe vietäessä keskustelujen tietokantaa Piilota - KONSOLIIN + Konsoliin poistettu ryhmä ryhmäprofiili päivitetty Vanhentunut kutsu! @@ -655,7 +655,7 @@ PING-väli Profiili- ja palvelinyhteydet Aseta ryhmän asetukset - PALVELIMET + Palvelimet Tallenna ja ilmoita kontaktille Tallenna ja ilmoita kontakteille Ohitetut viestit @@ -715,7 +715,7 @@ Itsetuho Itsetuhoutuva pääsykoodi vaihdettu! Itsetuhoutuva pääsykoodi käytössä! - SUKAT VÄLITYSPALVELIN + SOCKS välityspalvelin Uusi tietokanta-arkisto Ei vastaanotettuja tai lähetettyjä tiedostoja Poistetaanko tunnuslause Keystoresta\? @@ -752,7 +752,7 @@ Tallenna ja ilmoita ryhmän jäsenille Lopeta Pysäytä keskustelut viedäksesi, tuodaksesi tai poistaaksesi keskustelujen tietokannan. Et voi vastaanottaa ja lähettää viestejä, kun keskustelut on pysäytetty. - SUORITA CHAT + Suorita chat Aseta tunnuslause vientiä varten Anna oikea nykyinen tunnuslause. Palauta @@ -836,7 +836,7 @@ Avaa SimpleX Chat hyväksyäksesi puhelun ei e2e-salausta TUE SIMPLEX CHATia - VIESTIT JA TIEDOSTOT + Viestit ja tiedostot Jaa osoite Vain paikalliset profiilitiedot Vastaanotettu viesti @@ -867,7 +867,7 @@ OK ei tietoja Kertakutsulinkki - ASETUKSET + Asetukset Uusi tunnuslause… Palauta tietokannan varmuuskopio Tietokannan tunnuslauseen muuttamista ei suoritettu loppuun. @@ -967,7 +967,7 @@ Päivitetty: %s Lähetetty klo Lähetetty: %s - JÄSEN + Jäsen Moderoitu klo: %s %s (nykyinen) Vaihda @@ -1061,7 +1061,7 @@ Hallitset keskustelujasi! Nykyinen profiilisi Profiilisi tallennetaan laitteeseesi ja jaetaan vain kontaktiesi kanssa. SimpleX -palvelimet eivät näe profiiliasi. - TEEMAT + Teemat Tämä asetus koskee nykyisen keskusteluprofiilisi viestejä Tätä toimintoa ei voi kumota - kaikki vastaanotetut ja lähetetyt tiedostot ja media poistetaan. Matalan resoluution kuvat säilyvät. Tuntematon virhe @@ -1116,7 +1116,7 @@ SMP-palvelimesi XFTP-palvelimesi Käytä SimpleX Chat palvelimia\? - KÄYTTÖLIITTYMÄN VÄRIT + Käyttöliittymän värit Päivitä kuljetuksen eristystila\? Voit luoda sen myöhemmin Voit paljastaa piilotetun profiilisi kirjoittamalla koko salasanan Keskusteluprofiilit-sivun hakukenttään. @@ -1151,7 +1151,7 @@ Video lähetetty Odottaa videota Tämä merkkijono ei ole yhteyslinkki! - SINÄ + Sinä Päivitä ja avaa keskustelu Aikavyöhykkeen suojaamiseksi kuva-/äänitiedostot käyttävät UTC:tä. Videot ja tiedostot 1 Gt asti @@ -1228,7 +1228,7 @@ viikkoa Ilmoitukset lakkaavat toimimasta, kunnes käynnistät sovelluksen uudelleen Sulje - SOVELLUS + Sovellus Käynnistä uudelleen Sulje\? Pois @@ -1305,7 +1305,7 @@ Salli kuittaukset\? Kuittauksien lähettäminen on pois käytöstä %d kontakteilta Kuittauksien lähettäminen on käytössä %d kontakteille - LÄHETÄ TOIMITUSKUITTAUKSET VASTAANOTTAJALLE + Lähetä toimituskuittaukset vastaanottajalle turvakoodi on muuttunut hyväksyy salausta… salauksen uudelleenneuvottelu sallittu %s:lle @@ -1465,7 +1465,7 @@ Kamera Avaa asetukset Suojaa IP-osoite - TIEDOSTOT + Tiedostot Profiilikuvat tuntematon Poista jäsen diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml index d95f8ad500..571823140a 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/fr/strings.xml @@ -453,7 +453,7 @@ Consomme davantage de batterie L\'app fonctionne toujours en arrière-plan - les notifications s\'affichent instantanément.]]> %1$d message(s) manqué(s) ID du message incorrect - PARAMÈTRES + Paramètres Cela peut arriver quand : \n1. Les messages ont expiré dans le client expéditeur après 2 jours ou sur le serveur après 30 jours. \n2. Le déchiffrement du message a échoué, car vous ou votre contact avez utilisé une ancienne sauvegarde de base de données. @@ -487,12 +487,12 @@ Appel en cours Appel terminé Votre vie privée - APPAREIL - DISCUSSIONS + Appareil + Discussions Outils du développeur - ICONE DE L\'APP + Icone de l\'app Votre base de données de chat - LANCER LE CHAT + Lancer le chat Arrêter le chat \? Redémarrez l\'application pour utiliser la base de données de chat importée. 1 jour @@ -522,10 +522,10 @@ Appels audio et vidéo chiffré de bout en bout Fonctionnalités expérimentales - SOCKS PROXY - THEMES - MESSAGES ET FICHIERS - APPELS + SOCKS proxy + Themes + Messages et fichiers + Appels Importer la base de données Nouvelle archive de base de données Archives de l\'ancienne base de données @@ -601,13 +601,13 @@ Protéger l\'écran de l\'app Acceptation automatique des images Sauvegarde des données de l\'app - VOUS - AIDE - SOUTENEZ SIMPLEX CHAT + Vous + Aide + Soutenez SimpleX Chat Mode Incognito Le chat est en cours d\'exécution Le chat est arrêté - BASE DE DONNÉES DU CHAT + Base de données du chat Phrase secrète de la base de données Exporter la base de données Arrêter @@ -694,7 +694,7 @@ Créer un lien Modifier le profil du groupe Supprimer - MEMBRE + Membre Message dynamique ! Envoyer un message dynamique Envoyez un message dynamique - il sera mis à jour pour le⸱s destinataire⸱s au fur et à mesure que vous le tapez @@ -708,7 +708,7 @@ Erreur lors de la suppression du lien du groupe Erreur lors de la création du lien du groupe Seuls les propriétaires du groupe peuvent modifier les préférences du groupe. - POUR TERMINAL + Pour terminal Changer le rôle du groupe \? Son rôle est désormais %s. Tous les membres du groupe en seront informés. Contact vérifié⸱e @@ -747,7 +747,7 @@ Messages directs Supprimer pour tous Vous êtes le seul à pouvoir supprimer des messages de manière irréversible (votre contact peut les marquer comme supprimé). (24 heures) - SERVEURS + Serveurs Réception via Système Autoriser l\'envoi de messages directs aux membres. @@ -996,7 +996,7 @@ Afficher les options pour les développeurs Le fichier sera reçu lorsque votre contact aura terminé de le mettre en ligne. IDs de base de données et option d\'isolement du transport. - EXPÉRIMENTALE + Expérimentale Cacher : Dévoiler le profil de chat Dévoiler le profil @@ -1102,7 +1102,7 @@ Vous ne perdrez pas vos contacts si vous supprimez votre adresse ultérieurement. Adresse SimpleX Vous pouvez accepter ou refuser les demandes de contacts. - COULEURS DE L\'INTERFACE + Couleurs de l\'interface Vos contacts resteront connectés. Partager l\'adresse avec vos contacts ? Partager avec vos contacts @@ -1232,7 +1232,7 @@ Arrêt \? Mise à l\'arrêt Redémarrer - APP + App Abandonner Erreur lors de l\'annulation du changement d\'adresse Abandonner le changement d\'adresse \? @@ -1251,7 +1251,7 @@ Les membres peuvent envoyer des fichiers et des médias. Les fichiers et les médias sont interdits. Correction non prise en charge par un membre du groupe - ENVOYER DES ACCUSÉS DE RÉCEPTION AUX + Envoyer des accusés de réception aux Le chiffrement fonctionne et le nouvel accord de chiffrement n\'est pas nécessaire. Cela peut provoquer des erreurs de connexion ! Encore quelques points Justificatifs de réception! @@ -1776,8 +1776,8 @@ Rabattement du routage des messages Afficher le statut du message Protection de l\'adresse IP - FICHIERS - ROUTAGE PRIVÉ DES MESSAGES + Fichiers + Routage privé des messages Erreur au niveau du serveur de destination : %1$s Erreur : %1$s Capacité dépassée - le destinataire n\'a pas pu recevoir les messages envoyés précédemment. @@ -2091,7 +2091,7 @@ Utiliser des identifiants aléatoires Nom d\'utilisateur Les messages seront supprimés - il n\'est pas possible de revenir en arrière ! - BASE DE DONNÉES DU CHAT + Base de données du chat Mode système Serveur De nouveaux identifiants SOCKS seront utilisées pour chaque serveur. @@ -2374,7 +2374,7 @@ Se connecter Se connecter connecté - CONNEXION ÉCHOUÉE + Connexion échouée contact supprimé contact désactivé le contact devrait accepter… @@ -2410,7 +2410,7 @@ rejeté Rejeter le membre? relais - RELAIS + Relais Adresse de relais Adresse de relais Échec de la connexion au relais diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hr/strings.xml index 84e806dda0..55d3e14907 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/hr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/hr/strings.xml @@ -29,7 +29,7 @@ prihvati poziv Dodeliti dozvolu Slušalice - POMOĆ + Pomoć Grupa će biti obrisana za Vas – ovo ne može da se poništi! Akcenat Grupni linkovi @@ -120,15 +120,15 @@ Greška Napravi jednokratnu poveznicu Nalepiti - PODEŠAVANJE + Podešavanje Profilne slike Razumeo Odstranjeno odstranjeno Napraviti - PORUKE I DATOTEKE + Poruke i datoteke Poruka - SERVERI + Serveri Odstraniti profil razgovora administratori Nasumično @@ -240,7 +240,7 @@ Preuzimanje Napredna podešavanja Poziv u toku - POZIVI + Pozivi Blokiraj članove grupe Nepoznati serveri! Datoteka @@ -253,7 +253,7 @@ %d poruka blokirano povezivanje Povezan telefon - VI + Vi Zamućeno za bolju privatnost. %d meseca(i) Poziv završen @@ -295,7 +295,7 @@ %d minut(a) Proveri ažuriranje Stabilno - DATOTEKE + Datoteke %s otpremljeno Onemogućiti obavještenja %s nije verifikovan @@ -312,7 +312,7 @@ Skenirati QR kod Server Onemogućiti - BAZA PODATAKA CHATA + Baza podataka chata onemogućeno Greška pri uvoženju teme Datoteke i medijski sadržaji su zabranjeni. @@ -328,7 +328,7 @@ Ili skenirati QR kod Onemogućeno Aplikacija - RAZGOVORI + Razgovori Datoteke i medijski sadržaji su zabranjeni! Poruke koje nestaju su zabranjene u ovom razgovoru. Chat je zaustavljen @@ -370,7 +370,7 @@ QR kod Chat je pokrenut Uvesti bazu podataka - BAZA PODATAKA CHATA + Baza podataka chata Chat je zaustavljen %s, %s i %d ostali članovi povezani Uvoz neuspešan @@ -428,7 +428,7 @@ SimpleX adresa SimpleX Logo Prikazati: - UREĐAJ + Uređaj Nova poruka Sekundarni Kontakti @@ -474,7 +474,7 @@ Omiljen Nikada Veza - TEME + Teme Audio/video pozivi ne šifrovanje ok @@ -491,7 +491,7 @@ SimpleX Adresa Sačuvati simplexmq: v%s (%2s) - EKSPERIMENTALNO + Eksperimentalno nikada Očistiti Zahvaljujući korisnicima – doprinesi pomoću Weblate! @@ -694,7 +694,7 @@ Izabrati profil razgovora Skenirati QR kod servera Napredna mrežna podešavanja - SOCKS PROXY + SOCKS proxy Anonimni režim broj PING Obnoviti statistiku? @@ -725,7 +725,7 @@ Arhiviraj bazu podataka Periodično Ukloniti - ČLAN + Član Pristupanje grupi SMP server Pozvati u razgovor @@ -986,7 +986,7 @@ Novi server Prikazati procente Napustiti bez čuvanja - POKRENUTI RAZGOVOR + Pokrenuti razgovor Odblokirati člana za sve? Priprema za preuzimanje Proxied(posredovan) @@ -1260,9 +1260,9 @@ Pin kod postavljen! Svi podaci u aplikaciji su odstranjeni. Pin kod aplikacije je zamenjen pin kodom za samouništenje. - POTPORI SIMPLEX CHAT + Potpori SimpleX Chat Oblik poruke - IKONA APLIKACIJE + Ikona aplikacije Pristupna fraza baze podataka Odrediti pristupnu frazu Baza podataka će biti šifrovana. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml index 2df64ae590..e1730a54aa 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml @@ -71,7 +71,7 @@ Továbbfejlesztett csoportok Az összes üzenet törölve lesz – ez a művelet nem vonható vissza! Az üzenetek CSAK az Ön számára törlődnek. A hívás véget ért - HÍVÁSOK + Hívások és további %d esemény Cím A csatlakozás folyamatban van a csoporthoz! @@ -149,13 +149,13 @@ hívás folyamatban Képek automatikus elfogadása A hívások kezdeményezése engedélyezve van a partnerei számára. - ALKALMAZÁSIKON + Alkalmazásikon Kiszolgáló hozzáadása QR-kód beolvasásával. Az eltűnő üzenetek küldése engedélyezve van. Az eltűnő üzenetek küldése csak abban az esetben van engedélyezve, ha a partnere is engedélyezi. Hang kikapcsolva A közvetlen üzenetek küldése a tagok között engedélyezve van. - ALKALMAZÁS + Alkalmazás Hívás folyamatban Mindkét fél hozzáadhat az üzenetekhez reakciókat. Mindkét fél tud hívásokat kezdeményezni. @@ -300,7 +300,7 @@ Hívás kapcsolása Törli a fájlokat és a médiatartalmakat? kész - CSEVEGÉSI ADATBÁZIS + Csevegési adatbázis Önmegsemmisítő jelkód módosítása Várólista létrehozása színezett @@ -313,7 +313,7 @@ kapcsolódás Egyéni időköz Kapcsolódás inkognitóban - CSEVEGÉSEK + Csevegések Új profil létrehozása a számítógépes alkalmazásban. 💻 kapcsolódás (bejelentve) kapcsolódás… @@ -393,7 +393,7 @@ Ne jelenjen meg újra SimpleX-zár kikapcsolása végpontok között titkosított - ESZKÖZ + Eszköz végpontok között titkosított videóhívás közvetlen Számítógép @@ -522,7 +522,7 @@ Akkor is, ha le van tiltva a beszélgetésben. Gyorsabb csatlakozás és megbízhatóbb üzenetkézbesítés. Zárolás engedélyezése - SÚGÓ + Súgó Teljesen decentralizált – csak a tagok számára látható. Fájl: %s Hívás befejezése @@ -530,7 +530,7 @@ Fájl mentve Kapcsolat javítása? Fájlok és médiatartalmak - KONZOLHOZ + Konzolhoz Nem sikerült a titkosítást újraegyeztetni. Hiba történt a felhasználói profil törlésekor Csoporttag általi javítás nem támogatott @@ -579,7 +579,7 @@ A csoport teljes neve: súgó Önmegsemmisítő jelkód engedélyezése - KÍSÉRLETI + Kísérleti Hiba történt a cím módosításának megszakításakor Hiba történt a fájl fogadásakor titkosítása rendben van @@ -722,7 +722,7 @@ A reakciók hozzáadása az üzenetekhez le van tiltva. Nem nincs szöveg - TAG + Tag Hogyan befolyásolja az akkumulátort Új tag szerepköre Kikapcsolva @@ -842,7 +842,7 @@ Név és üzenet Az értesítések csak az alkalmazás bezárásáig érkeznek! Információ - ÜZENETEK ÉS FÁJLOK + Üzenetek és fájlok tag Privát kapcsolat létrehozása %s moderálta ezt az üzenetet @@ -918,7 +918,7 @@ Üdvözlőüzenet %s, %s és további %d tag kapcsolódott Csak a partnere kezdeményezhet hívásokat. - TÉMÁK + Témák Túl sok videó! Üdvözöljük! Önmegsemmisítő jelkód @@ -963,7 +963,7 @@ Ön elfogadta a kapcsolatot Elutasítás Partner nevének és az üzenet tartalmának megjelenítése - BEÁLLÍTÁSOK + Beállítások Profiljelszó mentése Megállítja a fájlküldést? Leválasztja a számítógépet? @@ -1007,7 +1007,7 @@ QR-kód beolvasása Kiszolgáló tesztelése Küldjön nekünk e-mailt - KISZOLGÁLÓK + Kiszolgálók Kiszolgálók tesztelése Jelkód bevitele Rendszer @@ -1018,12 +1018,12 @@ A reakciók hozzáadása az üzenethez le van tiltva. Véletlenszerű jelmondat használata egyenrangú - CSEVEGÉSI SZOLGÁLTATÁS INDÍTÁSA + Csevegési szolgáltatás indítása Kapott hivatkozás beillesztése Menti a kiszolgálókat? A SimpleX Chat biztonsága a Trail of Bits által lett auditálva. frissítette a csoportprofilt - SIMPLEX CHAT TÁMOGATÁSA + SimpleX Chat támogatása SimpleX Chat szolgáltatás Ön megfigyelő %s ellenőrizve @@ -1072,10 +1072,10 @@ Egyszer használható SimpleX meghívó Hívások nem sikerült elküldeni - KEZELŐFELÜLET SZÍNEI + Kezelőfelület színei Adja meg a korábbi jelszót az adatbázis biztonsági mentésének visszaállítása után. Ez a művelet nem vonható vissza. Másodlagos szín - SOCKS PROXY + SOCKS proxy Mentés Újraindítás SMP-kiszolgálók @@ -1106,7 +1106,7 @@ igen Hangüzenet Társítás számítógéppel - PROFIL + Profil %d-s port Kapcsolódás egy hivatkozáson keresztül Cím megosztása @@ -1457,7 +1457,7 @@ Kis csoportok (legfeljebb 20 tag) Az Ön által elfogadott kapcsolat vissza lesz vonva! Élő üzenet küldése – az üzenet a címzett(ek) számára valós időben frissül, ahogy Ön beírja az üzenetet - A KÉZBESÍTÉSI JELENTÉSEKET A KÖVETKEZŐ CÍMRE KELL KÜLDENI + A kézbesítési jelentéseket a következő címre kell küldeni A következő üzenet azonosítója érvénytelen (kisebb vagy egyenlő az előzővel).\nEz valamilyen hiba vagy sérült kapcsolat esetén fordulhat elő. Az eszköz neve meg lesz osztva a társított hordozható eszközön használt alkalmazással. A címzettek a beírás közben látják a szövegváltozásokat. @@ -1747,11 +1747,11 @@ Közvetlen üzenetküldés, ha a saját kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. Az IP-cím védelmének érdekében a privát útválasztás az SMP-kiszolgálókat használja az üzenetek kézbesítéséhez. Üzenet-útválasztási tartalék - PRIVÁT ÜZENET-ÚTVÁLASZTÁS + Privát üzenet-útválasztás Privát útválasztás használata az ismeretlen kiszolgálókkal, ha az IP-cím nem védett. NE küldjön üzeneteket közvetlenül, még akkor sem, ha a saját kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. Tor vagy VPN nélkül az IP-címe láthatóvá válik a fájlkiszolgálók számára. - FÁJLOK + Fájlok IP-cím védelme Az alkalmazás kérni fogja az ismeretlen fájlkiszolgálókról történő letöltések megerősítését (kivéve, ha az .onion vagy a SOCKS proxy engedélyezve van). Ismeretlen kiszolgálók! @@ -2019,7 +2019,7 @@ Az üzenetek törölve lesznek – ez a művelet nem vonható vissza! Eltávolítja az archívumot? A feltöltött adatbázis-archívum véglegesen el lesz távolítva a kiszolgálókról. - CSEVEGÉSI ADATBÁZIS + Csevegési adatbázis Profil megosztása Rendszerbeállítások használata Csevegési profil kiválasztása @@ -2476,7 +2476,7 @@ A hivatkozás rövid lesz és a csoportprofil meg lesz osztva a hivatkozáson keresztül. Régi cím megosztása Régi (hosszú) hivatkozás megosztása - PARTNERI KAPCSOLATKÉRÉSEK A CSOPORTOKBÓL + Partneri kapcsolatkérések a csoportokból A tag törölve lett – nem lehet elfogadni a kérést a(z) %1$s nevű csoportból partneri kapcsolatot kért Ez a beállítás a jelenlegi profiljára vonatkozik @@ -2519,7 +2519,7 @@ Hangüzenetek keresése Videók Hangüzenetek - NEM SIKERÜLT LÉTREHOZNI A KAPCSOLATOT + Nem sikerült létrehozni a kapcsolatot sikertelen Ha csatornákat hozott létre vagy csak csatlakozott hozzájuk, akkor azok véglegesen le fognak állni. aktív @@ -2545,7 +2545,7 @@ meghíva Csatorna megnyitása Új csatorna megnyitása - TULAJDONOS + Tulajdonos Tulajdonosok Csatorna elhagyása Elhagyja a csatornát? @@ -2555,7 +2555,7 @@ Ön Saját csatorna Saját csatorna - FELIRATKOZÓ + Feliratkozó Feliratkozók %1$d feliratkozó %1$d feliratkozó @@ -2607,7 +2607,7 @@ %1$d/%2$d átjátszó aktív %1$d/%2$d átjátszó kapcsolódva, %3$d hiba %1$d/%2$d átjátszó kapcsolódva - ÁTJÁTSZÓ + Átjátszó Átjátszóhivatkozás Átjátszó címe a következőn keresztül: %1$s diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/in/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/in/strings.xml index 60ed7db384..70c31f5399 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/in/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/in/strings.xml @@ -44,7 +44,7 @@ Tambahkan ke perangkat lain Boleh Selalu - APLIKASI + Aplikasi Tampilan Tentang SimpleX Chat Terima @@ -293,7 +293,7 @@ Terlalu banyak gambar! cari panggilan - PENGATURAN + Pengaturan Untuk semua orang Hentikan berkas Cabut berkas @@ -643,9 +643,9 @@ Kode sandi hapus otomatis Aktifkan hapus otomatis Pasang kode sandi - BANTUAN - DUKUNG SIMPLEX CHAT - PANGGILAN + Bantuan + Dukung SimpleX Chat + Panggilan Mulai ulang aplikasi untuk buat profil obrolan baru. Hapus pesan keluar @@ -729,9 +729,9 @@ Sedang Buram media Kuat - ANDA + Anda Lunak - BASIS DATA OBROLAN + Basis data obrolan Setel frasa sandi untuk diekspor Buka folder basis data menghapus anda @@ -968,7 +968,7 @@ Build aplikasi: %s Versi inti: v%s Ketika IP disembunyikan - WARNA ANTARMUKA + Warna antarmuka Fallback perutean pesan Mode routing pesan Routing pribadi @@ -1003,7 +1003,7 @@ Server ICE Anda Server ICE WebRTC Jika Anda memasukkan kode sandi hapus otomatis saat membuka aplikasi: - IKON APLIKASI + Ikon aplikasi Aplikasi akan meminta untuk mengonfirmasi unduhan dari server berkas yang tidak dikenal (kecuali .onion atau saat proxy SOCKS diaktifkan). Reaksi pesan dilarang dalam obrolan ini. Pindah ke perangkat lain @@ -1020,8 +1020,8 @@ Panggilan tak terjawab Panggilan ditolak ID pesan berikutnya salah (kurang atau sama dengan yang sebelumnya).\nHal ini dapat terjadi karena beberapa bug atau ketika koneksi terganggu. - TEMA - KIRIM TANDA TERIMA KIRIMAN KE + Tema + Kirim tanda terima kiriman ke Hal ini dapat terjadi ketika Anda atau koneksi Anda menggunakan cadangan basis data lama. Android Keystore digunakan untuk menyimpan frasa sandi dengan aman - memungkinkan layanan notifikasi berfungsi. Hapus @@ -1134,9 +1134,9 @@ Dikenal Menunggu gambar Menunggu video - PERANGKAT - OBROLAN - BERKAS + Perangkat + Obrolan + Berkas Reset semua petunjuk Gagal menambah anggota Gagal gabung ke grup @@ -1281,7 +1281,7 @@ Buka blokir anggota untuk semua? Buka untuk semua Diblokir oleh admin - ANGGOTA + Anggota Hapus anggota Status pesan: %s Status berkas: %s @@ -1326,7 +1326,7 @@ Perbaikan tidak didukung oleh kontak Obrolan Terima kondisi - SERVER + Server Buat grup Nama lengkap grup: Simpan profil grup @@ -1466,7 +1466,7 @@ Terbaik untuk baterai. Anda akan menerima notifikasi saat aplikasi sedang berjalan (TANPA layanan latar belakang).]]> Baik untuk baterai. Aplikasi memeriksa pesan setiap 10 menit. Anda mungkin melewatkan panggilan atau pesan penting.]]> Tema obrolan - BASIS DATA OBROLAN + Basis data obrolan Basis data dienkripsi menggunakan frasa sandi acak. Harap ubah frasa sandi sebelum mengekspor. Basis data obrolan diekspor Frasa sandi saat ini… @@ -1685,7 +1685,7 @@ Berkas dan media Enkripsi basis data? Versi basis data tidak kompatibel - UNTUK KONSOL + Untuk konsol Grup sudah ada! Masukkan frasa sandi Aktifkan hapus pesan otomatis? @@ -1703,7 +1703,7 @@ Gagal verifikasi frasa sandi: Gagal hubungkan ulang server Gagal hubungkan ulang server - EKSPERIMENTAL + Eksperimental Ekspor basis data Impor basis data Gagal hentikan obrolan @@ -1830,7 +1830,7 @@ %s diunduh Pesan diterima Catatan diperbarui pada - PESAN DAN BERKAS + Pesan dan berkas Tema profil Gambar profil Harap masukkan frasa sandi saat ini yang benar. @@ -1908,7 +1908,7 @@ Simpan Jadikan profil pribadi! Ponsel jarak jauh - JALANKAN OBROLAN + Jalankan obrolan Harap simpan frasa sandi dengan aman, Anda TIDAK akan dapat mengakses obrolan jika hilang. dihapus %1$s Dikirim pada: %s @@ -1979,7 +1979,7 @@ Server baru Info antrian pesan Bentuk pesan - ROUTING PESAN PRIBADI + Routing pesan pribadi info antrean server: %1$s\n\npesan terakhir diterima: %2$s Hanya data profil lokal Buka perubahan @@ -2024,7 +2024,7 @@ Profil, kontak, dan pesan terkirim Anda disimpan di perangkat Anda. Platform perpesanan dan aplikasi yang melindungi privasi dan keamanan Anda. Untuk melindungi privasi Anda, SimpleX gunakan ID terpisah untuk setiap kontak. - PROXY SOCKS + Proxy SOCKS Tingkatkan dan buka obrolan Ketuk untuk gabung ke samaran Anda memblokir %s @@ -2423,7 +2423,7 @@ Chat dengan anggota sebelum mereka bergabung. Hubungkan Terhubung lebih cepat! 🚀 - PERMINTAAN KONTAK DARI GRUP + Permintaan kontak dari grup kontak harus menerima… Buat alamat Anda Opsi tidak berlaku diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml index adce58e804..9db5b3a58f 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml @@ -269,7 +269,7 @@ L\'archivio chiavi di Android è usato per memorizzare in modo sicuro la password; permette il funzionamento del servizio di notifica. Permetti ai tuoi contatti di inviare messaggi vocali. Database della chat eliminato - ICONA APP + Icona app Ideale per la batteria. Riceverai notifiche solo quando l\'app è in esecuzione (NESSUN servizio in secondo piano).]]> Consuma più batteria! L\'app funziona sempre in secondo piano: le notifiche vengono mostrate istantaneamente.]]> chiamata… @@ -378,24 +378,24 @@ Attiva le chiamate dalla schermata di blocco tramite le impostazioni. Fotocamera frontale/posteriore Riaggancia - CHIAMATE - DATABASE DELLA CHAT + Chiamate + Database della chat Database della chat importato Chat in esecuzione - CHAT + Chat Il database è crittografato con una password casuale. Cambiala prima di esportare. Password del database Eliminare il profilo di chat\? Elimina database Strumenti di sviluppo - DISPOSITIVO + Dispositivo Errore nell\'eliminazione del database della chat Errore nell\'esportazione del database della chat Errore nell\'avvio della chat Errore nell\'interruzione della chat Funzionalità sperimentali Esporta database - AIUTO + Aiuto Chat fermata Errore del database La password del database è diversa da quella salvata nell\'archivio chiavi. @@ -437,7 +437,7 @@ Errore nella creazione del link del gruppo Errore nell\'eliminazione del link del gruppo Espandi la selezione dei ruoli - PER CONSOLE + Per console Link del gruppo Il gruppo verrà eliminato per tutti i membri. Non è reversibile! Il gruppo verrà eliminato per te. Non è reversibile! @@ -697,23 +697,23 @@ Importare il database della chat\? Importa database Modalità incognito - MESSAGGI E FILE + Messaggi e file Nuovo archivio database Vecchio archivio del database Riavvia l\'app per creare un profilo di chat nuovo. Riavvia l\'app per usare il database della chat importato. - AVVIA CHAT + Avvia chat Invia le anteprime dei link Imposta la password per esportare - IMPOSTAZIONI - PROXY SOCKS + Impostazioni + Proxy SOCKS Ferma Fermare la chat\? Ferma la chat per esportare, importare o eliminare il database della chat. Non potrai ricevere e inviare messaggi mentre la chat è ferma. - SUPPORTA SIMPLEX CHAT - TEMI + Supporta SimpleX Chat + Temi Questa azione non può essere annullata: il tuo profilo, i contatti, i messaggi e i file andranno persi in modo irreversibile. - TU + Tu Il tuo database della chat Il tuo attuale database di chat verrà ELIMINATO e SOSTITUITO con quello importato. \nQuesta azione non può essere annullata: il tuo profilo, i contatti, i messaggi e i file andranno persi in modo irreversibile. @@ -774,7 +774,7 @@ Invita al gruppo Esci dal gruppo Nome locale - MEMBRO + Membro Il membro verrà rimosso dal gruppo, non è reversibile! Nuovo ruolo del membro Nessun contatto selezionato @@ -806,7 +806,7 @@ Salva il profilo del gruppo sec Invio tramite - SERVER + Server Cambia indirizzo di ricezione Sistema Scadenza connessione TCP @@ -994,7 +994,7 @@ Conferma aggiornamenti database migrazione diversa nell\'app/nel database: %s / %s Conferma di migrazione non valida - SPERIMENTALE + Sperimentale L\'immagine verrà ricevuta quando il tuo contatto completerà l\'invio. la versione del database è più recente di quella dell\'app, ma nessuna migrazione downgrade per: %s Il file verrà ricevuto quando il tuo contatto completerà l\'invio. @@ -1102,7 +1102,7 @@ Per connettervi, il tuo contatto può scansionare il codice QR o usare il link nell\'app. Quando le persone chiedono di connettersi, puoi accettare o rifiutare. Indirizzo SimpleX - COLORI DELL\'INTERFACCIA + Colori dell\'interfaccia I tuoi contatti resteranno connessi. Aggiungi l\'indirizzo al tuo profilo, in modo che i tuoi contatti di SimpleX possano condividerlo con altre persone. L\'aggiornamento del profilo verrà inviato ai tuoi contatti di SimpleX. Crea un indirizzo per consentire alle persone di connettersi con te. @@ -1230,7 +1230,7 @@ nessun testo Si sono verificati alcuni errori non fatali durante l\'importazione: Riavvia - APP + App Le notifiche smetteranno di funzionare fino a quando non riavvierai l\'app Spegni Spegnere\? @@ -1261,7 +1261,7 @@ L\'invio delle ricevute di consegna sarà attivo per tutti i contatti. Errore nell\'attivazione delle ricevute di consegna! Puoi attivarle più tardi nelle impostazioni - INVIA RICEVUTE DI CONSEGNA A + Invia ricevute di consegna a concordando la crittografia per %s… Ricevute di consegna! Contatti @@ -1779,7 +1779,7 @@ NON inviare messaggi direttamente, anche se il tuo server o quello di destinazione non supporta l\'instradamento privato. NON usare l\'instradamento privato. No - INSTRADAMENTO PRIVATO DEI MESSAGGI + Instradamento privato dei messaggi Invia messaggi direttamente quando l\'indirizzo IP è protetto e il tuo server o quello di destinazione non supporta l\'instradamento privato. Per proteggere il tuo indirizzo IP, l\'instradamento privato usa i tuoi server SMP per consegnare i messaggi. Non protetto @@ -1787,7 +1787,7 @@ Proteggi l\'indirizzo IP L\'app chiederà di confermare i download da server di file sconosciuti (eccetto .onion o quando il proxy SOCKS è attivo). Senza Tor o VPN, il tuo indirizzo IP sarà visibile ai server di file. - FILE + File Senza Tor o VPN, il tuo indirizzo IP sarà visibile a questi relay XFTP: \n%1$s. Tema della chat @@ -2056,7 +2056,7 @@ Errore nel cambio di profilo Seleziona il profilo di chat Condividi il profilo - DATABASE DELLA CHAT + Database della chat Modalità di sistema Rimuovere l\'archivio? I messaggi verranno eliminati. Non è reversibile! @@ -2512,7 +2512,7 @@ Condividi il link vecchio Il link sarà breve e il profilo del gruppo verrà condiviso attraverso il link. Aggiorna il link del gruppo - RICHIESTE DI CONTATTO DAI GRUPPI + Richieste di contatto dai gruppi Il membro è eliminato - impossibile accettare la richiesta connessione richiesta dal gruppo %1$s Questa impostazione è per il tuo profilo attuale @@ -2555,7 +2555,7 @@ Video Messaggi vocali Filtro - CONNESSIONE FALLITA + Connessione fallita fallito Se sei dentro canali o ne hai creati, essi smetteranno di funzionare definitivamente. %1$d/%2$d relay attivo/i @@ -2620,12 +2620,12 @@ Non tutti i relay sono connessi Apri canale Apri un canale nuovo - PROPRIETARIO + Proprietario Proprietari Indirizzo relay preimpostato Nome relay preimpostato relay - RELAY + Relay Indirizzo del relay Indirizzo del relay Connessione del relay fallita @@ -2636,7 +2636,7 @@ Il server richiede l\'autorizzazione per connettersi al relay, controlla la password. Avviso del server Condividi l\'indirizzo del relay - ISCRITTO + Iscritto Iscritti Gli iscritti usano il link del relay per connettersi al canale.\nL\'indirizzo del relay è stato usato per impostare questo relay per il canale. L\'iscritto verrà rimosso dal canale, non è reversibile! diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml index faf69dfd03..61613e63b0 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/iw/strings.xml @@ -973,7 +973,7 @@ רמקול כבוי רמקול פעיל הגדרות - תמיכה ב־SIMPLEX CHAT + תמיכה ב־SimpleX Chat לעצור צ׳אט\? עיצרו את הצ׳אט כדי לייצא, לייבא או למחוק את מסד הנתונים. לא תוכלו לקבל ולשלוח הודעות בזמן שהצ׳אט מופסק. עצור diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml index 5c17946c24..9784befef6 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml @@ -880,7 +880,7 @@ メールを送る メディア共有… SimpleXリンク - SIMPLEX CHATを支援 + SimpleX Chatを支援 テストサーバ 受信アドレスは別のサーバーに変更されます。アドレス変更は送信者がオンラインになった後に完了します。 あなたのプライバシーを守るために、他のアプリと違って、ユーザーIDの変わりに SimpleX メッセージ束毎にIDを配布し、各連絡先が別々と扱います。 diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml index 83f937db32..a60dea56b7 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ko/strings.xml @@ -822,7 +822,7 @@ 설정 링크 미리보기 보내기 SOCKS 프록시 - SIMPLEX CHAT 도와주기 + SimpleX Chat 도와주기 실험적 기능 표시 : diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ku/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ku/strings.xml index 92985b15be..09c428e48b 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ku/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ku/strings.xml @@ -282,13 +282,13 @@ Adresa serverê Adres Adresa serverê li eyarên torê nayê. - SERVER + Server Melûmata serveran Ceribandina serverê bi ser neket! Versiyona serverê li eyarên torê nayê. 1 roj deyne Tercihên komê diyar bike - EYAR + Eyar Parve bike Lînka 1-carê parve bike Adresê parve bike @@ -337,7 +337,7 @@ xet/xêz/xîşk Biqewet Abonekirî - PIŞT BIDE SIMPLEX CHATÊ + Pişt bide SimpleX Chatê Biguhere Sîstem Sîstem @@ -513,7 +513,7 @@ Kompîter ne aktîv e Girêdana bi kompîterê re qut bû Detay - CIHAZ + Cihaz %d dosya bi mezibnbûniya timam ya %s %d hewadîsên komê %d seet @@ -588,7 +588,7 @@ Tu dihêlî te ev endam qebûl kir tu: %1$s - TU + Tu tu Erê erê @@ -633,11 +633,11 @@ Lînkê veke Lînka timam veke Lînka paqij veke - ARÎKARÎ - APLÎKASYON - DOSYA + Arîkarî + Aplîkasyon + Dosya Ji nû ve veke - PROKSIYA SOCKSÊ + Proksiya SOCKSê Sûretên profîlan Girêdana torê Ji kompîterê bişuxulîne @@ -687,7 +687,7 @@ Ji admîn blokkirî blokkirî ne aktîv - ENDAM + Endam Rol Kom Te standin bi riya @@ -785,10 +785,10 @@ Profîla siḧbetê Tu siḧbeta xwe qontrol dikî! Siḧbetê bişuxulîne - SIḦBET + Siḧbet Rengên siḧbetê Siḧbet sekinandî ye - DATABASA SIḦBETÊ + Databasa siḧbetê Ber siḧbet were sekinandin? Xeletî di sekinandina siḧbetê de Ber profîla siḧbetê were jêbirin? diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml index bccd49eed9..950569c85b 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/lt/strings.xml @@ -17,10 +17,10 @@ Skambutis jau baigtas! Atsiliepti Skambutis baigtas - SKAMBUČIAI + Skambučiai Leisti jūsų kontaktams negrįžtamai ištrinti išsiųstas žinutes. (24 valandas) Atgal - PROGRAMĖLĖS PIKTOGRAMA + Programėlės piktograma visada Leisti jūsų kontaktams siųsti balso žinutes. Leisti negrįžtamą žinučių ištrynimą tik tuo atveju, jei jūsų kontaktas jums tai leidžia. (24 valandas) @@ -78,8 +78,8 @@ Apversti kamerą Atmestas skambutis Privatumas ir saugumas - ĮRENGINYS - PAGALBA + Įrenginys + Pagalba Šifruoti Šalinti Ištrinti grupę @@ -241,7 +241,7 @@ Išjungti garsiakalbį Įjungti garsiakalbį Praleistos žinutės - NUSTATYMAI + Nustatymai Sistemos nežinomas žinutės formatas SimpleX kontakto adresas @@ -292,7 +292,7 @@ Išjungti vaizdą Įjungti vaizdą Jūsų privatumas - JŪS + Jūs Neteisinga slaptafrazė! SimpleX jūs @@ -348,10 +348,10 @@ Įrašyti ir pranešti grupės nariams gautas patvirtinimas… Praleistas skambutis - POKALBIAI - APIPAVIDALINIMAI + Pokalbiai + Apipavidalinimai Inkognito veiksena - ŽINUTĖS IR FAILAI + Žinutės ir failai Norėdami naudoti importuotą pokalbio duomenų bazę, paleiskite programėlę iš naujo. Pakviesti narius Išnykstančios žinutės šiame pokalbyje yra uždraustos. @@ -420,7 +420,7 @@ Pokalbio profilis Profilis yra bendrinamas tik su jūsų kontaktais. „GitHub“ saugykloje.]]> - SOCKS ĮGALIOTASIS SERVERIS + SOCKS įgaliotasis serveris Įrašyti slaptafrazę ir atverti pokalbį Atkurti atsarginę duomenų bazės kopiją Atkurti atsarginę duomenų bazės kopiją\? @@ -459,7 +459,7 @@ Kontakto nuostatos Prisijungti Keisti - SERVERIAI + Serveriai Išvalyti Nebeslėpti profilio Per daug vaizdo įrašų! @@ -545,7 +545,7 @@ Išjungti garsą Visi programėlės duomenys bus ištrinti. Sukuriamas tuščias pokalbių profilis nurodytu pavadinimu ir programėlė atveriama kaip įprasta. - PROGRAMĖLĖ + Programėlė Saugiam slaptafrazės saugojimui yra naudojama „Android Keystore“ – tai įgalina pranešimų tarnybą veikti. Papildoma antrinė spalva Papildomas akcentavimas @@ -636,7 +636,7 @@ Sukurti grupę: sukurti naują grupę.]]> Pridėti kontaktą Tinkinti apipavidalinimą - POKALBIO DUOMENŲ BAZĖ + Pokalbio duomenų bazė Naudotojo sąsaja kinų ir ispanų kalbomis Pranešimai apie pristatymą! Išjungti SimpleX užraktą @@ -855,7 +855,7 @@ Prisijungti inkognito režimu Reikalinga slaptafrazė Uždrausti siųsti balso žinutes. - EKSPERIMENTINIS + Eksperimentinis Greitai ir nelaukiant kol siuntėjas prisijungs! Failai ir medija Failai ir medija yra draudžiami šioje grupėje. @@ -1000,7 +1000,7 @@ ištrintas kontaktas pakviestas Ištrinta - KONSOLEI + Konsolei Blokuoti Protokolui skirtas laikas numatyta (%s) @@ -1106,7 +1106,7 @@ Prisijungimas, kurį priėmėte, bus atšauktas! Bakstelėkite, kad įklijuoti nuorodą Testuoti serverį - TEMOS SPALVOS + Temos spalvos Rodyti lėtus API iškvietimus Nustoti bendrinti adresą? Žinučių siuntimo ir programų platforma, apsauganti jūsų privatumą ir saugumą. @@ -1217,7 +1217,7 @@ Nustatyti duomenų slaptafrazę Nustatyti slaptafrazę Rodyti paskutines žinutes - PALAIKYKITE SIMPLEX CHAT + Palaikykite SimpleX Chat Jų galima nepaisyti kontaktų ir grupių nustatymuose. Šis veiksmas negali būti atšauktas - žinutės išsiųstos ir gautos anksčiau nei pasirinkta bus ištrintos. Tai gali užtrukti kelias minutes. %s, %s ir %d kiti nariai prisijungė @@ -1516,7 +1516,7 @@ paslaptis Pranešimai nustos veikti iki tol kol paleisite programėlę iš naujo Galite naudoti markdown, kad formatuoti žinutes: - PALEISTI POKALBIUS + Paleisti pokalbius Naudoti iš darbastalio Sveikinimo žinutė yra per ilga Žinučių reakcijos @@ -1618,7 +1618,7 @@ Galite paleisti pokalbius per programėlės nustatymus/ duomenų bazę arba paleisdami programėlę iš naujo. pašalino jus Moderuota - NARYS + Narys %s %s nėra teksto Meniu ir įspėjimai @@ -1651,7 +1651,7 @@ Naudoti atsiktinę slaptafrazę lygiaverčiai mazgai Pašalinti slaptafrazę iš nustatymų? - SIŲSTI PRISTATYMO KVITUS PAS + Siųsti pristatymo kvitus pas Pristatymo kvitai yra išjungti %d grupėms Turite naudoti pačią naujausią pokalbių duomenų bazės versiją TIK viename įrenginyje, kitaip galite nebegauti žinučių iš kai kurių kontaktų. Nauja slaptafrazė… diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/nb-rNO/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/nb-rNO/strings.xml index a6385a5ce0..1275c31573 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/nb-rNO/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/nb-rNO/strings.xml @@ -124,7 +124,7 @@ En annen grunn Svar anrop Hvem som helst kan være vert for servere. - APP + App Appen kjører alltid i bakgrunnen App build: %s Appen kan bare motta varsler når den er åpen, ingen bakgrunnstjeneste vil bli startet. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml index cc81e5365b..53ff325f43 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/nl/strings.xml @@ -5,7 +5,7 @@ Oproepen op vergrendelscherm: oproep bezig Gesprek bezig - OPROEPEN + Oproepen Annuleren Bestandsvoorbeeld annuleren Annuleer afbeeldingsvoorbeeld @@ -23,7 +23,7 @@ Sta toe om spraak berichten te verzenden. Chat is actief Wissen - CHAT DATABASE + Chat database Chat console Chat database geïmporteerd Chat database verwijderd @@ -85,7 +85,7 @@ App build: %s App kan alleen meldingen ontvangen wanneer deze actief is, er wordt geen achtergrondservice gestart Uiterlijk - APP ICON + App icon App versie App versie: v%s voor elk chatprofiel dat je in de app hebt .]]> @@ -119,7 +119,7 @@ Chat is gestopt Chat voorkeuren Chatprofiel - CHATS + Chats Praat met de ontwikkelaars Controleer het server adres en probeer het opnieuw. Bestand @@ -231,7 +231,7 @@ Verwijderen voor iedereen Link verwijderen direct - APPARAAT + Apparaat Verwijder alle bestanden Berichten verwijderen na Directe berichten @@ -309,7 +309,7 @@ e2e versleuteld video gesprek Schakel oproepen vanaf het vergrendelscherm in via Instellingen. Ophangen - HELP + Help Experimentele functies Fout bij het starten van de chat Database exporteren @@ -358,7 +358,7 @@ Fout bij het accepteren van een contactverzoek Groep uitnodiging verlopen Bestand - VOOR CONSOLE + Voor console Groep profiel wordt opgeslagen op de apparaten van de leden, niet op de servers. Verborgen De groep wordt voor u verwijderd, dit kan niet ongedaan worden gemaakt! @@ -473,8 +473,8 @@ Verlaten Lid link voorbeeld afbeelding - LID - BERICHTEN EN BESTANDEN + Lid + Berichten en bestanden Openen in mobiele app en tik vervolgens op Verbinden in de app.]]> Lid wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt! Fout bij bezorging van bericht @@ -730,10 +730,10 @@ App scherm verbergen Uw privacy Link voorbeelden verzenden - INSTELLINGEN - ONDERSTEUNING SIMPLEX CHAT - JIJ - CHAT UITVOEREN + Instellingen + Ondersteuning SimpleX Chat + Jij + Chat uitvoeren Uw chat database Wachtwoord instellen om te exporteren Start de app opnieuw om een nieuw chatprofiel aan te maken. @@ -790,7 +790,7 @@ Direct bericht sturen De rol wordt gewijzigd in "%s". De gebruiker ontvangt een nieuwe uitnodiging. Verzenden via - SERVERS + Servers Resetten naar standaardwaarden Ontvangst adres wijzigen Protocol timeout @@ -874,11 +874,11 @@ Bericht delen… SimpleX Vergrendelen Sla het wachtwoord op in Keychain - SOCKS PROXY + SOCKS proxy Dank aan de gebruikers – draag bij via Weblate! De app haalt regelmatig nieuwe berichten op - het gebruikt een paar procent van de batterij per dag. De app maakt geen gebruik van push meldingen, gegevens van uw apparaat worden niet naar de servers verzonden. De afbeelding kan niet worden gedecodeerd. Probeer een andere afbeelding of neem contact op met de ontwikkelaars. - THEMA\'S + Thema\'s Scan server QR-code Deze string is geen verbinding link! Deze actie kan niet ongedaan worden gemaakt, de berichten die eerder zijn verzonden en ontvangen dan geselecteerd, worden verwijderd. Het kan enkele minuten duren. @@ -994,7 +994,7 @@ Database-ID\'s en Transport isolatie optie. Verbergen: Ontwikkelaars opties tonen - EXPERIMENTEEL + Experimenteel Verwijder profiel Profiel wachtwoord Chatprofiel zichtbaar maken @@ -1146,7 +1146,7 @@ Zorg ervoor dat het bestand de juiste YAML-syntaxis heeft. Exporteer het thema om een voorbeeld te hebben van de themabestandsstructuur. Database openen… Gebruikershandleiding.]]> - INTERFACE KLEUREN + Interface kleuren U kunt uw adres delen als een link of QR-code - iedereen kan verbinding met u maken. Alle app-gegevens worden verwijderd. Er wordt een leeg chatprofiel met de opgegeven naam gemaakt en de app wordt zoals gewoonlijk geopend. @@ -1226,7 +1226,7 @@ geen tekst Er zijn enkele niet-fatale fouten opgetreden tijdens het importeren: Afsluiten\? - APP + App Herstarten Afsluiten Meldingen werken niet meer totdat u de app opnieuw start @@ -1285,7 +1285,7 @@ Inschakelen (overschrijvingen behouden) Het verzenden van ontvangst bevestiging is uitgeschakeld voor %d-contactpersonen Uitschakelen voor iedereen - STUUR ONTVANGST BEVESTIGING NAAR + Stuur ontvangst bevestiging naar Ontvangst bevestiging verzenden De tweede vink die we gemist hebben! ✅ Filter ongelezen en favoriete chats. @@ -1779,13 +1779,13 @@ Om uw IP-adres te beschermen, gebruikt privéroutering uw SMP-servers om berichten te bezorgen. Stuur GEEN berichten rechtstreeks, zelfs als uw of de bestemmingsserver geen privéroutering ondersteunt. Terugval op berichtroutering - PRIVÉBERICHT ROUTING + Privébericht routing Stuur berichten rechtstreeks als het IP-adres beschermd is en uw of bestemmingsserver geen privéroutering ondersteunt. Onbekende servers! Zonder Tor of VPN is uw IP-adres zichtbaar voor deze XFTP-relays: \n%1$s. Zonder Tor of VPN is uw IP-adres zichtbaar voor bestandsservers. - BESTANDEN + Bestanden Bescherm het IP-adres De app vraagt om downloads van onbekende bestandsservers te bevestigen (behalve .onion of wanneer SOCKS-proxy is ingeschakeld). Fout bij het initialiseren van WebView. Update uw systeem naar de nieuwe versie. Neem contact op met ontwikkelaars. @@ -2055,7 +2055,7 @@ Selecteer chatprofiel Profiel delen Uw verbinding is verplaatst naar %s, maar er is een onverwachte fout opgetreden tijdens het omleiden naar het profiel. - CHAT DATABASE + Chat database Systeemmodus Archief verwijderen? Berichten worden verwijderd. Dit kan niet ongedaan worden gemaakt! diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml index 9cc43851d6..51bfacb404 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pl/strings.xml @@ -495,36 +495,36 @@ Pominięte wiadomości Twoja prywatność Kopia zapasowa danych aplikacji - IKONA APLIKACJI + Ikona aplikacji Automatyczne akceptowanie obrazów - POŁĄCZENIA - BAZA DANYCH CZATU + Połączenia + Baza danych czatu Czat jest uruchomiony Czat jest zatrzymany - CZATY + Czaty Hasło do bazy danych Usuń bazę danych Narzędzia deweloperskie - URZĄDZENIE + Urządzenie Błąd uruchamiania czatu - EKSPERYMENTALNE + Eksperymentalne Funkcje eksperymentalne Eksportuj bazę danych - POMOC + Pomoc Importuj bazę danych Tryb incognito - WIADOMOŚCI I PLIKI + Wiadomości i pliki Nowe archiwum bazy danych Stare archiwum bazy danych Chroń ekran aplikacji - URUCHOM CZAT + Uruchom czat Wyślij podgląd linku - USTAWIENIA - PROXY SOCKS + Ustawienia + Proxy SOCKS Zatrzymać czat\? - WSPIERAJ SIMPLEX CHAT - MOTYWY - TY + Wspieraj SimpleX Chat + Motywy + Ty Twoja baza danych czatu Ustaw hasło do eksportu Zatrzymaj @@ -707,12 +707,12 @@ Błąd tworzenia linku grupy Błąd usuwania linku grupy Błąd usuwania członka - DLA KONSOLI + Dla konsoli Grupa Wprowadź nazwę grupy: Pełna nazwa grupy: Nazwa lokalna - CZŁONEK + Członek Członek zostanie usunięty z grupy - nie można tego cofnąć! Status sieci Tylko właściciele grup mogą zmieniać preferencje grupy. @@ -724,7 +724,7 @@ Zapisać wiadomość powitalną\? Wyślij wiadomość bezpośrednią Wysyłanie przez - SERWERY + Serwery Przełącz Zmień adres odbioru W pełni zdecentralizowana – widoczna tylko dla członków. @@ -1136,7 +1136,7 @@ Kiedy ludzie proszą o połączenie, możesz je zaakceptować lub odrzucić. Nie stracisz kontaktów, jeśli później usuniesz swój adres. Dostosuj motyw - KOLORY INTERFEJSU + Kolory interfejsu Twoje kontakty pozostaną połączone. Dodaj adres do swojego profilu, aby Twoje kontakty mogły go udostępnić innym osobom. Aktualizacja profilu zostanie wysłana do Twoich kontaktów. Utwórz adres, aby ludzie mogli się z Tobą połączyć. @@ -1229,7 +1229,7 @@ brak tekstu Podczas importu wystąpiły niekrytyczne błędy: Restart - APLIKACJA + Aplikacja Powiadomienia przestaną działać do momentu ponownego uruchomienia aplikacji. Wyłączenie Wyłączyć\? @@ -1262,7 +1262,7 @@ Spraw, aby jedna wiadomość zniknęła Renegocjuj szyfrowanie kod bezpieczeństwa zmieniony - WYŚLIJ POTWIERDZENIA DOSTAWY DO + Wyślij potwierdzenia dostawy do Wysyłanie potwierdzeń dostawy zostanie włączone dla wszystkich kontaktów we wszystkich widocznych profilach czatu. Kontakty Włączyć potwierdzenia\? @@ -1772,7 +1772,7 @@ Nie Gdy IP ukryty Pokaż status wiadomości - TRASOWANIE PRYWATNYCH WIADOMOŚCI + Trasowanie prywatnych wiadomości NIE wysyłaj wiadomości bezpośrednio, nawet jeśli serwer docelowy nie obsługuje prywatnego trasowania. Aby chronić Twój adres IP, prywatne trasowanie używa Twoich serwerów SMP, aby dostarczyć wiadomości. Nieznane serwery @@ -1788,7 +1788,7 @@ Chroń adres IP Aplikacja będzie prosić o potwierdzenie pobierań z nieznanych serwerów plików (z wyjątkiem .onion lub gdy proxy SOCKS jest włączone). Bez Tor lub VPN, Twój adres IP będzie widoczny do serwerów plików. - PLIKI + Pliki Motyw profilu Pokaż listę czatów w nowym oknie Kolory ciemnego trybu @@ -2065,7 +2065,7 @@ %1$d plik(ów/i) dalej są pobierane. %1$d plik(ów/i) nie udało się pobrać. Błąd zmiany profilu - BAZA CZATU + Baza czatu %1$d błędów plików:\n%2$s %1$d innych błędów plików. Wiadomości zostały usunięte po wybraniu ich. @@ -2233,7 +2233,7 @@ kontakt usunięty kontakt wyłączony kontakt nie gotowy - PROŚBY O KONTAKT OD GRUP + Prośby o kontakt od grup kontakt powinien zaakceptować… Stwórz swój adres %d czat(y) diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml index c129d68521..2d33731ce1 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pt-rBR/strings.xml @@ -74,16 +74,16 @@ para cada perfil de bate-papo que você tiver no aplicativo.]]> Melhor para bateria. Você receberá notificações apenas quando o aplicativo estiver em execução (SEM o serviço em segundo plano).]]> Consome mais bateria! O aplicativo em segundo plano está sempre em execução - as notificações são exibidas instantaneamente.]]> - BATE-PAPOS - ÍCONE DO APLICATIVO - BANCO DE DADOS DE BATE-PAPO + Bate-papos + Ícone do aplicativo + Banco de dados de bate-papo O bate-papo está em execução O bate-papo está parado Alterar senha do banco de dados\? endereço alterado para você Você e seu contato podem enviar mensagens temporárias. Backup de dados do aplicativo - CHAMADAS + Chamadas Aceitar solicitações de contato automaticamente Aparência O serviço em segundo plano está sempre em execução - as notificações serão exibidas assim que as mensagens estiverem disponíveis. @@ -247,7 +247,7 @@ Tempo de conexão esgotado Excluir mensagem do membro\? Excluir fila - DISPOSITIVO + Dispositivo Ferramentas de desenvolvedor conectando (introduzido) Tonalidade @@ -378,7 +378,7 @@ Arquivo salvo Os membros podem enviar mensagens de voz. O grupo será excluído para todos os membros - isso não pode ser desfeito! - AJUDA + Ajuda Ocultar contato e mensagem Como usar Como usar markdown @@ -420,7 +420,7 @@ Servidores ICE (um por linha) Ignorar A imagem será recebida quando seu contato estiver online, aguarde ou verifique mais tarde! - SERVIDORES + Servidores Recebendo via Status da conexão seg @@ -495,8 +495,8 @@ Usar proxy SOCKS\? Chamada rejeitada Restaurar o backup do banco de dados - PARA CONSOLE - EXECUTAR BATE-PAPO + Para console + Executar bate-papo Parar Definir senha para exportar Reinicie o aplicativo para usar o banco de dados do chat importado. @@ -571,7 +571,7 @@ você mudou o cargo de %s para %s Novo cargo de membro Remover - MEMBRO + Membro O membro será removido do grupo - isso não pode ser desfeito! Cargo Enviando via @@ -663,8 +663,8 @@ Interface chinesa e espanhola Maior redução no uso da bateria Mais melhorias chegarão em breve! - VOCÊ - MENSAGENS E ARQUIVOS + Você + Mensagens e arquivos Seu banco de dados de bate-papo Você removeu %1$s removido @@ -800,7 +800,7 @@ Ocultar perfil confirmação recebida… O servidor de relay protege seu endereço IP, mas pode observar a duração da chamada. - EXPERIMENTAL + Experimental você alterou o endereço Atualização do banco de dados O cargo será alterado para "%s". O membro receberá um novo convite. @@ -819,7 +819,7 @@ Somente o proprietários de grupo podem ativar mensagens de voz você compartilhou um link de uso único Você será conectado quando sua solicitação de conexão for aceita, aguarde ou verifique mais tarde! - CONFIGURAÇÕES + Configurações Defina a mensagem mostrada aos novos membros! Configurações Alternar endereço de recebimento @@ -848,7 +848,7 @@ Ligar Bem-vindo(a)! O futuro da transmissão de mensagens - PROXY SOCKS + Proxy SOCKS A tentativa de alterar a senha do banco de dados não foi concluída. Pare o bate-papo para exportar, importar ou excluir o banco de dados do chat. Você não poderá receber e enviar mensagens enquanto o chat estiver interrompido. %s segundo(s) @@ -887,7 +887,7 @@ chamada de vídeo Mostrar Servidores ICE WebRTC - TEMAS + Temas Atualizar O app busca novas mensagens periodicamente – ele usa alguns por cento da bateria por dia. O aplicativo não usa notificações por push – os dados do seu dispositivo não são enviados para os servidores. Para receber notificações, por favor, digite a senha do banco de dados @@ -1001,7 +1001,7 @@ desativado Desatualizar e abrir o bate-papo desativado - APOIE SIMPLEX CHAT + Apoie SimpleX Chat Esta ação não pode ser desfeita - as mensagens enviadas e recebidas antes do selecionado serão excluídas. Pode levar vários minutos. Confirme as atualizações do banco de dados Somente o cliente dos dispositivos armazenam perfis de usuários, contatos, grupos e mensagens. @@ -1127,7 +1127,7 @@ Você não perderá seus contatos se, posteriormente, excluir seu endereço. Endereço SimpleX Quando as pessoas solicitam uma conexão, você pode aceitá-la ou rejeitá-la. - CORES DA INTERFACE + Cores da interface compartilhar com os contatos A atualização do perfil será enviada aos seus contatos. Salvar configurações\? @@ -1253,7 +1253,7 @@ Correção não suportada pelo membro do grupo concordando com criptografia… Permitir o envio de arquivos e mídia. - APP + App criptografia OK renegociação de criptografia necessária criptografia concordada para %s @@ -1284,7 +1284,7 @@ Ativar recibos? Encontrar conversas mais rápido Contatos - ENVIAR RECIBOS DE ENTREGA PARA + Enviar recibos de entrega para Enviar confirmações está desativado para %d contatos. Enviar confirmações está ativado para %d contatos. Enviar confirmações @@ -1862,9 +1862,9 @@ Alto falante Headphones Sem Tor ou VPN, seu endereço de IP ficará visível para servidores de arquivo. - ARQUIVOS + Arquivos Fotos de perfil - ROTEAMENTO DE MENSAGEM PRIVADA + Roteamento de mensagem privada criptografia padrão ponta a ponta proprietários Migrar para outro dispositivo @@ -2055,7 +2055,7 @@ Barras de ferramentas de aplicativos acessível Falha no baixar de %1$d arquivo(s). %1$s mensagens não encaminhadas. - DADOS DO BATE-PAPO + Dados do bate-papo Utilize credenciais aleatórias O arquivo de banco de dados enviado será removido permanentemente dos servidores. Use credenciais diferentes de proxy para cada conexão. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml index 5f12e762aa..af292da504 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/pt/strings.xml @@ -28,9 +28,9 @@ Backup de dados da aplicação Aceitar imagens automaticamente Código de acesso definido! - VOCÊ - MENSAGENS E FICHEIROS - ÍCONE DA APLICAÇÃO + Você + Mensagens e ficheiros + Ícone da aplicação 1 mês Mensagens Adicionar mensagem de boas-vindas @@ -137,7 +137,7 @@ Eliminar Eliminar todos os ficheiros Eliminar base de dados - BASE DE DADOS DE CONVERSA + Base de dados de conversa Base de dados de conversa eliminada Nome para Exibição Mostrar: @@ -184,7 +184,7 @@ Colar ligação recebida Senha não encontrada na Keystore, por favor insira-a manualmente. Isto pode ter acontecido se você restaurou os dados da aplicação usando uma ferramenta de backup. Se não for o caso, entre em contato com os desenvolvedores. O servidor requer autorização para criar filas, verifique a senha - SERVIDORES + Servidores O servidor requer autorização para fazer upload, verifique a senha Usar hosts .onion como Não se o proxy SOCKS não o suportar.]]> Usar hosts .onion @@ -226,7 +226,7 @@ Chamada já finalizada! Chamada em curso Chamada finalizada - CHAMADAS + Chamadas Por perfil de conversa (padrão) ou por ligação (BETA). Não é possível aceder à Keystore para salvar a senha da base de dados Não é possível convidar o contato! @@ -251,7 +251,7 @@ Erro ao eliminar ligação de grupo Perfil de conversa Alterar o modo de bloqueio - CONVERSAS + Conversas Conversa em execução Erro ao alterar configuração Alterar a senha da base de dados\? @@ -471,7 +471,7 @@ ID da base de dados Eliminar ficheiro Eliminar contacto? - DISPOSITIVO + Dispositivo Mensagens diretas Descentralizado mensagem duplicada @@ -540,7 +540,7 @@ %1$d mensagens ignoradas. Importar base de dados As suas definições - DEFINIÇÕES + Definições Partilhar Partilhar endereço Definições @@ -554,12 +554,12 @@ \nEsta ação é irreversível - o seu perfil, contactos, mensagens e ficheiros serão irreversivelmente perdidos. Marcar como não lido membro - MEMBRO + Membro Máximo de 40 segundos, recebido instantaneamente. Mais Rede e servidores Configurações avançadas - EXPERIMENTAL + Experimental Você pode iniciar a conversa através das Definições da aplicação / Base de Dados ou reiniciando a aplicação. Atualizar A atualização das definições reconectará o cliente a todos os servidores. @@ -572,10 +572,10 @@ Muito provavelmente este contato eliminou a conexão consigo. Este texto está disponível nas definições Pode ser alterado mais tarde através das definições. - AJUDA - SUPORTE SIMPLEX CHAT + Ajuda + Suporte SimpleX Chat Funcionalidades experimentais - TEMAS + Temas Escuro Tema escuro nunca diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml index 81cf8ed452..b8f8f3f111 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ro/strings.xml @@ -98,7 +98,7 @@ și %d alte evenimente Răspunde la apel Android Keystore va fi folosit pentru a stoca în siguranță parola după ce repornești aplicația sau schimbi parola — acest lucru va permite primirea de notificări. - APLICAȚIE + Aplicație Creează grup Apeluri audio și video Arhivează și încarcă @@ -109,7 +109,7 @@ Apel audio apel audio Audio oprit - PICTOGRAMĂ APLICAȚIE + Pictogramă aplicație Cod de acces aplicație Creează grup secret Creează coadă @@ -292,11 +292,11 @@ Afișează: Afișează erorile interne secret - SETĂRI + Setări %s conectat setați o nouă poză de profil Trimis la: %s - SERVERE + Servere Trimite mesaj în direct %s descărcat Partajați adresa cu contactele? @@ -376,7 +376,7 @@ Hash mesaj incorect Schimbă adresa de primire Conversația este oprită. Dacă ai folosit deja această bază de date pe alt dispozitiv, ar trebui să o transferi înapoi înainte de a porni conversația. - APELURI + Apeluri v-ați schimbat rolul în %s Capacitate depășită - destinatarul nu a primit mesajele trimise anterior. Schimbă codul de acces autodistructibil @@ -431,8 +431,8 @@ contactul are criptare e2e contactul nu are criptare e2e Contacte - CONVERSAȚII - BAZĂ DE DATE CONVERSAȚIE + Conversații + Bază de date conversație Baza de date a conversației a fost ștearsă Conversația rulează Baza de date a conversațiilor tale @@ -684,7 +684,7 @@ Verifică pentru actualizări Creează Estompează media - BAZĂ DE DATE CONVERSAȚIE + Bază de date conversație Conectează-te cu prietenii mai ușor. încercări Finalizat @@ -719,11 +719,11 @@ Setări apel audio criptat e2e apel video criptat e2e - DISPOZITIV - EXPERIMENTAL + Dispozitiv + Experimental Criptează erori de decriptare - TU + Tu nicio criptare e2e criptat e2e Apel video primit @@ -825,7 +825,7 @@ Notificări și baterie Deschide Activați confirmarea de primire pentru grupuri? - PENTRU CONSOLĂ + Pentru consolă Moderat la Remediați conexiunea Profiluri de conversație multiple @@ -915,7 +915,7 @@ Nicio conversație în lista %s. Nimic selectat deschis - AJUTOR + Ajutor Doar contactul tău poate trimite mesaje care dispar. Se importă arhiva Migrare dispozitiv @@ -1010,7 +1010,7 @@ Luminos Nu Deschizi linkul web? - MESAJE ȘI FIȘIERE + Mesaje și fișiere moderator Rol inițial Doar proprietarii grupului pot modifica preferințele grupului. @@ -1043,7 +1043,7 @@ Cum afectează bateria Activare (păstrați suprascrierile) Activează codul de autodistrugere - MEMBRU + Membru Operator de rețea Desktop-uri conectate Eroare la acceptarea membrului @@ -1148,7 +1148,7 @@ Activați confirmarea de primire? Nume nou afișat: Instrumente pentru dezvoltatori - FIȘIERE + Fișiere Deschide linkurile din lista de conversații Forma mesajului Importați baza de date @@ -1393,7 +1393,7 @@ Șterge Instalați SimpleX Chat pentru terminal Eroare la salvarea serverelor ICE - CULORILE INTERFEȚEI + Culorile interfeței %d fișier(e) cu dimensiunea totală de %s Fișiere și media invitat %1$s @@ -1636,7 +1636,7 @@ Conexiuni de profil și server răspuns primit… Politica de confidențialitate și condițiile de utilizare. - RUTAREA MESAJELOR PRIVATE + Rutarea mesajelor private Te rugăm să stochezi parola în siguranță, altfel NU o vei putea schimba dacă o pierzi. Parola nu a fost găsită în Keystore. Te rugăm să o introduci manual. Acest lucru s-ar putea întâmpla dacă ai restaurat datele aplicației folosind un instrument de backup. Dacă nu este cazul, te rugăm să contactezi dezvoltatorii. Parola stocată în Keystore nu poate fi citită. Acest lucru se poate întâmpla după o actualizare a sistemului incompatibilă cu aplicația. Dacă nu este cazul, te rugăm să contactezi dezvoltatorii. @@ -1767,7 +1767,7 @@ revizuit de administratori Operatori de server Serverul de retransmisie protejează adresa IP, dar poate observa durata apelului. - PORNIȚI CHATUL + Porniți chatul te-a eliminat %s la %s Protocolul serverului a fost modificat. @@ -1800,7 +1800,7 @@ Selectează profilul de conversație Salvează setările adresei SimpleX Salvează lista - TRIMITE CONFIRMĂRI DE LIVRARE LA + Trimite confirmări de livrare la Parola de autodistrugere a fost schimbată! Înregistrare actualizată la Selectează operatorii de rețea de utilizat. @@ -1973,9 +1973,9 @@ Aplicația va cere să confirmați descărcările de pe servere de fișiere necunoscute (cu excepția celor .onion sau când proxy-ul SOCKS este activat). Sistem Acestea pot fi ignorate în setările de contact și de grup. - SUPORT SIMPLEX CHAT - PROXY SOCKS - TEME + Suport SimpleX Chat + Proxy SOCKS + Teme În timpul importului au apărut câteva erori non-fatale: Atingeți pentru a vă alătura Atenție: este posibil să pierdeți unele date! @@ -2430,7 +2430,7 @@ Trimis contactului tău după conectare. Actualizezi la o adresă permanentă? Mesaj de bun venit - SOLICITĂRI DE CONTACT DE LA GRUPURI + Solicitări de contact de la grupuri Această setare este pentru profilul tău actual Partajează adresa veche Partajează linkul vechi diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml index b5bbf47973..18f9118d3d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml @@ -548,26 +548,26 @@ Отправлять картинки ссылок Резервная копия данных - ВЫ - НАСТРОЙКИ - ПОМОЩЬ - ПОДДЕРЖАТЬ SIMPLEX CHAT - УСТРОЙСТВО - ЧАТЫ + Вы + Настройки + Помощь + Поддержать SimpleX Chat + Устройство + Чаты Инструменты разработчика Экспериментальные функции - SOCKS-ПРОКСИ - ЗНАЧОК - ТЕМЫ - СООБЩЕНИЯ И ФАЙЛЫ - ЗВОНКИ + SOCKS-прокси + Значок + Темы + Сообщения и файлы + Звонки Режим Инкогнито База данных - ЗАПУСТИТЬ ЧАТ + Запустить чат Чат запущен Чат остановлен - БАЗА ДАННЫХ + База данных Пароль базы данных Экспорт архива чата Импорт архива чата @@ -767,7 +767,7 @@ Ошибка при удалении ссылки группы Только владельцы группы могут изменять предпочтения группы. - ДЛЯ КОНСОЛИ + Для консоли Локальное имя ID базы данных @@ -775,7 +775,7 @@ Отправить сообщение Член группы будет удалён - это действие нельзя отменить! Удалить - ЧЛЕН ГРУППЫ + Член группы Роль Поменять роль Поменять @@ -790,7 +790,7 @@ прямое непрямое (%1$s) - СЕРВЕРЫ + Серверы Получение через Отправка через Состояние сети @@ -1084,7 +1084,7 @@ Ожидание видео Видео будет получено когда Ваш контакт загрузит его. Скрыть: - ЭКСПЕРИМЕНТАЛЬНЫЕ + Экспериментальные Только 10 видео могут быть отправлены одновременно Раскрыть профиль Видео будет получено, когда Ваш контакт будет онлайн, пожалуйста, подождите или проверьте позже! @@ -1226,7 +1226,7 @@ Запретить реакции на сообщения. Запретить реакции на сообщения. секунд - ЦВЕТА ИНТЕРФЕЙСА + Цвета интерфейса Поделиться адресом с контактами SimpleX? Обновление профиля будет отправлено Вашим SimpleX контактам. Об адресе SimpleX @@ -1347,15 +1347,15 @@ Только владельцы группы могут разрешить файлы и медиа. Файлы и медиа Выключить\? - ПРИЛОЖЕНИЕ + Приложение Перезапустить Выключить Выключить для всех Включить для всех Включить (кроме исключений) Выключить отчёты о доставке\? - ОТПРАВКА ОТЧЁТОВ О ДОСТАВКЕ - ЗАПРОСЫ НА СОЕДИНЕНИЕ ИЗ ГРУПП + Отправка отчётов о доставке + Запросы на соединение из групп шифрование согласовано шифрование согласовано для %s шифрование работает @@ -1829,7 +1829,7 @@ Форма картинок профилей Квадрат, круг и все, что между ними. Будет включено в прямых разговорах! - ФАЙЛЫ + Файлы Новые темы чатов нет Светлая @@ -1898,7 +1898,7 @@ Показать статус сообщения Прямая доставка сообщений Режим доставки сообщений - КОНФИДЕНЦИАЛЬНАЯ ДОСТАВКА СООБЩЕНИЙ + Конфиденциальная доставка сообщений Цвета чата Тема чата Тема профиля @@ -2151,7 +2151,7 @@ Переслать сообщения… Проверьте правильность ссылки SimpleX. Ошибка ссылки - БАЗА ДАННЫХ + База данных Ошибка инициализации WebView. Убедитесь, что у вас установлен WebView и его поддерживаемая архитектура - arm64.\nОшибка: %s Звук отключен Сообщения будут удалены - это нельзя отменить! @@ -2719,9 +2719,9 @@ Открыть канал Открыть новый канал Владельцы - ВЛАДЕЛЕЦ + Владелец релей - РЕЛЕЙ + Релей Адрес релея Адрес релея Ошибка подключения релея @@ -2740,7 +2740,7 @@ Поделиться адресом релея Поделиться в чате ⚠️ Ошибка проверки подписи: %s. - ПОДПИСЧИК + Подписчик Подписчики Подписчик будет удалён из канала - это нельзя отменить! Начните разговор @@ -2801,7 +2801,7 @@ Вы перестанете получать сообщения из этого канала. История чата сохранится. обновлён профиль канала ошибка - ОШИБКА СОЕДИНЕНИЯ + Ошибка соединения Чат с админами Разрешить членам группы общаться с админами. Запретить чаты с админами. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml index c355d8d9fb..df879fe7ff 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/th/strings.xml @@ -996,7 +996,7 @@ ข้อความที่ข้ามไป ส่ง ระบบ - สนับสนุน SIMPLEX แชท + สนับสนุน SimpleX Chat พร็อกซี SOCKS หยุด หยุดแชท\? diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml index 0e9c54fb87..d56d308654 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml @@ -50,8 +50,8 @@ Aramayı cevapla Uygulama veri yedekleme Tüm uygulama verileri silinir. - UYGULAMA - UYGULAMA SİMGESİ + Uygulama + Uygulama simgesi 1 hafta şifreleme kabul ediliyor… yönetici @@ -86,7 +86,7 @@ Konuştuğunuz kişinin uygulamasından güvenlik kodunu okut. WebRTC ICE sunucu adreslerinin doğru formatta olduğundan emin olun: Satırlara ayrılmış ve yinelenmemiş şekilde. Kaydet - ARAYÜZ RENKLERİ + Arayüz renkleri SimpleX adres ayarlarını kaydet Ayarlar kaydedilsin mi? Kaydet ve konuştuğun kişilere bildir @@ -97,7 +97,7 @@ Ses kapalı Doğrulama iptal edildi Yeniden başlat - TEMALAR + Temalar İçe aktarılan konuşma veri tabanını kullanmak için uygulamayı yeniden başlat. Yeni bir konuşma profili oluşturmak için uygulamayı yeniden başlatın. Geri Yükle @@ -184,7 +184,7 @@ silindi dosya alma henüz desteklenmiyor sen - geçersi̇z sohbet + geçersiz sohbet bağlantı %1$d Tarayıcı ile %1$s tarafından @@ -287,10 +287,10 @@ Ek ikincil renk Üyeyi çıkar Kaldır - ARAMALAR - SOHBETLER - SEN - SOHBET VERİTABANI + Aramalar + Sohbetler + Sen + Sohbet veritabanı Kaldır Yanlış parola! Veritabanı yükseltmelerini onayla @@ -300,7 +300,7 @@ bağlanılıyor (duyuruldu) sen: %1$s kaldırıldı - ÜYE + Üye Üyeler kendiliğinden yok olan mesajlar gönderebilir. Kendiliğinden yok olan mesaj gönderimini engelle. Yalnızca kişiniz sesli mesaj göndermeye izin veriyorsa sen de ver. @@ -422,7 +422,7 @@ Eğer uygulamayı açarken tüm verileri yok eden erişim kodunu girersen: Eğer uygulamayı açarken bu erişim kodunu kullanırsan uygulama içi tüm veriler kalıcı olarak silinecektir! Erişim kodu belirle - AYGIT + Aygit Veri tabanı parolası Veri tabanı, rastgele bir parola ile şifrelendi. Dışa aktarmadan önce lütfen değiştir. Dosyaları ve medyayı sil\? @@ -600,7 +600,7 @@ ICE sonucuları kaydedilirken hata oluştu Kullanıcı gizliliği güncellenirken hata oluştu Gözde - DENEYSEL + Deneysel Dosya, sunuculardan silinecektir. Yedekleri geri yükledikten sonra şifrelemeyi onar. Fransız arayüzü @@ -622,7 +622,7 @@ Konuşma başlatılırken hata oluştu Deneysel özellikler Veri tabanını dışa aktar - YARDIM + Yardim Veri tabanını içe aktar Konuşma durdulurken hata oluştu İçe aktar @@ -634,7 +634,7 @@ grup profili güncellendi grup silindi Toplu konuşma bağlantısı güncellenirken hata oluştu - UÇBİRİM İÇİN + Uçbirim için Grup bağlantısı Grup dolaylı (%1$s) @@ -801,7 +801,7 @@ arama sona erdi %1$s Kilit ekranında aramalar: Kötü mesaj kimliği - MESAJLAR VE DOSYALAR + Mesajlar ve dosyalar Veri tabanı parolasını değiştir\? Parola Keystore\'da bulunamadı, lütfen manuel olarak girin. Bu, uygulamanın verilerini bir yedekleme aracı kullanarak geri yüklediyseniz olabilir. Eğer durum böyle değilse, lütfen geliştiricilerle iletişime geçin. Ayrıl @@ -1037,7 +1037,7 @@ Sohbeti durdur Mevcut profili kullan Sistem - SIMPLEX CHAT\'İ DESTEKLE + SimpleX Chat\'i destekle Sohbet veri tabanını dışa aktarmak, içe aktarmak veya silmek için sohbeti durdur. Sohbet durdurulduğunda mesaj alamaz ve gönderemezsiniz. Masaüstü Bağlanmak için dokun @@ -1134,7 +1134,7 @@ Bağlantı paylaş SimpleX Ekibi %s, %s ve %s bağlandı - SOCKS VEKİLİ + SOCKS vekili Masaüstür cihazlar SMP sunucuları Uyumlu değil! @@ -1217,7 +1217,7 @@ güvenlik kodu değiştirildi Bluetooth desteği ve diğer iyileştirmeler. Ayarlar - AYARLAR + Ayarlar Bağlanmak için doğrudan mesaj gönderin Güvenlik kodu Daha hızlı gruplara katılma ve daha güvenilir mesajlar. @@ -1352,7 +1352,7 @@ Yönlendirici sunucusu sadece lazım ise kullanılacak. Diğer taraf IP adresini görebilir. %s ın bağlantısı kesildi]]> Sunucuyu test et - SUNUCULAR + Sunucular Sunucuları test et Mesaj taslağı Bir mesajı yok edin @@ -1361,7 +1361,7 @@ Kişi doğrulandı Rasgele parola kullan Sistem yetkilendirilmesi yerine ayarla. - SOHBETİ ÇALIŞTIR + Sohbeti çalıştır Direkt internet bağlantısı kullan? grup profili güncellendi Onion ana bilgisayarları bağlantı için gerekli olacaktır. @@ -1446,7 +1446,7 @@ Yeni sohbet Bir canlı mesaj gönder - bu yazdıklarını anlık olarak alıcıya(lara) güncelleyen bir mesajdır Şifre Yöneticisindeki parola silinsin mi? - LERE GÖNDER + Lere gönder Takma adla bağlan Her zaman yönlendirici kullan. Kilidini aç @@ -1778,7 +1778,7 @@ Sizin veya hedef sunucunun özel yönlendirmeyi desteklememesi durumunda bile mesajları doğrudan GÖNDERMEYİN. IP adresi korumalı olduğunda ve sizin veya hedef sunucunun özel yönlendirmeyi desteklemediği durumlarda mesajları doğrudan gönderin. Sizin veya hedef sunucunun özel yönlendirmeyi desteklemediği durumlarda mesajları doğrudan gönderin. - GİZLİ MESAJ YÖNLENDİRME + Gizli mesaj yönlendirme Mesaj durumunu göster IP adresinizi korumak için,gizli yönlendirme mesajları iletmek için SMP sunucularınızı kullanır. Korumasız @@ -1805,7 +1805,7 @@ Karanlık Aydınlık mod IP adresini koru - DOSYALAR + Dosyalar Sohbet renkleri Sığdır Alınan cevap diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml index 4e62631dbb..b61b77ec9d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml @@ -33,14 +33,14 @@ Дозволити надсилати зникаючі повідомлення. прийнятий виклик Завжди використовувати реле - ДОДАТОК + Додаток Дозволити надсилання приватних повідомлень учасникам. Дозволити безповоротно видаляти надіслані повідомлення. (24 години) Дозволяйте надсилати голосові повідомлення. Дозволити реакції на повідомлення. Вся інформація стирається при його введенні. Пароль для додатка - ІКОНКА ДОДАТКУ + Іконка додатку Дозволити зникаючі повідомлення тільки за умови, що ваш контакт дозволяє їх. Дозвольте вашим контактам додавати реакції на повідомлення. Дозволити реакції на повідомлення тільки за умови, що ваш контакт дозволяє їх. @@ -278,8 +278,8 @@ Повернути камеру Відхилений виклик %1$d пропущено повідомлень - ЧАТИ - SOCKS-ПРОКСІ + Чати + SOCKS-проксі Помилка при запуску чату Зупинити Імпортувати @@ -416,9 +416,9 @@ Підключення виклику Конфіденційність і безпека Конфіденційність - НАЛАШТУВАННЯ - ДОПОМОГА - ПІДТРИМАЙТЕ SIMPLEX CHAT + Налаштування + Допомога + Підтримайте SimpleX Chat Зупиніть чат, щоб експортувати, імпортувати або видалити базу даних чату. Ви не зможете отримувати та надсилати повідомлення, поки чат зупинено. Помилка видалення бази даних чату Сповіщення будуть доставлятися лише до зупинки додатка! @@ -464,7 +464,7 @@ Перезапустити База даних чату Чат зупинено - БАЗА ДАНИХ ЧАТУ + База даних чату Новий архів бази даних Зупинити чат\? Ваша поточна база даних чату буде ВИДАЛЕНА та ЗАМІНЕНА імпортованою. @@ -658,11 +658,11 @@ Пароль самознищення увімкнено! Пароль самознищення змінено! Ваш профіль, контакти та доставлені повідомлення зберігаються на вашому пристрої. - ВИ - ПРИСТРІЙ + Ви + Пристрій Вимкнути - ТЕМИ - ПОВІДОМЛЕННЯ ТА ФАЙЛИ + Теми + Повідомлення та файли Чат працює Імпортувати базу даних Старий архів бази даних @@ -782,7 +782,7 @@ місяці Ви вже підключені до %1$s через це посилання. Режим інкогніто - СЕРВЕРИ + Сервери Зберегти вітальне повідомлення? Отримання через Приглушено, коли неактивно! @@ -879,7 +879,7 @@ %d день %d днів скасовано %s - ЗАПУСК ЧАТУ + Запуск чату Пароль бази даних Експортувати базу даних Видалити всі файли @@ -930,7 +930,7 @@ змінює адресу… Залишити спостерігач - УЧАСНИК + Учасник Режим інкогніто захищає вашу конфіденційність, використовуючи новий випадковий профіль для кожного контакту. Більше поліпшень незабаром! Тільки власники груп можуть увімкнути голосові повідомлення. @@ -979,7 +979,7 @@ Контакт відмічено Ви намагаєтеся запросити контакт, з яким ви поділилися інкогніто-профілем, до групи, в якій ви використовуєте основний профіль Помилка при створенні посилання на групу - ДЛЯ КОНСОЛІ + Для консолі Учасника буде вилучено з групи - цю дію неможливо скасувати! Змінити роль Ви все ще отримуватимете дзвінки та сповіщення від приглушених профілів, коли вони активні. @@ -1021,7 +1021,7 @@ Хост Порт Обов\'язково - КОЛЬОРИ ІНТЕРФЕЙСУ + Кольори інтерфейсу Створіть адресу, щоб дозволити людям підключатися до вас. Контакти залишатимуться підключеними. Створити SimpleX-адресу @@ -1110,7 +1110,7 @@ Галерея Команда SimpleX хоче підключитися до вас! - ЕКСПЕРИМЕНТАЛЬНІ ФУНКЦІЇ + Експериментальні функції Ви повинні використовувати найновішу версію бази даних чату лише на одному пристрої, інакше ви можете припинити отримання повідомлень від деяких контактів. Цей параметр застосовується до повідомлень у вашому поточному профілі чату Зашифрована база даних @@ -1163,7 +1163,7 @@ Кожен може хостити сервери. Інструменти розробника Експериментальні функції - ДЗВІНКИ + Дзвінки Зберегти ключову фразу в сховищі ключів Помилка шифрування бази даних Вилучити ключову фразу із сховища ключів? @@ -1259,7 +1259,7 @@ Заборонено файли та медіа! Буде відправлено ваш профіль %1$s. Вимкнути для всіх груп - НАДСИЛАТИ ПОВІДОМЛЕННЯ ПРО ДОСТАВКУ + Надсилати повідомлення про доставку Підключитися безпосередньо? %s: %s Запит на підключення буде відправлено учаснику групи. @@ -1734,7 +1734,7 @@ Звуки вхідного дзвінка Світлий режим Запасний варіант маршрутизації повідомлень - МАРШРУТИЗАЦІЯ ПРИВАТНИХ ПОВІДОМЛЕНЬ + Маршрутизація приватних повідомлень переслано Інше Дозволити надсилати посилання SimpleX. @@ -1746,7 +1746,7 @@ Камера та мікрофон Надайте дозвіл(и) на здійснення дзвінків Відкрити налаштування - ФАЙЛИ + Файли Зображення профілів Підключення до мережі адміністратори @@ -2049,7 +2049,7 @@ Скинути всі підказки Доступно оновлення: %s Завантаження оновлення скасовано - БАЗА ДАНИХ ЧАТУ + База даних чату Вибрати профіль чату Помилка при зміні профілю Повідомлення будуть видалені — це не можна скасувати! @@ -2513,7 +2513,7 @@ Дозвольте своїм контактам надсилати файли та медіа. Бот Ви, і ваш контакт можете надсилати файли та медіа. - ЗАПИТИ НА ЗВ’ЯЗОК ВІД ГРУП + Запити на зв’язок від груп Застарілі опції Помилка при відмітці як прочитане Файли та медіа заборонені у цьому чаті. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/vi/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/vi/strings.xml index 235158585d..93347fa228 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/vi/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/vi/strings.xml @@ -93,14 +93,14 @@ Ứng dụng chỉ có thể nhận thông báo khi nó đang chạy, không có dịch vụ nền nào được khởi động Bản dựng ứng dụng: %s Giao diện - ỨNG DỤNG + Ứng dụng Di chuyển dữ liệu ứng dụng Sao lưu dữ liệu ứng dụng Mã truy cập ứng dụng đã được thay thế bằng mã tự hủy. Ứng dụng mã hóa các tệp cục bộ mới (trừ video). Áp dụng Mã truy cập ứng dụng - BIỂU TƯỢNG ỨNG DỤNG + Biểu tượng ứng dụng Mã truy cập Phiên bản ứng dụng: v%s Phiên bản ứng dụng @@ -184,7 +184,7 @@ Cuộc gọi kết thúc cuộc gọi kết thúc %1$s lỗi cuộc gọi - CUỘC GỌI + Cuộc gọi Hủy xem trước ảnh Hủy xem trước tệp Hủy @@ -234,11 +234,11 @@ đang thay đổi địa chỉ cho %s… Tùy chọn trò chuyện Màu trò chuyện - CƠ SỞ DỮ LIỆU TRÒ CHUYỆN + Cơ sở dữ liệu trò chuyện Kết nối trò chuyện đã được dừng lại Cơ sở dữ liệu đã được di chuyển! Các cuộc trò chuyện - CÁC CUỘC TRÒ CHUYỆN + Các cuộc trò chuyện Kiểm tra tin nhắn mới mỗi 10 phút trong tối đa 1 phút Giao diện Trung Quốc và Tây Ban Nha Trò chuyện với nhà phát triển @@ -463,7 +463,7 @@ Xóa máy chủ Xóa hàng đợi Công cụ nhà phát triển - THIẾT BỊ + Thiết bị Tùy chọn cho nhà phát triển Xác thực thiết bị đã bị vô hiệu hóa. Tắt Khóa SimpleX. Lỗi máy chủ đích: %1$s @@ -738,7 +738,7 @@ Lỗi cập nhật cấu hình mạng Lỗi cập nhật quyền riêng tư người dùng Mở rộng chọn chức vụ - THỬ NGHIỆM + Thử nghiệm Mở rộng Thoát mà không lưu đã hết hạn @@ -748,7 +748,7 @@ Xuất cơ sở dữ liệu Lỗi tải lên kho lưu trữ Tập tin đã xuất không tồn tại - TẬP TIN + Tập tin Không thể tải các cuộc trò chuyện Không tìm thấy tệp - có thể tập tin đã bị xóa và hủy bỏ. Lỗi tệp @@ -776,7 +776,7 @@ Tệp sẽ được nhận khi liên hệ của bạn hoạt động, vui lòng chờ hoặc kiểm tra lại sau! Trạng thái tệp: %s Lấp đầy - CƠ SỞ DỮ LIỆU TRÒ CHUYỆN + Cơ sở dữ liệu trò chuyện Lỗi chuyển đổi hồ sơ Lọc các cuộc hội thoại chưa đọc và các cuộc hội thoại yêu thích. Cuối cùng, chúng ta đã có chúng! 🚀 @@ -821,7 +821,7 @@ Máy chủ chuyển tiếp %1$s không thể kết nối tới máy chủ đích %2$s. Vui lòng thử lại sau. Địa chỉ máy chủ chuyển tiếp không tương thích với cài đặt mạng: %1$s. Phiên bản máy chủ chuyển tiếp không tương thích với cài đặt mạng: %1$s. - CHO CONSOLE + Cho console Chuyển tiếp tin nhắn… Giảm thiểu sử dụng pin hơn nữa Chuyển tiếp tin nhắn mà không có tệp? @@ -863,7 +863,7 @@ Xin chào! \nKết nối với tôi qua SimpleX Chat: %s Ẩn hồ sơ - TRỢ GIÚP + Trợ giúp Nhóm sẽ bị xóa cho tất cả các thành viên - điều này không thể hoàn tác! Nhóm sẽ bị xóa cho bạn - điều này không thể hoàn tác! Tùy chọn nhóm @@ -952,7 +952,7 @@ Cài đặt cập nhật Cuộc gọi video đến Phiên bản không tương thích - MÀU SẮC GIAO DIỆN + Màu sắc giao diện đã được mời Đường dẫn không hợp lệ cuộc trò chuyện không hợp lệ @@ -1001,7 +1001,7 @@ Mời thành viên Mời vào nhóm Rời nhóm - THÀNH VIÊN + Thành viên Thông tin hàng đợi tin nhắn Chỉ dữ liệu hồ sơ cục bộ Giữ lại các kết nối của bạn @@ -1050,7 +1050,7 @@ Thành viên sẽ bị xóa khỏi nhóm - việc này không thể được hoàn tác! Chế độ sáng UI tiếng Litva - TIN NHẮN VÀ TỆP + Tin nhắn và tệp Việc xóa tin nhắn mà không thể phục hồi là bị cấm. Tham gia vào các cuộc trò chuyện nhóm Chế độ định tuyến tin nhắn @@ -1323,7 +1323,7 @@ Mật khẩu hồ sơ Ghi chú riêng tư Cấm xóa tin nhắn mà không thể phục hồi. - ĐỊNH TUYẾN TIN NHẮN RIÊNG TƯ + Định tuyến tin nhắn riêng tư Tên hồ sơ: ảnh đại diện Hồ sơ và các kết nối máy chủ @@ -1581,7 +1581,7 @@ Đặt lại tất cả số liệu thống kê? Lưu mật khẩu và mở kết nối trò chuyện Gửi - KHỞI CHẠY KẾT NỐI TRÒ CHUYỆN + Khởi chạy kết nối trò chuyện Lưu Quét / Dán đường dẫn Quét mã QR máy chủ @@ -1623,7 +1623,7 @@ Lưu lời chào? gửi thất bại Quét mã bảo mật từ ứng dụng của liên hệ bạn. - GỬI CHỈ BÁO ĐÃ NHẬN TỚI + Gửi chỉ báo đã nhận tới Tìm kiếm Tìm kiếm hoặc dán đường dẫn SimpleX Lưu danh sách @@ -1685,7 +1685,7 @@ đặt ảnh đại diện mới Các tin nhắn đã gửi sẽ bị xóa sau thời gian đã cài. thông tin hàng đợi máy chủ: %1$s\n\ntin nhắn được nhận cuối cùng: %2$s - CÀI ĐẶT + Cài đặt Đã gửi vào Địa chỉ máy chủ Mã phiên @@ -1716,7 +1716,7 @@ Đặt mật khẩu Cài đặt Địa chỉ máy chủ không tương thích với cài đặt mạng: %1$s. - CÁC MÁY CHỦ + Các máy chủ Máy chủ yêu cầu xác thực để tải lên, kiểm tra mật khẩu Máy chủ Đặt mã truy cập @@ -1828,7 +1828,7 @@ Loa ngoài bật Âm thanh đã bị tắt Ổn định - PROXY SOCKS + Proxy SOCKS Các nhóm nhỏ (tối đa 20 thành viên) Một vài lỗi không nghiêm trọng đã xảy ra trong lúc nhập: Loa ngoài tắt @@ -1896,7 +1896,7 @@ Xin gửi lời cảm ơn tới các người dùng đã góp công qua Weblate! Xin gửi lời cảm ơn tới các người dùng đã góp công qua Weblate! Chế độ hệ thống - HỖ TRỢ SIMPLEX CHAT + Hỗ trợ SimpleX Chat Lỗi tệp tạm thời Nhấn nút Kết nối TCP @@ -1947,7 +1947,7 @@ ID của tin nhắn tiếp theo là không chính xác (nhỏ hơn hoặc bằng với cái trước).\nViệc này có thể xảy ra do một vài lỗi hoặc khi kết nối bị xâm phạm. Nỗ lực đổi mật khẩu cơ sở dữ liệu đã không được hoàn thành. Tên thiết bị sẽ được chia sẻ với thiết bị di động đã được kết nối. - CÁC CHỦ ĐỀ + Các chủ đề Tên hiển thị này không hợp lệ. Xin vui lòng chọn một cái tên khác. Hồ sơ chỉ được chia sẻ với các liên hệ của bạn. Cuộc trò chuyện này được bảo vệ bằng mã hóa đầu cuối có kháng lượng tử. @@ -2196,7 +2196,7 @@ Bạn có thể thay đổi nói trong cài đặt Giao diện. Bạn đang tham gia nhóm thông qua đường dẫn này. Bạn có thể bật vào lúc sau thông qua Cài đặt - BẠN + Bạn Bạn có thể chia sẻ một đường dẫn hoặc mã QR - bất kỳ ai cũng sẽ có thể tham gia nhóm. Bạn sẽ không mất các thành viên của nhóm nếu sau này bạn xóa nó đi. Bạn có thể thử một lần nữa. Bạn đã kết nối tới máy chủ dùng để nhận tin nhắn từ liên hệ này. diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml index 1392d7b42b..ff69251bc6 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml @@ -754,7 +754,7 @@ 下一代私密通讯软件 粘贴你收到的链接 已跳过消息 - 支持 SIMPLEX CHAT + 支持 SimpleX Chat 发送链接预览 SOCKS 代理 停止聊天程序? diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml index 9ec116058a..9e51b9ba9d 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml @@ -668,7 +668,7 @@ 裝置 幫助 設定 - 幫助 SIMPLEX CHAT + 幫助 SimpleX Chat 聊天 開發者工具 SOCKS 代理伺服器 diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.desktop.kt index a1f70213d0..c875c0c9da 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.desktop.kt @@ -1,6 +1,5 @@ package chat.simplex.common.views.chatlist -import SectionDivider import androidx.compose.foundation.* import androidx.compose.foundation.interaction.InteractionSource import androidx.compose.foundation.layout.* @@ -62,6 +61,6 @@ actual fun ChatListNavLinkLayout( if (selectedChat.value || nextChatSelected.value) { Divider() } else { - SectionDivider() + Divider(Modifier.padding(horizontal = 8.dp)) } } diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt index 66be736fca..6b36a3b1b2 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/Appearance.desktop.kt @@ -1,10 +1,11 @@ package chat.simplex.common.views.usersettings +import CARD_PADDING import SectionBottomSpacer import SectionDividerSpaced -import SectionSpacer import SectionTextFooter import SectionView +import itemHPadding import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape @@ -23,7 +24,7 @@ import chat.simplex.common.model.CloseBehavior import chat.simplex.common.model.SharedPreference import chat.simplex.common.trayIsAvailable import chat.simplex.common.platform.* -import chat.simplex.common.ui.theme.DEFAULT_PADDING +import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* import chat.simplex.res.MR import dev.icerock.moko.resources.compose.stringResource @@ -82,10 +83,10 @@ fun AppearanceScope.AppearanceLayout( SectionDividerSpaced() ProfileImageSection() - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() FontScaleSection() - SectionDividerSpaced(maxTopPadding = true) + SectionDividerSpaced() DensityScaleSection() SectionBottomSpacer() @@ -110,8 +111,8 @@ private fun MinimizeToTraySection() { @Composable fun DensityScaleSection() { val localDensityScale = remember { mutableStateOf(appPrefs.densityScale.get()) } - SectionView(stringResource(MR.strings.appearance_zoom).uppercase(), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) { - Row(Modifier.padding(top = 10.dp), verticalAlignment = Alignment.CenterVertically) { + SectionView(stringResource(MR.strings.appearance_zoom), contentPadding = PaddingValues(horizontal = CARD_PADDING)) { + Row(Modifier.padding(vertical = 10.dp), verticalAlignment = Alignment.CenterVertically) { Box(Modifier.size(50.dp) .background(MaterialTheme.colors.surface, RoundedCornerShape(percent = 22)) .clip(RoundedCornerShape(percent = 22))