diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index bb7d28ba..bc768f2f 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -1,1497 +1,24 @@ - Machankura - - Channels watcher - Shows up when you need to start Phoenix. - - Payment finalisation - Tells you when Phoenix needs to be started to settle a pending payment. - - Payment rejected - Shows up when Phoenix cannot receive a payment because of a liquidity issue. - - Payment received - Shows up when you receive a payment while the app is in the background. - - Running in the background - Tells you when Phoenix is running in the background. - - Swap timeout - Tells you when a swap is going to timeout. - - - - Creating your wallet… - Wallet creation failed - This seed has already been imported - The wallet could not be written at this time. Try again later. - - Restore my wallet - Next - Restoring your wallet… - Use a custom Electrum server - - - - Etiam porttitor egestas faucibus. Curabitur condimentum eros non ipsum elementum egestas. - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut facilisis lectus. Integer massa tellus, suscipit sit amet felis vitae, blandit consectetur dolor. Fusce volutpat id magna id vestibulum. Integer a erat lacinia, placerat risus a, fermentum justo. Etiam euismod tincidunt dolor vel posuere. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur non euismod dui. Morbi enim dui, blandit sed erat sit amet, porta pulvinar odio. Cras metus felis, vestibulum eu consequat vitae, consectetur quis nulla. Fusce vulputate, elit et luctus sodales, metus metus elementum sem, eget commodo nunc nunc in ex. Sed aliquam eros nibh, ac volutpat turpis accumsan vitae. Cras suscipit ipsum accumsan aliquam interdum. - - Praesent ut nisi fringilla, pharetra dui sit amet, ornare urna. Donec at ultrices nunc. Fusce gravida metus vitae viverra egestas. In hac habitasse platea dictumst. Proin consequat fringilla felis, vehicula vehicula turpis ullamcorper nec. Pellentesque urna massa, blandit cursus metus et, ultrices consectetur neque. Suspendisse hendrerit venenatis mi ac tincidunt. Morbi hendrerit orci vitae erat luctus, at dignissim turpis accumsan. Integer elementum est eu tincidunt ullamcorper. Phasellus varius porttitor vestibulum. Maecenas faucibus ullamcorper diam, ac commodo dui fringilla sed. Aliquam arcu velit, porta eu sem vel, rhoncus bibendum dolor. - \nEtiam porttitor egestas faucibus. Curabitur condimentum eros non ipsum elementum egestas. Nam tempor euismod erat eget scelerisque. Integer sit amet laoreet erat. Duis enim turpis, vehicula eu justo vitae, dapibus auctor mauris. Aenean euismod eleifend dui a aliquet. Aliquam eleifend malesuada tortor ornare volutpat. In augue tortor, gravida et volutpat elementum, iaculis non sapien. Etiam dolor nisi, pulvinar a rhoncus ac, eleifend ac libero. In lobortis enim vitae ultricies viverra. Maecenas accumsan elementum sem, nec pharetra urna maximus maximus. - \nIn sit amet volutpat ligula, ac pretium dolor. Phasellus posuere rhoncus magna quis fermentum. Ut risus turpis, fermentum facilisis mollis in, porttitor eget erat. Donec luctus egestas ligula et interdum. Phasellus vitae hendrerit sem, at vehicula nulla. Curabitur mollis risus quis metus euismod ullamcorper. Nam eu aliquet mi. Duis id urna ac urna iaculis blandit. Morbi eros dui, congue a posuere efficitur, imperdiet a nisi. Morbi non orci non lorem aliquet tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce pulvinar, mi vitae sollicitudin dignissim, nunc urna facilisis massa, ut scelerisque mi felis in sapien. - \nNam felis felix, tristique commodo odio eget, imperdiet viverra erat. Donec venenatis magna pulvinar, finibus leo id, gravida augue. Integer ante leo, bibendum ac nibh quis, auctor commodo quam. Sed luctus vitae quam vel condimentum. Mauris eu rhoncus mauris. Fusce enim diam, consequat a odio sit amet, accumsan cursus nisl. Etiam lectus nunc, lacinia id purus sit amet, pulvinar auctor odio. Maecenas vitae arcu sit amet est cursus maximus. Nullam ac sapien non nibh tempor rhoncus. Mauris dignissim cursus libero quis egestas. - - - - - Unlock to continue - PIN code - System lock - - - - Initialising… - Preparing wallet… - Decrypting… - Starting wallet… - Opening wallet… - Select a wallet - - Could not start the wallet - Unable to read wallet data. - Try again - Unhandled file serialisation - Decryption failure:\n%1$s - Android keystore failure:\n%1$s - Manual recover - - - - Wallet recovery - This screen lets you manually recover a single wallet by entering its 12-words recovery phrase.\n\nWords must be entered in the correct order, and separated with a single space. - Enter word #%1$d - No more than 12 words! - This seed is not valid - - Import seed - Try again - Checking seed… - - An error occurred. - This seed does not match any existing wallet data. - Failed to perform keystore operations. - Recovering wallet… - - - - - - + - Waiting for confirmation - Payment pending - Payment confirmed - Payment complete - Payment has failed - - - - QR Code of the invoice/address - - Address - Synchronizing address… - Bitcoin address - Share this Bitcoin address with… - - Generating… - Single use - Bolt11 - Reusable - Bolt12 - Amount - Description - Could not generate invoice - Lightning payment - Share this Lightning payment code with… - - Bitcoin address - This QR code is a classic Bitcoin address.\n\nIt can be read by almost any Bitcoin service/wallet, but payments will be slower to arrive. - Lightning address - Lightning - This QR code is a Lightning invoice.\n\nLightning payments are very fast and usually cheaper, but some wallets and services may not support them yet.\n\nIn that case, swipe to the left to get a regular Bitcoin address. - Lightning Bolt11 - Lightning Bolt12 - Bitcoin URI - - What is this? - This Lightning address uses the modern Bip353 standard that works with Bolt12 payment requests.\n\nIt is more private than LNURL-based Lightning addresses, and can even be self-hosted.\n\nHowever, it\'s is bleeding edge tech ; some wallets or services do not understand it yet and won\'t be able to pay you. - Learn more. - - Customise this Bolt11 invoice - Customise this Bolt12 invoice - Amount (optional) - Amount to receive - Description (optional) - Enter a description for this invoice - Generate - - - - Balance - Amount is too large. - Amount cannot be negative. - This is not a valid amount. - This amount exceeds your balance. - Cannot pay more than %1$s. - This amount is below the requested amount of %1$s. - Send to - Description - Fee - N/A - Loading fee… - Amountless invoice - The invoice for this payment does not request a specific amount. This may be exploited by malicious nodes during the payment.\n\nTo be safe, ask the recipient to specify an amount when generating the invoice. - Waiting for channels… - Pay - Confirm & Pay - Try again - - Message - Tap to attach a message… - Attach a custom message - The recipient will see this message - Enter a message… - Fetching payment details… - Payment has failed - Could not retrieve payment details within a reasonable time.\n\nThe recipient may be offline or unreachable. - - Pay on-chain - On-chain transactions are typically slower and best suited for large payments. - Pay with Lightning - Lightning payments are fast and best suited for small payments. - - Address - Fee rate - Retrieving current feerate… - - Please enter a valid feerate. - Total exceeds your balance - Payment has failed - - Prepare transaction - Preparing transaction… - Executing splice… - Miner fee - Uses an effective feerate of %1$s sat/vbyte. - Total - - - - Tap to grant camera permission - Camera permission has been denied - Zoom or tap the QR to focus - - - - Send - No contacts yet… - No matches for search… - satoshi@domain, bc1q..., lnbc... - - Paste - Scan QR code - Choose image - This image could not be processed. - No QR code found in this image. - Reading input… - Fetching data from service… - Resolving payment request over DNS… - - You have on-chain funds on the final wallet, but none on Lightning. - View final wallet - - - - - ≈ %1$s - !? - Exchange rate unavailable - - just now - N/A - Processing data… - Loading data… - Loading preferences… - Copied to clipboard! - - ₿%1$s - - Open link in a browser - Open transaction in an explorer - Open address in an explorer - This field cannot be blank - Please enter a valid amount - Please enter a valid number - This field must be an integer - - Go back - Next - Copy - Share - OK - Save - Delete - Confirm - Cancel - Close - - - - Drain my wallet - Loading… - Checking balance… - Balance: %1$s (≈ %2$s) - The wallet does not have any channels that are eligible for closing. - Review closing - This address uses a different blockchain - This address uses unsupported features - This address is not supported - Closing has been initiated. The closing transaction is in your transactions list. - - No channels eligible for closing. - - - - Payment channels - Import channels - Spend channel address - Overview - Balance - Balance is the aggregated balance of your active channels. It\'s what you can spend over Lightning. - Inbound liquidity - Inbound liquidity is what your channels can receive over Lightning without having to go on-chain and pay fees. - Loading channel data… - You don\'t have any channels yet.\n\nA new payment channel will be created automatically when needed. - - - - Channel details - No active channel exists for that identifier. - Channel id - State - Balance - Inbound liquidity - - Active commitments - Inactive commitments - Funding tx: - Balance: - Capacity: - Triggered by: - - Display raw data - Share - Channels data - Share channel data - - - - Import raw channel data - This screen is a debugging tool that can be used to manually import encrypted channels data.\n\nUse with caution. - Data blob - Import - Importing data… - Import successful - You must now restart Phoenix. - Import has failed - Data are malformed. A encrypted hex blob is expected. - Data could not be decrypted by this wallet. - Version %1$d is not supported - - - - Spend channel address - This screen is a debugging tool that helps recover funds that have been accidentally sent to a channel\'s outpoint. - Amount - Tx index - Raw channel data - Remote funding pubkey - Unsigned tx - Sign - Signing… - - Signature successfully generated. - Public key - Signature - - Failed to sign data - Invalid amount - Invalid tx index - Malformed channel data - Cannot decrypt channel data - Unhandled channel state [%1$s] - Malformed channel version [%1$s] - Malformed remote funding pubkey [%1$s] - Malformed unsigned tx [%1$s] - Malformed remote funding pubkey [%1$s] - Malformed transaction [%1$s] - Invalid signature - - - - Loading… - +%1$s - - FAQ - Use the Receive and Send buttons at the bottom of this screen to get started! - Show all payments… - Desync! - Certificate - Invalid address - Connecting… - Tor - Request liquidity - You currently have %1$d payment(s) pending in your wallet.\n\nKeep the app open to make sure these payments settle properly without issues. - - - - Notifications - Important messages - Recent activity - No notifications yet - - - - Recovery phrase - Unlocking seed… - Could not unlock seed - BIP39 seed with standard BIP84 derivation path - Loading preferences… - Backup confirmation - - - - Application logs - Exporting logs… - Error: logs could not be exported - View logs… - View logs with… - Share logs… - Phoenix App logs - Share Phoenix logs… - - - - Loading payment details… - Could not find payment details - - LIQUIDITY ADDED %1$s - CHANNEL MANAGEMENT %1$s - COMPLETE %1$s - SENT %1$s - Pending… - FAILED\nNo money has been sent. - - Not received yet. - Waiting for channel to open - RECEIVED %1$s - - Waiting for confirmations - Fetching status… - 0 confirmation - Tap to accelerate - %1$d confirmation(s) - Confirmed on-chain - - Message - Sent by - Unknown - Be careful with messages from unknown sources - - Serviced by - Message - Link - Open link - Message - Decrypting message… - - Description - Note - Sent to - Bitcoin miners - Fees - Error - No description - This payment happened following a conflict in a channel. - - On-chain payment - Closing channel - Migration from legacy app - Bump transactions - Manual liquidity (+%1$s) - Channel management - Swap-out to %1$s - On-chain deposit - - to %1$s - from %1$s - - Add a custom description to this payment - Description - Attach note - Edit note - Technical details - - - - Technical details - Type of payment - Channel closing - Incoming on-chain payment (splice) - Incoming on-chain payment (new channel) - Incoming payment (legacy pay-to-open) - Incoming on-chain payment (legacy swap-in) - Incoming Lightning payment (bolt11) - Incoming Lightning payment (bolt12) - Outgoing Lightning payment (bolt11) - Outgoing Lightning payment (bolt12) - Outgoing on-chain payment - Outgoing on-chain payment (legacy swap) - Accelerate on-chain transactions - Inbound liquidity request (manual) - Inbound liquidity request (auto) - - Deposit address - Bitcoin address - - Spliced channel - Local inputs - - #%1$s: - - Liquidity requested - - Closing type - Mutual - Local - Remote - Revoked - Other - - Target public key - Payment Hash - Preimage - Cryptographic proof that the recipient successfully received the payment. - Bolt11 invoice - Invoice description - Bolt12 invoice - Offer - Metadata - Payer key - Your offer key - Purchase type - - Payment status - Successful - Confirming - Pending - Failed - - Payment parts (%1$d) - Part - Hops - - Received via - Channel operation (new or splice-in) - Lightning payment - Fee credit - Channel id - Transaction - - Created at - Completed at - Elapsed - %1$s ms - - Amount requested - Amount sent (fees included) - Amount received - Fee credit accrued - Amount added to fee credit - ≈ %1$s (now) - ≈ %1$s (then) - - - - Add contact - Send a payment - - Create new contact… - - Name cannot be left empty - Invalid Bolt12 code - Code already attached to \"%1$s\" - Invalid Lightning address - Address already attached to \"%1$s\" - This code or address is invalid - - Add an address for this contact - Edit Bolt12 code - Edit Lightning address for this contact. - - Label (optional) - Bolt12 code or Lightning address - Lightning address - Bolt12 offer code - - Do you want to delete this address? - Do you want to delete this contact? - - Attach a name to a Bolt12 code - Name - Enter a name - Pay with your Bolt12 key - If they know your own Bolt12 payment code, they will be able to tell when payments are from you. - Use a throwaway id when you pay this contact. - Addresses - Add Bolt12 code or Lightning address… - Add new… - - Search by name - No contacts found… - - Take a photo - Browse images - Delete picture - - - - Access control - - System authentication unavailable - No suitable authentication hardware on this device. - The biometric hardware is not available. Try again later. - Please enroll a PIN/Schema/Fingerprint in Android first. - The hardware is unsafe. An Android security update is required. - Not supported by this version of Android. - Too many attempts, try again later. - Unhandled hardware vendor error - Authentication attempt timed out - Authentication has been cancelled - This version of Android is not compatible. - Unhandled error code: %1$d - - Accessing the application - System authentication - Secures app entry behind the Android user credentials - Lock PIN - Secures app entry behind a 6-digits PIN code - - Lock timeout - After %1$s minute(s) of inactivity - Never - - Sending payments - Spending PIN - If enabled, a PIN code is required to spend funds from the wallet. - - Misc - Shuffle PIN keypad - - - - Legacy mode - Tap here for more info - How does it work? - Phoenix authenticates with a key unique to %1$s. This unique key becomes your password for your account there. - Privacy - The service will not have access to your wallet whatsoever. They cannot see your balance, payments, or keys. - Legacy mode - Phoenix uses a non-standard scheme on this service to be compatible with older versions of the app. The associated account will not be portable to other wallets. - Change scheme - Sign-in - Try again - Signing-in to\n%1$s - Authentication success. - Authentication failure: - Network error. Check your internet connection and try again. - An unknown error occurred. Try again. - - - - Default - Use a standard scheme compliant with the LNURL specifications. This is the recommended option for new wallets, and what the Phoenix iOS app uses. - Android Legacy - Use a legacy scheme to connect to accounts created with the old Phoenix Android app. - - - - Redeem - Requesting funds… - Amount must be at least %1$s. - Amount cannot exceed %1$s. - Withdrawal has failed: - - - - The service %1$s returned an error. Contact the helpdesk of this service if the problem persists.\n\nService message details : \"%2$s\" - The service %1$s returned an HTTP error (%2$s). Contact their helpdesk if needed. - The service %1$s returned a malformed message. - Could not connect to service %1$s. - This appears to be a website (not a lightning invoice):\n\n%1$s - Service %1$s doesn\'t support lightning addresses, or doesn\'t know this user. - - - - Served by - Description - Attach a message - My message - You can attach a message to the payment. This message will be sent to the recipient. - Pay - Requesting invoice… - Paying invoice… - - Amount must be at least %1$s - Amount must be at most %1$s - - Payment has failed. - The invoice returned by %1$s does not use the same chain as your wallet. - The invoice returned by %1$s is already in progress. - The invoice returned by %1$s has already been paid. - The invoice returned by %1$s has an incorrect amount. - The invoice returned by %1$s is malformed. - - - - Display options - Filter by name - Bitcoin unit - Satoshi - 1 sat is 0.00000001 btc - Bit - 1 bit is 0.000001 btc - Milli-Bitcoin - 1 mbtc is 0.001 btc - Bitcoin - Fiat currency - Application theme - Dark theme - Light theme - Follow system - Application language - - - - Electrum server - To secure your payment channels Phoenix monitors the Bitcoin blockchain through Electrum servers.\n\nBy default, random servers are used. You can also configure Phoenix to connect only to your own server. - Block height - Use the TLS port (default 50002). - For onion services, use the plain TCP port, not the TLS one. - Since you\'ve enabled Tor, you should use an onion address for this server. - No, I don\'t want to use an onion address - - Disconnected from Electrum - Disconnected from %1$s - Connecting to (random) %1$s - Connecting to %1$s - Connected to %1$s - - You are using a custom server - This server provided an unknown certificate. Connection is rejected. - Tor is enabled. This server should use an onion address. - - Use a custom server - Server address (host:port) - This address is invalid. - Connect - Checking certificate… - Failed to connect - This address cannot be resolved. - Untrusted certificate - SHA1 Fingerprint - SHA256 Fingerprint - Issuer - Subject - Valid until - Copy certificate - Trust certificate - - - - Tor - Enable Tor - How it works - - - - Connections status - Some connections are not established yet. The app will not function correctly until they are. - Your device has no Internet connection. The app will not function properly.\n\nPlease check your device\'s setting. - Electrum - Peer - Manage connection for %1$s - Connecting… - Connected - Disconnected - Bad certificate! - Invalid address! - Tor is enabled! - Make sure your Tor VPN is active and running. - - - - About Phoenix - Phoenix version: %1$s - Any questions? Check the FAQ - Support - Privacy - Terms - - - - Payment options - - Incoming payments - Outgoing payments - LNURL - - Invoice description - No description set… - Default description - Your invoices will use this description by default. You can override it on a case-by-case basis. - Invoice description - - Invoice expiry - Invoice expiry - Invoices that you create are stale after this delay. Default value is 1 week. - 1 hour - 1 day - 1 week (default) - 2 weeks - 3 weeks - %1$s seconds - - LNURL authentication scheme - - Bitcoin address format - Legacy - A less efficient and less private format that does not rotate addresses. However, it is compatible with almost every services and wallets. - Taproot (recommended) - Default format, with better privacy, cheaper fees and address rotation. Some services or wallets may however not understand the address. - - Enable overpayment - You\'ll be able to overpay Lightning invoices up to 2 times the amount requested. Useful for manual tipping, or as a privacy measure. - Disabled (default) - - - - Argentine Peso (official rate) - Argentine Peso - Cuban Peso (official rate) - Cuban Peso - Lebanese Pound (official rate) - Lebanese Pound - - - - Local payments - Export - No payments yet… - Today - Yesterday - Earlier this week - Last week - - Export payments - CSV export - Export your local successful payments in CSV format. Useful for accounting purposes. - Start date - End date - Include origin/destination - Include description - Export - No successful payments yet - Please pick a valid start/end date - Exporting payments… - Copy data to clipboard… - Phoenix - payments from %1$s to %2$s - Share Phoenix payments… - Share file - Export failed - No payments found. - - Database export - Encrypt and export your payments database. This can be used to migrate your payments history from this device to another. - Export database - Export has failed - The file can be found in your device\'s public folders. - - - - (inclusive) - - - - Wallet info - Legacy descriptor - Descriptor - User public key - Swap addresses - Master public key - (Path: %1$s) - - Ready for swap - Waiting for %1$d confirmations - +%1$d more… - Confirmed balance - Unconfirmed balance - +%1$s incoming - Loading wallet data… - - Swap-in addresses - Synchronizing… - Taproot - Legacy - - Lightning - Node id - Show legacy node id - Legacy node id - - Final wallet - Spend - - - - Channel management - Retrieving feerate… - My fee setting - Advanced channels management - Retrieving policy… - - - - Feerate - %1$s sat/vbyte - - Prepare payment - Estimating fees… - You will pay %1$s to the Bitcoin miners - Execute payment - Executing payment… - Payment complete - Payment failed - Cannot proceed - - - - Unknown mempool state - Phoenix was unable to retrieve the current state of the mempool and cannot estimate the speed of your transactions.\n\nCheck the mempool manually on an explorer, and use an adequate value! - ≈ 10 minutes - ≈ 30 minutes` - ≈ 1 hour - Low feerate - - - - You don\'t have any channels - Aborted by peer [%1$s] - Unable to create a new commitment - There\'s another splice in progress - Aborted due to an error - Channel is disconnected - Funding has failed [%1$s] - Not enough funds - Cannot start transaction session with the peer - Interactive tx session failed [%1$s] - Invalid splice-out pubkey script - A splice payment is already in progress - Invalid liquidity-ads request: [%1$s] - Invalid channel parameters: [%1$s] - Unexpected error: [%1$s] - - - - Delete wallet - This screens allows you delete this wallet from your device. - All data for this wallet will be deleted. This includes your payments history. - Save payments history - Review - - Confirm wallet deletion - The wallet will be completely deleted from this device. - This wallet\'s seed and its payments history will be deleted from the disk. You will be prompted to use another wallet, or create a new one. - Other wallets that you have already imported will not be deleted. - Don\'t lose your funds - I understand that if I lose the recovery phrase after deleting the wallet, any remaining funds would be permanently lost. - Delete wallet - Shutting down… - Deleting preferences… - Deleting seed… - Deleting databases… - The wallet has been successfully reset. - Reset failed - - - - Swap-in signer - This debugging tool lets you sign swap-in inputs. Only use if you understand what it does. - Unsigned tx - Server nonce - Sign - Signing… - User signature - Invalid unsigned transaction - Check that the input is complete and not missing any character. - Failed to sign input - - - - This screen allows you to link a Bolt12 code or a Lightning address to a name.\n\nThese contacts data are specific to Phoenix and stored locally. - - - - Experimental features - - Bip353 DNS address - No address yet… - Claim my address - Claiming address… - Failed to claim address - - - - Enter Lock PIN - Enter Spending PIN - Enter Spending PIN to view the seed] - Enter PIN to continue - Create Lock PIN - Create Spending PIN - Confirm PIN - - Checking PIN… - Incorrect - Locked for %1$s - - An error occurred - Malformed PIN - PIN mismatch! - Error when saving PIN - - - - APDU service for Phoenix to emulate a NFC tag - AID for the NFC tag emulated by Phoenix - - NFC is busy - NFC is not available - NFC is disabled - Tag emulation is not supported - - Nfc - Hold near the NFC reader - Ready to scan - Hold near the NFC device to read it - - - - Currency Converter - Done - Enter amount in %1$s - Add new currency… - Last refreshed: %1$s - Other… - Select a currency - No match found… - - - - Wallet - Add new wallet - Lock - - - Enter a name - Default Wallet - If a default wallet is selected, it will be automatically opened on app launch. - Hidden Wallet (WIP) - Wallet will not be visible in selector screens. To access the wallet, you must enter its lock PIN. - Pick an avatar - - - - I understand. - - - - Phoenix is running in the background - %1$s Received %2$s - - Please start wallet - An incoming settlement is pending. - - A payment is pending - Start Phoenix so the payment can be finalised in due course. - - Missed incoming payment - Phoenix was unable to start in the background. - - On-chain deposit pending (+%1$s) - Payment rejected (+%1$s) - Automated channel management is disabled. Tap for details. - Automated channel management is disabled. This deposit will expire by %1$s. - The fee was %1$s, but your max fee was set to %2$s. Tap for details. - The fee was %1$s, but your max fee was set to %2$s. This deposit will expire by %3$s. - The fee was %1$s which is more than %2$s%% of the amount received. Tap for details. - The fee was %1$s which is more than %2$s%% of the amount received. This deposit will expire by %3$s. - Payment amount is too low. - An error occurred during funding. Please try again later. - - Please start Phoenix - Some of your channels may have closed. - - - - General - Fees - Privacy & Security - Advanced - Danger zone - - Display - Wallet info - Channel management - Recovery phrase - Access control - Payment channels - Logs - Electrum server - Delete wallet - Close channels - Force-close channels - Tor - About - Payment options - Payment history - Notifications - Contacts - Currency converter - Add liquidity - - - - Confirming - Waiting for confirmation first before they can be swapped to Lightning. - - Waiting for swap - Will deploy to Lightning when mining fees are below %1$s. - Will remain on-chain because automated channels management is disabled. - Will deploy to Lightning when conditions apply. - Attention! Some funds will expire soon and won\'t be eligible for a swap anymore. - - Expired - Cannot be swapped anymore, after 4 months waiting. These funds must be spent manually. - - Final wallet - These funds come from closed Lightning channels. They must be spent manually. - On-chain balance - - Background processing restricted - Phoenix may not be able to receive payments when it is in the background, or when it is closed. - This happens because: - The device is in power saving mode - FCM notifications unavailable - If you\'re on GrapheneOS or CalyxOS, install Google Play Services to get FCM notifications. Check the FAQ for guidance. - - - - Settings - Send - Receive - - - - Create new wallet - Restore my wallet - - Phoenix is only on Lightning - Phoenix will only display funds that have already been managed by Phoenix. Funds attached to a seed generated by another application will not appear here (this includes on-chain funds). - Beware of using the same seed in parallel - Do not use the same seed simultaneously on different devices. This can cause conflicts between the two instances of Phoenix, and result in Lightning channels being closed. - - Your wallet\'s seed is a list of 12 English words. Type-in each word of this list in the box below. - Enter word #%1$s - This is not a valid word. - This seed is valid - You can now proceed and restore your wallet - This seed is not valid - Make sure you entered the correct words in the right order. - - Import payments history - Optional. Use this button to restore a payments database file from another device. - Will restore payments history - Use another file - Cannot restore payments - Try again - The file cannot be decrypted. Make sure you are using a Phoenix database file (not a CSV), and that this file matches the wallet you\'re restoring. - This file cannot be opened. Try again. - This file could not be written to the application\'s data folder. Try again. - Restore wallet - - - - Update required - This version of Phoenix (v%1$s) is not compatible with your wallet. Please update, or use a compatible version. - Update on Google Play - - - - Payment will fail - On-chain fee expected - Tap to know more - - Dismiss - Enable automated channels - Configure fee limit - - An on-chain operation will be likely required for you to receive this amount.\n\nThe fee is estimated to be around %1$s. - An on-chain operation will likely be required for you to receive this amount. - - A fee of %1$s is expected to receive this amount, and that fee is above your limit of %2$s.\n\nIncrease this limit in the channel management settings. - A fee of %1$s is expected to receive this amount, and that fee is above your limit of %2$s.\n\nIncrease this limit in the channel management settings, or request additional liquidity. - A fee of %1$s is expected to receive this amount, and that fee is more than %2$s%% of the amount.\n\nIncrease this limit in the channel management settings. - A fee of %1$s is expected to receive this amount, and that fee is more than %2$s%% of the amount.\n\nIncrease this limit in the channel management settings, or request additional liquidity. - - Inbound liquidity is insufficient for this amount, and you have disabled automated channel management. - - - - Tor is enabled - Phoenix may have issues receiving payments. Make sure the app stays open in the foreground and that connection is stable. - - - - This invoice is expired. - This payment is already being processed. Please wait for it to complete. - This payment has already been paid. - This payment does not use the same blockchain as your wallet. - Failed to process this LNURL link. Make sure it is valid. - This type of LNURL is not supported yet. - This is not a supported payment request. - Unable to retrieve data for this address. You may be experiencing a connectivity issue. - Name \"%1$s\" is not found on \"%2$s\". - This address uses an invalid Bip21 resource. - This address uses an invalid Bolt12 offer. - This address is hosted on an unsecure DNS. DNSSEC must be enabled. - - - - Must be at least %1$s - Must be no more than %1$s - - - - Bitcoin address - Send all funds to a Bitcoin address. All payments channels will be closed. - Confirm closing - All the funds will be sent to: - Miner fees estimated to: - Fee cost could not be estimated. - - Force-close channels - This screen allows you to unilaterally close your channels.\n\nThis is not a \"fix-everything\" magic button: it is here as a safety measure and should only be used in extreme scenarios. For example, if your peer (ACINQ) disappears permanently, preventing you from spending your money. In all other cases, if you experience issues with Phoenix you should contact support.\n\nForce closing channels will cost you money (to cover the on-chain fees) and will cause your funds to be locked for days.\n\nDo not uninstall the app until your channels are fully closed, or you will lose money.\n\nDo not use this feature if you don\'t fully understand what it does. - Funds will eventually be sent to the final wallet: - - Confirm force-closing - All the funds will be sent to your final wallet, after a significant delay. - Force-close all my channels - - - - Backup your wallet to prevent losing your bitcoins. - Backup my wallet - - Enable Android notifications - Notifications are disabled in Android settings. Phoenix won\'t be able to notify you when a payment is processing. - Enable - - A deposit will expire soon. - View details - - Phoenix regularly monitors the blockchain when in the background, but was unable to do so the last few days.\n\nMake sure Android does not block Phoenix, and that it can connect to Electrum. - Dismiss - - An update is available - A critical update is available. You should update Phoenix as soon as possible. - Update on Google Play - - On-chain fees are high. - See how Phoenix is affected - - Cannot access the Tor network. Phoenix will not function correctly. - Fix it - - On-chain funds pending (+%1$s) - An incoming payment has been recently rejected - %1$d incoming payments recently rejected - Payment rejected (+%1$s) - Automated channel management is disabled. - The fee was %1$s, but your max fee was set to %2$s. - The fee was %1$s which is more than %2$s%% of the amount. - Tap to configure. - View details - - Watchtower report - %1$d channel was successfully checked on %2$s. No issues were found. - %1$d channels were successfully checked on %2$s. No issues were found. - Watchtower alert - Revoked commitments were found on %1$s for channel(s): %2$s. This channel may be closed. - - - - The recovery phrase (sometimes called a seed), is a list of 12 English words. It allows you to recover full access to your funds if needed.\n\nOnly you alone possess this seed. Keep it private.\n\nDo not share this seed with anyone.\nBeware of phishing. The developers of Phoenix will never ask for your seed.\n\nDo not lose this seed.\nSave it somewhere safe (not on this phone). If you lose your seed and your phone, you\'ve lost your funds. - Display seed - KEEP THIS SEED SAFE.\nDO NOT SHARE. - You have not backed up your recovery phrase! - If you do not back it up and you lose access to Phoenix, you will lose your funds! - I have saved my recovery phrase somewhere safe. - I understand that if I lose my phone and my recovery phrase, then I will lose the funds in my wallet. - - - - Miner fees - Fees paid to the Bitcoin network miners to process the on-chain transaction. - Service fees - Fees paid for the creation of a new payment channel. This is not always required. - - Liquidity - Service fees - Fees paid for the liquidity service. - Miner fees - Fees paid to the Bitcoin network miners to process the on-chain transaction. - Caused by - This liquidity was required to receive a payment. - See how to optimise - - - - You can anonymously sign-in and authorize an action on: - You can redeem funds from\n%1$s. - The withdrawal request has been sent to %1$s.\n\nIt may take some time before they send the funds. Please keep the app online in the meanwhile. - - - - Enabling Tor - This requires installing a third-party Tor Proxy VPN app such as Orbot. - Tor can improve privacy, but may cause performance issues and missed payments. - Disabling Tor - If you disable this option, your IP address may be revealed to various service providers. - Are you sure you want to proceed ? - Processing changes… - - No access to the Tor network - Fix it - Phoenix needs access to Tor to function properly. - Make sure your Tor Proxy VPN app is up and running, and that it\'s connected to Tor. - If you don\'t have a Tor VPN app, install one. We recommend Orbot. - Open Tor settings - Open Orbot page - - - - Phoenix is a Bitcoin wallet using the Lightning network for sending and receiving payments.\n\nIt is a free open source software, developed by ACINQ under the Apache 2.0 License. - Safeguarding your key - This wallet is self-custodial: you have sole custody of the wallet\'s 12-words seed key.\n\nThis key gives access to your money. Do not reveal it to anyone, and beware of phishing. - Exchange rates - Bitcoin/fiat exchange rates are retrieved from various third-party APIs:\n\n- Blockchain.info\n- Coinbase.com\n- Bluelytics.com.ar\n- Yadio.io\n\nThose rates may not be accurate. Always check the actual Bitcoin amount before sending a payment. - - - - Welcome! - With Phoenix, sending and receiving bitcoins is easy and safe. - Next - - Bitcoin supercharged - Phoenix uses payment channels to make Bitcoin fast and private. - Next - - Your key, your bitcoins - Phoenix is self-custodial. You take control. - You can restore your wallet at anytime using your secret key. Keep it safe! - Get started - - - - Swap-in wallet - The swap-in wallet manages on-chain funds deposited to Phoenix.\n\nIt swaps them automatically to Lightning when possible, according to your channels management setting. - See how it works - Tap to configure - There are no swaps in progress. - - On-chain funds are automatically swapped into Lightning if the fee paid to miners is less than %1$s (can be configured). - Funds not swapped after %1$d months are recoverable on-chain. - Automated channels management is disabled. No swap will occur, funds will remain on-chain. - - A swap attempt failed %1$s - Channels management was disabled. - This swap will expire in a day! - This swap will expire in %1$s days. - - Timed out - These funds will be available from %1$s days onwards. - - Cancelled funds - These funds were not swapped in time. Tap to spend. - - The final wallet is where funds are sent when your Lightning channels are closed or when there is a problem. It usually should be empty. - - - - Incoming payments sometimes require on-chain transactions. This does not always happen, only when needed. - Fees are currently estimated at around %1$s (≈%2$s). - Automated channel management - Incoming payments that require on-chain operations will be rejected. - - Max fee amount - Payments whose fees exceed that value will be rejected. - This value is too low. - Below the expected fee. Some payments may be rejected. - - Advanced options - Channel management is disabled. It can be enabled in the Channel management setting screen. - Attention! - This screen is for advanced users. Do not change these settings unless you understand their purposes. - - Additional verifications - Percentage check - Check the fee relative to the amount received. This option is useful as a sanity check for small payments. - Policy overrides - Skip absolute fee check for Lightning - When enabled, incoming Lightning payments will ignore the absolute max fee limit. Only the percentage check will apply.\n\nAttention: if the Bitcoin mempool feerate is high, incoming LN payments requiring an on-chain operation could be expensive. - Save policy - Request inbound liquidity - - - Phoenix allows you to receive payments on Bitcoin\'s blockchain (L1) and Bitcoin\'s Lightning layer (L2). - \n\n - - the blockchain layer (L1) is slower, and generally much more expensive (requires miner fees) - \n - - the Lightning layer (L2) is much faster, and generally much cheaper (especially for smaller payments) - \n\n - When you receive a payment on L1, Phoenix will automatically move the funds to L2 IF the miner fees adhere to your configured fee policy. - \n\n - Payments you receive on L2 can be received instantly and for zero fees. However, occasionally an L1 operation is also required in order to manage the L2 payment channel. This can be done automatically IF the miner fees adhere to your configured fee policy. - - - - - No channels yet! - You first need funds in the wallet to use this feature. - Plan ahead your liquidity - Inbound liquidity lets you avoid on-chain transaction fees for future payments received over Lightning.\n\nBy requesting more liquidity now, you can save fees later. - More info - Current liquidity - - Request liquidity - Estimate liquidity cost - Estimating cost… - Miner fee - Mining fee contribution for the underlying on-chain transaction. - Service fee - This fee goes to the service providing the liquidity. - Duration - 1 year - As you receive funds, liquidity will be consumed and become your balance. After one year, the remaining unused liquidity will be reclaimed by the service. - The total fee is more than 25% of the liquidity amount requested. - The total fees exceed your balance. - - Review - You are requesting an initial amount of liquidity. Liquidity is not constant over time: as you receive funds over Lightning, the liquidity will be consumed and become your balance. - After one year, the remaining unused liquidity will be reclaimed by the service. - - Accept - Processing splice… - - Liquidity successfully added! - Amount added: %1$s - - Liquidity request has failed - Channels are not available. Try again later. - The requested amount is invalid. - - - - Unconfirmed - tap to accelerate - - - - Accelerate my transactions. - You can make all your unconfirmed transactions use a higher feerate to encourage miners to favour your payments. - This feerate is less than what your unconfirmed transactions are already using. Use a higher feerate. - - - - Channels are closing. - Channels are already processing a splice. Try again later. - Fee is insufficient. - This payment exceeds your balance. - The payment amount is too big - try splitting it in several parts. - The payment amount is too small. - The expiry of this payment is too far in the future. - The payment was rejected by the recipient. This particular invoice may have already been paid. - The recipient is offline. - The payment could not be relayed to the recipient (probably insufficient inbound liquidity). - An error occurred on a node in the payment route. The payment may succeed if you try again. - You have too many pending payments. Try again once they are settled. - - The ID of the payment is not valid. Try again. - This invoice has already been paid. - Your channel is not connected yet. Wait for a stable connection and try again. - Your channel is still in the process of being opened. Wait and try again. - This invoice uses unsupported features. Make sure you\'re on the latest Phoenix version. - The payment amount is invalid. - The payment could not be sent through your existing channels. - Recipient is not reachable, or does not have enough inbound liquidity. - An unknown error occurred and payment has failed. - The wallet was restarted while the payment was processing. - - - - Low feerate! - Transactions with insufficient feerate may linger for days or weeks without confirming. - Choosing the feerate is your responsibility. Once sent, this transaction cannot be cancelled, only accelerated with higher fees. - Are you sure you want to proceed? - - - - Channel size impacted - Funds sent on-chain are taken from your side of the channel, reducing the channel size by the same amount. Your inbound liquidity remains unchanged. - Don\'t show this message again. - - - - Spend cancelled swap-ins - No cancelled swap-ins yet. - Available: %1$s (%2$s) - Use this screen to spend on-chain deposits that were not swapped in time. This does not affect your Lightning channels. - Make sure the destination address is valid, and use a reasonable feerate. - Estimate fees - Estimating fees… - Broadcast - Broadcasting… - Transaction error. - This address is not valid. - Cannot create the refund transaction. - Transaction published. - You can find the transaction below. It will not appear in your payments history, so make a copy of its ID now if needed. - - - - Spend funds from final wallet - No funds available - Amount available - Use this screen to spend funds from your final wallet. These funds come from channels that have been closed in the past. This does not affect your existing Lightning channels. - - - - This is a human-readable address for your Bolt12 payment request. - Want a prettier address? Use third-party services, or self-host the address! - \ No newline at end of file + + Mantra + diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/database/repository/DatabaseChatRepository.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/database/repository/DatabaseChatRepository.kt index d3d569e4..a2c8112c 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/database/repository/DatabaseChatRepository.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/database/repository/DatabaseChatRepository.kt @@ -480,7 +480,7 @@ class DatabaseChatRepository( // TODO: Process this in the notary... sendChatMessage( - text = "Left Group", + text = "Left group", localChatRoom = localChatRoom, // TODO: Add Information/LeaveChatGroup Message Type... ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ActiveProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ActiveProfileScreen.kt index 03ae36ed..43b167fc 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ActiveProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ActiveProfileScreen.kt @@ -163,7 +163,7 @@ fun ActiveProfileScreen( TextButton( onClick = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Edit Profile") + ImplementationPendingRoute("Edit profile") ) } ) { @@ -177,7 +177,7 @@ fun ActiveProfileScreen( ) Text( - "Edit Profile" + "Edit profile" ) } @@ -204,7 +204,7 @@ fun ActiveProfileScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) Text( - "Share Profile" + "Share profile" ) } @@ -228,7 +228,7 @@ fun ActiveProfileScreen( Icon( Icons.Default.Bento, - contentDescription = "Key Packages" + contentDescription = "Key packages" ) Spacer( @@ -236,7 +236,7 @@ fun ActiveProfileScreen( ) Text( - "Key Package Management" + "Key package management" ) } } @@ -246,14 +246,14 @@ fun ActiveProfileScreen( TextButton( onClick = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Change Account") + ImplementationPendingRoute("Change account") ) } ) { Icon( Icons.Default.ImportExport, - contentDescription = "Change Profile" + contentDescription = "Change profile" ) Spacer( @@ -261,7 +261,7 @@ fun ActiveProfileScreen( ) Text( - "Change Account" + "Change account" ) } } @@ -272,20 +272,20 @@ fun ActiveProfileScreen( onClick = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Profile Keys") + ImplementationPendingRoute("Profile keys") ) } ) { Icon( Icons.Default.Key, - contentDescription = "Profile Keys" + contentDescription = "Profile keys" ) Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Profile Keys") + Text("Profile keys") } } @@ -293,14 +293,14 @@ fun ActiveProfileScreen( TextButton( onClick = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Network Relays") + ImplementationPendingRoute("Network relays") ) } ) { Icon( Icons.Default.Hub, - contentDescription = "Network Relays" + contentDescription = "Network relays" ) Spacer( @@ -308,7 +308,7 @@ fun ActiveProfileScreen( ) Text( - "Network Relays" + "Network relays" ) } } @@ -317,7 +317,7 @@ fun ActiveProfileScreen( Button( onClick = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Sign Out") + ImplementationPendingRoute("Sign out") ) } ) { diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddArtifactScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddArtifactScreen.kt index 6d39f689..dfe07bd9 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddArtifactScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddArtifactScreen.kt @@ -194,7 +194,7 @@ fun AddArtifactScreen( }, onFailure = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Failed Artifact") + ImplementationPendingRoute("Failed artifact") ) } ) @@ -205,7 +205,7 @@ fun AddArtifactScreen( Icons.Default.Add, contentDescription = "Propose artifact" ) - Text("Propose Artifact") + Text("Propose artifact") } } ) @@ -220,7 +220,7 @@ fun AddArtifactScreen( verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.space125), horizontalAlignment = Alignment.CenterHorizontally ) { - Text("Add Artifact to the group library") + Text("Add artifact to the group library") if (!addArtifactUIState.canSign) { Text( @@ -248,7 +248,7 @@ fun AddArtifactScreen( }, label = { Text( - text = "Name of Artifact" + text = "Name of artifact" ) }, placeholder = { @@ -302,7 +302,7 @@ fun AddArtifactScreen( }, label = { Text( - text = "Initial Version Label" + text = "Initial version label" ) }, placeholder = { @@ -352,7 +352,7 @@ fun AddArtifactScreen( modifier = Modifier.weight(1f) ) Text( - text = "Direct Message Detail", + text = "Direct message detail", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddChapterScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddChapterScreen.kt index 1e8e1251..cf5958a1 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddChapterScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddChapterScreen.kt @@ -187,7 +187,7 @@ fun AddChapterScreen( }, onFailure = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Failed Chapter") + ImplementationPendingRoute("Failed chapter") ) } ) @@ -197,7 +197,7 @@ fun AddChapterScreen( Icons.Default.Add, contentDescription = "Propose chapter" ) - Text("Propose Chapter") + Text("Propose chapter") } } ) @@ -239,7 +239,7 @@ fun AddChapterScreen( contentDescription = "Name of the chapter" ) }, - label = { Text("Chapter Name") }, + label = { Text("Chapter name") }, placeholder = { Text("eg. Chapter 1 — The Beginning") }, ) @@ -276,7 +276,7 @@ fun AddChapterScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Add Chapter", + text = "Add chapter", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddDialectScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddDialectScreen.kt index 54a9d997..7df205dd 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddDialectScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddDialectScreen.kt @@ -164,7 +164,7 @@ fun AddDialectScreen( }, onFailure = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Failed Dialect") + ImplementationPendingRoute("Failed dialect") ) } ) @@ -174,7 +174,7 @@ fun AddDialectScreen( Icons.Default.Add, contentDescription = "Propose dialect" ) - Text("Propose Dialect") + Text("Propose dialect") } } ) @@ -216,7 +216,7 @@ fun AddDialectScreen( }, label = { Text( - text = "Dialect Name" + text = "Dialect name" ) }, placeholder = { @@ -296,7 +296,7 @@ fun AddDialectScreen( modifier = Modifier.weight(1f) ) Text( - text = "Add Dialect", + text = "Add dialect", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddMemberToChatRoomConfirmationScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddMemberToChatRoomConfirmationScreen.kt index 0cc1f626..1670219d 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddMemberToChatRoomConfirmationScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddMemberToChatRoomConfirmationScreen.kt @@ -170,7 +170,7 @@ fun AddMemberToChatRoomConfirmationScreen( modifier = Modifier.weight(1f) ) Text( - text = "Direct Message Detail", + text = "Direct message detail", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) @@ -218,7 +218,7 @@ private fun ChatRoomDetailScreenPreview() { chatRoom = ChatRoom( id = "hex", userPublicKey = "hex", - subject = "Room Title", + subject = "Room title", description = "See something... say something.", initialGiftWrapPayloadId = "sdfaer", mlsGroupState = null diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddTranslationArtifactVersionScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddTranslationArtifactVersionScreen.kt index aa278e97..03b489f6 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddTranslationArtifactVersionScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/AddTranslationArtifactVersionScreen.kt @@ -191,7 +191,7 @@ fun AddTranslationArtifactVersionScreen( }, onFailure = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Failed Translation") + ImplementationPendingRoute("Failed translation") ) } ) @@ -201,7 +201,7 @@ fun AddTranslationArtifactVersionScreen( Icons.Default.Translate, contentDescription = "Propose translation" ) - Text("Propose Translation") + Text("Propose translation") } } ) @@ -283,7 +283,7 @@ fun AddTranslationArtifactVersionScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Add Translation", + text = "Add translation", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ArtifactDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ArtifactDetailScreen.kt index d62d2963..816f01b5 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ArtifactDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ArtifactDetailScreen.kt @@ -167,7 +167,7 @@ fun ArtifactDetailScreen( contentDescription = "Add chapter" ) Spacer(modifier = Modifier.width(MaterialTheme.spacing.space125)) - Text("Add Chapter") + Text("Add chapter") } } @@ -232,7 +232,7 @@ fun ArtifactDetailScreen( contentDescription = "Add translation" ) Spacer(modifier = Modifier.width(MaterialTheme.spacing.space125)) - Text("Add Translation") + Text("Add translation") } } @@ -291,7 +291,7 @@ fun ArtifactDetailScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Artifact Detail", + text = "Artifact detail", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChapterDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChapterDetailScreen.kt index abafbd67..7cc799a4 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChapterDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChapterDetailScreen.kt @@ -163,7 +163,7 @@ fun ChapterDetailScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Chapter Detail", + text = "Chapter detail", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomDetailScreen.kt index 25e2ae93..173705a8 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomDetailScreen.kt @@ -217,7 +217,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Add Artifact to Library") + Text("Add artifact to library") } } @@ -283,7 +283,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Add Dialect") + Text("Add dialect") } } @@ -365,7 +365,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Shared Key") + Text("Shared key") } } } @@ -426,7 +426,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Invite New Member") + Text("Invite new member") } } @@ -496,15 +496,30 @@ fun ChatRoomDetailScreen( ) { Icon( Icons.Default.Unsubscribe, - contentDescription = "Leave Group" + contentDescription = "Leave group" ) Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Leave Group") + Text("Leave group") } + + // What it actually does: sets leftGroupAt and posts a line to + // the room. Said here because the button fires immediately -- + // there is no confirmation step to say it in. + Text( + text = "Posts a line to the room saying you left, and " + + "lets you delete it from this device afterwards.", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding( + start = MaterialTheme.spacing.space600, + end = MaterialTheme.spacing.containerPadding, + bottom = MaterialTheme.spacing.compactPadding, + ) + ) } item { @@ -522,15 +537,31 @@ fun ChatRoomDetailScreen( ) { Icon( Icons.Default.DeleteForever, - contentDescription = "Delete Group" + contentDescription = "Delete group" ) Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Delete Group") + Text("Delete group") } + + // A soft delete: it sets deletedAt on the local row. Saying + // "delete" without saying where would leave somebody believing + // the messages are gone from the relays and from the other + // members, which is the opposite of true. + Text( + text = "Removes the room from this device. The messages " + + "stay on the relays and with the other members.", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding( + start = MaterialTheme.spacing.space600, + end = MaterialTheme.spacing.containerPadding, + bottom = MaterialTheme.spacing.compactPadding, + ) + ) } // Only MLS rooms have group events to read again. A NIP-17 @@ -565,7 +596,7 @@ fun ChatRoomDetailScreen( modifier = Modifier.weight(1f) ) Text( - text = "Direct Message Detail", + text = "Direct message detail", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) @@ -632,7 +663,7 @@ private fun ReindexMarmotGroupEventsButton( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Reindex Events") + Text("Reindex events") } when (reindexState) { @@ -695,7 +726,7 @@ private fun ChatRoomMessagingScreenPreview() { chatRoom = ChatRoom( id = "", userPublicKey = "", - subject = "Message Title", + subject = "Message title", description = "Description of a chat room so that members now why they are here.", initialGiftWrapPayloadId = "sdfaer", mlsGroupState = null diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomMessagingScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomMessagingScreen.kt index 51c18a6e..e33b746f 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomMessagingScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/ChatRoomMessagingScreen.kt @@ -380,7 +380,7 @@ fun ChatRoomMessagingScreen( modifier = Modifier.weight(1f) ) Text( - text = "Direct Message Detail", + text = "Direct message detail", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/CreateProfileScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/CreateProfileScreen.kt index 68800ef9..4f2102e3 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/CreateProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/CreateProfileScreen.kt @@ -73,7 +73,7 @@ fun CreateProfileScreen( is CreateProfileUIState.Declaration -> { Text( - "Create Profile", + "Create profile", style = MaterialTheme.typography.headlineSmall ) @@ -106,7 +106,7 @@ fun CreateProfileScreen( } is CreateProfileUIState.InputPrompt -> { Text( - "Create Profile", + "Create profile", style = MaterialTheme.typography.headlineSmall ) @@ -277,7 +277,7 @@ fun CreateProfileScreen( } ) { Text( - text = "Create Profile" + text = "Create profile" ) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRitualScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRitualScreen.kt index 12715e88..9066e5f2 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRitualScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/DkgRitualScreen.kt @@ -665,7 +665,7 @@ private fun DkgRitualScreenPreview() { chatRoom = ChatRoom( id = "", userPublicKey = "", - subject = "Group Discussions", + subject = "Group discussions", description = "See something... say something.", initialGiftWrapPayloadId = null, mlsGroupState = null diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/HomeScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/HomeScreen.kt index 2df7cac9..2e892a44 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/HomeScreen.kt @@ -116,9 +116,13 @@ fun HomeScreen( // default is `surface`/`onSurface` and needs no help. TopAppBar( title = { - Text( - "Torch" - ) + // "Mantra". The launcher label, the desktop window title, the + // landing screen and the package name all say so; this bar was + // the last place still saying "Torch". `UserAgent.APP_NAME` is + // the other, and is left alone -- it goes on the wire to relay + // operators, so it is a network identity question rather than + // a content one. + Text("Mantra") }, navigationIcon = { IconButton( @@ -160,11 +164,11 @@ fun HomeScreen( icon = { Icon( Icons.Default.Add, - contentDescription = "New Chat" + contentDescription = "New chat" ) }, text = { - Text("New Chat") + Text("New chat") } ) } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/KeyPackageManagementScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/KeyPackageManagementScreen.kt index b6b252b7..17a0d80a 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/KeyPackageManagementScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/KeyPackageManagementScreen.kt @@ -81,7 +81,7 @@ fun KeyPackageManagementScreen( TopAppBar( title = { Text( - text = "Key Package Management" + text = "Key package management" ) }, navigationIcon = { @@ -123,7 +123,7 @@ fun KeyPackageManagementScreen( ) Text( - text = "Publish New Key Package" + text = "Publish new key package" ) } } @@ -191,7 +191,7 @@ fun KeyPackageManagementScreen( ) { Icon( Icons.Default.LockReset, - contentDescription = "Rotate Key" + contentDescription = "Rotate key" ) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/LandingScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/LandingScreen.kt index 7b189bbb..40b1af2a 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/LandingScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/LandingScreen.kt @@ -49,7 +49,7 @@ fun LandingScreen( onClick = onNavigateToLearnMore ) { Text( - text = "Learn More", + text = "Learn more", style = MaterialTheme.typography.labelLarge, ) } @@ -83,7 +83,7 @@ fun LandingScreen( onClick = onNavigateToCreateProfile ) { Text( - "Create Profile", + "Create profile", style = MaterialTheme.typography.bodyLarge ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchResultScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchResultScreen.kt index c7dbc705..ca4ca0f6 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchResultScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SearchResultScreen.kt @@ -146,7 +146,7 @@ fun SearchResultScreen( ) { Icon( Icons.Default.Tune, - contentDescription = "Adjust Search" + contentDescription = "Adjust search" ) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomMembersScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomMembersScreen.kt index c50f8908..f4468b9c 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomMembersScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomMembersScreen.kt @@ -272,7 +272,7 @@ private fun SelectChatRoomMembersScreenPreview() { ) { SelectChatRoomMembersScreen( activeUserPublicKey = "", - name = "Group Discussions", + name = "Group discussions", description = "See something... say something.", initialSelectChatRoomMembersUIState = SelectChatRoomMembersUIState.Loaded( profiles = listOf( diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomTypeScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomTypeScreen.kt index 5b4ea830..9a03ffae 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomTypeScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SelectChatRoomTypeScreen.kt @@ -451,7 +451,7 @@ private fun SelectChatRoomTypeScreenPreview() { ) { SelectChatRoomTypeScreen( activeUserPublicKey = "", - name = "Group Discussions", + name = "Group discussions", description = "See something... say something.", memberPublicKeys = listOf("hex", "otherHex"), initialSelectChatRoomTypeUIState = SelectChatRoomTypeUIState.Loaded( diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SignInScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SignInScreen.kt index a276c263..1cbeda64 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SignInScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SignInScreen.kt @@ -63,7 +63,7 @@ fun SignInToProfileScreen( when (val signInToProfileUIState = signInToProfileViewModel.signInToProfileUIState.value) { is press.mantra.compose.ui.view.state.SignInToProfileUIState.InputPrompt -> { Text( - "Sign In", + "Sign in", style = MaterialTheme.typography.headlineSmall ) @@ -144,7 +144,7 @@ fun SignInToProfileScreen( modifier = Modifier.weight(1f) ) Text( - text = "Sign in to Npub", + text = "Sign in with an npub", style = MaterialTheme.typography.headlineMedium ) @@ -184,7 +184,7 @@ fun SignInToProfileScreen( } ) { Text( - text = "Sign In" + text = "Sign in" ) } } @@ -230,7 +230,7 @@ fun SignInToProfileScreen( } ) { Text( - text = "Sign In" + text = "Sign in" ) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SocialPreconditionScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SocialPreconditionScreen.kt index c060bba4..a4d20fb4 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SocialPreconditionScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SocialPreconditionScreen.kt @@ -87,7 +87,7 @@ fun SocialPreconditionScreen( } ) { Text( - "Invite a Friend" + "Invite a friend" ) } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SovereignWalletStartupScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SovereignWalletStartupScreen.kt index cc4a408b..3dd8a638 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SovereignWalletStartupScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/SovereignWalletStartupScreen.kt @@ -96,7 +96,7 @@ fun SovereignWalletStartupScreen( } activeWallet != null -> { LoadingDataIndicator( - text = "Opening Wallet" + text = "Opening wallet" ) LaunchedEffect(Unit) { sovereignWalletViewModel.loadSovereignData(activeWallet.id) @@ -191,7 +191,7 @@ fun SovereignWalletStartupScreen( Column(horizontalAlignment = Alignment.CenterHorizontally) { Text( - text = "Startup Error" + text = "Startup error" ) when (startupState) { diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslateChunkScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslateChunkScreen.kt index 6735f3a8..15826db4 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslateChunkScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslateChunkScreen.kt @@ -167,7 +167,7 @@ fun TranslateChunkScreen( }, onFailure = { onNavigateToRoute.invoke( - ImplementationPendingRoute("Failed Translation") + ImplementationPendingRoute("Failed translation") ) } ) @@ -177,7 +177,7 @@ fun TranslateChunkScreen( Icons.Default.Add, contentDescription = "Propose translation" ) - Text("Propose Translation") + Text("Propose translation") } } ) @@ -234,7 +234,7 @@ fun TranslateChunkScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Translate Chunk", + text = "Translate chunk", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationArtifactVersionDetailScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationArtifactVersionDetailScreen.kt index 03f311e4..7d72bf70 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationArtifactVersionDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationArtifactVersionDetailScreen.kt @@ -250,7 +250,7 @@ fun TranslationArtifactVersionDetailScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Translation Detail", + text = "Translation detail", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationChapterScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationChapterScreen.kt index 423a6b4f..40eede45 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationChapterScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/TranslationChapterScreen.kt @@ -164,7 +164,7 @@ fun TranslationChapterScreen( ) { Spacer(modifier = Modifier.weight(1f)) Text( - text = "Chapter Translation", + text = "Chapter translation", style = MaterialTheme.typography.bodyLarge, textAlign = TextAlign.Center ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/WriteNewNoteScreen.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/WriteNewNoteScreen.kt index e1601b25..cfb5a817 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/WriteNewNoteScreen.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/WriteNewNoteScreen.kt @@ -419,7 +419,7 @@ fun WriteNewNoteScreen( } ) { Text( - text = "Transmit Note" + text = "Transmit note" ) } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/navigation/MantraNavHost.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/navigation/MantraNavHost.kt index 931641a2..e7d147cd 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/navigation/MantraNavHost.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/navigation/MantraNavHost.kt @@ -627,7 +627,7 @@ fun MantraNavHost( onNavigateToInviteFriend = { navController.navigate( route = ImplementationPendingRoute( - "Invite Friend" + "Invite friend" ) ) }, @@ -1136,7 +1136,7 @@ fun MantraNavHost( onNavigateToEditProfile = { navController.navigate( route = ImplementationPendingRoute( - "Edit Profile" + "Edit profile" ) ) }, diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ArticleCard.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ArticleCard.kt index 26d5aa9b..89cbf02f 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ArticleCard.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/ArticleCard.kt @@ -106,7 +106,7 @@ private fun ArticleCard( ) } Text( - text = title ?: "Untitled Article", + text = title ?: "Untitled article", style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.onSurface, maxLines = 2, diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LightningInvoiceCard.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LightningInvoiceCard.kt index 833975d9..83739e03 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LightningInvoiceCard.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LightningInvoiceCard.kt @@ -52,7 +52,7 @@ internal fun LightningInvoiceCard( if (showConfirm) { AlertDialog( onDismissRequest = { showConfirm = false }, - title = { Text("Lightning Invoice") }, + title = { Text("Lightning invoice") }, text = { Column { Text( @@ -119,7 +119,7 @@ internal fun LightningInvoiceCard( Text( text = if (decoded.amount != null) "${decoded.amount!!.truncateToSatoshi()}" - else "Any Amount", + else "Any amount", style = MaterialTheme.typography.titleSmall, color = primary ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LiveStreamCardContent.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LiveStreamCardContent.kt index 438ae59a..af8f3235 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LiveStreamCardContent.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/content/LiveStreamCardContent.kt @@ -113,7 +113,7 @@ internal fun LiveStreamCardContent( } } Text( - text = title ?: "Live Stream", + text = title ?: "Live stream", style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.onSurface, maxLines = 2, diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/MetadataEventDetail.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/MetadataEventDetail.kt index 88e69371..a04d24cd 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/MetadataEventDetail.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/MetadataEventDetail.kt @@ -115,7 +115,7 @@ fun MetadataEventDetail( ) { Icon( Icons.Default.Bolt, - contentDescription = "Lightning Bolt", + contentDescription = "Lightning payment", modifier = Modifier.size(20.dp) ) Text( @@ -181,7 +181,7 @@ fun MetadataEventDetail( onClick = onNavigateToEditProfile ) { Text( - "Edit Profile" + "Edit profile" ) } @@ -239,20 +239,20 @@ fun MetadataEventDetail( TextButton( onClick = { onNavigateToEvent.invoke( - ImplementationPendingRoute("Add to Group") + ImplementationPendingRoute("Add to group") ) } ) { Icon( Icons.Default.GroupAdd, - contentDescription = "Add to Group" + contentDescription = "Add to group" ) Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Add To Group") + Text("Add to group") } } @@ -260,7 +260,7 @@ fun MetadataEventDetail( TextButton( onClick = { onNavigateToEvent.invoke( - ImplementationPendingRoute("Block User") + ImplementationPendingRoute("Block user") ) } ) { @@ -273,7 +273,7 @@ fun MetadataEventDetail( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Block User") + Text("Block user") } } @@ -291,13 +291,13 @@ fun MetadataEventDetail( ) { Icon( Icons.Default.Mail, - contentDescription = "Direct Message" + contentDescription = "Direct message" ) Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) ) - Text("Send Message") + Text("Send message") } } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/TextNoteEventDetail.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/TextNoteEventDetail.kt index bdd1c9fa..2a8aaac6 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/TextNoteEventDetail.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/detail/TextNoteEventDetail.kt @@ -287,7 +287,7 @@ fun TextNoteEventDetail( ) { Icon( Icons.Default.AddReaction, - contentDescription = "Add Reaction" + contentDescription = "Add reaction" ) } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/NewChatBottomSheetDialog.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/NewChatBottomSheetDialog.kt index 4bbad9ff..924593f7 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/NewChatBottomSheetDialog.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/NewChatBottomSheetDialog.kt @@ -70,16 +70,16 @@ fun NewChatBottomSheetDialog( leadingContent = { Icon( Icons.Default.Key, - contentDescription = "Direct Message via npub" + contentDescription = "Direct message via npub" ) }, headlineContent = { - Text("Direct Message via npub") + Text("Direct message via npub") }, trailingContent = { Icon( Icons.Default.ChevronRight, - contentDescription = "Direct Message via npub" + contentDescription = "Direct message via npub" ) } ) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/StartDirectMessageToNpubOrNip05Dialog.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/StartDirectMessageToNpubOrNip05Dialog.kt index bf92a99a..a3cdc745 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/StartDirectMessageToNpubOrNip05Dialog.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/dialogs/StartDirectMessageToNpubOrNip05Dialog.kt @@ -112,7 +112,7 @@ fun StartDirectMessageToNpubOrNip05Dialog( ) { Icon( Icons.Default.Close, - contentDescription = "Close Start Npub Direct Message" + contentDescription = "Close" ) } }, @@ -166,7 +166,7 @@ fun StartDirectMessageToNpubOrNip05Dialog( } } ) { - Text("Start Chat") + Text("Start chat") Spacer( modifier = Modifier.width(MaterialTheme.spacing.space125) diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/EventListView.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/EventListView.kt index c0cea8d0..ea28444a 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/EventListView.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/composable/widgets/feed/EventListView.kt @@ -100,7 +100,7 @@ fun press.mantra.compose.database.model.intermdiate.LocalNostrEvent.ListView( text = Instant.fromEpochSeconds(containedPost.createdAt).toFormattedTimeAndDateString() ) } else { - Text("Malformed Note") + Text("Malformed note") } } diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatMessageListViewModel.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatMessageListViewModel.kt index eafed371..e8a53e83 100755 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatMessageListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/ui/view/model/ChatMessageListViewModel.kt @@ -489,7 +489,7 @@ class ChatMessageListViewModel( modifier = Modifier.weight(1f) ) { Text( - text = "No Chat Message Relays were found for this user.", + text = "No chat message relays were found for this user.", textAlign = TextAlign.Center, style = MaterialTheme.typography.labelSmall ) diff --git a/docs/scripts/m3-audit.sh b/docs/scripts/m3-audit.sh index 22faa957..5a8e1e97 100755 --- a/docs/scripts/m3-audit.sh +++ b/docs/scripts/m3-audit.sh @@ -29,7 +29,7 @@ BUDGET_SPACING_LITERALS=0 # phase 2: reached 2026-09-08 BUDGET_BARE_CLICKABLE=0 # phase 3: reached 2026-09-08 BUDGET_NULL_DESCRIPTION=0 # phase 3: reached 2026-09-08 BUDGET_STRING_LITERALS=-1 # phase 4 drives to <10 -BUDGET_TITLE_CASE=-1 # phase 4 drives to 0 +BUDGET_TITLE_CASE=0 # phase 4: reached 2026-09-08 BUDGET_UNSET_COLOR_ROLES=0 # phase 1: reached 2026-09-07 fail_count=0 @@ -193,9 +193,13 @@ literals=$(( $(count 'text = "') + $(count 'Text\("') )) report 'string literals in composables' "$literals" "$BUDGET_STRING_LITERALS" res=$(count 'stringResource|Res\.string') note "stringResource / Res.string: $res" -title_case=$(grep -rhoE '"[A-Z][a-z]+( [A-Z][a-z]+)+"' "$UI" --include=*.kt 2>/dev/null | sort -u | wc -l | tr -d ' ') -report 'distinct Title Case strings' "$title_case" "$BUDGET_TITLE_CASE" -note 'includes preview sample data (person names); phase 4 triages' +# Delegated, because the grep version was wrong twice: it required every word after the +# first to be capitalised (missing "Invite a Friend") and it read one line at a time +# (missing a `Text(` whose literal was on the next). It also counted sample data -- +# "Steve Biko" is title case because that is how a name is written. +title_case=$(python3 docs/scripts/m3-title-case.py | grep -oE '[0-9]+$') +report 'Title Case in UI strings' "$title_case" "$BUDGET_TITLE_CASE" +note 'run docs/scripts/m3-title-case.py --list to see them' # --------------------------------------------------------------------------- hdr 'States and feedback (phase 5)' diff --git a/docs/scripts/m3-title-case.py b/docs/scripts/m3-title-case.py new file mode 100755 index 00000000..9f6335a8 --- /dev/null +++ b/docs/scripts/m3-title-case.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Find UI strings still written in title case. + +M3's style guide: "All text, including titles, headings, labels, menu items, navigation +components, app bars, and buttons should use sentence-style capitalization." Product names +and branded terms keep their capitals. + +Two things this gets right that the first, grep-based version did not: + + - It allows lowercase articles inside a title-cased phrase, so "Invite a Friend" is + caught. Requiring every word after the first to be capitalised missed four strings. + - It scans the whole file rather than one line at a time, so a `Text(` whose literal is + on the next line is caught. That missed one more. + +Sample data is excluded by name rather than by pattern, because "Steve Biko" and "To Kill +a Mockingbird" are title case for the correct reason: they are a person and a book. + +Usage: m3-title-case.py [--list] +""" +import os, re, sys + +UI = 'composeApp/src/commonMain/kotlin/press/mantra/compose/ui' + +SMALL = {'a', 'an', 'the', 'to', 'of', 'for', 'and', 'or', 'via', + 'in', 'on', 'at', 'with', 'from', 'by'} + +# People, book titles and other proper nouns used as preview and test fixtures. +SAMPLE = { + 'Steve Biko', 'John Doe', 'Frank Talk', 'Alan Turing', + 'To Kill a Mockingbird', 'Man With A Plan', 'Woman Of Few Words', +} + + +def offenders(): + found = [] + for root, _, files in os.walk(UI): + for f in sorted(files): + if not f.endswith('.kt'): + continue + path = os.path.join(root, f) + text = open(path, encoding='utf-8').read() + for m in re.finditer(r'"([^"$\\]{4,90})"', text): + phrase = m.group(1) + if phrase in SAMPLE: + continue + line_start = text.rfind('\n', 0, m.start()) + 1 + line = text[line_start:text.find('\n', m.start())] + if line.lstrip().startswith(('//', '*', '/*')): + continue + # A log line is not UI copy. `logger.d("Queried Sync")` is written for + # whoever is reading logcat, and sentence-casing it would be cargo cult. + if re.search(r'\blogger\s*\.\s*[dewiv]\s*\(', line): + continue + words = phrase.split() + if len(words) < 2 or not words[0][:1].isupper(): + continue + later = [w for w in words[1:] if w.lower() not in SMALL] + if not later: + continue + # Title case: every significant word capitalised, and at least one of + # them an ordinary capitalised word rather than an acronym like NIP. + if all(w[:1].isupper() for w in later) and \ + any(w[:1].isupper() and w[1:].islower() for w in later): + found.append((path, text[:m.start()].count('\n') + 1, phrase)) + return found + + +def main(): + found = offenders() + print(f' {"Title Case in UI strings":42s} {len(found):6d}') + if '--list' in sys.argv: + for path, line, phrase in found: + print(f' {path.replace(UI + "/", "")}:{line} {phrase!r}') + return 1 if found else 0 + + +if __name__ == '__main__': + sys.exit(main())