Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
39e932c674
|
|||
|
6919460d18
|
|||
|
bf58fdce1f
|
|||
|
419102959f
|
|||
|
9bcbcae688
|
|||
| 96ab4ee681 | |||
| 2524ff1061 | |||
| eb0ab75e87 | |||
| 009b4cf6b0 | |||
| c891f8585d | |||
| 2648967d7b | |||
| 438dbb2397 | |||
| 2bd139ef9e | |||
| cda0a68854 | |||
| a555707f67 | |||
| 1601914b8b | |||
| aac0f54991 | |||
| 8960b3f052 | |||
| 6db6cf7b7a | |||
| 0bc32272d2 | |||
| b05d39cc81 | |||
| 7a83483758 | |||
| 1a3112d8ef | |||
| c1d0ea1901 | |||
| db6103d448 | |||
| 8f63546524 | |||
| 90975180f5 | |||
| bd9a78b305 | |||
| 4e27c1f491 | |||
| f9f8b3fe1b | |||
| 5ddd8660a3 | |||
| fe30704496 | |||
| e997f1bf68 | |||
| ff0428550b | |||
| da6ede5f69 | |||
| 56cbf68ea5 | |||
| ebf31abafa | |||
| e317c57769 | |||
| f722a58d66 | |||
| ffcd38ef96 | |||
| 088704a768 | |||
| 10eedc0ca6 | |||
|
b285be97a1
|
|||
|
7321e82800
|
|||
|
e686afed1c
|
|||
| 2b48a20ccd | |||
| b3bd68db3d | |||
| 3e2a1fa0d7 | |||
| 26143cad54 | |||
| ed38c75193 | |||
| fdef74c353 | |||
| 030e4226f8 | |||
| 508d8dc0ba | |||
| 34afa755b8 | |||
| 45490c918d | |||
| a31fdd3ed2 |
+2
-1
@@ -14,9 +14,10 @@ target
|
||||
.gradle
|
||||
queries/damus-notifs.json
|
||||
.git
|
||||
cache
|
||||
/dist
|
||||
/packages
|
||||
.direnv/
|
||||
scripts/macos_build_secrets.sh
|
||||
/tags
|
||||
.zed
|
||||
.lsp
|
||||
Generated
+40
-8
@@ -802,6 +802,17 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e79769241dcd44edf79a732545e8b5cec84c247ac060f5252cd51885d093a8fc"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata 0.4.9",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "built"
|
||||
version = "0.7.7"
|
||||
@@ -1515,7 +1526,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "egui_nav"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/damus-io/egui-nav?rev=111de8ac40b5d18df53e9691eb18a50d49cb31d8#111de8ac40b5d18df53e9691eb18a50d49cb31d8"
|
||||
source = "git+https://github.com/damus-io/egui-nav?rev=3c67eb6298edbff36d46546897cfac33df4f04db#3c67eb6298edbff36d46546897cfac33df4f04db"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"egui_extras",
|
||||
@@ -3304,6 +3315,15 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
|
||||
|
||||
[[package]]
|
||||
name = "normpath"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nostr"
|
||||
version = "0.37.0"
|
||||
@@ -3383,8 +3403,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nostrdb"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/damus-io/nostrdb-rs?rev=a307f5d3863b5319c728b2782959839b8df544cb#a307f5d3863b5319c728b2782959839b8df544cb"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/damus-io/nostrdb-rs?rev=2b2e5e43c019b80b98f1db6a03a1b88ca699bfa3#2b2e5e43c019b80b98f1db6a03a1b88ca699bfa3"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
@@ -3398,7 +3418,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "notedeck"
|
||||
version = "0.5.6"
|
||||
version = "0.5.8"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"bech32",
|
||||
@@ -3446,7 +3466,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "notedeck_chrome"
|
||||
version = "0.5.6"
|
||||
version = "0.5.8"
|
||||
dependencies = [
|
||||
"eframe",
|
||||
"egui",
|
||||
@@ -3475,7 +3495,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "notedeck_columns"
|
||||
version = "0.5.6"
|
||||
version = "0.5.8"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bech32",
|
||||
@@ -3500,6 +3520,7 @@ dependencies = [
|
||||
"notedeck_ui",
|
||||
"oot_bitset",
|
||||
"open",
|
||||
"opener",
|
||||
"poll-promise",
|
||||
"pretty_assertions",
|
||||
"profiling",
|
||||
@@ -3528,7 +3549,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "notedeck_dave"
|
||||
version = "0.5.6"
|
||||
version = "0.5.8"
|
||||
dependencies = [
|
||||
"async-openai",
|
||||
"bytemuck",
|
||||
@@ -3552,7 +3573,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "notedeck_ui"
|
||||
version = "0.5.6"
|
||||
version = "0.5.8"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"blurhash",
|
||||
@@ -4002,6 +4023,17 @@ dependencies = [
|
||||
"pathdiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opener"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "771b9704f8cd8b424ec747a320b30b47517a6966ba2c7da90047c16f4a962223"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"normpath",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.6"
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
package.version = "0.5.6"
|
||||
package.version = "0.5.8"
|
||||
members = [
|
||||
"crates/notedeck",
|
||||
"crates/notedeck_chrome",
|
||||
@@ -12,6 +12,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
opener = "0.8.2"
|
||||
base32 = "0.4.0"
|
||||
base64 = "0.22.1"
|
||||
rmpv = "1.3.0"
|
||||
@@ -23,7 +24,7 @@ egui = { version = "0.31.1", features = ["serde"] }
|
||||
egui-wgpu = "0.31.1"
|
||||
egui_extras = { version = "0.31.1", features = ["all_loaders"] }
|
||||
egui-winit = { version = "0.31.1", features = ["android-game-activity", "clipboard"] }
|
||||
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "111de8ac40b5d18df53e9691eb18a50d49cb31d8" }
|
||||
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "3c67eb6298edbff36d46546897cfac33df4f04db" }
|
||||
egui_tabs = { git = "https://github.com/damus-io/egui-tabs", rev = "6eb91740577b374a8a6658c09c9a4181299734d0" }
|
||||
#egui_virtual_list = "0.6.0"
|
||||
egui_virtual_list = { git = "https://github.com/jb55/hello_egui", rev = "a66b6794f5e707a2f4109633770e02b02fb722e1" }
|
||||
@@ -41,7 +42,7 @@ md5 = "0.7.0"
|
||||
nostr = { version = "0.37.0", default-features = false, features = ["std", "nip49"] }
|
||||
nwc = "0.39.0"
|
||||
mio = { version = "1.0.3", features = ["os-poll", "net"] }
|
||||
nostrdb = { git = "https://github.com/damus-io/nostrdb-rs", rev = "a307f5d3863b5319c728b2782959839b8df544cb" }
|
||||
nostrdb = { git = "https://github.com/damus-io/nostrdb-rs", rev = "2b2e5e43c019b80b98f1db6a03a1b88ca699bfa3" }
|
||||
#nostrdb = "0.6.1"
|
||||
notedeck = { path = "crates/notedeck" }
|
||||
notedeck_chrome = { path = "crates/notedeck_chrome" }
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
root_dir=$PWD
|
||||
|
||||
cargo ndk --target arm64-v8a -o ./crates/notedeck_chrome/android/app/src/main/jniLibs/ build --profile release
|
||||
|
||||
cd ./crates/notedeck_chrome/android
|
||||
|
||||
./gradlew build && ./gradlew installDebug
|
||||
|
||||
cd $root_dir
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -6,9 +6,7 @@
|
||||
# Regular strings
|
||||
|
||||
# Profile about/bio field label
|
||||
About_00c0 = Über
|
||||
# Display name for account management
|
||||
Accounts_e233 = Konten
|
||||
About_00c0 = Über mich
|
||||
# Column title for account management
|
||||
Accounts_f018 = Konten
|
||||
# Button label to add a relay
|
||||
@@ -23,16 +21,10 @@ Add_a_wallet_to_continue_d170 = Wallet hinzufügen um fortzufahren
|
||||
Add_account_1cfc = Konto hinzufügen
|
||||
# Column title for adding new account
|
||||
Add_Account_d06c = Konto hinzufügen
|
||||
# Display name for adding account
|
||||
Add_Account_d715 = Konto hinzufügen
|
||||
# Column title for adding algorithm column
|
||||
Add_Algo_Column_0d75 = Algorithmus-Spalte hinzufügen
|
||||
# Display name for adding column
|
||||
Add_Column_c6ff = Spalte hinzufügen
|
||||
# Column title for adding new column
|
||||
Add_Column_c764 = Spalte hinzufügen
|
||||
# Display name for adding deck
|
||||
Add_Deck_6e5f = Deck hinzufügen
|
||||
# Column title for adding new deck
|
||||
Add_Deck_fabf = Deck hinzufügen
|
||||
# Column title for adding external notifications column
|
||||
@@ -69,8 +61,6 @@ Broadcast_Local_7e50 = Lokal senden
|
||||
Cancel_ed3b = Abbrechen
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = Zum Bearbeiten anklicken
|
||||
# Display name for note composition
|
||||
Compose_Note_ad11 = Notiz erstellen
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = Notiz erstellen
|
||||
# Button label to confirm an action
|
||||
@@ -83,8 +73,6 @@ Connecting_6b7e = Verbinde...
|
||||
Contact_List_f85a = Kontaktliste
|
||||
# Column title for contact lists
|
||||
Contacts_7533 = Kontakte
|
||||
# Timeline kind label for contact lists
|
||||
Contacts_8b98 = Kontakte
|
||||
# Column title for last notes per contact
|
||||
Contacts__last_notes_3f84 = Kontakte (letzte Notizen)
|
||||
# Button label to copy logs
|
||||
@@ -100,7 +88,7 @@ Copy_Pubkey_9cc4 = Pubkey kopieren
|
||||
# Copy the text content of the note to clipboard
|
||||
Copy_Text_f81c = Text kopieren
|
||||
# Relative time in days
|
||||
count_d_b9be = { $count }T.
|
||||
count_d_b9be = { $count }Tg.
|
||||
# Relative time in hours
|
||||
count_h_3ecb = { $count }Std.
|
||||
# Relative time in minutes
|
||||
@@ -119,12 +107,8 @@ Create_Account_6994 = Konto erstellen
|
||||
Create_Deck_16b7 = Deck erstellen
|
||||
# Column title for custom timelines
|
||||
Custom_a69e = Benutzerdefiniert
|
||||
# Display name for custom timelines
|
||||
Custom_cb4f = Benutzerdefiniert
|
||||
# Column title for zap amount customization
|
||||
Customize_Zap_Amount_cfc4 = Zap-Betrag anpassen
|
||||
# Display name for zap customization
|
||||
Customize_Zap_Amount_ed29 = Zap-Betrag anpassen
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = Damus Support
|
||||
# Label for deck name input field
|
||||
@@ -147,14 +131,10 @@ Display_name_f9d9 = Anzeigename
|
||||
domain___will_be_used_for_identification_b67e = "{ $domain }" wird zur Identifikation verwendet
|
||||
# Column title for editing deck
|
||||
Edit_Deck_4018 = Deck bearbeiten
|
||||
# Display name for editing deck
|
||||
Edit_Deck_c9ba = Deck bearbeiten
|
||||
# Button label to edit a deck
|
||||
Edit_Deck_fd93 = Deck bearbeiten
|
||||
# Button label to edit user profile
|
||||
Edit_Profile_49e6 = Profil bearbeiten
|
||||
# Display name for profile editing
|
||||
Edit_Profile_6699 = Profil bearbeiten
|
||||
# Column title for profile editing
|
||||
Edit_Profile_8ad4 = Profil bearbeiten
|
||||
# Placeholder for hashtag input field
|
||||
@@ -171,14 +151,8 @@ Enter_your_public_key__npub___nostr_address__e_g___address____or_private_key__ns
|
||||
Für das Veröffentlichen von Beiträgen und andere Aktionen ist dein privater Schlüssel erforderlich.
|
||||
# Label for find user button
|
||||
Find_User_bd12 = Profil finden
|
||||
# Timeline kind label for hashtag feeds
|
||||
Hashtag_a0ab = Hashtag
|
||||
# Display name for hashtag feeds
|
||||
Hashtags_617e = Hashtags
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = Hashtags
|
||||
# Display name for home feed
|
||||
Home_3efc = Startseite
|
||||
# Title for Home column
|
||||
Home_8c19 = Startseite
|
||||
# Label for deck icon selection
|
||||
@@ -205,10 +179,6 @@ k_5K_f7e6 = 5K
|
||||
Keep_track_of_your_notes___replies_a334 = Behalte den Überblick über deine Notizen & Antworten
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = Letzte Notiz pro Profil
|
||||
# Timeline kind label for last notes per pubkey
|
||||
Last_Notes_aefe = Letzte Notizen
|
||||
# Display name for last notes per contact
|
||||
Last_Per_Pubkey__Contact_33ce = Zuletzt pro Pubkey (Kontakt)
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = Lightning-Netzwerkadresse (lud16)
|
||||
# Login page title
|
||||
@@ -241,10 +211,6 @@ Notes_60d2 = Notizen
|
||||
Notes___Replies_1ec2 = Notizen & Antworten
|
||||
# Label for notes and replies filter
|
||||
Notes___Replies_6e3b = Notizen & Antworten
|
||||
# Timeline kind label for notifications
|
||||
Notifications_6228 = Benachrichtigungen
|
||||
# Display name for notifications
|
||||
Notifications_8029 = Benachrichtigungen
|
||||
# Column title for notifications
|
||||
Notifications_d673 = Benachrichtigungen
|
||||
# Title for notifications column
|
||||
@@ -267,30 +233,20 @@ Please_select_an_icon_655b = Bitte wählen ein Symbol aus.
|
||||
Post_now_8a49 = Jetzt veröffentlichen
|
||||
# Instruction for copying logs
|
||||
Press_the_button_below_to_copy_your_most_recent_logs_to_your_system_s_clipboard__Then_paste_it_into_your_email_322e = Drücke die Schaltfläche unten, um deine neuesten Protokolle in die Zwischenablage deines Systems zu kopieren. Dann füge sie in deine E-Mail ein.
|
||||
# Display name for user profiles
|
||||
Profile_2478 = Profil
|
||||
# Timeline kind label for user profiles
|
||||
Profile_9027 = Profil
|
||||
# Profile picture URL field label
|
||||
Profile_picture_81ff = Profilbild
|
||||
# Column title for quote composition
|
||||
Quote_475c = Zitat
|
||||
# Display name for quote composition
|
||||
Quote_a38e = Zitat
|
||||
# Error message when quote note cannot be found
|
||||
Quote_of_unknown_note_e4f0 = Zitat von unbekannter Notiz
|
||||
# Label for read-only profile mode
|
||||
Read_only_82ff = Nur Lesezugriff
|
||||
# Display name for relay management
|
||||
Relays_7335 = Relays
|
||||
# Column title for relay management
|
||||
Relays_9d89 = Relays
|
||||
# Label for relay list section
|
||||
Relays_ad5e = Relays
|
||||
# Column title for reply composition
|
||||
Reply_3bf1 = Antwort
|
||||
# Display name for reply composition
|
||||
Reply_b40f = Antworten
|
||||
# Hover text for reply button
|
||||
Reply_to_this_note_f5de = Auf diese Notiz antworten
|
||||
# Error message when reply note cannot be found
|
||||
@@ -321,12 +277,6 @@ sats_e5ec = Sats
|
||||
Save_6f7c = Speichern
|
||||
# Button label to save profile changes
|
||||
Save_changes_00db = Änderungen speichern
|
||||
# Display name for search results
|
||||
Search_0aa0 = Suche
|
||||
# Display name for search page
|
||||
Search_4503 = Suche
|
||||
# Timeline kind label for search results
|
||||
Search_a0b8 = Suche
|
||||
# Column title for search page
|
||||
Search_c573 = Suche
|
||||
# Placeholder for search notes input field
|
||||
@@ -369,8 +319,6 @@ Step_2_d08d = Schritt 2
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = Abonniere die Notizen eines anderen
|
||||
# Column title for subscribing to individual user
|
||||
Subscribe_to_someone_s_notes_b3c8 = Abonniere die Notizen von jemandem
|
||||
# Display name for support page
|
||||
Support_a4b4 = Support
|
||||
# Hover text for dark mode toggle button
|
||||
Switch_to_dark_mode_4dec = Zum Dunkelmodus wechseln
|
||||
# Hover text for light mode toggle button
|
||||
@@ -380,17 +328,9 @@ Tap_to_Load_4b05 = Zum Laden antippen
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = Die Testphase des Dave Nostr KI-Assistenten ist beendet :(. Vielen Dank fürs Ausprobieren! Zap-fähiger Dave kommt bald!
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = Unterhaltungen
|
||||
# Display name for thread view
|
||||
Thread_9957 = Unterhaltungen
|
||||
Thread_0f20 = Unterhaltung
|
||||
# Link text for thread references
|
||||
thread_ad1f = Unterhaltungen
|
||||
# Generic timeline kind label
|
||||
Timeline_b0fc = Timeline
|
||||
# Timeline kind label for universe feed
|
||||
Universe_0a3e = Weltraum
|
||||
# Display name for universe feed
|
||||
Universe_d47e = Weltraum
|
||||
thread_ad1f = Unterhaltung
|
||||
# Title for universe column
|
||||
Universe_e01e = Weltraum
|
||||
# Column title for universe feed
|
||||
@@ -403,8 +343,6 @@ username___at___domain___will_be_used_for_identification_a4fd = "{ $username }"
|
||||
Username_daa7 = Benutzername
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = Wallet
|
||||
# Display name for wallet management
|
||||
Wallet_cdca = Wallet
|
||||
# Hint for deck name input field
|
||||
We_recommend_short_names_083e = Wir empfehlen kurze Namen
|
||||
# Profile website field label
|
||||
|
||||
@@ -64,6 +64,9 @@ Algorithmic_feeds_to_aid_in_note_discovery_d344 = Algorithmic feeds to aid in no
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = Amount
|
||||
|
||||
# Label for appearance settings section
|
||||
Appearance_4c7f = Appearance
|
||||
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = Ask
|
||||
|
||||
@@ -76,6 +79,9 @@ Banner_52ef = Banner
|
||||
# Beta version label
|
||||
BETA_8e5d = BETA
|
||||
|
||||
# Option in settings section to show the source client label at the bottom of the note
|
||||
Bottom_33c8 = Bottom
|
||||
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = Broadcast
|
||||
|
||||
@@ -85,12 +91,24 @@ Broadcast_Local_7e50 = Broadcast Local
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = Cancel
|
||||
|
||||
# Label for cancel clear cache, Storage settings section
|
||||
Cancel_fd8b = Cancel
|
||||
|
||||
# Label for clear cache button, Storage settings section
|
||||
Clear_cache_dccb = Clear cache
|
||||
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = Click to edit
|
||||
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = Compose Note
|
||||
|
||||
# Label for configure relays, settings section
|
||||
Configure_relays_d156 = Configure relays
|
||||
|
||||
# Label for confirm clear cache, Storage settings section
|
||||
Confirm_9d9d = Confirm
|
||||
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = Confirm
|
||||
|
||||
@@ -163,6 +181,9 @@ Customize_Zap_Amount_cfc4 = Customize Zap Amount
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = Damus Support
|
||||
|
||||
# Label for Theme Dark, Appearance settings section
|
||||
Dark_85fe = Dark
|
||||
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = Deck name
|
||||
|
||||
@@ -223,12 +244,18 @@ Find_User_bd12 = Find User
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = Hashtags
|
||||
|
||||
# Option in settings section to hide the source client label in note display
|
||||
Hide_281d = Hide
|
||||
|
||||
# Title for Home column
|
||||
Home_8c19 = Home
|
||||
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = Icon
|
||||
|
||||
# Label for Image cache size, Storage settings section
|
||||
Image_cache_size_3004 = Image cache size:
|
||||
|
||||
# Title for individual user column
|
||||
Individual_b776 = Individual
|
||||
|
||||
@@ -259,9 +286,15 @@ k_5K_f7e6 = 5K
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = Keep track of your notes & replies
|
||||
|
||||
# Label for language, Appearance settings section
|
||||
Language_e264 = Language:
|
||||
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = Last Note per User
|
||||
|
||||
# Label for Theme Light, Appearance settings section
|
||||
Light_7475 = Light
|
||||
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = Lightning network address (lud16)
|
||||
|
||||
@@ -325,6 +358,9 @@ Open_Email_25e9 = Open Email
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = Open your default email client to get help from the Damus team
|
||||
|
||||
# Label for others settings section
|
||||
Others_7267 = Others
|
||||
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = Paste your NWC URI here...
|
||||
|
||||
@@ -394,6 +430,9 @@ Repost_this_note_8e56 = Repost this note
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = Reposted
|
||||
|
||||
# Label for reset zoom level, Appearance settings section
|
||||
Reset_62d4 = Reset
|
||||
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = Running into a bug?
|
||||
|
||||
@@ -427,6 +466,12 @@ See_the_whole_nostr_universe_7694 = See the whole nostr universe
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = Send
|
||||
|
||||
# Column title for app settings
|
||||
Settings_7a4f = Settings
|
||||
|
||||
# Label for Show source client, others settings section
|
||||
Show_source_client_9e31 = Show source client
|
||||
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = Show the last note for each user from a list
|
||||
|
||||
@@ -466,6 +511,9 @@ Step_1_8656 = Step 1
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = Step 2
|
||||
|
||||
# Label for storage settings section
|
||||
Storage_ed65 = Storage
|
||||
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = Subscribe to someone else's notes
|
||||
|
||||
@@ -484,12 +532,18 @@ Tap_to_Load_4b05 = Tap to Load
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = The Dave Nostr AI assistant trial has ended :(. Thanks for testing! Zap-enabled Dave coming soon!
|
||||
|
||||
# Label for theme, Appearance settings section
|
||||
Theme_4aac = Theme:
|
||||
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = Thread
|
||||
|
||||
# Link text for thread references
|
||||
thread_ad1f = thread
|
||||
|
||||
# Option in settings section to show the source client label at the top of the note
|
||||
Top_6aeb = Top
|
||||
|
||||
# Title for universe column
|
||||
Universe_e01e = Universe
|
||||
|
||||
@@ -505,6 +559,9 @@ username___at___domain___will_be_used_for_identification_a4fd = "{$username}" at
|
||||
# Profile username field label
|
||||
Username_daa7 = Username
|
||||
|
||||
# Label for view folder button, Storage settings section
|
||||
View_folder_9742 = View folder:
|
||||
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = Wallet
|
||||
|
||||
@@ -532,6 +589,9 @@ Zap_16b4 = Zap
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = Zap this note
|
||||
|
||||
# Label for zoom level, Appearance settings section
|
||||
Zoom_Level_29a8 = Zoom Level:
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
# Search results count
|
||||
|
||||
@@ -64,6 +64,9 @@ Algorithmic_feeds_to_aid_in_note_discovery_d344 = {"["}Àlgóríthmíç fééds
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = {"["}Àmóúñt{"]"}
|
||||
|
||||
# Label for appearance settings section
|
||||
Appearance_4c7f = {"["}Àppéàràñçé{"]"}
|
||||
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = {"["}Àsk{"]"}
|
||||
|
||||
@@ -76,6 +79,9 @@ Banner_52ef = {"["}Bàññér{"]"}
|
||||
# Beta version label
|
||||
BETA_8e5d = {"["}BÉTÀ{"]"}
|
||||
|
||||
# Option in settings section to show the source client label at the bottom of the note
|
||||
Bottom_33c8 = {"["}Bóttóm{"]"}
|
||||
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = {"["}Bróàdçàst{"]"}
|
||||
|
||||
@@ -85,12 +91,24 @@ Broadcast_Local_7e50 = {"["}Bróàdçàst Lóçàl{"]"}
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = {"["}Çàñçél{"]"}
|
||||
|
||||
# Label for cancel clear cache, Storage settings section
|
||||
Cancel_fd8b = {"["}Çàñçél{"]"}
|
||||
|
||||
# Label for clear cache button, Storage settings section
|
||||
Clear_cache_dccb = {"["}Çléàr çàçhé{"]"}
|
||||
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = {"["}Çlíçk tó édít{"]"}
|
||||
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = {"["}Çómpósé Ñóté{"]"}
|
||||
|
||||
# Label for configure relays, settings section
|
||||
Configure_relays_d156 = {"["}Çóñfígúré rélàys{"]"}
|
||||
|
||||
# Label for confirm clear cache, Storage settings section
|
||||
Confirm_9d9d = {"["}Çóñfírm{"]"}
|
||||
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = {"["}Çóñfírm{"]"}
|
||||
|
||||
@@ -163,6 +181,9 @@ Customize_Zap_Amount_cfc4 = {"["}Çústómízé Zàp Àmóúñt{"]"}
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = {"["}Dàmús Súppórt{"]"}
|
||||
|
||||
# Label for Theme Dark, Appearance settings section
|
||||
Dark_85fe = {"["}Dàrk{"]"}
|
||||
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = {"["}Déçk ñàmé{"]"}
|
||||
|
||||
@@ -223,12 +244,18 @@ Find_User_bd12 = {"["}Fíñd Úsér{"]"}
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = {"["}Hàshtàgs{"]"}
|
||||
|
||||
# Option in settings section to hide the source client label in note display
|
||||
Hide_281d = {"["}Hídé{"]"}
|
||||
|
||||
# Title for Home column
|
||||
Home_8c19 = {"["}Hómé{"]"}
|
||||
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = {"["}Íçóñ{"]"}
|
||||
|
||||
# Label for Image cache size, Storage settings section
|
||||
Image_cache_size_3004 = {"["}Ímàgé çàçhé sízé:{"]"}
|
||||
|
||||
# Title for individual user column
|
||||
Individual_b776 = {"["}Íñdívídúàl{"]"}
|
||||
|
||||
@@ -259,9 +286,15 @@ k_5K_f7e6 = {"["}5K{"]"}
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = {"["}Kéép tràçk óf yóúr ñótés & réplíés{"]"}
|
||||
|
||||
# Label for language, Appearance settings section
|
||||
Language_e264 = {"["}Làñgúàgé:{"]"}
|
||||
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = {"["}Làst Ñóté pér Úsér{"]"}
|
||||
|
||||
# Label for Theme Light, Appearance settings section
|
||||
Light_7475 = {"["}Líght{"]"}
|
||||
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = {"["}Líghtñíñg ñétwórk àddréss (lúd16){"]"}
|
||||
|
||||
@@ -325,6 +358,9 @@ Open_Email_25e9 = {"["}Ópéñ Émàíl{"]"}
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = {"["}Ópéñ yóúr défàúlt émàíl çlíéñt tó gét hélp fróm thé Dàmús téàm{"]"}
|
||||
|
||||
# Label for others settings section
|
||||
Others_7267 = {"["}Óthérs{"]"}
|
||||
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = {"["}Pàsté yóúr ÑWÇ ÚRÍ héré...{"]"}
|
||||
|
||||
@@ -394,6 +430,9 @@ Repost_this_note_8e56 = {"["}Répóst thís ñóté{"]"}
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = {"["}Répóstéd{"]"}
|
||||
|
||||
# Label for reset zoom level, Appearance settings section
|
||||
Reset_62d4 = {"["}Rését{"]"}
|
||||
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = {"["}Rúññíñg íñtó à búg?{"]"}
|
||||
|
||||
@@ -427,6 +466,12 @@ See_the_whole_nostr_universe_7694 = {"["}Séé thé whólé ñóstr úñívérs
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = {"["}Séñd{"]"}
|
||||
|
||||
# Column title for app settings
|
||||
Settings_7a4f = {"["}Séttíñgs{"]"}
|
||||
|
||||
# Label for Show source client, others settings section
|
||||
Show_source_client_9e31 = {"["}Shów sóúrçé çlíéñt{"]"}
|
||||
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = {"["}Shów thé làst ñóté fór éàçh úsér fróm à líst{"]"}
|
||||
|
||||
@@ -466,6 +511,9 @@ Step_1_8656 = {"["}Stép 1{"]"}
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = {"["}Stép 2{"]"}
|
||||
|
||||
# Label for storage settings section
|
||||
Storage_ed65 = {"["}Stóràgé{"]"}
|
||||
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = {"["}Súbsçríbé tó sóméóñé élsé's ñótés{"]"}
|
||||
|
||||
@@ -484,12 +532,18 @@ Tap_to_Load_4b05 = {"["}Tàp tó Lóàd{"]"}
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = {"["}Thé Dàvé Ñóstr ÀÍ àssístàñt tríàl hàs éñdéd :(. Thàñks fór téstíñg! Zàp-éñàbléd Dàvé çómíñg sóóñ!{"]"}
|
||||
|
||||
# Label for theme, Appearance settings section
|
||||
Theme_4aac = {"["}Thémé:{"]"}
|
||||
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = {"["}Thréàd{"]"}
|
||||
|
||||
# Link text for thread references
|
||||
thread_ad1f = {"["}thréàd{"]"}
|
||||
|
||||
# Option in settings section to show the source client label at the top of the note
|
||||
Top_6aeb = {"["}Tóp{"]"}
|
||||
|
||||
# Title for universe column
|
||||
Universe_e01e = {"["}Úñívérsé{"]"}
|
||||
|
||||
@@ -505,6 +559,9 @@ username___at___domain___will_be_used_for_identification_a4fd = {"["}"{$username
|
||||
# Profile username field label
|
||||
Username_daa7 = {"["}Úsérñàmé{"]"}
|
||||
|
||||
# Label for view folder button, Storage settings section
|
||||
View_folder_9742 = {"["}Víéw fóldér:{"]"}
|
||||
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = {"["}Wàllét{"]"}
|
||||
|
||||
@@ -532,6 +589,9 @@ Zap_16b4 = {"["}Zàp{"]"}
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = {"["}Zàp thís ñóté{"]"}
|
||||
|
||||
# Label for zoom level, Appearance settings section
|
||||
Zoom_Level_29a8 = {"["}Zóóm Lévél:{"]"}
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
# Search results count
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
# Main translation file for Notedeck
|
||||
# This file contains common UI strings used throughout the application
|
||||
# Auto-generated by extract_i18n.py - DO NOT EDIT MANUALLY
|
||||
|
||||
|
||||
# Regular strings
|
||||
|
||||
# Profile about/bio field label
|
||||
About_00c0 = Información
|
||||
# Column title for account management
|
||||
Accounts_f018 = Cuentas
|
||||
# Button label to add a relay
|
||||
Add_269d = Agregar
|
||||
# Label for add column button
|
||||
Add_47df = Agregar
|
||||
# Button label to add a different wallet
|
||||
Add_a_different_wallet_that_will_only_be_used_for_this_account_de8d = Agregar una billetera diferente que solo se utilizará para esta cuenta
|
||||
# Error message for missing wallet
|
||||
Add_a_wallet_to_continue_d170 = Agregar una billetera para continuar
|
||||
# Button label to add a new account
|
||||
Add_account_1cfc = Agregar cuenta
|
||||
# Column title for adding new account
|
||||
Add_Account_d06c = Agregar cuenta
|
||||
# Column title for adding algorithm column
|
||||
Add_Algo_Column_0d75 = Agregar columna algorítmica
|
||||
# Column title for adding new column
|
||||
Add_Column_c764 = Agregar columna
|
||||
# Column title for adding new deck
|
||||
Add_Deck_fabf = Agregar deck
|
||||
# Column title for adding external notifications column
|
||||
Add_External_Notifications_Column_41ae = Agregar columna de notificaciones externas
|
||||
# Column title for adding hashtag column
|
||||
Add_Hashtag_Column_ebf4 = Agregar columna de hashtags
|
||||
# Column title for adding last notes column
|
||||
Add_Last_Notes_Column_bbad = Agregar columna de últimas notas
|
||||
# Column title for adding notifications column
|
||||
Add_Notifications_Column_79f8 = Agregar columna de notificaciones
|
||||
# Button label to add a relay
|
||||
Add_relay_269d = Agregar relé
|
||||
# Button label to add a wallet
|
||||
Add_Wallet_d1be = Agregar billetera
|
||||
# Title for algorithmic feeds column
|
||||
Algo_2452 = Algo
|
||||
# Description for algorithmic feeds column
|
||||
Algorithmic_feeds_to_aid_in_note_discovery_d344 = Feeds algorítmicos para ayudar en el descubrimiento de notas
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = Cantidad
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = Preguntar
|
||||
# Placeholder text for Dave AI input field
|
||||
Ask_dave_anything_33d1 = Pregúntale cualquier cosa a Dave...
|
||||
# Profile banner URL field label
|
||||
Banner_52ef = Banner
|
||||
# Beta version label
|
||||
BETA_8e5d = BETA
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = Transmitir
|
||||
# Broadcast the note only to local network relays
|
||||
Broadcast_Local_7e50 = Transmitir localmente
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = Cancelar
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = Haz clic para editar
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = Redactar nota
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = Confirmar
|
||||
# Status label for connected relay
|
||||
Connected_f8cc = Conectado
|
||||
# Status label for connecting relay
|
||||
Connecting_6b7e = Conectando...
|
||||
# Title for contact list column
|
||||
Contact_List_f85a = Lista de contactos
|
||||
# Column title for contact lists
|
||||
Contacts_7533 = Contactos
|
||||
# Column title for last notes per contact
|
||||
Contacts__last_notes_3f84 = Contactos (últimas notas)
|
||||
# Button label to copy logs
|
||||
Copy_a688 = Copiar
|
||||
# Button to copy media link to clipboard
|
||||
Copy_Link_dc7c = Copiar enlace
|
||||
# Copy the unique note identifier to clipboard
|
||||
Copy_Note_ID_6b45 = Copiar ID de nota
|
||||
# Copy the raw note data in JSON format to clipboard
|
||||
Copy_Note_JSON_9e4e = Copiar JSON de nota
|
||||
# Copy the author's public key to clipboard
|
||||
Copy_Pubkey_9cc4 = Copiar pubkey
|
||||
# Copy the text content of the note to clipboard
|
||||
Copy_Text_f81c = Copiar texto
|
||||
# Relative time in days
|
||||
count_d_b9be = { $count }d
|
||||
# Relative time in hours
|
||||
count_h_3ecb = { $count }h
|
||||
# Relative time in minutes
|
||||
count_m_b41e = { $count }m
|
||||
# Relative time in months
|
||||
count_mo_7aba = { $count }mes
|
||||
# Relative time in seconds
|
||||
count_s_aa26 = { $count }s
|
||||
# Relative time in weeks
|
||||
count_w_7468 = { $count }sem
|
||||
# Relative time in years
|
||||
count_y_9408 = { $count }a
|
||||
# Button to create a new account
|
||||
Create_Account_6994 = Crear cuenta
|
||||
# Button label to create a new deck
|
||||
Create_Deck_16b7 = Crear deck
|
||||
# Column title for custom timelines
|
||||
Custom_a69e = Personalizado
|
||||
# Column title for zap amount customization
|
||||
Customize_Zap_Amount_cfc4 = Personalizar cantidad de zap
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = Ayuda de Damus
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = Nombre del deck
|
||||
# Label for decks section in side panel
|
||||
DECKS_1fad = DECKS
|
||||
# Label for default zap amount input
|
||||
Default_amount_per_zap_399d = Cantidad predeterminada por zap:
|
||||
# Name of the default deck feed
|
||||
Default_Deck_fcca = Deck predeterminado
|
||||
# Button label to delete a deck
|
||||
Delete_Deck_bb29 = Eliminar deck
|
||||
# Tooltip for deleting a column
|
||||
Delete_this_column_8d5a = Eliminar esta columna
|
||||
# Button label to delete a wallet
|
||||
Delete_Wallet_d1d4 = Eliminar billetera
|
||||
# Profile display name field label
|
||||
Display_name_f9d9 = Nombre para mostrar
|
||||
# Domain identification message
|
||||
domain___will_be_used_for_identification_b67e = "{ $domain }" se utilizará para la identificación
|
||||
# Column title for editing deck
|
||||
Edit_Deck_4018 = Editar deck
|
||||
# Button label to edit a deck
|
||||
Edit_Deck_fd93 = Editar deck
|
||||
# Button label to edit user profile
|
||||
Edit_Profile_49e6 = Editar perfil
|
||||
# Column title for profile editing
|
||||
Edit_Profile_8ad4 = Editar perfil
|
||||
# Placeholder for hashtag input field
|
||||
Enter_the_desired_hashtags_here__for_multiple_space-separated_7a69 = Ingresa aquí los hashtags deseados (si son varios, sepáralos con un espacio)
|
||||
# Placeholder for relay input field
|
||||
Enter_the_relay_here_1c8b = Ingresa el relé aquí
|
||||
# Hint text to prompt entering the user's public key.
|
||||
Enter_the_user_s_key__npub__hex__nip05__here_650c = Ingresa la clave del usuario (npub, hex, nip05) aquí...
|
||||
# Label for key input field. Key can be public key (npub), private key (nsec), or Nostr address (NIP-05).
|
||||
Enter_your_key_0fca = Ingresa tu clave
|
||||
# Instructions for entering Nostr credentials
|
||||
Enter_your_public_key__npub___nostr_address__e_g___address____or_private_key__nsec___You_must_enter_your_private_key_to_be_able_to_post__reply__etc_48e9 = Ingresa tu clave pública (npub), dirección de Nostr (por ejemplo, { $address }) o clave privada (nsec). Debes ingresar tu clave privada para poder publicar, responder, etc.
|
||||
# Label for find user button
|
||||
Find_User_bd12 = Buscar usuario
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = Hashtags
|
||||
# Title for Home column
|
||||
Home_8c19 = Inicio
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = Ícono
|
||||
# Title for individual user column
|
||||
Individual_b776 = Individual
|
||||
# Error message for invalid zap amount
|
||||
Invalid_amount_6630 = Cantidad no válida
|
||||
# Error message for invalid key input
|
||||
Invalid_key_4726 = Clave no válida.
|
||||
# Error message for invalid Nostr Wallet Connect URI
|
||||
Invalid_NWC_URI_031b = NWC URI no válido
|
||||
# Zap amount button for 100000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_100K_686c = 100.000
|
||||
# Zap amount button for 10000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_10K_f7e6 = 10.000
|
||||
# Zap amount button for 20000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_20K_4977 = 20.000
|
||||
# Zap amount button for 50000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_50K_c2dc = 50.000
|
||||
# Zap amount button for 5000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_5K_f7e6 = 5.000
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = Haz seguimiento de tus notas y respuestas
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = Última nota por usuario
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = Dirección de la red Lightning (lud16)
|
||||
# Login page title
|
||||
Login_9eef = Inicio de sesión
|
||||
# Login button text
|
||||
Login_now___let_s_do_this_5630 = Inicia sesión ahora, ¡manos a la obra!
|
||||
# Text shown on blurred media from unfollowed users
|
||||
Media_from_someone_you_don_t_follow_5611 = Contenido multimedia de alguien que no sigues
|
||||
# Tooltip for moving a column
|
||||
Moves_this_column_to_another_position_0d4b = Mueve esta columna a otra posición
|
||||
# Title for the user's deck
|
||||
My_Deck_4ac5 = Mi deck
|
||||
# Label asking if the user is new to Nostr. Underneath this label is a button to create an account.
|
||||
New_to_Nostr_a2fd = ¿Primera vez en Nostr?
|
||||
# NIP-05 identity field label
|
||||
Nostr_address__NIP-05_identity_74a2 = Dirección de Nostr (identidad NIP-05)
|
||||
# Default username when profile is not available
|
||||
nostrich_df29 = nostrich
|
||||
# Status label for disconnected relay
|
||||
Not_Connected_6292 = No conectado
|
||||
# Link text for note references
|
||||
note_cad6 = nota
|
||||
# Beta product warning message
|
||||
Notedeck_is_a_beta_product__Expect_bugs_and_contact_us_when_you_run_into_issues_a671 = Notedeck es un producto en fase beta. Es posible que haya errores, así que ponte en contacto con nosotros si tienes algún problema.
|
||||
# Filter label for notes only view
|
||||
Notes_03fb = Notas
|
||||
# Label for notes-only filter
|
||||
Notes_60d2 = Notas
|
||||
# Filter label for notes and replies view
|
||||
Notes___Replies_1ec2 = Notas y respuestas
|
||||
# Label for notes and replies filter
|
||||
Notes___Replies_6e3b = Notas y respuestas
|
||||
# Column title for notifications
|
||||
Notifications_d673 = Notificaciones
|
||||
# Title for notifications column
|
||||
Notifications_ef56 = Notificaciones
|
||||
# Relative time for very recent events (less than 3 seconds)
|
||||
now_2181 = ahora
|
||||
# Button label to open email client
|
||||
Open_Email_25e9 = Abrir correo electrónico
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = Abre tu cliente de correo predeterminado para recibir ayuda del equipo de Damus
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = Pega tu NWC URI aquí...
|
||||
# Error message for missing deck name
|
||||
Please_create_a_name_for_the_deck_38e7 = Crea un nombre para el deck.
|
||||
# Error message for missing deck name and icon
|
||||
Please_create_a_name_for_the_deck_and_select_an_icon_0add = Crea un nombre para el deck y selecciona un ícono.
|
||||
# Error message for missing deck icon
|
||||
Please_select_an_icon_655b = Selecciona un ícono.
|
||||
# Button label to post a note
|
||||
Post_now_8a49 = Publicar ahora
|
||||
# Instruction for copying logs
|
||||
Press_the_button_below_to_copy_your_most_recent_logs_to_your_system_s_clipboard__Then_paste_it_into_your_email_322e = Presiona el siguiente botón para copiar los registros más recientes al portapapeles del sistema. A continuación, pégalos en tu correo electrónico.
|
||||
# Profile picture URL field label
|
||||
Profile_picture_81ff = Imagen de perfil
|
||||
# Column title for quote composition
|
||||
Quote_475c = Citar
|
||||
# Error message when quote note cannot be found
|
||||
Quote_of_unknown_note_e4f0 = Cita de nota desconocida
|
||||
# Label for read-only profile mode
|
||||
Read_only_82ff = Solo lectura
|
||||
# Column title for relay management
|
||||
Relays_9d89 = Relés
|
||||
# Label for relay list section
|
||||
Relays_ad5e = Relés
|
||||
# Column title for reply composition
|
||||
Reply_3bf1 = Respuesta
|
||||
# Hover text for reply button
|
||||
Reply_to_this_note_f5de = Responder a esta nota
|
||||
# Error message when reply note cannot be found
|
||||
Reply_to_unknown_note_4401 = Responder a nota desconocida
|
||||
# Fallback template for replying to user
|
||||
replying_to__user_15ab = respondiendo a { $user }
|
||||
# Template for replying to user in unknown thread
|
||||
replying_to__user__in_someone_s_thread_e148 = respondiendo a { $user } en la conversación de alguien
|
||||
# Template for replying to note in different user's thread
|
||||
replying_to__user__s__note__in__thread_user__s__thread_daa8 = respondiendo a { $note } de { $user } en { $thread } de { $thread_user }
|
||||
# Template for replying to user's note
|
||||
replying_to__user__s__note_ccba = respondiendo a { $note } de { $user }
|
||||
# Template for replying to root thread
|
||||
replying_to__user__s__thread_444d = respondiendo a { $thread } de { $user }
|
||||
# Fallback text when reply note is not found
|
||||
replying_to_a_note_e0bc = respondiendo a una nota
|
||||
# Hover text for repost button
|
||||
Repost_this_note_8e56 = Volver a publicar esta nota
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = Publicadas de nuevo
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = ¿Encontraste un error?
|
||||
# Label for satoshis (Bitcoin unit) for custom zap amount input field
|
||||
SATS_45d7 = SATS
|
||||
# Unit label for satoshis (Bitcoin unit) for configuring default zap amount in wallet settings.
|
||||
sats_e5ec = sats
|
||||
# Button to save default zap amount
|
||||
Save_6f7c = Guardar
|
||||
# Button label to save profile changes
|
||||
Save_changes_00db = Guardar cambios
|
||||
# Column title for search page
|
||||
Search_c573 = Búsqueda
|
||||
# Placeholder for search notes input field
|
||||
Search_notes_42a6 = Buscar notas...
|
||||
# Search in progress message
|
||||
Searching_for___query_5d18 = Buscando '{ $query }'
|
||||
# Description for Home column
|
||||
See_notes_from_your_contacts_ac16 = Ver notas de tus contactos
|
||||
# Description for universe column
|
||||
See_the_whole_nostr_universe_7694 = Ver todo el universo de nostr
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = Enviar
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = Mostrar la última nota para cada usuario de una lista
|
||||
# Button label to sign out of account
|
||||
Sign_out_337b = Cerrar sesión
|
||||
# Title for someone else's notes column
|
||||
Someone_else_s_Notes_7e5f = Notas de otra persona
|
||||
# Title for someone else's notifications column
|
||||
Someone_else_s_Notifications_82e6 = Notificaciones de otra persona
|
||||
# Description for contact list column
|
||||
Source_the_last_note_for_each_user_in_your_contact_list_e157 = Busca la última nota de cada usuario en tu lista de contactos
|
||||
# Description for hashtags column
|
||||
Stay_up_to_date_with_a_certain_hashtag_88e3 = Mantente al día con un hashtag específico
|
||||
# Description for notifications column
|
||||
Stay_up_to_date_with_notifications_and_mentions_6f4e = Mantente al día con notificaciones y menciones
|
||||
# Description for someone else's notes column
|
||||
Stay_up_to_date_with_someone_else_s_notes___replies_464c = Mantente al día con las notas y respuestas de otra persona
|
||||
# Description for someone else's notifications column
|
||||
Stay_up_to_date_with_someone_else_s_notifications_and_mentions_3473 = Mantente al día con las notificaciones y menciones de otra persona
|
||||
# Description for individual user column
|
||||
Stay_up_to_date_with_someone_s_notes___replies_aa78 = Mantente al día con las notas y respuestas de alguien
|
||||
# Description for your notifications column
|
||||
Stay_up_to_date_with_your_notifications_and_mentions_e73e = Mantente al día con tus notificaciones y menciones
|
||||
# Step 1 label in support instructions
|
||||
Step_1_8656 = Paso 1
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = Paso 2
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = Suscribirse a las notas de otra persona
|
||||
# Column title for subscribing to individual user
|
||||
Subscribe_to_someone_s_notes_b3c8 = Suscribirse a las notas de alguien
|
||||
# Hover text for dark mode toggle button
|
||||
Switch_to_dark_mode_4dec = Cambiar a modo oscuro
|
||||
# Hover text for light mode toggle button
|
||||
Switch_to_light_mode_72ce = Cambiar a modo claro
|
||||
# Button text to load blurred media
|
||||
Tap_to_Load_4b05 = Toca para cargar
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = La prueba del asistente de IA Dave de Nostr finalizó :(. ¡Gracias por probarlo! ¡Dave con zaps estará disponible muy pronto!
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = Conversación
|
||||
# Link text for thread references
|
||||
thread_ad1f = conversación
|
||||
# Title for universe column
|
||||
Universe_e01e = Universo
|
||||
# Column title for universe feed
|
||||
Universe_ffaa = Universo
|
||||
# Checkbox label for using wallet only for current account
|
||||
Use_this_wallet_for_the_current_account_only_61dc = Usar esta billetera solo para la cuenta actual
|
||||
# Username and domain identification message
|
||||
username___at___domain___will_be_used_for_identification_a4fd = Se utilizará "{ $username }" en "{ $domain }" para la identificación
|
||||
# Profile username field label
|
||||
Username_daa7 = Nombre de usuario
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = Billetera
|
||||
# Hint for deck name input field
|
||||
We_recommend_short_names_083e = Recomendamos nombres cortos
|
||||
# Profile website field label
|
||||
Website_7980 = Sitio web
|
||||
# Placeholder for note input field
|
||||
Write_a_banger_note_here_bad2 = Escribe aquí una nota impactante...
|
||||
# Placeholder text for key input field
|
||||
Your_key_here_81bd = Tu clave aquí...
|
||||
# Title for your notes column
|
||||
Your_Notes_f6db = Tus notas
|
||||
# Title for your notifications column
|
||||
Your_Notifications_080d = Tus notificaciones
|
||||
# Heading for zap (tip) action
|
||||
Zap_16b4 = Zap
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = Enviar un zap a esta nota
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
# Search results count
|
||||
Got__count__results_for___query_85fb =
|
||||
{ $count ->
|
||||
[uno] Obtuvo { $count } resultado para '{ $query }'
|
||||
*[otro] Obtuvo { $count } resultados para '{ $query }'
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
# Main translation file for Notedeck
|
||||
# This file contains common UI strings used throughout the application
|
||||
# Auto-generated by extract_i18n.py - DO NOT EDIT MANUALLY
|
||||
|
||||
|
||||
# Regular strings
|
||||
|
||||
# Profile about/bio field label
|
||||
About_00c0 = Información
|
||||
# Column title for account management
|
||||
Accounts_f018 = Cuentas
|
||||
# Button label to add a relay
|
||||
Add_269d = Añadir
|
||||
# Label for add column button
|
||||
Add_47df = Añadir
|
||||
# Button label to add a different wallet
|
||||
Add_a_different_wallet_that_will_only_be_used_for_this_account_de8d = Añadir un monedero diferente que solo se utilizará para esta cuenta
|
||||
# Error message for missing wallet
|
||||
Add_a_wallet_to_continue_d170 = Añadir un monedero para continuar
|
||||
# Button label to add a new account
|
||||
Add_account_1cfc = Añadir cuenta
|
||||
# Column title for adding new account
|
||||
Add_Account_d06c = Añadir cuenta
|
||||
# Column title for adding algorithm column
|
||||
Add_Algo_Column_0d75 = Añadir columna algorítmica
|
||||
# Column title for adding new column
|
||||
Add_Column_c764 = Añadir columna
|
||||
# Column title for adding new deck
|
||||
Add_Deck_fabf = Añadir deck
|
||||
# Column title for adding external notifications column
|
||||
Add_External_Notifications_Column_41ae = Añadir columna de notificaciones externas
|
||||
# Column title for adding hashtag column
|
||||
Add_Hashtag_Column_ebf4 = Añadir columna de hashtags
|
||||
# Column title for adding last notes column
|
||||
Add_Last_Notes_Column_bbad = Añadir columna de últimas notas
|
||||
# Column title for adding notifications column
|
||||
Add_Notifications_Column_79f8 = Añadir columna de notificaciones
|
||||
# Button label to add a relay
|
||||
Add_relay_269d = Añadir relé
|
||||
# Button label to add a wallet
|
||||
Add_Wallet_d1be = Añadir monedero
|
||||
# Title for algorithmic feeds column
|
||||
Algo_2452 = Algo
|
||||
# Description for algorithmic feeds column
|
||||
Algorithmic_feeds_to_aid_in_note_discovery_d344 = Feeds algorítmicos para ayudar en el descubrimiento de notas
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = Cantidad
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = Preguntar
|
||||
# Placeholder text for Dave AI input field
|
||||
Ask_dave_anything_33d1 = Pregúntale cualquier cosa a Dave...
|
||||
# Profile banner URL field label
|
||||
Banner_52ef = Banner
|
||||
# Beta version label
|
||||
BETA_8e5d = BETA
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = Transmitir
|
||||
# Broadcast the note only to local network relays
|
||||
Broadcast_Local_7e50 = Transmitir localmente
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = Cancelar
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = Haz clic para editar
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = Redactar nota
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = Confirmar
|
||||
# Status label for connected relay
|
||||
Connected_f8cc = Conectado
|
||||
# Status label for connecting relay
|
||||
Connecting_6b7e = Conectando...
|
||||
# Title for contact list column
|
||||
Contact_List_f85a = Lista de contactos
|
||||
# Column title for contact lists
|
||||
Contacts_7533 = Contactos
|
||||
# Column title for last notes per contact
|
||||
Contacts__last_notes_3f84 = Contactos (últimas notas)
|
||||
# Button label to copy logs
|
||||
Copy_a688 = Copiar
|
||||
# Button to copy media link to clipboard
|
||||
Copy_Link_dc7c = Copiar enlace
|
||||
# Copy the unique note identifier to clipboard
|
||||
Copy_Note_ID_6b45 = Copiar ID de nota
|
||||
# Copy the raw note data in JSON format to clipboard
|
||||
Copy_Note_JSON_9e4e = Copiar JSON de nota
|
||||
# Copy the author's public key to clipboard
|
||||
Copy_Pubkey_9cc4 = Copiar pubkey
|
||||
# Copy the text content of the note to clipboard
|
||||
Copy_Text_f81c = Copiar texto
|
||||
# Relative time in days
|
||||
count_d_b9be = { $count }d
|
||||
# Relative time in hours
|
||||
count_h_3ecb = { $count }h
|
||||
# Relative time in minutes
|
||||
count_m_b41e = { $count }m
|
||||
# Relative time in months
|
||||
count_mo_7aba = { $count }mes
|
||||
# Relative time in seconds
|
||||
count_s_aa26 = { $count }s
|
||||
# Relative time in weeks
|
||||
count_w_7468 = { $count }sem
|
||||
# Relative time in years
|
||||
count_y_9408 = { $count }a
|
||||
# Button to create a new account
|
||||
Create_Account_6994 = Crear cuenta
|
||||
# Button label to create a new deck
|
||||
Create_Deck_16b7 = Crear deck
|
||||
# Column title for custom timelines
|
||||
Custom_a69e = Personalizado
|
||||
# Column title for zap amount customization
|
||||
Customize_Zap_Amount_cfc4 = Personalizar cantidad de zap
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = Ayuda de Damus
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = Nombre del deck
|
||||
# Label for decks section in side panel
|
||||
DECKS_1fad = DECKS
|
||||
# Label for default zap amount input
|
||||
Default_amount_per_zap_399d = Cantidad predeterminada por zap:
|
||||
# Name of the default deck feed
|
||||
Default_Deck_fcca = Deck predeterminado
|
||||
# Button label to delete a deck
|
||||
Delete_Deck_bb29 = Eliminar deck
|
||||
# Tooltip for deleting a column
|
||||
Delete_this_column_8d5a = Eliminar esta columna
|
||||
# Button label to delete a wallet
|
||||
Delete_Wallet_d1d4 = Eliminar monedero
|
||||
# Profile display name field label
|
||||
Display_name_f9d9 = Nombre para mostrar
|
||||
# Domain identification message
|
||||
domain___will_be_used_for_identification_b67e = "{ $domain }" se utilizará para la identificación
|
||||
# Column title for editing deck
|
||||
Edit_Deck_4018 = Editar deck
|
||||
# Button label to edit a deck
|
||||
Edit_Deck_fd93 = Editar deck
|
||||
# Button label to edit user profile
|
||||
Edit_Profile_49e6 = Editar perfil
|
||||
# Column title for profile editing
|
||||
Edit_Profile_8ad4 = Editar perfil
|
||||
# Placeholder for hashtag input field
|
||||
Enter_the_desired_hashtags_here__for_multiple_space-separated_7a69 = Ingresa aquí los hashtags deseados (si son varios, sepáralos con un espacio)
|
||||
# Placeholder for relay input field
|
||||
Enter_the_relay_here_1c8b = Ingresa el relé aquí
|
||||
# Hint text to prompt entering the user's public key.
|
||||
Enter_the_user_s_key__npub__hex__nip05__here_650c = Ingresa la clave del usuario (npub, hex, nip05) aquí...
|
||||
# Label for key input field. Key can be public key (npub), private key (nsec), or Nostr address (NIP-05).
|
||||
Enter_your_key_0fca = Ingresa tu clave
|
||||
# Instructions for entering Nostr credentials
|
||||
Enter_your_public_key__npub___nostr_address__e_g___address____or_private_key__nsec___You_must_enter_your_private_key_to_be_able_to_post__reply__etc_48e9 = Ingresa tu clave pública (npub), dirección de Nostr (por ejemplo, { $address }) o clave privada (nsec). Debes ingresar tu clave privada para poder publicar, responder, etc.
|
||||
# Label for find user button
|
||||
Find_User_bd12 = Buscar usuario
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = Hashtags
|
||||
# Title for Home column
|
||||
Home_8c19 = Inicio
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = Icono
|
||||
# Title for individual user column
|
||||
Individual_b776 = Individual
|
||||
# Error message for invalid zap amount
|
||||
Invalid_amount_6630 = Cantidad no válida
|
||||
# Error message for invalid key input
|
||||
Invalid_key_4726 = Clave no válida.
|
||||
# Error message for invalid Nostr Wallet Connect URI
|
||||
Invalid_NWC_URI_031b = NWC URI no válido
|
||||
# Zap amount button for 100000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_100K_686c = 100.000
|
||||
# Zap amount button for 10000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_10K_f7e6 = 10.000
|
||||
# Zap amount button for 20000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_20K_4977 = 20.000
|
||||
# Zap amount button for 50000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_50K_c2dc = 50.000
|
||||
# Zap amount button for 5000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_5K_f7e6 = 5.000
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = Haz seguimiento de tus notas y respuestas
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = Última nota por usuario
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = Dirección de la red Lightning (lud16)
|
||||
# Login page title
|
||||
Login_9eef = Inicio de sesión
|
||||
# Login button text
|
||||
Login_now___let_s_do_this_5630 = Inicia sesión ahora, ¡manos a la obra!
|
||||
# Text shown on blurred media from unfollowed users
|
||||
Media_from_someone_you_don_t_follow_5611 = Contenido multimedia de alguien que no sigues
|
||||
# Tooltip for moving a column
|
||||
Moves_this_column_to_another_position_0d4b = Mueve esta columna a otra posición
|
||||
# Title for the user's deck
|
||||
My_Deck_4ac5 = Mi deck
|
||||
# Label asking if the user is new to Nostr. Underneath this label is a button to create an account.
|
||||
New_to_Nostr_a2fd = ¿Primera vez en Nostr?
|
||||
# NIP-05 identity field label
|
||||
Nostr_address__NIP-05_identity_74a2 = Dirección de Nostr (identidad NIP-05)
|
||||
# Default username when profile is not available
|
||||
nostrich_df29 = nostrich
|
||||
# Status label for disconnected relay
|
||||
Not_Connected_6292 = No conectado
|
||||
# Link text for note references
|
||||
note_cad6 = nota
|
||||
# Beta product warning message
|
||||
Notedeck_is_a_beta_product__Expect_bugs_and_contact_us_when_you_run_into_issues_a671 = Notedeck es un producto en fase beta. Es posible que haya errores, así que ponte en contacto con nosotros si tienes algún problema.
|
||||
# Filter label for notes only view
|
||||
Notes_03fb = Notas
|
||||
# Label for notes-only filter
|
||||
Notes_60d2 = Notas
|
||||
# Filter label for notes and replies view
|
||||
Notes___Replies_1ec2 = Notas y respuestas
|
||||
# Label for notes and replies filter
|
||||
Notes___Replies_6e3b = Notas y respuestas
|
||||
# Column title for notifications
|
||||
Notifications_d673 = Notificaciones
|
||||
# Title for notifications column
|
||||
Notifications_ef56 = Notificaciones
|
||||
# Relative time for very recent events (less than 3 seconds)
|
||||
now_2181 = ahora
|
||||
# Button label to open email client
|
||||
Open_Email_25e9 = Abrir correo electrónico
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = Abre tu cliente de correo predeterminado para recibir ayuda del equipo de Damus
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = Pega tu NWC URI aquí...
|
||||
# Error message for missing deck name
|
||||
Please_create_a_name_for_the_deck_38e7 = Crea un nombre para el Deck.
|
||||
# Error message for missing deck name and icon
|
||||
Please_create_a_name_for_the_deck_and_select_an_icon_0add = Crea un nombre para el deck y selecciona un icono.
|
||||
# Error message for missing deck icon
|
||||
Please_select_an_icon_655b = Selecciona un icono.
|
||||
# Button label to post a note
|
||||
Post_now_8a49 = Publicar ahora
|
||||
# Instruction for copying logs
|
||||
Press_the_button_below_to_copy_your_most_recent_logs_to_your_system_s_clipboard__Then_paste_it_into_your_email_322e = Presiona el siguiente botón para copiar los registros más recientes al portapapeles del sistema. A continuación, pégalos en tu correo electrónico.
|
||||
# Profile picture URL field label
|
||||
Profile_picture_81ff = Imagen de perfil
|
||||
# Column title for quote composition
|
||||
Quote_475c = Citar
|
||||
# Error message when quote note cannot be found
|
||||
Quote_of_unknown_note_e4f0 = Cita de nota desconocida
|
||||
# Label for read-only profile mode
|
||||
Read_only_82ff = Solo lectura
|
||||
# Column title for relay management
|
||||
Relays_9d89 = Relés
|
||||
# Label for relay list section
|
||||
Relays_ad5e = Relés
|
||||
# Column title for reply composition
|
||||
Reply_3bf1 = Respuesta
|
||||
# Hover text for reply button
|
||||
Reply_to_this_note_f5de = Responder a esta nota
|
||||
# Error message when reply note cannot be found
|
||||
Reply_to_unknown_note_4401 = Responder a nota desconocida
|
||||
# Fallback template for replying to user
|
||||
replying_to__user_15ab = respondiendo a { $user }
|
||||
# Template for replying to user in unknown thread
|
||||
replying_to__user__in_someone_s_thread_e148 = respondiendo a { $user } en la conversación de alguien
|
||||
# Template for replying to note in different user's thread
|
||||
replying_to__user__s__note__in__thread_user__s__thread_daa8 = respondiendo a { $note } de { $user } en { $thread } de { $thread_user }
|
||||
# Template for replying to user's note
|
||||
replying_to__user__s__note_ccba = respondiendo a { $note } de { $user }
|
||||
# Template for replying to root thread
|
||||
replying_to__user__s__thread_444d = respondiendo a { $thread } de { $user }
|
||||
# Fallback text when reply note is not found
|
||||
replying_to_a_note_e0bc = respondiendo a una nota
|
||||
# Hover text for repost button
|
||||
Repost_this_note_8e56 = Volver a publicar esta nota
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = Publicadas de nuevo
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = ¿Has encontrado un error?
|
||||
# Label for satoshis (Bitcoin unit) for custom zap amount input field
|
||||
SATS_45d7 = SATS
|
||||
# Unit label for satoshis (Bitcoin unit) for configuring default zap amount in wallet settings.
|
||||
sats_e5ec = sats
|
||||
# Button to save default zap amount
|
||||
Save_6f7c = Guardar
|
||||
# Button label to save profile changes
|
||||
Save_changes_00db = Guardar cambios
|
||||
# Column title for search page
|
||||
Search_c573 = Búsqueda
|
||||
# Placeholder for search notes input field
|
||||
Search_notes_42a6 = Buscar notas...
|
||||
# Search in progress message
|
||||
Searching_for___query_5d18 = Buscando '{ $query }'
|
||||
# Description for Home column
|
||||
See_notes_from_your_contacts_ac16 = Ver notas de tus contactos
|
||||
# Description for universe column
|
||||
See_the_whole_nostr_universe_7694 = Ver todo el universo de nostr
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = Enviar
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = Mostrar la última nota para cada usuario de una lista
|
||||
# Button label to sign out of account
|
||||
Sign_out_337b = Cerrar sesión
|
||||
# Title for someone else's notes column
|
||||
Someone_else_s_Notes_7e5f = Notas de otra persona
|
||||
# Title for someone else's notifications column
|
||||
Someone_else_s_Notifications_82e6 = Notificaciones de otra persona
|
||||
# Description for contact list column
|
||||
Source_the_last_note_for_each_user_in_your_contact_list_e157 = Busca la última nota de cada usuario en tu lista de contactos
|
||||
# Description for hashtags column
|
||||
Stay_up_to_date_with_a_certain_hashtag_88e3 = Mantente al día con un hashtag específico
|
||||
# Description for notifications column
|
||||
Stay_up_to_date_with_notifications_and_mentions_6f4e = Mantente al día con notificaciones y menciones
|
||||
# Description for someone else's notes column
|
||||
Stay_up_to_date_with_someone_else_s_notes___replies_464c = Mantente al día con las notas y respuestas de otra persona
|
||||
# Description for someone else's notifications column
|
||||
Stay_up_to_date_with_someone_else_s_notifications_and_mentions_3473 = Mantente al día con las notificaciones y menciones de otra persona
|
||||
# Description for individual user column
|
||||
Stay_up_to_date_with_someone_s_notes___replies_aa78 = Mantente al día con las notas y respuestas de alguien
|
||||
# Description for your notifications column
|
||||
Stay_up_to_date_with_your_notifications_and_mentions_e73e = Mantente al día con tus notificaciones y menciones
|
||||
# Step 1 label in support instructions
|
||||
Step_1_8656 = Paso 1
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = Paso 2
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = Suscribirse a las notas de otra persona
|
||||
# Column title for subscribing to individual user
|
||||
Subscribe_to_someone_s_notes_b3c8 = Suscribirse a las notas de alguien
|
||||
# Hover text for dark mode toggle button
|
||||
Switch_to_dark_mode_4dec = Cambiar a modo oscuro
|
||||
# Hover text for light mode toggle button
|
||||
Switch_to_light_mode_72ce = Cambiar a modo claro
|
||||
# Button text to load blurred media
|
||||
Tap_to_Load_4b05 = Toca para cargar
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = La prueba del asistente de IA Dave de Nostr ha finalizado :(. ¡Gracias por probarlo! ¡Dave con zaps estará disponible muy pronto!
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = Conversación
|
||||
# Link text for thread references
|
||||
thread_ad1f = conversación
|
||||
# Title for universe column
|
||||
Universe_e01e = Universo
|
||||
# Column title for universe feed
|
||||
Universe_ffaa = Universo
|
||||
# Checkbox label for using wallet only for current account
|
||||
Use_this_wallet_for_the_current_account_only_61dc = Usar este monedero solo para la cuenta actual
|
||||
# Username and domain identification message
|
||||
username___at___domain___will_be_used_for_identification_a4fd = Se utilizará "{ $username }" en "{ $domain }" para la identificación
|
||||
# Profile username field label
|
||||
Username_daa7 = Nombre de usuario
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = Monedero
|
||||
# Hint for deck name input field
|
||||
We_recommend_short_names_083e = Recomendamos nombres cortos
|
||||
# Profile website field label
|
||||
Website_7980 = Sitio web
|
||||
# Placeholder for note input field
|
||||
Write_a_banger_note_here_bad2 = Escribe aquí una nota impactante...
|
||||
# Placeholder text for key input field
|
||||
Your_key_here_81bd = Tu clave aquí...
|
||||
# Title for your notes column
|
||||
Your_Notes_f6db = Tus notas
|
||||
# Title for your notifications column
|
||||
Your_Notifications_080d = Tus notificaciones
|
||||
# Heading for zap (tip) action
|
||||
Zap_16b4 = Zap
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = Enviar un zap a esta nota
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
# Search results count
|
||||
Got__count__results_for___query_85fb =
|
||||
{ $count ->
|
||||
[uno] Obtuvo { $count } resultado para '{ $query }'
|
||||
*[otro] Obtuvo { $count } resultados para '{ $query }'
|
||||
}
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
# Profile about/bio field label
|
||||
About_00c0 = A propos
|
||||
# Display name for account management
|
||||
Accounts_e233 = Comptes
|
||||
# Column title for account management
|
||||
Accounts_f018 = Comptes
|
||||
# Button label to add a relay
|
||||
@@ -23,16 +21,10 @@ Add_a_wallet_to_continue_d170 = Ajouter un portefeuille pour continuer
|
||||
Add_account_1cfc = Ajouter un compte
|
||||
# Column title for adding new account
|
||||
Add_Account_d06c = Ajouter un compte
|
||||
# Display name for adding account
|
||||
Add_Account_d715 = Ajouter un compte
|
||||
# Column title for adding algorithm column
|
||||
Add_Algo_Column_0d75 = Ajouter une colonne Algo
|
||||
# Display name for adding column
|
||||
Add_Column_c6ff = Ajouter une colonne
|
||||
# Column title for adding new column
|
||||
Add_Column_c764 = Ajouter une colonne
|
||||
# Display name for adding deck
|
||||
Add_Deck_6e5f = Ajouter un deck
|
||||
# Column title for adding new deck
|
||||
Add_Deck_fabf = Ajouter un deck
|
||||
# Column title for adding external notifications column
|
||||
@@ -53,6 +45,8 @@ Algo_2452 = Algo
|
||||
Algorithmic_feeds_to_aid_in_note_discovery_d344 = Des fils algorithmiques pour faciliter la découverte de notes
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = Montant
|
||||
# Label for appearance settings section
|
||||
Appearance_4c7f = Apparence
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = Demander
|
||||
# Placeholder text for Dave AI input field
|
||||
@@ -61,18 +55,26 @@ Ask_dave_anything_33d1 = Demandez à Dave n'importe quoi...
|
||||
Banner_52ef = Bannière
|
||||
# Beta version label
|
||||
BETA_8e5d = BETA
|
||||
# Option in settings section to show the source client label at the bottom of the note
|
||||
Bottom_33c8 = En bas
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = Diffusion
|
||||
# Broadcast the note only to local network relays
|
||||
Broadcast_Local_7e50 = Diffusion locale
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = Annuler
|
||||
# Label for cancel clear cache, Storage settings section
|
||||
Cancel_fd8b = Annuler
|
||||
# Label for clear cache button, Storage settings section
|
||||
Clear_cache_dccb = Vider le cache
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = Cliquer pour modifier
|
||||
# Display name for note composition
|
||||
Compose_Note_ad11 = Ecrire une note
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = Ecrire une note
|
||||
# Label for configure relays, settings section
|
||||
Configure_relays_d156 = Configurer les relais
|
||||
# Label for confirm clear cache, Storage settings section
|
||||
Confirm_9d9d = Confirmer
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = Confirmer
|
||||
# Status label for connected relay
|
||||
@@ -83,8 +85,6 @@ Connecting_6b7e = Connexion...
|
||||
Contact_List_f85a = Liste de contacts
|
||||
# Column title for contact lists
|
||||
Contacts_7533 = Contacts
|
||||
# Timeline kind label for contact lists
|
||||
Contacts_8b98 = Contacts
|
||||
# Column title for last notes per contact
|
||||
Contacts__last_notes_3f84 = Contacts (dernières notes)
|
||||
# Button label to copy logs
|
||||
@@ -119,14 +119,12 @@ Create_Account_6994 = Créer un compte
|
||||
Create_Deck_16b7 = Créer un deck
|
||||
# Column title for custom timelines
|
||||
Custom_a69e = Personnaliser
|
||||
# Display name for custom timelines
|
||||
Custom_cb4f = Personnaliser
|
||||
# Column title for zap amount customization
|
||||
Customize_Zap_Amount_cfc4 = Personnaliser le montant du Zap
|
||||
# Display name for zap customization
|
||||
Customize_Zap_Amount_ed29 = Personnaliser le montant du Zap
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = Assistance Damus
|
||||
# Label for Theme Dark, Appearance settings section
|
||||
Dark_85fe = Sombre
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = Nom du deck
|
||||
# Label for decks section in side panel
|
||||
@@ -147,14 +145,10 @@ Display_name_f9d9 = Nom d'utilisateur
|
||||
domain___will_be_used_for_identification_b67e = "{ $domain }" sera utilisé pour l'identification
|
||||
# Column title for editing deck
|
||||
Edit_Deck_4018 = Modifier le deck
|
||||
# Display name for editing deck
|
||||
Edit_Deck_c9ba = Modifier le deck
|
||||
# Button label to edit a deck
|
||||
Edit_Deck_fd93 = Modifier le deck
|
||||
# Button label to edit user profile
|
||||
Edit_Profile_49e6 = Modifier le profil
|
||||
# Display name for profile editing
|
||||
Edit_Profile_6699 = Modifier le profil
|
||||
# Column title for profile editing
|
||||
Edit_Profile_8ad4 = Modifier le profil
|
||||
# Placeholder for hashtag input field
|
||||
@@ -169,18 +163,16 @@ Enter_your_key_0fca = Entrez votre clé
|
||||
Enter_your_public_key__npub___nostr_address__e_g___address____or_private_key__nsec___You_must_enter_your_private_key_to_be_able_to_post__reply__etc_48e9 = Entrez votre clé publique (npub), votre adresse nostr (par exemple { $address }), ou votre clé privée (nsec). Vous devez entrer votre clé privée pour pouvoir poster, répondre, etc.
|
||||
# Label for find user button
|
||||
Find_User_bd12 = Trouver un utilisateur
|
||||
# Timeline kind label for hashtag feeds
|
||||
Hashtag_a0ab = Hashtag
|
||||
# Display name for hashtag feeds
|
||||
Hashtags_617e = Hashtags
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = Hashtags
|
||||
# Display name for home feed
|
||||
Home_3efc = Accueil
|
||||
# Option in settings section to hide the source client label in note display
|
||||
Hide_281d = Masquer
|
||||
# Title for Home column
|
||||
Home_8c19 = Accueil
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = Icone
|
||||
# Label for Image cache size, Storage settings section
|
||||
Image_cache_size_3004 = Taille du cache des images :
|
||||
# Title for individual user column
|
||||
Individual_b776 = Individuel
|
||||
# Error message for invalid zap amount
|
||||
@@ -201,12 +193,12 @@ k_50K_c2dc = 50K
|
||||
k_5K_f7e6 = 5K
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = Gardez une trace de vos notes & réponses
|
||||
# Label for language, Appearance settings section
|
||||
Language_e264 = Langue :
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = Dernière note par utilisateur
|
||||
# Timeline kind label for last notes per pubkey
|
||||
Last_Notes_aefe = Dernières notes
|
||||
# Display name for last notes per contact
|
||||
Last_Per_Pubkey__Contact_33ce = Dernière par Pubkey (Contact)
|
||||
# Label for Theme Light, Appearance settings section
|
||||
Light_7475 = Clair
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = Adresse réseau Lightning (lud16)
|
||||
# Login page title
|
||||
@@ -239,10 +231,6 @@ Notes_60d2 = Notes
|
||||
Notes___Replies_1ec2 = Notes & Réponses
|
||||
# Label for notes and replies filter
|
||||
Notes___Replies_6e3b = Notes & Réponses
|
||||
# Timeline kind label for notifications
|
||||
Notifications_6228 = Notifications
|
||||
# Display name for notifications
|
||||
Notifications_8029 = Notifications
|
||||
# Column title for notifications
|
||||
Notifications_d673 = Notifications
|
||||
# Title for notifications column
|
||||
@@ -253,6 +241,8 @@ now_2181 = maintenant
|
||||
Open_Email_25e9 = Ouvrir Email
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = Ouvrez votre service d'email par défaut pour obtenir de l'aide de l'équipe Damus
|
||||
# Label for others settings section
|
||||
Others_7267 = Autres
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = Collez ici votre NWC URI...
|
||||
# Error message for missing deck name
|
||||
@@ -265,30 +255,20 @@ Please_select_an_icon_655b = Veuillez choisir une icône.
|
||||
Post_now_8a49 = Publier maintenant
|
||||
# Instruction for copying logs
|
||||
Press_the_button_below_to_copy_your_most_recent_logs_to_your_system_s_clipboard__Then_paste_it_into_your_email_322e = Cliquez sur le bouton ci-dessous pour copier vos données les plus récentes dans le presse-papiers de votre système. Collez-les ensuite dans votre courrier électronique.
|
||||
# Display name for user profiles
|
||||
Profile_2478 = Profil
|
||||
# Timeline kind label for user profiles
|
||||
Profile_9027 = Profil
|
||||
# Profile picture URL field label
|
||||
Profile_picture_81ff = Photo de profil
|
||||
# Column title for quote composition
|
||||
Quote_475c = Citation
|
||||
# Display name for quote composition
|
||||
Quote_a38e = Citation
|
||||
# Error message when quote note cannot be found
|
||||
Quote_of_unknown_note_e4f0 = Citation d'une note inconnue
|
||||
# Label for read-only profile mode
|
||||
Read_only_82ff = En lecture seule
|
||||
# Display name for relay management
|
||||
Relays_7335 = Relais
|
||||
# Column title for relay management
|
||||
Relays_9d89 = Relais
|
||||
# Label for relay list section
|
||||
Relays_ad5e = Relais
|
||||
# Column title for reply composition
|
||||
Reply_3bf1 = Répondre
|
||||
# Display name for reply composition
|
||||
Reply_b40f = Répondre
|
||||
# Hover text for reply button
|
||||
Reply_to_this_note_f5de = Répondre à cette note
|
||||
# Error message when reply note cannot be found
|
||||
@@ -309,6 +289,8 @@ replying_to_a_note_e0bc = répondre à une note
|
||||
Repost_this_note_8e56 = Republier cette note
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = Republier
|
||||
# Label for reset zoom level, Appearance settings section
|
||||
Reset_62d4 = Réinitialiser
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = Vous rencontrez un problème ?
|
||||
# Label for satoshis (Bitcoin unit) for custom zap amount input field
|
||||
@@ -319,12 +301,6 @@ sats_e5ec = sats
|
||||
Save_6f7c = Enregistrer
|
||||
# Button label to save profile changes
|
||||
Save_changes_00db = Enregistrer les modifications
|
||||
# Display name for search results
|
||||
Search_0aa0 = Recherche
|
||||
# Display name for search page
|
||||
Search_4503 = Rechercher
|
||||
# Timeline kind label for search results
|
||||
Search_a0b8 = Recherche
|
||||
# Column title for search page
|
||||
Search_c573 = Rechercher
|
||||
# Placeholder for search notes input field
|
||||
@@ -337,6 +313,10 @@ See_notes_from_your_contacts_ac16 = Afficher les notes de vos contacts
|
||||
See_the_whole_nostr_universe_7694 = Voir l'ensemble de l'univers nostr
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = Envoyer
|
||||
# Column title for app settings
|
||||
Settings_7a4f = Paramètres
|
||||
# Label for Show source client, others settings section
|
||||
Show_source_client_9e31 = Afficher le client source
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = Afficher la dernière note de chaque utilisateur à partir d'une liste
|
||||
# Button label to sign out of account
|
||||
@@ -363,12 +343,12 @@ Stay_up_to_date_with_your_notifications_and_mentions_e73e = Restez informé pour
|
||||
Step_1_8656 = Etape 1
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = Etape 2
|
||||
# Label for storage settings section
|
||||
Storage_ed65 = Stockage
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = S'abonner aux notes de quelqu'un d'autre
|
||||
# Column title for subscribing to individual user
|
||||
Subscribe_to_someone_s_notes_b3c8 = S'abonner aux notes de quelqu'un
|
||||
# Display name for support page
|
||||
Support_a4b4 = Assistance
|
||||
# Hover text for dark mode toggle button
|
||||
Switch_to_dark_mode_4dec = Passer en mode sombre
|
||||
# Hover text for light mode toggle button
|
||||
@@ -377,18 +357,14 @@ Switch_to_light_mode_72ce = Passer en mode clair
|
||||
Tap_to_Load_4b05 = Appuyer pour charger
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = La période d'essai de l'assistant IA Dave Nostr est terminée :(. Merci de l'avoir testé ! Un Dave compatible-Zap sera bientôt disponible !
|
||||
# Label for theme, Appearance settings section
|
||||
Theme_4aac = Thème :
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = Fil
|
||||
# Display name for thread view
|
||||
Thread_9957 = Fil
|
||||
# Link text for thread references
|
||||
thread_ad1f = fil
|
||||
# Generic timeline kind label
|
||||
Timeline_b0fc = Chronologie
|
||||
# Timeline kind label for universe feed
|
||||
Universe_0a3e = Universel
|
||||
# Display name for universe feed
|
||||
Universe_d47e = Universel
|
||||
# Option in settings section to show the source client label at the top of the note
|
||||
Top_6aeb = En haut
|
||||
# Title for universe column
|
||||
Universe_e01e = Universel
|
||||
# Column title for universe feed
|
||||
@@ -399,10 +375,10 @@ Use_this_wallet_for_the_current_account_only_61dc = Utiliser ce portefeuille pou
|
||||
username___at___domain___will_be_used_for_identification_a4fd = "{ $username }" à "{ $domain }" sera utilisé pour l'identification
|
||||
# Profile username field label
|
||||
Username_daa7 = Nom d'utilisateur
|
||||
# Label for view folder button, Storage settings section
|
||||
View_folder_9742 = Voir le dossier :
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = Portefeuille
|
||||
# Display name for wallet management
|
||||
Wallet_cdca = Portefeuille
|
||||
# Hint for deck name input field
|
||||
We_recommend_short_names_083e = Nous recommandons des noms courts
|
||||
# Profile website field label
|
||||
@@ -419,6 +395,8 @@ Your_Notifications_080d = Vos notifications
|
||||
Zap_16b4 = Zap
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = Zap cette note
|
||||
# Label for zoom level, Appearance settings section
|
||||
Zoom_Level_29a8 = Niveau de zoom :
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
|
||||
@@ -0,0 +1,408 @@
|
||||
# Main translation file for Notedeck
|
||||
# This file contains common UI strings used throughout the application
|
||||
# Auto-generated by extract_i18n.py - DO NOT EDIT MANUALLY
|
||||
|
||||
|
||||
# Regular strings
|
||||
|
||||
# Profile about/bio field label
|
||||
About_00c0 = Sobre
|
||||
# Column title for account management
|
||||
Accounts_f018 = Contas
|
||||
# Button label to add a relay
|
||||
Add_269d = Transmitir
|
||||
# Label for add column button
|
||||
Add_47df = Adicionar coluna
|
||||
# Button label to add a different wallet
|
||||
Add_a_different_wallet_that_will_only_be_used_for_this_account_de8d = Adicionar outra carteira a ser usada apenas nesta conta
|
||||
# Error message for missing wallet
|
||||
Add_a_wallet_to_continue_d170 = Obrigatório adicionar carteira
|
||||
# Button label to add a new account
|
||||
Add_account_1cfc = Adicionar conta nova aqui
|
||||
# Column title for adding new account
|
||||
Add_Account_d06c = Adicionar nova conta
|
||||
# Column title for adding algorithm column
|
||||
Add_Algo_Column_0d75 = Adicionar coluna de algoritmo
|
||||
# Column title for adding new column
|
||||
Add_Column_c764 = Adicionar coluna
|
||||
# Column title for adding new deck
|
||||
Add_Deck_fabf = Adicionar aba
|
||||
# Column title for adding external notifications column
|
||||
Add_External_Notifications_Column_41ae = Adicionar coluna de notificações externas
|
||||
# Column title for adding hashtag column
|
||||
Add_Hashtag_Column_ebf4 = Adicionar coluna de #
|
||||
# Column title for adding last notes column
|
||||
Add_Last_Notes_Column_bbad = Adicionar última coluna de notas
|
||||
# Column title for adding notifications column
|
||||
Add_Notifications_Column_79f8 = Adicionar coluna de notificações
|
||||
# Button label to add a relay
|
||||
Add_relay_269d = Adicionar transmissão
|
||||
# Button label to add a wallet
|
||||
Add_Wallet_d1be = Adicionar carteira
|
||||
# Title for algorithmic feeds column
|
||||
Algo_2452 = Algoritmos
|
||||
# Description for algorithmic feeds column
|
||||
Algorithmic_feeds_to_aid_in_note_discovery_d344 = Algoritmos para pesquisar notas
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = Valor
|
||||
# Label for appearance settings section
|
||||
Appearance_4c7f = Aparência
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = Perguntar
|
||||
# Placeholder text for Dave AI input field
|
||||
Ask_dave_anything_33d1 = Perguntar ao Dave
|
||||
# Profile banner URL field label
|
||||
Banner_52ef = Destaque
|
||||
# Beta version label
|
||||
BETA_8e5d = Beta
|
||||
# Option in settings section to show the source client label at the bottom of the note
|
||||
Bottom_33c8 = Abaixo
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = Encaminhar
|
||||
# Broadcast the note only to local network relays
|
||||
Broadcast_Local_7e50 = Encaminhar especificamente
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = Cancelar
|
||||
# Label for cancel clear cache, Storage settings section
|
||||
Cancel_fd8b = Cancelar
|
||||
# Label for clear cache button, Storage settings section
|
||||
Clear_cache_dccb = Limpar cache
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = Editar valor
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = Compor nota
|
||||
# Label for configure relays, settings section
|
||||
Configure_relays_d156 = Configurar canais
|
||||
# Label for confirm clear cache, Storage settings section
|
||||
Confirm_9d9d = Confirmar
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = Confirmar
|
||||
# Status label for connected relay
|
||||
Connected_f8cc = Conectar
|
||||
# Status label for connecting relay
|
||||
Connecting_6b7e = Conectando...
|
||||
# Title for contact list column
|
||||
Contact_List_f85a = Lista de contatos
|
||||
# Column title for contact lists
|
||||
Contacts_7533 = Contatos
|
||||
# Column title for last notes per contact
|
||||
Contacts__last_notes_3f84 = Contatos (últimas notas)
|
||||
# Button label to copy logs
|
||||
Copy_a688 = Copiar
|
||||
# Button to copy media link to clipboard
|
||||
Copy_Link_dc7c = Copiar link
|
||||
# Copy the unique note identifier to clipboard
|
||||
Copy_Note_ID_6b45 = Copiar ID da nota
|
||||
# Copy the raw note data in JSON format to clipboard
|
||||
Copy_Note_JSON_9e4e = Copiar nota "JSON"
|
||||
# Copy the author's public key to clipboard
|
||||
Copy_Pubkey_9cc4 = Copiar chave pública
|
||||
# Copy the text content of the note to clipboard
|
||||
Copy_Text_f81c = Copiar texto
|
||||
# Relative time in days
|
||||
count_d_b9be = { $count }D
|
||||
# Relative time in hours
|
||||
count_h_3ecb = { $count }H
|
||||
# Relative time in minutes
|
||||
count_m_b41e = { $count }M
|
||||
# Relative time in months
|
||||
count_mo_7aba = { $count }Mes
|
||||
# Relative time in seconds
|
||||
count_s_aa26 = { $count }S
|
||||
# Relative time in weeks
|
||||
count_w_7468 = { $count }Sem
|
||||
# Relative time in years
|
||||
count_y_9408 = { $count }A
|
||||
# Button to create a new account
|
||||
Create_Account_6994 = Criar conta
|
||||
# Button label to create a new deck
|
||||
Create_Deck_16b7 = Criar aba
|
||||
# Column title for custom timelines
|
||||
Custom_a69e = Personalizar
|
||||
# Column title for zap amount customization
|
||||
Customize_Zap_Amount_cfc4 = Personalizar valor do ZAP
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = Ajuda
|
||||
# Label for Theme Dark, Appearance settings section
|
||||
Dark_85fe = Modo escuro
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = Nome da aba
|
||||
# Label for decks section in side panel
|
||||
DECKS_1fad = ABAS
|
||||
# Label for default zap amount input
|
||||
Default_amount_per_zap_399d = Valor padrão de ZAP
|
||||
# Name of the default deck feed
|
||||
Default_Deck_fcca = Nome padrão de abas
|
||||
# Button label to delete a deck
|
||||
Delete_Deck_bb29 = Deletar aba
|
||||
# Tooltip for deleting a column
|
||||
Delete_this_column_8d5a = Deletar esta coluna
|
||||
# Button label to delete a wallet
|
||||
Delete_Wallet_d1d4 = Deletar carteira
|
||||
# Profile display name field label
|
||||
Display_name_f9d9 = Nome de exibição
|
||||
# Domain identification message
|
||||
domain___will_be_used_for_identification_b67e = "{ $domain }" será utilizado para identificação
|
||||
# Column title for editing deck
|
||||
Edit_Deck_4018 = Editar aba
|
||||
# Button label to edit a deck
|
||||
Edit_Deck_fd93 = Editar
|
||||
# Button label to edit user profile
|
||||
Edit_Profile_49e6 = Editar perfil
|
||||
# Column title for profile editing
|
||||
Edit_Profile_8ad4 = Editar perfil
|
||||
# Placeholder for hashtag input field
|
||||
Enter_the_desired_hashtags_here__for_multiple_space-separated_7a69 = Digite as # desejadas aqui (para múltiplos espaços separados)
|
||||
# Placeholder for relay input field
|
||||
Enter_the_relay_here_1c8b = Insira a retransmissão aqui
|
||||
# Hint text to prompt entering the user's public key.
|
||||
Enter_the_user_s_key__npub__hex__nip05__here_650c = Digite a chave do usuário (npub, hex, nip05) aqui...
|
||||
# Label for key input field. Key can be public key (npub), private key (nsec), or Nostr address (NIP-05).
|
||||
Enter_your_key_0fca = Sua chave aqui
|
||||
# Instructions for entering Nostr credentials
|
||||
Enter_your_public_key__npub___nostr_address__e_g___address____or_private_key__nsec___You_must_enter_your_private_key_to_be_able_to_post__reply__etc_48e9 = Insira sua chave pública (npub), endereço do Nostr (e.g. { $address }), ou chave privada (nsec). Você deve digitar sua chave privada para conseguir publicar, responder, etc.
|
||||
# Label for find user button
|
||||
Find_User_bd12 = Pesquisar usuário
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = #
|
||||
# Option in settings section to hide the source client label in note display
|
||||
Hide_281d = Ocultar
|
||||
# Title for Home column
|
||||
Home_8c19 = Início
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = Ícone
|
||||
# Label for Image cache size, Storage settings section
|
||||
Image_cache_size_3004 = Tamanho do cache de imagem:
|
||||
# Title for individual user column
|
||||
Individual_b776 = Individual
|
||||
# Error message for invalid zap amount
|
||||
Invalid_amount_6630 = Quantia inválida
|
||||
# Error message for invalid key input
|
||||
Invalid_key_4726 = Chave inválida
|
||||
# Error message for invalid Nostr Wallet Connect URI
|
||||
Invalid_NWC_URI_031b = NWC URI Inválido
|
||||
# Zap amount button for 100000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_100K_686c = 100 mil
|
||||
# Zap amount button for 10000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_10K_f7e6 = 10 mil
|
||||
# Zap amount button for 20000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_20K_4977 = 20 mil
|
||||
# Zap amount button for 50000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_50K_c2dc = 50 mil
|
||||
# Zap amount button for 5000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_5K_f7e6 = 5 mil
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = Acompanhe suas notas e respostas
|
||||
# Label for language, Appearance settings section
|
||||
Language_e264 = Idioma
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = Última Nota por Usuário
|
||||
# Label for Theme Light, Appearance settings section
|
||||
Light_7475 = Modo claro
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = Endereço de rede de eletrização (lud16)
|
||||
# Login page title
|
||||
Login_9eef = Entrar
|
||||
# Login button text
|
||||
Login_now___let_s_do_this_5630 = Entrar agora! Vamos nessa!
|
||||
# Text shown on blurred media from unfollowed users
|
||||
Media_from_someone_you_don_t_follow_5611 = Conteúdo de pessoas que você não segue
|
||||
# Tooltip for moving a column
|
||||
Moves_this_column_to_another_position_0d4b = Mover esta coluna
|
||||
# Title for the user's deck
|
||||
My_Deck_4ac5 = Minha aba
|
||||
# Label asking if the user is new to Nostr. Underneath this label is a button to create an account.
|
||||
New_to_Nostr_a2fd = Novo no Nostr?
|
||||
# NIP-05 identity field label
|
||||
Nostr_address__NIP-05_identity_74a2 = Endereço Nostr (Identidade NIP-05)
|
||||
# Default username when profile is not available
|
||||
nostrich_df29 = Nostrich
|
||||
# Status label for disconnected relay
|
||||
Not_Connected_6292 = Desconectado
|
||||
# Link text for note references
|
||||
note_cad6 = Nota
|
||||
# Beta product warning message
|
||||
Notedeck_is_a_beta_product__Expect_bugs_and_contact_us_when_you_run_into_issues_a671 = Notedeck é um produto beta. Espere erros e entre em contato conosco quando tiver problemas.
|
||||
# Filter label for notes only view
|
||||
Notes_03fb = Notas
|
||||
# Label for notes-only filter
|
||||
Notes_60d2 = Notas
|
||||
# Filter label for notes and replies view
|
||||
Notes___Replies_1ec2 = Notas e respostas
|
||||
# Label for notes and replies filter
|
||||
Notes___Replies_6e3b = Notas e respostas
|
||||
# Column title for notifications
|
||||
Notifications_d673 = Notificações
|
||||
# Title for notifications column
|
||||
Notifications_ef56 = Notificações
|
||||
# Relative time for very recent events (less than 3 seconds)
|
||||
now_2181 = Agora
|
||||
# Button label to open email client
|
||||
Open_Email_25e9 = Abrir E-mail
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = Abra o seu cliente de e-mail padrão para obter ajuda do time Damus
|
||||
# Label for others settings section
|
||||
Others_7267 = Outros
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = Cole seu URI NWC aqui...
|
||||
# Error message for missing deck name
|
||||
Please_create_a_name_for_the_deck_38e7 = Por favor, crie um nome para a aba.
|
||||
# Error message for missing deck name and icon
|
||||
Please_create_a_name_for_the_deck_and_select_an_icon_0add = Por favor, crie um nome para a aba e selecione um ícone.
|
||||
# Error message for missing deck icon
|
||||
Please_select_an_icon_655b = Favor selecionar um ícone.
|
||||
# Button label to post a note
|
||||
Post_now_8a49 = Postar
|
||||
# Instruction for copying logs
|
||||
Press_the_button_below_to_copy_your_most_recent_logs_to_your_system_s_clipboard__Then_paste_it_into_your_email_322e = Clique abaixo para copiar seus registros mais recentes para a área de transferência do seu sistema. Em seguida, cole-os no seu E-mail.
|
||||
# Profile picture URL field label
|
||||
Profile_picture_81ff = Foto de perfil
|
||||
# Column title for quote composition
|
||||
Quote_475c = Citação
|
||||
# Error message when quote note cannot be found
|
||||
Quote_of_unknown_note_e4f0 = Citação de nota desconhecida
|
||||
# Label for read-only profile mode
|
||||
Read_only_82ff = Modo leitura
|
||||
# Column title for relay management
|
||||
Relays_9d89 = Canais
|
||||
# Label for relay list section
|
||||
Relays_ad5e = Canais
|
||||
# Column title for reply composition
|
||||
Reply_3bf1 = Responder
|
||||
# Hover text for reply button
|
||||
Reply_to_this_note_f5de = Responder esta nota
|
||||
# Error message when reply note cannot be found
|
||||
Reply_to_unknown_note_4401 = Responder nota desconhecida
|
||||
# Fallback template for replying to user
|
||||
replying_to__user_15ab = Respondendo { $user }
|
||||
# Template for replying to user in unknown thread
|
||||
replying_to__user__in_someone_s_thread_e148 = Respondendo { $user } no tópico de alguém
|
||||
# Template for replying to note in different user's thread
|
||||
replying_to__user__s__note__in__thread_user__s__thread_daa8 = Resposta { $user }de { $note } em { $thread_user }' { $thread }
|
||||
# Template for replying to user's note
|
||||
replying_to__user__s__note_ccba = Respondendo { $user }de { $note }
|
||||
# Template for replying to root thread
|
||||
replying_to__user__s__thread_444d = Respondendo { $user }de { $thread }
|
||||
# Fallback text when reply note is not found
|
||||
replying_to_a_note_e0bc = Respondendo nota
|
||||
# Hover text for repost button
|
||||
Repost_this_note_8e56 = Republicar nota
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = Publicada
|
||||
# Label for reset zoom level, Appearance settings section
|
||||
Reset_62d4 = Resetar
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = Precisa de ajuda?
|
||||
# Label for satoshis (Bitcoin unit) for custom zap amount input field
|
||||
SATS_45d7 = SATS
|
||||
# Unit label for satoshis (Bitcoin unit) for configuring default zap amount in wallet settings.
|
||||
sats_e5ec = sats
|
||||
# Button to save default zap amount
|
||||
Save_6f7c = Salvar
|
||||
# Button label to save profile changes
|
||||
Save_changes_00db = Salvo
|
||||
# Column title for search page
|
||||
Search_c573 = Pesquisar
|
||||
# Placeholder for search notes input field
|
||||
Search_notes_42a6 = Pesquisar notas...
|
||||
# Search in progress message
|
||||
Searching_for___query_5d18 = Pesquisando por '{ $query }'
|
||||
# Description for Home column
|
||||
See_notes_from_your_contacts_ac16 = Veja notas dos seus contatos
|
||||
# Description for universe column
|
||||
See_the_whole_nostr_universe_7694 = Veja todo o universo Nostr
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = Enviar
|
||||
# Column title for app settings
|
||||
Settings_7a4f = Configurações
|
||||
# Label for Show source client, others settings section
|
||||
Show_source_client_9e31 = Mostrar cliente de origem
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = Mostrar a última nota para cada usuário de uma lista
|
||||
# Button label to sign out of account
|
||||
Sign_out_337b = Sair
|
||||
# Title for someone else's notes column
|
||||
Someone_else_s_Notes_7e5f = Notas de outra pessoa
|
||||
# Title for someone else's notifications column
|
||||
Someone_else_s_Notifications_82e6 = Notificações de outra pessoa
|
||||
# Description for contact list column
|
||||
Source_the_last_note_for_each_user_in_your_contact_list_e157 = Fonte da última nota para cada usuário em sua lista de contatos
|
||||
# Description for hashtags column
|
||||
Stay_up_to_date_with_a_certain_hashtag_88e3 = Mantenha-se atualizado com uma certa hashtag
|
||||
# Description for notifications column
|
||||
Stay_up_to_date_with_notifications_and_mentions_6f4e = Ficar atualizado com notificações e menções
|
||||
# Description for someone else's notes column
|
||||
Stay_up_to_date_with_someone_else_s_notes___replies_464c = Mantenha-se atualizado com as notas e respostas de alguém
|
||||
# Description for someone else's notifications column
|
||||
Stay_up_to_date_with_someone_else_s_notifications_and_mentions_3473 = Mantenha-se atualizado com as notificações e menções de alguém
|
||||
# Description for individual user column
|
||||
Stay_up_to_date_with_someone_s_notes___replies_aa78 = Mantenha-se atualizado com as notas e respostas de alguém
|
||||
# Description for your notifications column
|
||||
Stay_up_to_date_with_your_notifications_and_mentions_e73e = Mantenha-se atualizado com suas notificações e menções
|
||||
# Step 1 label in support instructions
|
||||
Step_1_8656 = Passo 1
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = Passo 2
|
||||
# Label for storage settings section
|
||||
Storage_ed65 = Armazenamento
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = Inscrever-se em notas de outra pessoa
|
||||
# Column title for subscribing to individual user
|
||||
Subscribe_to_someone_s_notes_b3c8 = Inscrever-se nas notas de alguém
|
||||
# Hover text for dark mode toggle button
|
||||
Switch_to_dark_mode_4dec = Mudar para modo escuro
|
||||
# Hover text for light mode toggle button
|
||||
Switch_to_light_mode_72ce = Mudar para modo claro
|
||||
# Button text to load blurred media
|
||||
Tap_to_Load_4b05 = Toque para carregar
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = O teste do assistente de IA Dave Nostr terminou :(. Obrigado por testar! Em breve teremos Dave habilitado para Zap
|
||||
# Label for theme, Appearance settings section
|
||||
Theme_4aac = Tema:
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = Fio
|
||||
# Link text for thread references
|
||||
thread_ad1f = Fio
|
||||
# Option in settings section to show the source client label at the top of the note
|
||||
Top_6aeb = Topo
|
||||
# Title for universe column
|
||||
Universe_e01e = Universo
|
||||
# Column title for universe feed
|
||||
Universe_ffaa = Universo
|
||||
# Checkbox label for using wallet only for current account
|
||||
Use_this_wallet_for_the_current_account_only_61dc = Use esta carteira apenas para a conta atual
|
||||
# Username and domain identification message
|
||||
username___at___domain___will_be_used_for_identification_a4fd = d = "{ $username }" em "{ $domain }" será usado para identificação
|
||||
# Profile username field label
|
||||
Username_daa7 = Usuário
|
||||
# Label for view folder button, Storage settings section
|
||||
View_folder_9742 = Visualizar pasta:
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = Carteira
|
||||
# Hint for deck name input field
|
||||
We_recommend_short_names_083e = Recomendamos nomes pequenos
|
||||
# Profile website field label
|
||||
Website_7980 = Site
|
||||
# Placeholder for note input field
|
||||
Write_a_banger_note_here_bad2 = Escreva uma nota criativa aqui.
|
||||
# Placeholder text for key input field
|
||||
Your_key_here_81bd = Sua chave aqui...
|
||||
# Title for your notes column
|
||||
Your_Notes_f6db = Suas notas
|
||||
# Title for your notifications column
|
||||
Your_Notifications_080d = Suas notificações
|
||||
# Heading for zap (tip) action
|
||||
Zap_16b4 = Zap
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = Zap esta nota
|
||||
# Label for zoom level, Appearance settings section
|
||||
Zoom_Level_29a8 = Nível de zoom:
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
# Search results count
|
||||
Got__count__results_for___query_85fb =
|
||||
{ $count ->
|
||||
[one] Obteve um resultado { $count } para '{ $query }'
|
||||
*[other] Obteve { $count } resultados para '{ $query }'
|
||||
}
|
||||
@@ -0,0 +1,410 @@
|
||||
# Main translation file for Notedeck
|
||||
# This file contains common UI strings used throughout the application
|
||||
# Auto-generated by extract_i18n.py - DO NOT EDIT MANUALLY
|
||||
|
||||
|
||||
# Regular strings
|
||||
|
||||
# Profile about/bio field label
|
||||
About_00c0 = เกี่ยวกับเรา
|
||||
# Column title for account management
|
||||
Accounts_f018 = บัญชีผู้ใช้
|
||||
# Button label to add a relay
|
||||
Add_269d = เพิ่ม
|
||||
# Label for add column button
|
||||
Add_47df = เพิ่ม
|
||||
# Button label to add a different wallet
|
||||
Add_a_different_wallet_that_will_only_be_used_for_this_account_de8d = เพิ่มวอลเล็ตอื่นเพื่อใช้สำหรับบัญชีนี้โดยเฉพาะ
|
||||
# Error message for missing wallet
|
||||
Add_a_wallet_to_continue_d170 = พิ่มวอลเล็ตเพื่อดำเนินการต่อ
|
||||
# Button label to add a new account
|
||||
Add_account_1cfc = เพิ่มบัญชี
|
||||
# Column title for adding new account
|
||||
Add_Account_d06c = เพิ่มบัญชี
|
||||
# Column title for adding algorithm column
|
||||
Add_Algo_Column_0d75 = เพิ่มคอลัมน์อัลกอฯ
|
||||
# Column title for adding new column
|
||||
Add_Column_c764 = เพิ่มคอลัมน์
|
||||
# Column title for adding new deck
|
||||
Add_Deck_fabf = เพิ่ม Deck
|
||||
# Column title for adding external notifications column
|
||||
Add_External_Notifications_Column_41ae = เพิ่มคอลัมน์การแจ้งเตือนภายนอก
|
||||
# Column title for adding hashtag column
|
||||
Add_Hashtag_Column_ebf4 = เพิ่มคอลัมน์แฮชแท็ก
|
||||
# Column title for adding last notes column
|
||||
Add_Last_Notes_Column_bbad = เพิ่มคอลัมน์โน้ตล่าสุด
|
||||
# Column title for adding notifications column
|
||||
Add_Notifications_Column_79f8 = เพิ่มคอลัมน์การแจ้งเตือน
|
||||
# Button label to add a relay
|
||||
Add_relay_269d = เพิ่มรีเลย์
|
||||
# Button label to add a wallet
|
||||
Add_Wallet_d1be = เพิ่มวอลเล็ต
|
||||
# Title for algorithmic feeds column
|
||||
Algo_2452 = อัลกอฯ
|
||||
# Description for algorithmic feeds column
|
||||
Algorithmic_feeds_to_aid_in_note_discovery_d344 = ฟีดแบบอัลกอริทึมที่ช่วยในการค้นหาโน้ต
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = จำนวน
|
||||
# Label for appearance settings section
|
||||
Appearance_4c7f = รูปลักษณ์
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = ถาม
|
||||
# Placeholder text for Dave AI input field
|
||||
Ask_dave_anything_33d1 = ถามเดฟได้ทุกเรื่อง...
|
||||
# Profile banner URL field label
|
||||
Banner_52ef = ภาพปก
|
||||
# Beta version label
|
||||
BETA_8e5d = เบต้า
|
||||
# Option in settings section to show the source client label at the bottom of the note
|
||||
Bottom_33c8 = ด้านล่าง
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = เผยแพร่
|
||||
# Broadcast the note only to local network relays
|
||||
Broadcast_Local_7e50 = เผยแพร่เฉพาะที่
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = ยกเลิก
|
||||
# Label for cancel clear cache, Storage settings section
|
||||
Cancel_fd8b = ยกเลิก
|
||||
# Label for clear cache button, Storage settings section
|
||||
Clear_cache_dccb = ล้างแคช
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = คลิกเพื่อแก้ไข
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = เขียนโน้ต
|
||||
# Label for configure relays, settings section
|
||||
Configure_relays_d156 = กำหนดค่ารีเลย์
|
||||
# Label for confirm clear cache, Storage settings section
|
||||
Confirm_9d9d = ยืนยัน
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = ยืนยัน
|
||||
# Status label for connected relay
|
||||
Connected_f8cc = เชื่อมต่อแล้ว
|
||||
# Status label for connecting relay
|
||||
Connecting_6b7e = กำลังเชื่อมต่อ...
|
||||
# Title for contact list column
|
||||
Contact_List_f85a = รายชื่อผู้ติดต่อ
|
||||
# Column title for contact lists
|
||||
Contacts_7533 = ผู้ติดต่อ
|
||||
# Column title for last notes per contact
|
||||
Contacts__last_notes_3f84 = ผู้ติดต่อ (โน้ตล่าสุด)
|
||||
# Button label to copy logs
|
||||
Copy_a688 = คัดลอก
|
||||
# Button to copy media link to clipboard
|
||||
Copy_Link_dc7c = คัดลอกลิงก์
|
||||
# Copy the unique note identifier to clipboard
|
||||
Copy_Note_ID_6b45 = คัดลอก ID โน้ต
|
||||
# Copy the raw note data in JSON format to clipboard
|
||||
Copy_Note_JSON_9e4e = คัดลอก JSON ของโน้ต
|
||||
# Copy the author's public key to clipboard
|
||||
Copy_Pubkey_9cc4 = คัดลอก Pubkey
|
||||
# Copy the text content of the note to clipboard
|
||||
Copy_Text_f81c = คัดลอกข้อความ
|
||||
# Relative time in days
|
||||
count_d_b9be = { $count }d
|
||||
# Relative time in hours
|
||||
count_h_3ecb = { $count }h
|
||||
# Relative time in minutes
|
||||
count_m_b41e = { $count }m
|
||||
# Relative time in months
|
||||
count_mo_7aba = { $count }mo
|
||||
# Relative time in seconds
|
||||
count_s_aa26 = { $count }s
|
||||
# Relative time in weeks
|
||||
count_w_7468 = { $count }w
|
||||
# Relative time in years
|
||||
count_y_9408 = { $count }y
|
||||
# Button to create a new account
|
||||
Create_Account_6994 = สร้างบัญชี
|
||||
# Button label to create a new deck
|
||||
Create_Deck_16b7 = สร้าง Deck
|
||||
# Column title for custom timelines
|
||||
Custom_a69e = กำหนดเอง
|
||||
# Column title for zap amount customization
|
||||
Customize_Zap_Amount_cfc4 = กำหนดจำนวน Zap
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = ฝ่ายสนับสนุน Damus
|
||||
# Label for Theme Dark, Appearance settings section
|
||||
Dark_85fe = มืด
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = ชื่อ Deck
|
||||
# Label for decks section in side panel
|
||||
DECKS_1fad = DECKS
|
||||
# Label for default zap amount input
|
||||
Default_amount_per_zap_399d = ยอด Zap เริ่มต้น
|
||||
# Name of the default deck feed
|
||||
Default_Deck_fcca = Deck หลัก
|
||||
# Button label to delete a deck
|
||||
Delete_Deck_bb29 = ลบ Deck
|
||||
# Tooltip for deleting a column
|
||||
Delete_this_column_8d5a = ลบคอลัมน์นี้
|
||||
# Button label to delete a wallet
|
||||
Delete_Wallet_d1d4 = ลบวอลเล็ต
|
||||
# Profile display name field label
|
||||
Display_name_f9d9 = ชื่อที่แสดง
|
||||
# Domain identification message
|
||||
domain___will_be_used_for_identification_b67e = { $domain } จะใช้สำหรับการระบุตัวตน
|
||||
# Column title for editing deck
|
||||
Edit_Deck_4018 = แก้ไข Deck
|
||||
# Button label to edit a deck
|
||||
Edit_Deck_fd93 = แก้ไข Deck
|
||||
# Button label to edit user profile
|
||||
Edit_Profile_49e6 = แก้ไขโปรไฟล์
|
||||
# Column title for profile editing
|
||||
Edit_Profile_8ad4 = แก้ไขโปรไฟล์
|
||||
# Placeholder for hashtag input field
|
||||
Enter_the_desired_hashtags_here__for_multiple_space-separated_7a69 = ใส่แฮชแท็กที่ต้องการ (หากมีหลายอัน ให้คั่นด้วยการเว้นวรรค)
|
||||
# Placeholder for relay input field
|
||||
Enter_the_relay_here_1c8b = ใส่รีเลย์ที่นี่
|
||||
# Hint text to prompt entering the user's public key.
|
||||
Enter_the_user_s_key__npub__hex__nip05__here_650c = ใส่คีย์ของผู้ใช้ (npub, hex, nip05)...
|
||||
# Label for key input field. Key can be public key (npub), private key (nsec), or Nostr address (NIP-05).
|
||||
Enter_your_key_0fca = ใส่คีย์ของคุณ
|
||||
# Instructions for entering Nostr credentials
|
||||
Enter_your_public_key__npub___nostr_address__e_g___address____or_private_key__nsec___You_must_enter_your_private_key_to_be_able_to_post__reply__etc_48e9 =
|
||||
โปรดใส่คีย์สาธารณะ (npub), ที่อยู่ Nostr (เช่น { $address }) หรือคีย์ส่วนตัว (nsec)
|
||||
คุณจำเป็นต้องใส่คีย์ส่วนตัวเพื่อทำการโพสต์, ตอบกลับ และอื่นๆ
|
||||
# Label for find user button
|
||||
Find_User_bd12 = ค้นหาผู้ใช้
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = แฮชแท็ก
|
||||
# Option in settings section to hide the source client label in note display
|
||||
Hide_281d = ซ่อน
|
||||
# Title for Home column
|
||||
Home_8c19 = หน้าแรก
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = ไอคอน
|
||||
# Label for Image cache size, Storage settings section
|
||||
Image_cache_size_3004 = ขนาดแคชรูปภาพ:
|
||||
# Title for individual user column
|
||||
Individual_b776 = ปัจเจคบุคคล
|
||||
# Error message for invalid zap amount
|
||||
Invalid_amount_6630 = จำนวนเงินไม่ถูกต้อง
|
||||
# Error message for invalid key input
|
||||
Invalid_key_4726 = คีย์ไม่ถูกต้อง
|
||||
# Error message for invalid Nostr Wallet Connect URI
|
||||
Invalid_NWC_URI_031b = NWC URI ไม่ถูกต้อง
|
||||
# Zap amount button for 100000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_100K_686c = 100K
|
||||
# Zap amount button for 10000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_10K_f7e6 = 10K
|
||||
# Zap amount button for 20000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_20K_4977 = 20K
|
||||
# Zap amount button for 50000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_50K_c2dc = 50K
|
||||
# Zap amount button for 5000 sats. Abbreviated because the button is too small to display the full amount.
|
||||
k_5K_f7e6 = 5K
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = ติดตามโน้ตและการตอบกลับของคุณ
|
||||
# Label for language, Appearance settings section
|
||||
Language_e264 = ภาษา:
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = โน้ตล่าสุดของผู้ใช้แต่ละคน
|
||||
# Label for Theme Light, Appearance settings section
|
||||
Light_7475 = สว่าง
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = ที่อยู่ Lightning Network (lud16)
|
||||
# Login page title
|
||||
Login_9eef = เข้าสู่ระบบ
|
||||
# Login button text
|
||||
Login_now___let_s_do_this_5630 = เข้าสู่ระบบเลย — มาเริ่มกัน!
|
||||
# Text shown on blurred media from unfollowed users
|
||||
Media_from_someone_you_don_t_follow_5611 = สื่อจากคนที่คุณไม่ได้ติดตาม
|
||||
# Tooltip for moving a column
|
||||
Moves_this_column_to_another_position_0d4b = ย้ายคอลัมน์นี้ไปยังตำแหน่งอื่น
|
||||
# Title for the user's deck
|
||||
My_Deck_4ac5 = Deck ของฉัน
|
||||
# Label asking if the user is new to Nostr. Underneath this label is a button to create an account.
|
||||
New_to_Nostr_a2fd = มือใหม่สำหรับ Nostr?
|
||||
# NIP-05 identity field label
|
||||
Nostr_address__NIP-05_identity_74a2 = ที่อยู่ Nostr (NIP-05)
|
||||
# Default username when profile is not available
|
||||
nostrich_df29 = นกม่วง
|
||||
# Status label for disconnected relay
|
||||
Not_Connected_6292 = ไม่ได้เชื่อมต่อ
|
||||
# Link text for note references
|
||||
note_cad6 = โน้ต
|
||||
# Beta product warning message
|
||||
Notedeck_is_a_beta_product__Expect_bugs_and_contact_us_when_you_run_into_issues_a671 = Notedeck เป็นผลิตภัณฑ์รุ่นเบต้า ซึ่งอาจมีข้อบกพร่องเกิดขึ้นได้ โปรดติดต่อเราเมื่อคุณพบปัญหา
|
||||
# Filter label for notes only view
|
||||
Notes_03fb = โน้ต
|
||||
# Label for notes-only filter
|
||||
Notes_60d2 = โน้ต
|
||||
# Filter label for notes and replies view
|
||||
Notes___Replies_1ec2 = โน้ตและการตอบกลับ
|
||||
# Label for notes and replies filter
|
||||
Notes___Replies_6e3b = โน้ตและการตอบกลับ
|
||||
# Column title for notifications
|
||||
Notifications_d673 = การแจ้งเตือน
|
||||
# Title for notifications column
|
||||
Notifications_ef56 = การแจ้งเตือน
|
||||
# Relative time for very recent events (less than 3 seconds)
|
||||
now_2181 = เมื่อสักครู่
|
||||
# Button label to open email client
|
||||
Open_Email_25e9 = เปิดอีเมล
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = เปิดโปรแกรมอีเมลของคุณเพื่อรับความช่วยเหลือจากทีม Damus
|
||||
# Label for others settings section
|
||||
Others_7267 = อื่นๆ
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = วาง NWC URI ของคุณที่นี่...
|
||||
# Error message for missing deck name
|
||||
Please_create_a_name_for_the_deck_38e7 = กรุณาตั้งชื่อ Deck
|
||||
# Error message for missing deck name and icon
|
||||
Please_create_a_name_for_the_deck_and_select_an_icon_0add = กรุณาตั้งชื่อ Deck และเลือกไอคอน
|
||||
# Error message for missing deck icon
|
||||
Please_select_an_icon_655b = กรุณาเลือกไอคอน
|
||||
# Button label to post a note
|
||||
Post_now_8a49 = โพสต์เลย
|
||||
# Instruction for copying logs
|
||||
Press_the_button_below_to_copy_your_most_recent_logs_to_your_system_s_clipboard__Then_paste_it_into_your_email_322e = กดปุ่มด้านล่างเพื่อคัดลอกข้อมูลบันทึกล่าสุด ไปยังคลิปบอร์ด จากนั้นนำไปวางในอีเมลของคุณ
|
||||
# Profile picture URL field label
|
||||
Profile_picture_81ff = รูปโปรไฟล์
|
||||
# Column title for quote composition
|
||||
Quote_475c = อ้างอิง
|
||||
# Error message when quote note cannot be found
|
||||
Quote_of_unknown_note_e4f0 = อ้างอิงโน้ตที่ไม่รู้จัก
|
||||
# Label for read-only profile mode
|
||||
Read_only_82ff = อ่านอย่างเดียว
|
||||
# Column title for relay management
|
||||
Relays_9d89 = รีเลย์
|
||||
# Label for relay list section
|
||||
Relays_ad5e = รีเลย์
|
||||
# Column title for reply composition
|
||||
Reply_3bf1 = ตอบกลับ
|
||||
# Hover text for reply button
|
||||
Reply_to_this_note_f5de = ตอบกลับโน้ตนี้
|
||||
# Error message when reply note cannot be found
|
||||
Reply_to_unknown_note_4401 = ตอบกลับโน้ตที่ไม่รู้จัก
|
||||
# Fallback template for replying to user
|
||||
replying_to__user_15ab = ตอบกลับ { $user }
|
||||
# Template for replying to user in unknown thread
|
||||
replying_to__user__in_someone_s_thread_e148 = ตอบกลับ { $user } ในเธรดของผู้อื่น
|
||||
# Template for replying to note in different user's thread
|
||||
replying_to__user__s__note__in__thread_user__s__thread_daa8 = ตอบกลับโน้ต { $note } ของ { $user } ในเธรด { $thread } ของ { $thread_user }
|
||||
# Template for replying to user's note
|
||||
replying_to__user__s__note_ccba = ตอบกลับโน้ต { $user } ใน { $note }
|
||||
# Template for replying to root thread
|
||||
replying_to__user__s__thread_444d = ตอบกลับ { $user } ใน { $thread }
|
||||
# Fallback text when reply note is not found
|
||||
replying_to_a_note_e0bc = ตอบกลับโน้ต
|
||||
# Hover text for repost button
|
||||
Repost_this_note_8e56 = รีโพสต์โน้ตนี้
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = รีโพสต์แล้ว
|
||||
# Label for reset zoom level, Appearance settings section
|
||||
Reset_62d4 = รีเซ็ต
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = พบปัญหาในการใช้งานใช่ไหม?
|
||||
# Label for satoshis (Bitcoin unit) for custom zap amount input field
|
||||
SATS_45d7 = SATS
|
||||
# Unit label for satoshis (Bitcoin unit) for configuring default zap amount in wallet settings.
|
||||
sats_e5ec = sats
|
||||
# Button to save default zap amount
|
||||
Save_6f7c = บันทึก
|
||||
# Button label to save profile changes
|
||||
Save_changes_00db = บันทึกการเปลี่ยนแปลง
|
||||
# Column title for search page
|
||||
Search_c573 = ค้นหา
|
||||
# Placeholder for search notes input field
|
||||
Search_notes_42a6 = ค้นหาโน้ต...
|
||||
# Search in progress message
|
||||
Searching_for___query_5d18 = กำลังค้นหา '{ $query }'
|
||||
# Description for Home column
|
||||
See_notes_from_your_contacts_ac16 = ดูโน้ตจากผู้ติดต่อของคุณ
|
||||
# Description for universe column
|
||||
See_the_whole_nostr_universe_7694 = ท่องจักรวาล Nostr ทั้งหมด
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = ส่ง
|
||||
# Column title for app settings
|
||||
Settings_7a4f = การตั้งค่า
|
||||
# Label for Show source client, others settings section
|
||||
Show_source_client_9e31 = แสดงไคลเอนต์ต้นทาง
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = แสดงโน้ตล่าสุดของผู้ใช้แต่ละคนจากรายการ
|
||||
# Button label to sign out of account
|
||||
Sign_out_337b = ออกจากระบบ
|
||||
# Title for someone else's notes column
|
||||
Someone_else_s_Notes_7e5f = โน้ตของผู้อื่น
|
||||
# Title for someone else's notifications column
|
||||
Someone_else_s_Notifications_82e6 = การแจ้งเตือนของผู้อื่น
|
||||
# Description for contact list column
|
||||
Source_the_last_note_for_each_user_in_your_contact_list_e157 = ดึงโน้ตล่าสุดของผู้ใช้แต่ละคนในรายชื่อผู้ติดต่อ
|
||||
# Description for hashtags column
|
||||
Stay_up_to_date_with_a_certain_hashtag_88e3 = ติดตามความเคลื่อนไหวของแฮชแท็ก
|
||||
# Description for notifications column
|
||||
Stay_up_to_date_with_notifications_and_mentions_6f4e = ติดตามการแจ้งเตือนและการกล่าวถึง
|
||||
# Description for someone else's notes column
|
||||
Stay_up_to_date_with_someone_else_s_notes___replies_464c = ติดตามโน้ตและการตอบกลับของผู้อื่น
|
||||
# Description for someone else's notifications column
|
||||
Stay_up_to_date_with_someone_else_s_notifications_and_mentions_3473 = ติดตามการแจ้งเตือนและการกล่าวถึงของผู้อื่น
|
||||
# Description for individual user column
|
||||
Stay_up_to_date_with_someone_s_notes___replies_aa78 = ติดตามโน้ตและการตอบกลับของผู้อื่น
|
||||
# Description for your notifications column
|
||||
Stay_up_to_date_with_your_notifications_and_mentions_e73e = ติดตามการแจ้งเตือนและการกล่าวถึงของคุณ
|
||||
# Step 1 label in support instructions
|
||||
Step_1_8656 = ขั้นตอนที่ 1
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = ขั้นตอนที่ 2
|
||||
# Label for storage settings section
|
||||
Storage_ed65 = พื้นที่จัดเก็บ
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = ติดตามโน้ตของผู้อื่น
|
||||
# Column title for subscribing to individual user
|
||||
Subscribe_to_someone_s_notes_b3c8 = ติดตามโน้ตของผู้อื่น
|
||||
# Hover text for dark mode toggle button
|
||||
Switch_to_dark_mode_4dec = เปลี่ยนเป็นโหมดมืด
|
||||
# Hover text for light mode toggle button
|
||||
Switch_to_light_mode_72ce = เปลี่ยนเป็นโหมดสว่าง
|
||||
# Button text to load blurred media
|
||||
Tap_to_Load_4b05 = แตะเพื่อโหลด
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = ช่วงทดลองใช้ผู้ช่วย AI 'Dave Nostr' ได้สิ้นสุดลงแล้ว :( ขอบคุณที่ร่วมทดสอบ! Dave ที่รองรับการ Zap กำลังจะมาเร็วๆ นี้!
|
||||
# Label for theme, Appearance settings section
|
||||
Theme_4aac = ธีม:
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = เธรด
|
||||
# Link text for thread references
|
||||
thread_ad1f = เธรด
|
||||
# Option in settings section to show the source client label at the top of the note
|
||||
Top_6aeb = ด้านบน
|
||||
# Title for universe column
|
||||
Universe_e01e = จักรวาล
|
||||
# Column title for universe feed
|
||||
Universe_ffaa = จักรวาล
|
||||
# Checkbox label for using wallet only for current account
|
||||
Use_this_wallet_for_the_current_account_only_61dc = ใช้วอลเล็ตนี้สำหรับบัญชีปัจจุบันเท่านั้น
|
||||
# Username and domain identification message
|
||||
username___at___domain___will_be_used_for_identification_a4fd = "{ $username }" ที่ "{ $domain }" จะถูกใช้สำหรับการระบุตัวตน
|
||||
# Profile username field label
|
||||
Username_daa7 = ชื่อผู้ใช้
|
||||
# Label for view folder button, Storage settings section
|
||||
View_folder_9742 = ดูโฟลเดอร์:
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = วอลเล็ต
|
||||
# Hint for deck name input field
|
||||
We_recommend_short_names_083e = เราแนะนำให้ใช้ชื่อสั้นๆ
|
||||
# Profile website field label
|
||||
Website_7980 = เว็บไซต์
|
||||
# Placeholder for note input field
|
||||
Write_a_banger_note_here_bad2 = เขียนโน้ตปังๆ ที่นี่...
|
||||
# Placeholder text for key input field
|
||||
Your_key_here_81bd = ใส่คีย์ของคุณที่นี่...
|
||||
# Title for your notes column
|
||||
Your_Notes_f6db = โน้ตของคุณ
|
||||
# Title for your notifications column
|
||||
Your_Notifications_080d = การแจ้งเตือนของคุณ
|
||||
# Heading for zap (tip) action
|
||||
Zap_16b4 = Zap
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = Zap โน้ตนี้
|
||||
# Label for zoom level, Appearance settings section
|
||||
Zoom_Level_29a8 = ระดับการซูม:
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
# Search results count
|
||||
Got__count__results_for___query_85fb =
|
||||
{ $count ->
|
||||
[one] ผลการค้นหา '{ $query }': พบ { $count } รายการ
|
||||
*[other] ผลการค้นหา '{ $query }': พบ { $count } รายการ
|
||||
}
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
# Profile about/bio field label
|
||||
About_00c0 = 关于
|
||||
# Display name for account management
|
||||
Accounts_e233 = 帐户
|
||||
# Column title for account management
|
||||
Accounts_f018 = 帐户
|
||||
# Button label to add a relay
|
||||
@@ -23,16 +21,10 @@ Add_a_wallet_to_continue_d170 = 添加钱包以继续
|
||||
Add_account_1cfc = 添加帐户
|
||||
# Column title for adding new account
|
||||
Add_Account_d06c = 添加帐户
|
||||
# Display name for adding account
|
||||
Add_Account_d715 = 添加帐户
|
||||
# Column title for adding algorithm column
|
||||
Add_Algo_Column_0d75 = 添加算法列
|
||||
# Display name for adding column
|
||||
Add_Column_c6ff = 添加列
|
||||
# Column title for adding new column
|
||||
Add_Column_c764 = 添加列
|
||||
# Display name for adding deck
|
||||
Add_Deck_6e5f = 添加仪表板
|
||||
# Column title for adding new deck
|
||||
Add_Deck_fabf = 添加仪表板
|
||||
# Column title for adding external notifications column
|
||||
@@ -53,6 +45,8 @@ Algo_2452 = 算法
|
||||
Algorithmic_feeds_to_aid_in_note_discovery_d344 = 用于帮助发现笔记的算法源
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = 金额
|
||||
# Label for appearance settings section
|
||||
Appearance_4c7f = 外观
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = 询问
|
||||
# Placeholder text for Dave AI input field
|
||||
@@ -61,18 +55,26 @@ Ask_dave_anything_33d1 = 向 Dave 提问任何问题…
|
||||
Banner_52ef = 横幅
|
||||
# Beta version label
|
||||
BETA_8e5d = BETA
|
||||
# Option in settings section to show the source client label at the bottom of the note
|
||||
Bottom_33c8 = 底部
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = 广播
|
||||
# Broadcast the note only to local network relays
|
||||
Broadcast_Local_7e50 = 仅广播至本地中继
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = 取消
|
||||
# Label for cancel clear cache, Storage settings section
|
||||
Cancel_fd8b = 取消
|
||||
# Label for clear cache button, Storage settings section
|
||||
Clear_cache_dccb = 清除缓存
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = 点击以编辑
|
||||
# Display name for note composition
|
||||
Compose_Note_ad11 = 撰写笔记
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = 撰写笔记
|
||||
# Label for configure relays, settings section
|
||||
Configure_relays_d156 = 配置中继器
|
||||
# Label for confirm clear cache, Storage settings section
|
||||
Confirm_9d9d = 确认
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = 确认
|
||||
# Status label for connected relay
|
||||
@@ -83,8 +85,6 @@ Connecting_6b7e = 正在连接...
|
||||
Contact_List_f85a = 联系人列表
|
||||
# Column title for contact lists
|
||||
Contacts_7533 = 联系人
|
||||
# Timeline kind label for contact lists
|
||||
Contacts_8b98 = 联系人
|
||||
# Column title for last notes per contact
|
||||
Contacts__last_notes_3f84 = 联系人(最新笔记)
|
||||
# Button label to copy logs
|
||||
@@ -119,14 +119,12 @@ Create_Account_6994 = 创建帐户
|
||||
Create_Deck_16b7 = 创建仪表板
|
||||
# Column title for custom timelines
|
||||
Custom_a69e = 自定义
|
||||
# Display name for custom timelines
|
||||
Custom_cb4f = 自定义
|
||||
# Column title for zap amount customization
|
||||
Customize_Zap_Amount_cfc4 = 自定义打闪金额
|
||||
# Display name for zap customization
|
||||
Customize_Zap_Amount_ed29 = 自定义打闪金额
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = 达摩支持
|
||||
# Label for Theme Dark, Appearance settings section
|
||||
Dark_85fe = 暗色
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = 仪表板名称
|
||||
# Label for decks section in side panel
|
||||
@@ -147,14 +145,10 @@ Display_name_f9d9 = 显示名称
|
||||
domain___will_be_used_for_identification_b67e = "{ $domain }" 将用于身份识别
|
||||
# Column title for editing deck
|
||||
Edit_Deck_4018 = 编辑仪表板
|
||||
# Display name for editing deck
|
||||
Edit_Deck_c9ba = 编辑仪表板
|
||||
# Button label to edit a deck
|
||||
Edit_Deck_fd93 = 编辑仪表板
|
||||
# Button label to edit user profile
|
||||
Edit_Profile_49e6 = 编辑个人档案
|
||||
# Display name for profile editing
|
||||
Edit_Profile_6699 = 编辑个人档案
|
||||
# Column title for profile editing
|
||||
Edit_Profile_8ad4 = 编辑个人档案
|
||||
# Placeholder for hashtag input field
|
||||
@@ -169,18 +163,16 @@ Enter_your_key_0fca = 请输入你的密钥
|
||||
Enter_your_public_key__npub___nostr_address__e_g___address____or_private_key__nsec___You_must_enter_your_private_key_to_be_able_to_post__reply__etc_48e9 = 请输入你的公钥(npub)、nostr 地址(如 { $address })、或私钥(nsec)。 你必须输入你的私钥才能发帖、回复等等。
|
||||
# Label for find user button
|
||||
Find_User_bd12 = 查找用户
|
||||
# Timeline kind label for hashtag feeds
|
||||
Hashtag_a0ab = 标签
|
||||
# Display name for hashtag feeds
|
||||
Hashtags_617e = 标签
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = 标签
|
||||
# Display name for home feed
|
||||
Home_3efc = 主页
|
||||
# Option in settings section to hide the source client label in note display
|
||||
Hide_281d = 隐藏
|
||||
# Title for Home column
|
||||
Home_8c19 = 主页
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = 图标
|
||||
# Label for Image cache size, Storage settings section
|
||||
Image_cache_size_3004 = 图像缓存大小:
|
||||
# Title for individual user column
|
||||
Individual_b776 = 个人
|
||||
# Error message for invalid zap amount
|
||||
@@ -201,12 +193,12 @@ k_50K_c2dc = 5万
|
||||
k_5K_f7e6 = 5千
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = 随时查看你的笔记和回复
|
||||
# Label for language, Appearance settings section
|
||||
Language_e264 = 语言:
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = 每个用户的最新笔记
|
||||
# Timeline kind label for last notes per pubkey
|
||||
Last_Notes_aefe = 最新笔记
|
||||
# Display name for last notes per contact
|
||||
Last_Per_Pubkey__Contact_33ce = 每个公钥(联系人)的最新笔记
|
||||
# Label for Theme Light, Appearance settings section
|
||||
Light_7475 = 亮色
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = 闪电网络地址(lud16)
|
||||
# Login page title
|
||||
@@ -239,10 +231,6 @@ Notes_60d2 = 笔记
|
||||
Notes___Replies_1ec2 = 笔记和回复
|
||||
# Label for notes and replies filter
|
||||
Notes___Replies_6e3b = 笔记和回复
|
||||
# Timeline kind label for notifications
|
||||
Notifications_6228 = 通知
|
||||
# Display name for notifications
|
||||
Notifications_8029 = 通知
|
||||
# Column title for notifications
|
||||
Notifications_d673 = 通知
|
||||
# Title for notifications column
|
||||
@@ -253,6 +241,8 @@ now_2181 = 刚刚
|
||||
Open_Email_25e9 = 打开电子邮箱
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = 打开你的默认电子邮件客户端以获得达摩团队的帮助
|
||||
# Label for others settings section
|
||||
Others_7267 = 其它
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = 在此粘贴你的 NWC URI...
|
||||
# Error message for missing deck name
|
||||
@@ -265,30 +255,20 @@ Please_select_an_icon_655b = 请选择一个图标。
|
||||
Post_now_8a49 = 立即发布
|
||||
# Instruction for copying logs
|
||||
Press_the_button_below_to_copy_your_most_recent_logs_to_your_system_s_clipboard__Then_paste_it_into_your_email_322e = 请按下面的按钮将你最近的日志复制到系统剪贴板,然后将其粘贴到你的电子邮件。
|
||||
# Display name for user profiles
|
||||
Profile_2478 = 个人资料
|
||||
# Timeline kind label for user profiles
|
||||
Profile_9027 = 个人资料
|
||||
# Profile picture URL field label
|
||||
Profile_picture_81ff = 头像图片
|
||||
# Column title for quote composition
|
||||
Quote_475c = 引用
|
||||
# Display name for quote composition
|
||||
Quote_a38e = 引用
|
||||
# Error message when quote note cannot be found
|
||||
Quote_of_unknown_note_e4f0 = 引用未知笔记
|
||||
# Label for read-only profile mode
|
||||
Read_only_82ff = 只读
|
||||
# Display name for relay management
|
||||
Relays_7335 = 中继器
|
||||
# Column title for relay management
|
||||
Relays_9d89 = 中继器
|
||||
# Label for relay list section
|
||||
Relays_ad5e = 中继器
|
||||
# Column title for reply composition
|
||||
Reply_3bf1 = 回复
|
||||
# Display name for reply composition
|
||||
Reply_b40f = 回复
|
||||
# Hover text for reply button
|
||||
Reply_to_this_note_f5de = 回复此笔记
|
||||
# Error message when reply note cannot be found
|
||||
@@ -309,6 +289,8 @@ replying_to_a_note_e0bc = 正在回复笔记
|
||||
Repost_this_note_8e56 = 转发此笔记
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = 已转发
|
||||
# Label for reset zoom level, Appearance settings section
|
||||
Reset_62d4 = 重置
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = 遇到故障了吗?
|
||||
# Label for satoshis (Bitcoin unit) for custom zap amount input field
|
||||
@@ -319,12 +301,6 @@ sats_e5ec = 聪
|
||||
Save_6f7c = 保存
|
||||
# Button label to save profile changes
|
||||
Save_changes_00db = 保存变更
|
||||
# Display name for search results
|
||||
Search_0aa0 = 搜索
|
||||
# Display name for search page
|
||||
Search_4503 = 搜索
|
||||
# Timeline kind label for search results
|
||||
Search_a0b8 = 搜索
|
||||
# Column title for search page
|
||||
Search_c573 = 搜索
|
||||
# Placeholder for search notes input field
|
||||
@@ -337,6 +313,10 @@ See_notes_from_your_contacts_ac16 = 查看来自你的联系人的笔记
|
||||
See_the_whole_nostr_universe_7694 = 查看整个 nostr 宇宙
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = 发送
|
||||
# Column title for app settings
|
||||
Settings_7a4f = 设置
|
||||
# Label for Show source client, others settings section
|
||||
Show_source_client_9e31 = 显示来源客户端
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = 显示列表中每个用户的最新一条笔记
|
||||
# Button label to sign out of account
|
||||
@@ -363,12 +343,12 @@ Stay_up_to_date_with_your_notifications_and_mentions_e73e = 获取你的通知
|
||||
Step_1_8656 = 第一步
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = 第二步
|
||||
# Label for storage settings section
|
||||
Storage_ed65 = 存储
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = 订阅他人的笔记
|
||||
# Column title for subscribing to individual user
|
||||
Subscribe_to_someone_s_notes_b3c8 = 订阅某人的笔记
|
||||
# Display name for support page
|
||||
Support_a4b4 = 获取帮助
|
||||
# Hover text for dark mode toggle button
|
||||
Switch_to_dark_mode_4dec = 切换到暗色模式
|
||||
# Hover text for light mode toggle button
|
||||
@@ -377,18 +357,14 @@ Switch_to_light_mode_72ce = 切换到亮色模式
|
||||
Tap_to_Load_4b05 = 点击加载
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = Dave Nostr AI 助手试用期已经结束 :(。感谢测试!可打闪付款的 Dave 即将来临!
|
||||
# Label for theme, Appearance settings section
|
||||
Theme_4aac = 主题:
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = 帖子
|
||||
# Display name for thread view
|
||||
Thread_9957 = 帖子
|
||||
# Link text for thread references
|
||||
thread_ad1f = 帖子
|
||||
# Generic timeline kind label
|
||||
Timeline_b0fc = 时间线
|
||||
# Timeline kind label for universe feed
|
||||
Universe_0a3e = 宇宙
|
||||
# Display name for universe feed
|
||||
Universe_d47e = 宇宙
|
||||
# Option in settings section to show the source client label at the top of the note
|
||||
Top_6aeb = 顶部
|
||||
# Title for universe column
|
||||
Universe_e01e = 宇宙
|
||||
# Column title for universe feed
|
||||
@@ -399,10 +375,10 @@ Use_this_wallet_for_the_current_account_only_61dc = 此钱包仅限用于当前
|
||||
username___at___domain___will_be_used_for_identification_a4fd = "{ $username }" 于 "{ $domain }" 将被用于身份识别
|
||||
# Profile username field label
|
||||
Username_daa7 = 用户名
|
||||
# Label for view folder button, Storage settings section
|
||||
View_folder_9742 = 查看文件夹:
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = 钱包
|
||||
# Display name for wallet management
|
||||
Wallet_cdca = 钱包
|
||||
# Hint for deck name input field
|
||||
We_recommend_short_names_083e = 我们推荐使用简短的名称
|
||||
# Profile website field label
|
||||
@@ -419,6 +395,8 @@ Your_Notifications_080d = 你的通知
|
||||
Zap_16b4 = 打闪
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = 打闪此笔记
|
||||
# Label for zoom level, Appearance settings section
|
||||
Zoom_Level_29a8 = 缩放大小:
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
# Profile about/bio field label
|
||||
About_00c0 = 關於
|
||||
# Display name for account management
|
||||
Accounts_e233 = 帳戶
|
||||
# Column title for account management
|
||||
Accounts_f018 = 帳戶
|
||||
# Button label to add a relay
|
||||
@@ -23,16 +21,10 @@ Add_a_wallet_to_continue_d170 = 添加錢包以繼續
|
||||
Add_account_1cfc = 新增帳戶
|
||||
# Column title for adding new account
|
||||
Add_Account_d06c = 新增帳戶
|
||||
# Display name for adding account
|
||||
Add_Account_d715 = 新增帳戶
|
||||
# Column title for adding algorithm column
|
||||
Add_Algo_Column_0d75 = 添加算法列
|
||||
# Display name for adding column
|
||||
Add_Column_c6ff = 添加列
|
||||
# Column title for adding new column
|
||||
Add_Column_c764 = 添加列
|
||||
# Display name for adding deck
|
||||
Add_Deck_6e5f = 添加儀表板
|
||||
# Column title for adding new deck
|
||||
Add_Deck_fabf = 添加儀表板
|
||||
# Column title for adding external notifications column
|
||||
@@ -53,6 +45,8 @@ Algo_2452 = 算法
|
||||
Algorithmic_feeds_to_aid_in_note_discovery_d344 = 用於幫助發現筆記的算法源
|
||||
# Label for zap amount input field
|
||||
Amount_70f0 = 金額
|
||||
# Label for appearance settings section
|
||||
Appearance_4c7f = 外觀
|
||||
# Button to send message to Dave AI assistant
|
||||
Ask_b7f4 = 詢問
|
||||
# Placeholder text for Dave AI input field
|
||||
@@ -61,18 +55,26 @@ Ask_dave_anything_33d1 = 向 Dave 提問任何問題...
|
||||
Banner_52ef = 橫幅
|
||||
# Beta version label
|
||||
BETA_8e5d = 測試版
|
||||
# Option in settings section to show the source client label at the bottom of the note
|
||||
Bottom_33c8 = 底部
|
||||
# Broadcast the note to all connected relays
|
||||
Broadcast_fe43 = 廣播
|
||||
# Broadcast the note only to local network relays
|
||||
Broadcast_Local_7e50 = 僅廣播至本地中繼
|
||||
# Button label to cancel an action
|
||||
Cancel_ed3b = 取消
|
||||
# Label for cancel clear cache, Storage settings section
|
||||
Cancel_fd8b = 取消
|
||||
# Label for clear cache button, Storage settings section
|
||||
Clear_cache_dccb = 清除快取
|
||||
# Hover text for editable zap amount
|
||||
Click_to_edit_0414 = 點擊編輯
|
||||
# Display name for note composition
|
||||
Compose_Note_ad11 = 撰寫筆記
|
||||
# Column title for note composition
|
||||
Compose_Note_c094 = 撰寫筆記
|
||||
# Label for configure relays, settings section
|
||||
Configure_relays_d156 = 配置中繼器
|
||||
# Label for confirm clear cache, Storage settings section
|
||||
Confirm_9d9d = 確認
|
||||
# Button label to confirm an action
|
||||
Confirm_f8a6 = 確認
|
||||
# Status label for connected relay
|
||||
@@ -83,8 +85,6 @@ Connecting_6b7e = 正在連接 ...
|
||||
Contact_List_f85a = 聯絡人列表
|
||||
# Column title for contact lists
|
||||
Contacts_7533 = 聯絡人
|
||||
# Timeline kind label for contact lists
|
||||
Contacts_8b98 = 聯絡人
|
||||
# Column title for last notes per contact
|
||||
Contacts__last_notes_3f84 = 聯絡人(最新筆記)
|
||||
# Button label to copy logs
|
||||
@@ -119,14 +119,12 @@ Create_Account_6994 = 創建帳戶
|
||||
Create_Deck_16b7 = 創建儀表板
|
||||
# Column title for custom timelines
|
||||
Custom_a69e = 自訂
|
||||
# Display name for custom timelines
|
||||
Custom_cb4f = 自訂
|
||||
# Column title for zap amount customization
|
||||
Customize_Zap_Amount_cfc4 = 自訂打閃金額
|
||||
# Display name for zap customization
|
||||
Customize_Zap_Amount_ed29 = 自訂打閃金額
|
||||
# Column title for support page
|
||||
Damus_Support_27c0 = 達摩支持
|
||||
# Label for Theme Dark, Appearance settings section
|
||||
Dark_85fe = 暗色
|
||||
# Label for deck name input field
|
||||
Deck_name_cd32 = 儀表板名稱
|
||||
# Label for decks section in side panel
|
||||
@@ -147,14 +145,10 @@ Display_name_f9d9 = 顯示名稱
|
||||
domain___will_be_used_for_identification_b67e = "{ $domain }" 將用於身份識別
|
||||
# Column title for editing deck
|
||||
Edit_Deck_4018 = 編輯儀表板
|
||||
# Display name for editing deck
|
||||
Edit_Deck_c9ba = 編輯儀表板
|
||||
# Button label to edit a deck
|
||||
Edit_Deck_fd93 = 編輯儀表板
|
||||
# Button label to edit user profile
|
||||
Edit_Profile_49e6 = 編輯個人檔案
|
||||
# Display name for profile editing
|
||||
Edit_Profile_6699 = 編輯個人檔案
|
||||
# Column title for profile editing
|
||||
Edit_Profile_8ad4 = 編輯個人檔案
|
||||
# Placeholder for hashtag input field
|
||||
@@ -169,18 +163,16 @@ Enter_your_key_0fca = 請輸入你的密鑰
|
||||
Enter_your_public_key__npub___nostr_address__e_g___address____or_private_key__nsec___You_must_enter_your_private_key_to_be_able_to_post__reply__etc_48e9 = 請輸入你的公鑰(npub)、nostr 地址(如 { $address })、或私鑰(nsec)。你必須輸入你的私鑰才能發貼、回覆等等。
|
||||
# Label for find user button
|
||||
Find_User_bd12 = 查找用戶
|
||||
# Timeline kind label for hashtag feeds
|
||||
Hashtag_a0ab = 標籤
|
||||
# Display name for hashtag feeds
|
||||
Hashtags_617e = 標籤
|
||||
# Title for hashtags column
|
||||
Hashtags_f8e0 = 標籤
|
||||
# Display name for home feed
|
||||
Home_3efc = 主頁
|
||||
# Option in settings section to hide the source client label in note display
|
||||
Hide_281d = 隱藏
|
||||
# Title for Home column
|
||||
Home_8c19 = 主頁
|
||||
# Label for deck icon selection
|
||||
Icon_b0ab = 圖標
|
||||
# Label for Image cache size, Storage settings section
|
||||
Image_cache_size_3004 = 圖像快取大小:
|
||||
# Title for individual user column
|
||||
Individual_b776 = 個人
|
||||
# Error message for invalid zap amount
|
||||
@@ -201,12 +193,12 @@ k_50K_c2dc = 5萬
|
||||
k_5K_f7e6 = 5千
|
||||
# Description for your notes column
|
||||
Keep_track_of_your_notes___replies_a334 = 隨時查看你的筆記和回覆
|
||||
# Label for language, Appearance settings section
|
||||
Language_e264 = 語言:
|
||||
# Title for last note per user column
|
||||
Last_Note_per_User_17ad = 每個用戶的最新筆記
|
||||
# Timeline kind label for last notes per pubkey
|
||||
Last_Notes_aefe = 最新筆記
|
||||
# Display name for last notes per contact
|
||||
Last_Per_Pubkey__Contact_33ce = 每個公鑰(聯繫人)的最新筆記
|
||||
# Label for Theme Light, Appearance settings section
|
||||
Light_7475 = 亮色
|
||||
# Bitcoin Lightning network address field label
|
||||
Lightning_network_address__lud16_ea51 = 閃電網絡地址(lud16)
|
||||
# Login page title
|
||||
@@ -239,10 +231,6 @@ Notes_60d2 = 筆記
|
||||
Notes___Replies_1ec2 = 筆記和回覆
|
||||
# Label for notes and replies filter
|
||||
Notes___Replies_6e3b = 筆記和回覆
|
||||
# Timeline kind label for notifications
|
||||
Notifications_6228 = 通知
|
||||
# Display name for notifications
|
||||
Notifications_8029 = 通知
|
||||
# Column title for notifications
|
||||
Notifications_d673 = 通知
|
||||
# Title for notifications column
|
||||
@@ -253,6 +241,8 @@ now_2181 = 剛剛
|
||||
Open_Email_25e9 = 打開電子郵箱
|
||||
# Instruction to open email client
|
||||
Open_your_default_email_client_to_get_help_from_the_Damus_team_68dc = 打開你的默認電子郵件客戶端以獲得達摩團隊的幫助
|
||||
# Label for others settings section
|
||||
Others_7267 = 其他
|
||||
# Placeholder text for NWC URI input
|
||||
Paste_your_NWC_URI_here_b471 = 在此貼上你的 NWC URI...
|
||||
# Error message for missing deck name
|
||||
@@ -265,30 +255,20 @@ Please_select_an_icon_655b = 請選擇一個圖標。
|
||||
Post_now_8a49 = 立即發布
|
||||
# Instruction for copying logs
|
||||
Press_the_button_below_to_copy_your_most_recent_logs_to_your_system_s_clipboard__Then_paste_it_into_your_email_322e = 請按下面的按鈕將你最近的日誌複製到剪貼板,然後將其粘貼到你的電子郵件。
|
||||
# Display name for user profiles
|
||||
Profile_2478 = 個人檔案
|
||||
# Timeline kind label for user profiles
|
||||
Profile_9027 = 個人檔案
|
||||
# Profile picture URL field label
|
||||
Profile_picture_81ff = 頭像圖片
|
||||
# Column title for quote composition
|
||||
Quote_475c = 引用
|
||||
# Display name for quote composition
|
||||
Quote_a38e = 引用
|
||||
# Error message when quote note cannot be found
|
||||
Quote_of_unknown_note_e4f0 = 引用未知筆記
|
||||
# Label for read-only profile mode
|
||||
Read_only_82ff = 只讀
|
||||
# Display name for relay management
|
||||
Relays_7335 = 中繼器
|
||||
# Column title for relay management
|
||||
Relays_9d89 = 中繼器
|
||||
# Label for relay list section
|
||||
Relays_ad5e = 中繼器
|
||||
# Column title for reply composition
|
||||
Reply_3bf1 = 回覆
|
||||
# Display name for reply composition
|
||||
Reply_b40f = 回覆
|
||||
# Hover text for reply button
|
||||
Reply_to_this_note_f5de = 回覆此筆記
|
||||
# Error message when reply note cannot be found
|
||||
@@ -309,6 +289,8 @@ replying_to_a_note_e0bc = 正在回覆筆記
|
||||
Repost_this_note_8e56 = 轉發此筆記
|
||||
# Label for reposted notes
|
||||
Reposted_61c8 = 已轉發
|
||||
# Label for reset zoom level, Appearance settings section
|
||||
Reset_62d4 = 重置
|
||||
# Heading for support section
|
||||
Running_into_a_bug_1796 = 遇到故障了嗎?
|
||||
# Label for satoshis (Bitcoin unit) for custom zap amount input field
|
||||
@@ -319,12 +301,6 @@ sats_e5ec = 聰
|
||||
Save_6f7c = 保存
|
||||
# Button label to save profile changes
|
||||
Save_changes_00db = 保存變更
|
||||
# Display name for search results
|
||||
Search_0aa0 = 搜索
|
||||
# Display name for search page
|
||||
Search_4503 = 搜索
|
||||
# Timeline kind label for search results
|
||||
Search_a0b8 = 搜索
|
||||
# Column title for search page
|
||||
Search_c573 = 搜索
|
||||
# Placeholder for search notes input field
|
||||
@@ -337,6 +313,10 @@ See_notes_from_your_contacts_ac16 = 查看來自你的聯繫人的筆記
|
||||
See_the_whole_nostr_universe_7694 = 查看整個 nostr 宇宙
|
||||
# Button label to send a zap
|
||||
Send_1ea4 = 發送
|
||||
# Column title for app settings
|
||||
Settings_7a4f = 設置
|
||||
# Label for Show source client, others settings section
|
||||
Show_source_client_9e31 = 顯示來源客戶端
|
||||
# Description for last note per user column
|
||||
Show_the_last_note_for_each_user_from_a_list_50e7 = 顯示列表中每個用戶的最後一條筆記
|
||||
# Button label to sign out of account
|
||||
@@ -363,12 +343,12 @@ Stay_up_to_date_with_your_notifications_and_mentions_e73e = 獲取你的通知
|
||||
Step_1_8656 = 第一步
|
||||
# Step 2 label in support instructions
|
||||
Step_2_d08d = 第二步
|
||||
# Label for storage settings section
|
||||
Storage_ed65 = 儲存
|
||||
# Column title for subscribing to external user
|
||||
Subscribe_to_someone_else_s_notes_d1e9 = 訂閱他人的筆記
|
||||
# Column title for subscribing to individual user
|
||||
Subscribe_to_someone_s_notes_b3c8 = 訂閱某人的筆記
|
||||
# Display name for support page
|
||||
Support_a4b4 = 獲取幫助
|
||||
# Hover text for dark mode toggle button
|
||||
Switch_to_dark_mode_4dec = 切換到暗色模式
|
||||
# Hover text for light mode toggle button
|
||||
@@ -377,18 +357,14 @@ Switch_to_light_mode_72ce = 切換到亮色模式
|
||||
Tap_to_Load_4b05 = 點擊加載
|
||||
# Message shown when Dave trial period has ended
|
||||
The_Dave_Nostr_AI_assistant_trial_has_ended_____Thanks_for_testing__Zap-enabled_Dave_coming_soon_c6c7 = Dave Nostr AI 助手試用期已經結束 :(。感謝測試!可打閃付款的 Dave 即將來臨!
|
||||
# Label for theme, Appearance settings section
|
||||
Theme_4aac = 主題:
|
||||
# Column title for note thread view
|
||||
Thread_0f20 = 串文
|
||||
# Display name for thread view
|
||||
Thread_9957 = 串文
|
||||
# Link text for thread references
|
||||
thread_ad1f = 串文
|
||||
# Generic timeline kind label
|
||||
Timeline_b0fc = 時間線
|
||||
# Timeline kind label for universe feed
|
||||
Universe_0a3e = 宇宙
|
||||
# Display name for universe feed
|
||||
Universe_d47e = 宇宙
|
||||
# Option in settings section to show the source client label at the top of the note
|
||||
Top_6aeb = 頂部
|
||||
# Title for universe column
|
||||
Universe_e01e = 宇宙
|
||||
# Column title for universe feed
|
||||
@@ -399,10 +375,10 @@ Use_this_wallet_for_the_current_account_only_61dc = 此錢包僅限用於當前
|
||||
username___at___domain___will_be_used_for_identification_a4fd = "{ $username }" 於 "{ $domain }" 將被用於身份識別
|
||||
# Profile username field label
|
||||
Username_daa7 = 用戶名
|
||||
# Label for view folder button, Storage settings section
|
||||
View_folder_9742 = 查看文件夾:
|
||||
# Column title for wallet management
|
||||
Wallet_5e50 = 錢包
|
||||
# Display name for wallet management
|
||||
Wallet_cdca = 錢包
|
||||
# Hint for deck name input field
|
||||
We_recommend_short_names_083e = 我們推薦使用簡短的名稱
|
||||
# Profile website field label
|
||||
@@ -419,6 +395,8 @@ Your_Notifications_080d = 你的通知
|
||||
Zap_16b4 = 打閃
|
||||
# Hover text for zap button
|
||||
Zap_this_note_42b2 = 打閃此筆記
|
||||
# Label for zoom level, Appearance settings section
|
||||
Zoom_Level_29a8 = 縮放大小:
|
||||
|
||||
# Pluralized strings
|
||||
|
||||
|
||||
@@ -207,6 +207,10 @@ impl Accounts {
|
||||
self.cache.selected_mut()
|
||||
}
|
||||
|
||||
pub fn get_selected_wallet(&self) -> Option<&ZapWallet> {
|
||||
self.cache.selected().wallet.as_ref()
|
||||
}
|
||||
|
||||
pub fn get_selected_wallet_mut(&mut self) -> Option<&mut ZapWallet> {
|
||||
self.cache.selected_mut().wallet.as_mut()
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ pub enum ContactState {
|
||||
Received {
|
||||
contacts: HashSet<Pubkey>,
|
||||
note_key: NoteKey,
|
||||
timestamp: u64,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -57,6 +58,7 @@ impl Contacts {
|
||||
ContactState::Received {
|
||||
contacts,
|
||||
note_key: _,
|
||||
timestamp: _,
|
||||
} => {
|
||||
if contacts.contains(other_pubkey) {
|
||||
IsFollowing::Yes
|
||||
@@ -82,6 +84,18 @@ impl Contacts {
|
||||
}
|
||||
};
|
||||
|
||||
if let ContactState::Received {
|
||||
contacts: _,
|
||||
note_key: _,
|
||||
timestamp,
|
||||
} = self.get_state()
|
||||
{
|
||||
if *timestamp > note.created_at() {
|
||||
// the current contact list is more up to date than the one we just received. ignore it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
update_state(&mut self.state, ¬e, *key);
|
||||
}
|
||||
|
||||
@@ -96,11 +110,17 @@ fn update_state(state: &mut ContactState, note: &Note, key: NoteKey) {
|
||||
*state = ContactState::Received {
|
||||
contacts: get_contacts_owned(note),
|
||||
note_key: key,
|
||||
timestamp: note.created_at(),
|
||||
};
|
||||
}
|
||||
ContactState::Received { contacts, note_key } => {
|
||||
ContactState::Received {
|
||||
contacts,
|
||||
note_key,
|
||||
timestamp,
|
||||
} => {
|
||||
update_contacts(contacts, note);
|
||||
*note_key = key;
|
||||
*timestamp = note.created_at();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::{AccountData, RelaySpec};
|
||||
use enostr::{Keypair, Pubkey, RelayPool};
|
||||
use nostrdb::{Filter, Ndb, NoteBuilder, NoteKey, Subscription, Transaction};
|
||||
use tracing::{debug, error, info};
|
||||
use url::Url;
|
||||
|
||||
use crate::{AccountData, RelaySpec};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct AccountRelayData {
|
||||
pub filter: Filter,
|
||||
|
||||
@@ -5,13 +5,28 @@ use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use unic_langid::{langid, LanguageIdentifier};
|
||||
|
||||
const EN_XA: LanguageIdentifier = langid!("en-XA");
|
||||
const EN_US: LanguageIdentifier = langid!("en-US");
|
||||
const EN_XA: LanguageIdentifier = langid!("en-XA");
|
||||
const DE: LanguageIdentifier = langid!("de");
|
||||
const FR: LanguageIdentifier = langid!("FR");
|
||||
const ZH_CN: LanguageIdentifier = langid!("ZH_CN");
|
||||
const ZH_TW: LanguageIdentifier = langid!("ZH_TW");
|
||||
const NUM_FTLS: usize = 6;
|
||||
const ES_419: LanguageIdentifier = langid!("es-419");
|
||||
const ES_ES: LanguageIdentifier = langid!("es-ES");
|
||||
const FR: LanguageIdentifier = langid!("fr");
|
||||
const PT_BR: LanguageIdentifier = langid!("pt-BR");
|
||||
const TH: LanguageIdentifier = langid!("th");
|
||||
const ZH_CN: LanguageIdentifier = langid!("zh-CN");
|
||||
const ZH_TW: LanguageIdentifier = langid!("zh-TW");
|
||||
const NUM_FTLS: usize = 10;
|
||||
|
||||
const EN_US_NATIVE_NAME: &str = "English (US)";
|
||||
const EN_XA_NATIVE_NAME: &str = "Éñglísh (Pséúdólóçàlé)";
|
||||
const DE_NATIVE_NAME: &str = "Deutsch";
|
||||
const ES_419_NATIVE_NAME: &str = "Español (Latinoamérica)";
|
||||
const ES_ES_NATIVE_NAME: &str = "Español (España)";
|
||||
const FR_NATIVE_NAME: &str = "Français";
|
||||
const PT_BR_NATIVE_NAME: &str = "Português (Brasil)";
|
||||
const TH_NATIVE_NAME: &str = "ภาษาไทย";
|
||||
const ZH_CN_NATIVE_NAME: &str = "简体中文";
|
||||
const ZH_TW_NATIVE_NAME: &str = "繁體中文";
|
||||
|
||||
struct StaticBundle {
|
||||
identifier: LanguageIdentifier,
|
||||
@@ -31,10 +46,26 @@ const FTLS: [StaticBundle; NUM_FTLS] = [
|
||||
identifier: DE,
|
||||
ftl: include_str!("../../../../assets/translations/de/main.ftl"),
|
||||
},
|
||||
StaticBundle {
|
||||
identifier: ES_419,
|
||||
ftl: include_str!("../../../../assets/translations/es-419/main.ftl"),
|
||||
},
|
||||
StaticBundle {
|
||||
identifier: ES_ES,
|
||||
ftl: include_str!("../../../../assets/translations/es-ES/main.ftl"),
|
||||
},
|
||||
StaticBundle {
|
||||
identifier: FR,
|
||||
ftl: include_str!("../../../../assets/translations/fr/main.ftl"),
|
||||
},
|
||||
StaticBundle {
|
||||
identifier: PT_BR,
|
||||
ftl: include_str!("../../../../assets/translations/pt-BR/main.ftl"),
|
||||
},
|
||||
StaticBundle {
|
||||
identifier: TH,
|
||||
ftl: include_str!("../../../../assets/translations/th/main.ftl"),
|
||||
},
|
||||
StaticBundle {
|
||||
identifier: ZH_CN,
|
||||
ftl: include_str!("../../../../assets/translations/zh-CN/main.ftl"),
|
||||
@@ -55,6 +86,8 @@ pub struct Localization {
|
||||
available_locales: Vec<LanguageIdentifier>,
|
||||
/// Fallback locale
|
||||
fallback_locale: LanguageIdentifier,
|
||||
/// Native names for locales
|
||||
locale_native_names: HashMap<LanguageIdentifier, String>,
|
||||
|
||||
/// Cached string results per locale (only for strings without arguments)
|
||||
string_cache: HashMap<LanguageIdentifier, HashMap<String, String>>,
|
||||
@@ -62,6 +95,8 @@ pub struct Localization {
|
||||
normalized_key_cache: HashMap<String, IntlKeyBuf>,
|
||||
/// Bundles
|
||||
bundles: HashMap<LanguageIdentifier, Bundle>,
|
||||
|
||||
use_isolating: bool,
|
||||
}
|
||||
|
||||
impl Default for Localization {
|
||||
@@ -75,15 +110,34 @@ impl Default for Localization {
|
||||
EN_US.clone(),
|
||||
EN_XA.clone(),
|
||||
DE.clone(),
|
||||
ES_419.clone(),
|
||||
ES_ES.clone(),
|
||||
FR.clone(),
|
||||
PT_BR.clone(),
|
||||
TH.clone(),
|
||||
ZH_CN.clone(),
|
||||
ZH_TW.clone(),
|
||||
];
|
||||
|
||||
let locale_native_names = HashMap::from([
|
||||
(EN_US, EN_US_NATIVE_NAME.to_owned()),
|
||||
(EN_XA, EN_XA_NATIVE_NAME.to_owned()),
|
||||
(DE, DE_NATIVE_NAME.to_owned()),
|
||||
(ES_419, ES_419_NATIVE_NAME.to_owned()),
|
||||
(ES_ES, ES_ES_NATIVE_NAME.to_owned()),
|
||||
(FR, FR_NATIVE_NAME.to_owned()),
|
||||
(PT_BR, PT_BR_NATIVE_NAME.to_owned()),
|
||||
(TH, TH_NATIVE_NAME.to_owned()),
|
||||
(ZH_CN, ZH_CN_NATIVE_NAME.to_owned()),
|
||||
(ZH_TW, ZH_TW_NATIVE_NAME.to_owned()),
|
||||
]);
|
||||
|
||||
Self {
|
||||
current_locale: default_locale.to_owned(),
|
||||
available_locales,
|
||||
fallback_locale,
|
||||
locale_native_names,
|
||||
use_isolating: true,
|
||||
normalized_key_cache: HashMap::new(),
|
||||
string_cache: HashMap::new(),
|
||||
bundles: HashMap::new(),
|
||||
@@ -97,6 +151,14 @@ impl Localization {
|
||||
Localization::default()
|
||||
}
|
||||
|
||||
/// Disable bidirectional isolation markers. mostly useful for tests
|
||||
pub fn no_bidi() -> Self {
|
||||
Localization {
|
||||
use_isolating: false,
|
||||
..Localization::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a localized string by its ID
|
||||
pub fn get_string(&mut self, id: IntlKey<'_>) -> Result<String, IntlError> {
|
||||
self.get_cached_string(id, None)
|
||||
@@ -152,8 +214,11 @@ impl Localization {
|
||||
}
|
||||
|
||||
fn try_load_bundle(&mut self, lang: &LanguageIdentifier) -> Result<(), IntlError> {
|
||||
self.bundles
|
||||
.insert(lang.to_owned(), Self::load_bundle(lang)?);
|
||||
let mut bundle = Self::load_bundle(lang)?;
|
||||
if !self.use_isolating {
|
||||
bundle.set_use_isolating(false);
|
||||
}
|
||||
self.bundles.insert(lang.to_owned(), bundle);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -228,6 +293,7 @@ impl Localization {
|
||||
);
|
||||
self.try_load_bundle(&locale)
|
||||
.expect("failed to load fallback bundle!?");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -358,6 +424,10 @@ impl Localization {
|
||||
&self.fallback_locale
|
||||
}
|
||||
|
||||
pub fn get_locale_native_name(&self, locale: &LanguageIdentifier) -> Option<&str> {
|
||||
self.locale_native_names.get(locale).map(|s| s.as_str())
|
||||
}
|
||||
|
||||
/// Gets cache statistics for monitoring performance
|
||||
pub fn get_cache_stats(&self) -> Result<CacheStats, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let mut total_strings = 0;
|
||||
@@ -414,8 +484,13 @@ pub struct CacheStats {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
//
|
||||
// TODO(jb55): write tests that work, i broke all these during the refacto
|
||||
//
|
||||
|
||||
/*
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_locale_management() {
|
||||
let i18n = Localization::default();
|
||||
@@ -431,26 +506,6 @@ mod tests {
|
||||
assert_eq!(available[1].to_string(), "en-XA");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ftl_caching() {
|
||||
let mut i18n = Localization::default();
|
||||
|
||||
// First call should load and cache the FTL content
|
||||
let result1 = i18n.get_string(IntlKeyBuf::new("test_key").borrow());
|
||||
assert!(result1.is_ok());
|
||||
assert_eq!(result1.as_ref().unwrap(), "Test Value");
|
||||
|
||||
// Second call should use cached FTL content
|
||||
let result2 = i18n.get_string(IntlKeyBuf::new("test_key").borrow());
|
||||
assert!(result2.is_ok());
|
||||
assert_eq!(result2.unwrap(), "Test Value");
|
||||
|
||||
// Test another key from the same FTL content
|
||||
let result3 = i18n.get_string(IntlKeyBuf::new("another_key").borrow());
|
||||
assert!(result3.is_ok());
|
||||
assert_eq!(result3.unwrap(), "Another Value");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cache_clearing() {
|
||||
let mut i18n = Localization::default();
|
||||
@@ -498,6 +553,26 @@ mod tests {
|
||||
assert_eq!(result3.unwrap(), "Test Value");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_ftl_caching() {
|
||||
let mut i18n = Localization::default();
|
||||
|
||||
// First call should load and cache the FTL content
|
||||
let result1 = i18n.get_string(IntlKeyBuf::new("test_key").borrow());
|
||||
assert!(result1.is_ok());
|
||||
assert_eq!(result1.as_ref().unwrap(), "Test Value");
|
||||
|
||||
// Second call should use cached FTL content
|
||||
let result2 = i18n.get_string(IntlKeyBuf::new("test_key").borrow());
|
||||
assert!(result2.is_ok());
|
||||
assert_eq!(result2.unwrap(), "Test Value");
|
||||
|
||||
// Test another key from the same FTL content
|
||||
let result3 = i18n.get_string(IntlKeyBuf::new("another_key").borrow());
|
||||
assert!(result3.is_ok());
|
||||
assert_eq!(result3.unwrap(), "Another Value");
|
||||
}
|
||||
#[test]
|
||||
fn test_bundle_caching() {
|
||||
let mut i18n = Localization::default();
|
||||
@@ -537,31 +612,6 @@ mod tests {
|
||||
let stats = i18n.get_cache_stats().unwrap();
|
||||
assert_eq!(stats.string_cache_size, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cache_clearing_on_locale_change() {
|
||||
// Enable pseudolocale for this test
|
||||
std::env::set_var("NOTEDECK_PSEUDOLOCALE", "1");
|
||||
|
||||
let mut i18n = Localization::default();
|
||||
|
||||
// Check that caches are populated
|
||||
let stats1 = i18n.get_cache_stats().unwrap();
|
||||
assert!(stats1.resource_cache_size > 0);
|
||||
assert!(stats1.string_cache_size > 0);
|
||||
|
||||
// Switch to en-XA
|
||||
let en_xa: LanguageIdentifier = langid!("en-XA");
|
||||
i18n.set_locale(en_xa).unwrap();
|
||||
|
||||
// Check that string cache is cleared (resource cache remains for both locales)
|
||||
let stats2 = i18n.get_cache_stats().unwrap();
|
||||
assert_eq!(stats2.string_cache_size, 0);
|
||||
|
||||
// Cleanup
|
||||
std::env::remove_var("NOTEDECK_PSEUDOLOCALE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_caching_with_arguments() {
|
||||
let mut manager = Localization::default();
|
||||
@@ -602,6 +652,25 @@ mod tests {
|
||||
let stats3 = manager.get_cache_stats().unwrap();
|
||||
assert_eq!(stats3.string_cache_size, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cache_clearing_on_locale_change() {
|
||||
let mut i18n = Localization::default();
|
||||
|
||||
// Check that caches are populated
|
||||
let stats1 = i18n.get_cache_stats().unwrap();
|
||||
assert!(stats1.resource_cache_size > 0);
|
||||
assert!(stats1.string_cache_size > 0);
|
||||
|
||||
// Switch to en-XA
|
||||
let en_xa: LanguageIdentifier = langid!("en-XA");
|
||||
i18n.set_locale(en_xa).unwrap();
|
||||
|
||||
// Check that string cache is cleared (resource cache remains for both locales)
|
||||
let stats2 = i18n.get_cache_stats().unwrap();
|
||||
assert_eq!(stats2.string_cache_size, 0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/// Replace each invalid character with exactly one underscore
|
||||
|
||||
@@ -7,9 +7,11 @@ use poll_promise::Promise;
|
||||
use egui::ColorImage;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::fs::{self, create_dir_all, File};
|
||||
use std::sync::mpsc::Receiver;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant, SystemTime};
|
||||
use std::{io, thread};
|
||||
|
||||
use hex::ToHex;
|
||||
use sha2::Digest;
|
||||
@@ -220,6 +222,7 @@ pub struct MediaCache {
|
||||
pub cache_dir: path::PathBuf,
|
||||
pub textures_cache: TexturesCache,
|
||||
pub cache_type: MediaCacheType,
|
||||
pub cache_size: Arc<Mutex<Option<u64>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
@@ -231,10 +234,29 @@ pub enum MediaCacheType {
|
||||
impl MediaCache {
|
||||
pub fn new(parent_dir: &Path, cache_type: MediaCacheType) -> Self {
|
||||
let cache_dir = parent_dir.join(Self::rel_dir(cache_type));
|
||||
|
||||
let cache_dir_clone = cache_dir.clone();
|
||||
let cache_size = Arc::new(Mutex::new(None));
|
||||
let cache_size_clone = Arc::clone(&cache_size);
|
||||
|
||||
thread::spawn(move || {
|
||||
let mut last_checked = Instant::now() - Duration::from_secs(999);
|
||||
loop {
|
||||
// check cache folder size every 60 s
|
||||
if last_checked.elapsed() >= Duration::from_secs(60) {
|
||||
let size = compute_folder_size(&cache_dir_clone);
|
||||
*cache_size_clone.lock().unwrap() = Some(size);
|
||||
last_checked = Instant::now();
|
||||
}
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
}
|
||||
});
|
||||
|
||||
Self {
|
||||
cache_dir,
|
||||
textures_cache: TexturesCache::default(),
|
||||
cache_type,
|
||||
cache_size,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,8 +353,14 @@ impl MediaCache {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.textures_cache.cache.clear();
|
||||
*self.cache_size.try_lock().unwrap() = Some(0);
|
||||
}
|
||||
}
|
||||
|
||||
fn color_image_to_rgba(color_image: ColorImage) -> image::RgbaImage {
|
||||
@@ -349,7 +377,28 @@ fn color_image_to_rgba(color_image: ColorImage) -> image::RgbaImage {
|
||||
.expect("Failed to create RgbaImage from ColorImage")
|
||||
}
|
||||
|
||||
fn compute_folder_size<P: AsRef<Path>>(path: P) -> u64 {
|
||||
fn walk(path: &Path) -> u64 {
|
||||
let mut size = 0;
|
||||
if let Ok(entries) = fs::read_dir(path) {
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if let Ok(metadata) = entry.metadata() {
|
||||
if metadata.is_file() {
|
||||
size += metadata.len();
|
||||
} else if metadata.is_dir() {
|
||||
size += walk(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
size
|
||||
}
|
||||
walk(path.as_ref())
|
||||
}
|
||||
|
||||
pub struct Images {
|
||||
pub base_path: path::PathBuf,
|
||||
pub static_imgs: MediaCache,
|
||||
pub gifs: MediaCache,
|
||||
pub urls: UrlMimes,
|
||||
@@ -360,6 +409,7 @@ impl Images {
|
||||
/// path to directory to place [`MediaCache`]s
|
||||
pub fn new(path: path::PathBuf) -> Self {
|
||||
Self {
|
||||
base_path: path.clone(),
|
||||
static_imgs: MediaCache::new(&path, MediaCacheType::Image),
|
||||
gifs: MediaCache::new(&path, MediaCacheType::Gif),
|
||||
urls: UrlMimes::new(UrlCache::new(path.join(UrlCache::rel_dir()))),
|
||||
@@ -385,6 +435,26 @@ impl Images {
|
||||
MediaCacheType::Gif => &mut self.gifs,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_folder_contents(&mut self) -> io::Result<()> {
|
||||
for entry in fs::read_dir(self.base_path.clone())? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
|
||||
if path.is_dir() {
|
||||
fs::remove_dir_all(path)?;
|
||||
} else {
|
||||
fs::remove_file(path)?;
|
||||
}
|
||||
}
|
||||
|
||||
self.urls.cache.clear();
|
||||
self.static_imgs.clear();
|
||||
self.gifs.clear();
|
||||
self.gif_states.clear();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub type GifStateMap = HashMap<String, GifState>;
|
||||
|
||||
@@ -72,8 +72,8 @@ pub use unknowns::{get_unknown_note_ids, NoteRefsUnkIdAction, SingleUnkIdAction,
|
||||
pub use urls::{supported_mime_hosted_at_url, SupportedMimeType, UrlMimes};
|
||||
pub use user_account::UserAccount;
|
||||
pub use wallet::{
|
||||
get_current_wallet, get_wallet_for, GlobalWallet, Wallet, WalletError, WalletType,
|
||||
WalletUIState, ZapWallet,
|
||||
get_current_wallet, get_current_wallet_mut, get_wallet_for, GlobalWallet, Wallet, WalletError,
|
||||
WalletType, WalletUIState, ZapWallet,
|
||||
};
|
||||
pub use zaps::{
|
||||
get_current_default_msats, AnyZapState, DefaultZapError, DefaultZapMsats, NoteZapTarget,
|
||||
|
||||
@@ -5,6 +5,7 @@ pub use action::{MediaAction, NoteAction, ScrollInfo, ZapAction, ZapTargetAmount
|
||||
pub use context::{BroadcastContext, ContextSelection, NoteContextSelection};
|
||||
|
||||
use crate::Accounts;
|
||||
use crate::GlobalWallet;
|
||||
use crate::JobPool;
|
||||
use crate::Localization;
|
||||
use crate::UnknownIds;
|
||||
@@ -20,6 +21,7 @@ use std::fmt;
|
||||
pub struct NoteContext<'d> {
|
||||
pub ndb: &'d Ndb,
|
||||
pub accounts: &'d Accounts,
|
||||
pub global_wallet: &'d GlobalWallet,
|
||||
pub i18n: &'d mut Localization,
|
||||
pub img_cache: &'d mut Images,
|
||||
pub note_cache: &'d mut NoteCache,
|
||||
@@ -28,7 +30,6 @@ pub struct NoteContext<'d> {
|
||||
pub job_pool: &'d mut JobPool,
|
||||
pub unknown_ids: &'d mut UnknownIds,
|
||||
pub clipboard: &'d mut egui_winit::clipboard::Clipboard,
|
||||
pub current_account_has_wallet: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
|
||||
|
||||
+10
-10
@@ -107,7 +107,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_now_condition() {
|
||||
let now = get_current_timestamp();
|
||||
let mut intl = Localization::default();
|
||||
let mut intl = Localization::no_bidi();
|
||||
|
||||
// Test 0 seconds ago
|
||||
let result = time_ago_between(&mut intl, now, now);
|
||||
@@ -137,7 +137,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_seconds_condition() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test 3 seconds ago
|
||||
let result = time_ago_between(&mut i18n, now - 3, now);
|
||||
@@ -163,7 +163,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_minutes_condition() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test 1 minute ago
|
||||
let result = time_ago_between(&mut i18n, now - ONE_MINUTE_IN_SECONDS, now);
|
||||
@@ -189,7 +189,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_hours_condition() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test 1 hour ago
|
||||
let result = time_ago_between(&mut i18n, now - ONE_HOUR_IN_SECONDS, now);
|
||||
@@ -215,7 +215,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_days_condition() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test 1 day ago
|
||||
let result = time_ago_between(&mut i18n, now - ONE_DAY_IN_SECONDS, now);
|
||||
@@ -233,7 +233,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_weeks_condition() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test 1 week ago
|
||||
let result = time_ago_between(&mut i18n, now - ONE_WEEK_IN_SECONDS, now);
|
||||
@@ -247,7 +247,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_months_condition() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test 1 month ago
|
||||
let result = time_ago_between(&mut i18n, now - ONE_MONTH_IN_SECONDS, now);
|
||||
@@ -265,7 +265,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_years_condition() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test 1 year ago
|
||||
let result = time_ago_between(&mut i18n, now - ONE_YEAR_IN_SECONDS, now);
|
||||
@@ -287,7 +287,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_future_timestamps() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test 1 minute in the future
|
||||
let result = time_ago_between(&mut i18n, now + ONE_MINUTE_IN_SECONDS, now);
|
||||
@@ -317,7 +317,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_boundary_conditions() {
|
||||
let now = get_current_timestamp();
|
||||
let mut i18n = Localization::default();
|
||||
let mut i18n = Localization::no_bidi();
|
||||
|
||||
// Test boundary between seconds and minutes
|
||||
let result = time_ago_between(&mut i18n, now - 60, now);
|
||||
|
||||
@@ -68,6 +68,17 @@ impl UrlCache {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
if self.from_disk_promise.is_none() {
|
||||
let cache = self.cache.clone();
|
||||
std::thread::spawn(move || {
|
||||
if let Ok(mut locked_cache) = cache.write() {
|
||||
locked_cache.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_cache(cur_cache: Arc<RwLock<UrlsToMime>>, from_disk: UrlsToMime) {
|
||||
|
||||
@@ -24,7 +24,7 @@ pub fn get_wallet_for<'a>(
|
||||
global_wallet.wallet.as_ref()
|
||||
}
|
||||
|
||||
pub fn get_current_wallet<'a>(
|
||||
pub fn get_current_wallet_mut<'a>(
|
||||
accounts: &'a mut Accounts,
|
||||
global_wallet: &'a mut GlobalWallet,
|
||||
) -> Option<&'a mut ZapWallet> {
|
||||
@@ -35,6 +35,17 @@ pub fn get_current_wallet<'a>(
|
||||
Some(wallet)
|
||||
}
|
||||
|
||||
pub fn get_current_wallet<'a>(
|
||||
accounts: &'a Accounts,
|
||||
global_wallet: &'a GlobalWallet,
|
||||
) -> Option<&'a ZapWallet> {
|
||||
let Some(wallet) = accounts.get_selected_wallet() else {
|
||||
return global_wallet.wallet.as_ref();
|
||||
};
|
||||
|
||||
Some(wallet)
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||
pub enum WalletType {
|
||||
Auto,
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
//use egui_android::run_android;
|
||||
|
||||
use egui_winit::winit::platform::android::activity::AndroidApp;
|
||||
use notedeck::enostr::Error;
|
||||
use notedeck_columns::Damus;
|
||||
use notedeck_dave::Dave;
|
||||
|
||||
use crate::{app::NotedeckApp, chrome::Chrome, setup::setup_chrome};
|
||||
use notedeck::Notedeck;
|
||||
use tracing::error;
|
||||
|
||||
#[no_mangle]
|
||||
#[tokio::main]
|
||||
@@ -80,11 +82,10 @@ pub async fn android_main(app: AndroidApp) {
|
||||
.intersection(columns.unrecognized_args())
|
||||
.cloned()
|
||||
.collect();
|
||||
assert!(
|
||||
completely_unrecognized.is_empty(),
|
||||
"unrecognized args: {:?}",
|
||||
completely_unrecognized
|
||||
);
|
||||
if !completely_unrecognized.is_empty() {
|
||||
error!("Unrecognized arguments: {:?}", completely_unrecognized);
|
||||
return Err(Error::Empty.into());
|
||||
}
|
||||
|
||||
chrome.add_app(NotedeckApp::Columns(columns));
|
||||
chrome.add_app(NotedeckApp::Dave(dave));
|
||||
|
||||
@@ -58,6 +58,7 @@ pub enum ChromePanelAction {
|
||||
Wallet,
|
||||
Toolbar(ToolbarAction),
|
||||
SaveTheme(ThemePreference),
|
||||
Profile(notedeck::enostr::Pubkey),
|
||||
}
|
||||
|
||||
impl ChromePanelAction {
|
||||
@@ -150,7 +151,7 @@ impl ChromePanelAction {
|
||||
}
|
||||
|
||||
Self::Settings => {
|
||||
Self::columns_navigate(ctx, chrome, notedeck_columns::Route::Relays);
|
||||
Self::columns_navigate(ctx, chrome, notedeck_columns::Route::Settings);
|
||||
}
|
||||
|
||||
Self::Wallet => {
|
||||
@@ -160,6 +161,9 @@ impl ChromePanelAction {
|
||||
notedeck_columns::Route::Wallet(WalletType::Auto),
|
||||
);
|
||||
}
|
||||
Self::Profile(pk) => {
|
||||
columns_route_to_profile(pk, chrome, ctx, ui);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -571,6 +575,16 @@ fn columns_button(ui: &mut egui::Ui) -> egui::Response {
|
||||
)
|
||||
}
|
||||
|
||||
fn accounts_button(ui: &mut egui::Ui) -> egui::Response {
|
||||
expanding_button(
|
||||
"accounts-button",
|
||||
24.0,
|
||||
app_images::accounts_image().tint(ui.visuals().text_color()),
|
||||
app_images::accounts_image(),
|
||||
ui,
|
||||
)
|
||||
}
|
||||
|
||||
fn dave_sidebar_rect(ui: &mut egui::Ui) -> Rect {
|
||||
let size = vec2(60.0, 60.0);
|
||||
let available = ui.available_rect_before_wrap();
|
||||
@@ -685,7 +699,7 @@ fn chrome_handle_app_action(
|
||||
);
|
||||
|
||||
if let Some(action) = m_action {
|
||||
let col = cols.column_mut(0);
|
||||
let col = cols.selected_mut();
|
||||
|
||||
action.process(&mut col.router, &mut col.sheet_router);
|
||||
}
|
||||
@@ -693,6 +707,59 @@ fn chrome_handle_app_action(
|
||||
}
|
||||
}
|
||||
|
||||
fn columns_route_to_profile(
|
||||
pk: ¬edeck::enostr::Pubkey,
|
||||
chrome: &mut Chrome,
|
||||
ctx: &mut AppContext,
|
||||
ui: &mut egui::Ui,
|
||||
) {
|
||||
chrome.switch_to_columns();
|
||||
let Some(columns) = chrome.get_columns_app() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let cols = columns
|
||||
.decks_cache
|
||||
.active_columns_mut(ctx.i18n, ctx.accounts)
|
||||
.unwrap();
|
||||
|
||||
let router = cols.get_selected_router();
|
||||
if router.routes().iter().any(|r| {
|
||||
matches!(
|
||||
r,
|
||||
notedeck_columns::Route::Timeline(TimelineKind::Profile(_))
|
||||
)
|
||||
}) {
|
||||
router.go_back();
|
||||
return;
|
||||
}
|
||||
|
||||
let txn = Transaction::new(ctx.ndb).unwrap();
|
||||
let m_action = notedeck_columns::actionbar::execute_and_process_note_action(
|
||||
notedeck::NoteAction::Profile(*pk),
|
||||
ctx.ndb,
|
||||
cols,
|
||||
0,
|
||||
&mut columns.timeline_cache,
|
||||
&mut columns.threads,
|
||||
ctx.note_cache,
|
||||
ctx.pool,
|
||||
&txn,
|
||||
ctx.unknown_ids,
|
||||
ctx.accounts,
|
||||
ctx.global_wallet,
|
||||
ctx.zaps,
|
||||
ctx.img_cache,
|
||||
ui,
|
||||
);
|
||||
|
||||
if let Some(action) = m_action {
|
||||
let col = cols.selected_mut();
|
||||
|
||||
action.process(&mut col.router, &mut col.sheet_router);
|
||||
}
|
||||
}
|
||||
|
||||
fn pfp_button(ctx: &mut AppContext, ui: &mut egui::Ui) -> egui::Response {
|
||||
let max_size = ICON_WIDTH * ICON_EXPANSION_MULTIPLE; // max size of the widget
|
||||
let helper = AnimationHelper::new(ui, "pfp-button", egui::vec2(max_size, max_size));
|
||||
@@ -708,6 +775,38 @@ fn pfp_button(ctx: &mut AppContext, ui: &mut egui::Ui) -> egui::Response {
|
||||
ui.put(helper.get_animation_rect(), &mut widget);
|
||||
|
||||
helper.take_animation_response()
|
||||
|
||||
// let selected = ctx.accounts.cache.selected();
|
||||
|
||||
// pfp_resp.context_menu(|ui| {
|
||||
// for (pk, account) in &ctx.accounts.cache {
|
||||
// let profile = ctx.ndb.get_profile_by_pubkey(&txn, pk).ok();
|
||||
// let is_selected = *pk == selected.key.pubkey;
|
||||
// let has_nsec = account.key.secret_key.is_some();
|
||||
|
||||
// let profile_peview_view = {
|
||||
// let max_size = egui::vec2(ui.available_width(), 77.0);
|
||||
// let resp = ui.allocate_response(max_size, egui::Sense::click());
|
||||
// ui.allocate_new_ui(UiBuilder::new().max_rect(resp.rect), |ui| {
|
||||
// ui.add(
|
||||
// &mut ProfilePic::new(ctx.img_cache, get_profile_url(profile.as_ref()))
|
||||
// .size(24.0),
|
||||
// )
|
||||
// })
|
||||
// };
|
||||
|
||||
// // if let Some(op) = profile_peview_view {
|
||||
// // return_op = Some(match op {
|
||||
// // ProfilePreviewAction::SwitchTo => AccountsViewResponse::SelectAccount(*pk),
|
||||
// // ProfilePreviewAction::RemoveAccount => AccountsViewResponse::RemoveAccount(*pk),
|
||||
// // });
|
||||
// // }
|
||||
// }
|
||||
// // if ui.menu_image_button(image, add_contents).clicked() {
|
||||
// // // ui.ctx().copy_text(url.to_owned());
|
||||
// // ui.close_menu();
|
||||
// // }
|
||||
// });
|
||||
}
|
||||
|
||||
/// The section of the chrome sidebar that starts at the
|
||||
@@ -720,6 +819,7 @@ fn bottomup_sidebar(
|
||||
ui.add_space(8.0);
|
||||
|
||||
let pfp_resp = pfp_button(ctx, ui).on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
let accounts_resp = accounts_button(ui).on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
let settings_resp = settings_button(ui).on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
|
||||
let theme_action = match ui.ctx().theme() {
|
||||
@@ -791,6 +891,9 @@ fn bottomup_sidebar(
|
||||
}
|
||||
|
||||
if pfp_resp.clicked() {
|
||||
let pk = ctx.accounts.get_selected_account().key.pubkey;
|
||||
Some(ChromePanelAction::Profile(pk))
|
||||
} else if accounts_resp.clicked() {
|
||||
Some(ChromePanelAction::Account)
|
||||
} else if settings_resp.clicked() {
|
||||
Some(ChromePanelAction::Settings)
|
||||
|
||||
@@ -9,6 +9,7 @@ use re_memory::AccountingAllocator;
|
||||
static GLOBAL: AccountingAllocator<std::alloc::System> =
|
||||
AccountingAllocator::new(std::alloc::System);
|
||||
|
||||
use notedeck::enostr::Error;
|
||||
use notedeck::{DataPath, DataPathType, Notedeck};
|
||||
use notedeck_chrome::{
|
||||
setup::{generate_native_options, setup_chrome},
|
||||
@@ -16,6 +17,7 @@ use notedeck_chrome::{
|
||||
};
|
||||
use notedeck_columns::Damus;
|
||||
use notedeck_dave::Dave;
|
||||
use tracing::error;
|
||||
use tracing_appender::non_blocking::WorkerGuard;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
@@ -104,10 +106,10 @@ async fn main() {
|
||||
.intersection(columns.unrecognized_args())
|
||||
.cloned()
|
||||
.collect();
|
||||
assert!(
|
||||
completely_unrecognized.is_empty(),
|
||||
"unrecognized args: {completely_unrecognized:?}"
|
||||
);
|
||||
if !completely_unrecognized.is_empty() {
|
||||
error!("Unrecognized arguments: {:?}", completely_unrecognized);
|
||||
return Err(Error::Empty.into());
|
||||
}
|
||||
|
||||
chrome.add_app(NotedeckApp::Columns(columns));
|
||||
chrome.add_app(NotedeckApp::Dave(dave));
|
||||
@@ -212,17 +214,6 @@ mod tests {
|
||||
let mut app_ctx = notedeck.app_context();
|
||||
let app = Damus::new(&mut app_ctx, &args);
|
||||
|
||||
// ensure we recognized all the arguments
|
||||
let completely_unrecognized: Vec<String> = unrecognized_args
|
||||
.intersection(app.unrecognized_args())
|
||||
.cloned()
|
||||
.collect();
|
||||
assert!(
|
||||
completely_unrecognized.is_empty(),
|
||||
"unrecognized args: {:?}",
|
||||
completely_unrecognized
|
||||
);
|
||||
|
||||
assert_eq!(app.columns(app_ctx.accounts).columns().len(), 2);
|
||||
|
||||
let tl1 = app
|
||||
|
||||
@@ -29,6 +29,7 @@ pub fn setup_chrome(ctx: &egui::Context, args: ¬edeck::Args, theme: ThemePref
|
||||
});
|
||||
ctx.set_visuals_of(egui::Theme::Dark, theme::dark_mode(is_oled));
|
||||
ctx.set_visuals_of(egui::Theme::Light, theme::light_mode());
|
||||
|
||||
setup_cc(ctx, is_mobile);
|
||||
}
|
||||
|
||||
@@ -38,6 +39,7 @@ pub fn setup_cc(ctx: &egui::Context, is_mobile: bool) {
|
||||
if notedeck::ui::is_compiled_as_mobile() {
|
||||
ctx.set_pixels_per_point(ctx.pixels_per_point() + 0.2);
|
||||
}
|
||||
|
||||
//ctx.set_pixels_per_point(1.0);
|
||||
//
|
||||
//
|
||||
|
||||
@@ -11,6 +11,7 @@ description = "A tweetdeck-style notedeck app"
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
||||
[dependencies]
|
||||
opener = { workspace = true }
|
||||
rmpv = { workspace = true }
|
||||
bech32 = { workspace = true }
|
||||
notedeck = { workspace = true }
|
||||
|
||||
@@ -38,6 +38,7 @@ pub enum DamusState {
|
||||
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
||||
pub struct Damus {
|
||||
state: DamusState,
|
||||
|
||||
pub decks_cache: DecksCache,
|
||||
pub view_state: ViewState,
|
||||
pub drafts: Drafts,
|
||||
@@ -77,9 +78,7 @@ fn handle_key_events(input: &egui::InputState, columns: &mut Columns) {
|
||||
columns.select_left();
|
||||
}
|
||||
egui::Key::BrowserBack | egui::Key::Escape => {
|
||||
if let Some(column) = columns.selected_mut() {
|
||||
column.router_mut().go_back();
|
||||
}
|
||||
columns.get_selected_router().go_back();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -393,13 +392,13 @@ fn determine_key_storage_type() -> KeyStorageType {
|
||||
|
||||
impl Damus {
|
||||
/// Called once before the first frame.
|
||||
pub fn new(ctx: &mut AppContext<'_>, args: &[String]) -> Self {
|
||||
pub fn new(app_context: &mut AppContext<'_>, args: &[String]) -> Self {
|
||||
// arg parsing
|
||||
|
||||
let (parsed_args, unrecognized_args) =
|
||||
ColumnsArgs::parse(args, Some(ctx.accounts.selected_account_pubkey()));
|
||||
ColumnsArgs::parse(args, Some(app_context.accounts.selected_account_pubkey()));
|
||||
|
||||
let account = ctx.accounts.selected_account_pubkey_bytes();
|
||||
let account = app_context.accounts.selected_account_pubkey_bytes();
|
||||
|
||||
let mut timeline_cache = TimelineCache::default();
|
||||
let mut options = AppOptions::default();
|
||||
@@ -409,31 +408,34 @@ impl Damus {
|
||||
let decks_cache = if tmp_columns {
|
||||
info!("DecksCache: loading from command line arguments");
|
||||
let mut columns: Columns = Columns::new();
|
||||
let txn = Transaction::new(ctx.ndb).unwrap();
|
||||
let txn = Transaction::new(app_context.ndb).unwrap();
|
||||
for col in &parsed_args.columns {
|
||||
let timeline_kind = col.clone().into_timeline_kind();
|
||||
if let Some(add_result) = columns.add_new_timeline_column(
|
||||
&mut timeline_cache,
|
||||
&txn,
|
||||
ctx.ndb,
|
||||
ctx.note_cache,
|
||||
ctx.pool,
|
||||
app_context.ndb,
|
||||
app_context.note_cache,
|
||||
app_context.pool,
|
||||
&timeline_kind,
|
||||
) {
|
||||
add_result.process(
|
||||
ctx.ndb,
|
||||
ctx.note_cache,
|
||||
app_context.ndb,
|
||||
app_context.note_cache,
|
||||
&txn,
|
||||
&mut timeline_cache,
|
||||
ctx.unknown_ids,
|
||||
app_context.unknown_ids,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
columns_to_decks_cache(ctx.i18n, columns, account)
|
||||
} else if let Some(decks_cache) =
|
||||
crate::storage::load_decks_cache(ctx.path, ctx.ndb, &mut timeline_cache, ctx.i18n)
|
||||
{
|
||||
columns_to_decks_cache(app_context.i18n, columns, account)
|
||||
} else if let Some(decks_cache) = crate::storage::load_decks_cache(
|
||||
app_context.path,
|
||||
app_context.ndb,
|
||||
&mut timeline_cache,
|
||||
app_context.i18n,
|
||||
) {
|
||||
info!(
|
||||
"DecksCache: loading from disk {}",
|
||||
crate::storage::DECKS_CACHE_FILE
|
||||
@@ -441,13 +443,13 @@ impl Damus {
|
||||
decks_cache
|
||||
} else {
|
||||
info!("DecksCache: creating new with demo configuration");
|
||||
DecksCache::new_with_demo_config(&mut timeline_cache, ctx)
|
||||
//for (pk, _) in &ctx.accounts.cache {
|
||||
DecksCache::new_with_demo_config(&mut timeline_cache, app_context)
|
||||
//for (pk, _) in &app_context.accounts.cache {
|
||||
// cache.add_deck_default(*pk);
|
||||
//}
|
||||
};
|
||||
|
||||
let support = Support::new(ctx.path);
|
||||
let support = Support::new(app_context.path);
|
||||
let mut note_options = NoteOptions::default();
|
||||
note_options.set(
|
||||
NoteOptions::Textmode,
|
||||
@@ -462,10 +464,14 @@ impl Damus {
|
||||
parsed_args.is_flag_set(ColumnsFlag::NoMedia),
|
||||
);
|
||||
note_options.set(
|
||||
NoteOptions::ShowNoteClient,
|
||||
parsed_args.is_flag_set(ColumnsFlag::ShowNoteClient),
|
||||
NoteOptions::ShowNoteClientTop,
|
||||
parsed_args.is_flag_set(ColumnsFlag::ShowNoteClientTop),
|
||||
);
|
||||
options.set(AppOptions::Debug, ctx.args.debug);
|
||||
note_options.set(
|
||||
NoteOptions::ShowNoteClientBottom,
|
||||
parsed_args.is_flag_set(ColumnsFlag::ShowNoteClientBottom),
|
||||
);
|
||||
options.set(AppOptions::Debug, app_context.args.debug);
|
||||
options.set(
|
||||
AppOptions::SinceOptimize,
|
||||
parsed_args.is_flag_set(ColumnsFlag::SinceOptimize),
|
||||
@@ -662,6 +668,7 @@ fn should_show_compose_button(decks: &DecksCache, accounts: &Accounts) -> bool {
|
||||
Route::Reply(_) => false,
|
||||
Route::Quote(_) => false,
|
||||
Route::Relays => false,
|
||||
Route::Settings => false,
|
||||
Route::ComposeNote => false,
|
||||
Route::AddColumn(_) => false,
|
||||
Route::EditProfile(_) => false,
|
||||
|
||||
@@ -11,7 +11,8 @@ pub enum ColumnsFlag {
|
||||
Textmode,
|
||||
Scramble,
|
||||
NoMedia,
|
||||
ShowNoteClient,
|
||||
ShowNoteClientTop,
|
||||
ShowNoteClientBottom,
|
||||
}
|
||||
|
||||
pub struct ColumnsArgs {
|
||||
@@ -53,8 +54,10 @@ impl ColumnsArgs {
|
||||
res.clear_flag(ColumnsFlag::SinceOptimize);
|
||||
} else if arg == "--scramble" {
|
||||
res.set_flag(ColumnsFlag::Scramble);
|
||||
} else if arg == "--show-note-client" {
|
||||
res.set_flag(ColumnsFlag::ShowNoteClient);
|
||||
} else if arg == "--show-note-client=top" {
|
||||
res.set_flag(ColumnsFlag::ShowNoteClientTop);
|
||||
} else if arg == "--show-note-client=bottom" {
|
||||
res.set_flag(ColumnsFlag::ShowNoteClientBottom);
|
||||
} else if arg == "--no-media" {
|
||||
res.set_flag(ColumnsFlag::NoMedia);
|
||||
} else if arg == "--filter" {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
actionbar::TimelineOpenResult,
|
||||
drag::DragSwitch,
|
||||
route::{Route, Router, SingletonRouter},
|
||||
timeline::{Timeline, TimelineCache, TimelineKind},
|
||||
};
|
||||
@@ -13,6 +14,7 @@ use tracing::warn;
|
||||
pub struct Column {
|
||||
pub router: Router<Route>,
|
||||
pub sheet_router: SingletonRouter<Route>,
|
||||
pub drag: DragSwitch,
|
||||
}
|
||||
|
||||
impl Column {
|
||||
@@ -21,6 +23,7 @@ impl Column {
|
||||
Column {
|
||||
router,
|
||||
sheet_router: SingletonRouter::default(),
|
||||
drag: DragSwitch::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,11 +159,9 @@ impl Columns {
|
||||
|
||||
// Get the first router in the columns if there are columns present.
|
||||
// Otherwise, create a new column picker and return the router
|
||||
pub fn get_first_router(&mut self) -> &mut Router<Route> {
|
||||
if self.columns.is_empty() {
|
||||
self.new_column_picker();
|
||||
}
|
||||
self.columns[0].router_mut()
|
||||
pub fn get_selected_router(&mut self) -> &mut Router<Route> {
|
||||
self.ensure_column();
|
||||
self.selected_mut().router_mut()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -181,16 +182,25 @@ impl Columns {
|
||||
Some(&self.columns[self.selected as usize])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn selected_mut(&mut self) -> Option<&mut Column> {
|
||||
// TODO(jb55): switch to non-empty container for columns?
|
||||
fn ensure_column(&mut self) {
|
||||
if self.columns.is_empty() {
|
||||
return None;
|
||||
self.new_column_picker();
|
||||
}
|
||||
Some(&mut self.columns[self.selected as usize])
|
||||
}
|
||||
|
||||
/// Get the selected column. If you're looking to route something
|
||||
/// and you're not sure which one to choose, use this one
|
||||
#[inline]
|
||||
pub fn selected_mut(&mut self) -> &mut Column {
|
||||
self.ensure_column();
|
||||
assert!(self.selected < self.columns.len() as i32);
|
||||
&mut self.columns[self.selected as usize]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn column_mut(&mut self, ind: usize) -> &mut Column {
|
||||
self.ensure_column();
|
||||
&mut self.columns[ind]
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ impl DecksCache {
|
||||
accounts: ¬edeck::Accounts,
|
||||
) -> Option<&mut Column> {
|
||||
self.active_columns_mut(i18n, accounts)
|
||||
.and_then(|ad| ad.selected_mut())
|
||||
.map(|ad| ad.selected_mut())
|
||||
}
|
||||
|
||||
pub fn selected_column(&self, accounts: ¬edeck::Accounts) -> Option<&Column> {
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct DragSwitch {
|
||||
state: Option<DragState>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct DragState {
|
||||
start_pos: egui::Pos2,
|
||||
cur_direction: DragDirection,
|
||||
}
|
||||
|
||||
impl DragSwitch {
|
||||
/// should call BEFORE both drag directions get rendered
|
||||
pub fn update(&mut self, horizontal: egui::Id, vertical: egui::Id, ctx: &egui::Context) {
|
||||
let horiz_being_dragged = ctx.is_being_dragged(horizontal);
|
||||
let vert_being_dragged = ctx.is_being_dragged(vertical);
|
||||
|
||||
if !horiz_being_dragged && !vert_being_dragged {
|
||||
self.state = None;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(state) = &mut self.state else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(cur_pos) = ctx.pointer_interact_pos() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let dx = (state.start_pos.x - cur_pos.x).abs();
|
||||
let dy = (state.start_pos.y - cur_pos.y).abs();
|
||||
|
||||
let new_direction = if dx > dy {
|
||||
DragDirection::Horizontal
|
||||
} else {
|
||||
DragDirection::Vertical
|
||||
};
|
||||
|
||||
if new_direction == DragDirection::Horizontal
|
||||
&& state.cur_direction == DragDirection::Vertical
|
||||
{
|
||||
// drag is occuring mostly in the horizontal direction
|
||||
ctx.set_dragged_id(horizontal);
|
||||
let new_dir = DragDirection::Horizontal;
|
||||
state.cur_direction = new_dir;
|
||||
} else if new_direction == DragDirection::Vertical
|
||||
&& state.cur_direction == DragDirection::Horizontal
|
||||
{
|
||||
// drag is occuring mostly in the vertical direction
|
||||
let new_dir = DragDirection::Vertical;
|
||||
state.cur_direction = new_dir;
|
||||
ctx.set_dragged_id(vertical);
|
||||
}
|
||||
}
|
||||
|
||||
/// should call AFTER both drag directions rendered
|
||||
pub fn check_for_drag_start(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
horizontal: egui::Id,
|
||||
vertical: egui::Id,
|
||||
) {
|
||||
let Some(drag_id) = ctx.drag_started_id() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let cur_direction = if drag_id == horizontal {
|
||||
DragDirection::Horizontal
|
||||
} else if drag_id == vertical {
|
||||
DragDirection::Vertical
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(cur_pos) = ctx.pointer_interact_pos() else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.state = Some(DragState {
|
||||
start_pos: cur_pos,
|
||||
cur_direction,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
enum DragDirection {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
}
|
||||
|
||||
pub fn get_drag_id(ui: &egui::Ui, scroll_id: egui::Id) -> egui::Id {
|
||||
ui.id().with(egui::Id::new(scroll_id)).with("area")
|
||||
}
|
||||
|
||||
// unfortunately a Frame makes a new id for the Ui
|
||||
pub fn get_drag_id_through_frame(ui: &egui::Ui, scroll_id: egui::Id) -> egui::Id {
|
||||
ui.id()
|
||||
.with(egui::Id::new("child"))
|
||||
.with(egui::Id::new(scroll_id))
|
||||
.with("area")
|
||||
}
|
||||
@@ -12,6 +12,7 @@ pub mod column;
|
||||
mod deck_state;
|
||||
mod decks;
|
||||
mod draft;
|
||||
mod drag;
|
||||
mod key_parsing;
|
||||
pub mod login_manager;
|
||||
mod media_upload;
|
||||
|
||||
@@ -474,12 +474,10 @@ impl TimelineSub {
|
||||
let before = self.state.clone();
|
||||
's: {
|
||||
match &mut self.state {
|
||||
SubState::NoSub { dependers } => {
|
||||
*dependers -= 1;
|
||||
}
|
||||
SubState::NoSub { dependers } => *dependers = dependers.saturating_sub(1),
|
||||
SubState::LocalOnly { local, dependers } => {
|
||||
if *dependers > 1 {
|
||||
*dependers -= 1;
|
||||
*dependers = dependers.saturating_sub(1);
|
||||
break 's;
|
||||
}
|
||||
|
||||
@@ -492,7 +490,7 @@ impl TimelineSub {
|
||||
}
|
||||
SubState::RemoteOnly { remote, dependers } => {
|
||||
if *dependers > 1 {
|
||||
*dependers -= 1;
|
||||
*dependers = dependers.saturating_sub(1);
|
||||
break 's;
|
||||
}
|
||||
|
||||
@@ -502,7 +500,7 @@ impl TimelineSub {
|
||||
}
|
||||
SubState::Unified { unified, dependers } => {
|
||||
if *dependers > 1 {
|
||||
*dependers -= 1;
|
||||
*dependers = dependers.saturating_sub(1);
|
||||
break 's;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,25 +4,28 @@ use crate::{
|
||||
column::ColumnsAction,
|
||||
deck_state::DeckState,
|
||||
decks::{Deck, DecksAction, DecksCache},
|
||||
drag::{get_drag_id, get_drag_id_through_frame},
|
||||
options::AppOptions,
|
||||
profile::{ProfileAction, SaveProfileChanges},
|
||||
route::{Route, Router, SingletonRouter},
|
||||
timeline::{
|
||||
route::{render_thread_route, render_timeline_route},
|
||||
TimelineCache,
|
||||
TimelineCache, TimelineKind,
|
||||
},
|
||||
ui::{
|
||||
self,
|
||||
add_column::render_add_column_routes,
|
||||
add_column::{render_add_column_routes, AddColumnView},
|
||||
column::NavTitle,
|
||||
configure_deck::ConfigureDeckView,
|
||||
edit_deck::{EditDeckResponse, EditDeckView},
|
||||
note::{custom_zap::CustomZapView, NewPostAction, PostAction, PostType},
|
||||
note::{custom_zap::CustomZapView, NewPostAction, PostAction, PostType, QuoteRepostView},
|
||||
profile::EditProfileView,
|
||||
search::{FocusState, SearchView},
|
||||
settings::{SettingsAction, ShowNoteClientOptions},
|
||||
support::SupportView,
|
||||
wallet::{get_default_zap_state, WalletAction, WalletState, WalletView},
|
||||
RelayView,
|
||||
AccountsView, PostReplyView, PostView, ProfileView, RelayView, SettingsView, ThreadView,
|
||||
TimelineView,
|
||||
},
|
||||
Damus,
|
||||
};
|
||||
@@ -31,9 +34,10 @@ use egui_nav::{Nav, NavAction, NavResponse, NavUiType, Percent, PopupResponse, P
|
||||
use enostr::ProfileState;
|
||||
use nostrdb::{Filter, Ndb, Transaction};
|
||||
use notedeck::{
|
||||
get_current_default_msats, get_current_wallet, tr, ui::is_narrow, Accounts, AppContext,
|
||||
NoteAction, NoteContext, RelayAction,
|
||||
get_current_default_msats, tr, ui::is_narrow, Accounts, AppContext, NoteAction, NoteContext,
|
||||
RelayAction,
|
||||
};
|
||||
use notedeck_ui::NoteOptions;
|
||||
use tracing::error;
|
||||
|
||||
/// The result of processing a nav response
|
||||
@@ -60,6 +64,7 @@ pub enum RenderNavAction {
|
||||
SwitchingAction(SwitchingAction),
|
||||
WalletAction(WalletAction),
|
||||
RelayAction(RelayAction),
|
||||
SettingsAction(SettingsAction),
|
||||
}
|
||||
|
||||
pub enum SwitchingAction {
|
||||
@@ -480,6 +485,9 @@ fn process_render_nav_action(
|
||||
.process_relay_action(ui.ctx(), ctx.pool, action);
|
||||
None
|
||||
}
|
||||
RenderNavAction::SettingsAction(action) => {
|
||||
action.process_settings_action(app, ctx.theme, ctx.i18n, ctx.img_cache, ui.ctx())
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(action) = router_action {
|
||||
@@ -497,13 +505,12 @@ fn process_render_nav_action(
|
||||
fn render_nav_body(
|
||||
ui: &mut egui::Ui,
|
||||
app: &mut Damus,
|
||||
ctx: &mut AppContext<'_>,
|
||||
ctx: &mut AppContext,
|
||||
top: &Route,
|
||||
depth: usize,
|
||||
col: usize,
|
||||
inner_rect: egui::Rect,
|
||||
) -> Option<RenderNavAction> {
|
||||
let current_account_has_wallet = get_current_wallet(ctx.accounts, ctx.global_wallet).is_some();
|
||||
let mut note_context = NoteContext {
|
||||
ndb: ctx.ndb,
|
||||
accounts: ctx.accounts,
|
||||
@@ -514,8 +521,8 @@ fn render_nav_body(
|
||||
job_pool: ctx.job_pool,
|
||||
unknown_ids: ctx.unknown_ids,
|
||||
clipboard: ctx.clipboard,
|
||||
current_account_has_wallet,
|
||||
i18n: ctx.i18n,
|
||||
global_wallet: ctx.global_wallet,
|
||||
};
|
||||
match top {
|
||||
Route::Timeline(kind) => {
|
||||
@@ -573,6 +580,36 @@ fn render_nav_body(
|
||||
Route::Relays => RelayView::new(ctx.pool, &mut app.view_state.id_string_map, ctx.i18n)
|
||||
.ui(ui)
|
||||
.map(RenderNavAction::RelayAction),
|
||||
|
||||
Route::Settings => {
|
||||
let mut show_note_client = if app.note_options.contains(NoteOptions::ShowNoteClientTop)
|
||||
{
|
||||
ShowNoteClientOptions::Top
|
||||
} else if app.note_options.contains(NoteOptions::ShowNoteClientBottom) {
|
||||
ShowNoteClientOptions::Bottom
|
||||
} else {
|
||||
ShowNoteClientOptions::Hide
|
||||
};
|
||||
|
||||
let mut theme: String = (if ui.visuals().dark_mode {
|
||||
"Dark"
|
||||
} else {
|
||||
"Light"
|
||||
})
|
||||
.into();
|
||||
|
||||
let mut selected_language: String = ctx.i18n.get_current_locale().to_string();
|
||||
|
||||
SettingsView::new(
|
||||
ctx.img_cache,
|
||||
&mut selected_language,
|
||||
&mut theme,
|
||||
&mut show_note_client,
|
||||
ctx.i18n,
|
||||
)
|
||||
.ui(ui)
|
||||
.map(RenderNavAction::SettingsAction)
|
||||
}
|
||||
Route::Reply(id) => {
|
||||
let txn = if let Ok(txn) = Transaction::new(ctx.ndb) {
|
||||
txn
|
||||
@@ -596,27 +633,22 @@ fn render_nav_body(
|
||||
return None;
|
||||
};
|
||||
|
||||
let id = egui::Id::new(("post", col, note.key().unwrap()));
|
||||
let poster = ctx.accounts.selected_filled()?;
|
||||
|
||||
let action = {
|
||||
let draft = app.drafts.reply_mut(note.id());
|
||||
|
||||
let response = egui::ScrollArea::vertical()
|
||||
.show(ui, |ui| {
|
||||
ui::PostReplyView::new(
|
||||
&mut note_context,
|
||||
poster,
|
||||
draft,
|
||||
¬e,
|
||||
inner_rect,
|
||||
app.note_options,
|
||||
&mut app.jobs,
|
||||
)
|
||||
.id_source(id)
|
||||
.show(ui)
|
||||
})
|
||||
.inner;
|
||||
let response = ui::PostReplyView::new(
|
||||
&mut note_context,
|
||||
poster,
|
||||
draft,
|
||||
¬e,
|
||||
inner_rect,
|
||||
app.note_options,
|
||||
&mut app.jobs,
|
||||
col,
|
||||
)
|
||||
.show(ui);
|
||||
|
||||
response.action
|
||||
};
|
||||
@@ -637,26 +669,20 @@ fn render_nav_body(
|
||||
return None;
|
||||
};
|
||||
|
||||
let id = egui::Id::new(("post", col, note.key().unwrap()));
|
||||
|
||||
let poster = ctx.accounts.selected_filled()?;
|
||||
let draft = app.drafts.quote_mut(note.id());
|
||||
|
||||
let response = egui::ScrollArea::vertical()
|
||||
.show(ui, |ui| {
|
||||
crate::ui::note::QuoteRepostView::new(
|
||||
&mut note_context,
|
||||
poster,
|
||||
draft,
|
||||
¬e,
|
||||
inner_rect,
|
||||
app.note_options,
|
||||
&mut app.jobs,
|
||||
)
|
||||
.id_source(id)
|
||||
.show(ui)
|
||||
})
|
||||
.inner;
|
||||
let response = crate::ui::note::QuoteRepostView::new(
|
||||
&mut note_context,
|
||||
poster,
|
||||
draft,
|
||||
¬e,
|
||||
inner_rect,
|
||||
app.note_options,
|
||||
&mut app.jobs,
|
||||
col,
|
||||
)
|
||||
.show(ui);
|
||||
|
||||
response.action.map(Into::into)
|
||||
}
|
||||
@@ -736,7 +762,7 @@ fn render_nav_body(
|
||||
|
||||
new_deck_state.clear();
|
||||
get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache)
|
||||
.get_first_router()
|
||||
.get_selected_router()
|
||||
.go_back();
|
||||
}
|
||||
resp
|
||||
@@ -767,7 +793,7 @@ fn render_nav_body(
|
||||
}
|
||||
}
|
||||
get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache)
|
||||
.get_first_router()
|
||||
.get_selected_router()
|
||||
.go_back();
|
||||
}
|
||||
|
||||
@@ -842,7 +868,7 @@ fn render_nav_body(
|
||||
}
|
||||
};
|
||||
|
||||
WalletView::new(state, ctx.i18n)
|
||||
WalletView::new(state, ctx.i18n, ctx.clipboard)
|
||||
.ui(ui)
|
||||
.map(RenderNavAction::WalletAction)
|
||||
}
|
||||
@@ -929,47 +955,165 @@ pub fn render_nav(
|
||||
}
|
||||
};
|
||||
|
||||
let nav_response = Nav::new(
|
||||
&app.columns(ctx.accounts)
|
||||
.column(col)
|
||||
.router()
|
||||
.routes()
|
||||
.clone(),
|
||||
)
|
||||
.navigating(
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.navigating,
|
||||
)
|
||||
.returning(
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.returning,
|
||||
)
|
||||
.id_source(egui::Id::new(("nav", col)))
|
||||
.show_mut(ui, |ui, render_type, nav| match render_type {
|
||||
NavUiType::Title => NavTitle::new(
|
||||
ctx.ndb,
|
||||
ctx.img_cache,
|
||||
get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache),
|
||||
nav.routes(),
|
||||
col,
|
||||
ctx.i18n,
|
||||
)
|
||||
.show_move_button(!narrow)
|
||||
.show_delete_button(!narrow)
|
||||
.show(ui),
|
||||
let routes = app
|
||||
.columns(ctx.accounts)
|
||||
.column(col)
|
||||
.router()
|
||||
.routes()
|
||||
.clone();
|
||||
let nav = Nav::new(&routes).id_source(egui::Id::new(("nav", col)));
|
||||
|
||||
NavUiType::Body => {
|
||||
if let Some(top) = nav.routes().last() {
|
||||
render_nav_body(ui, app, ctx, top, nav.routes().len(), col, inner_rect)
|
||||
} else {
|
||||
None
|
||||
let drag_ids = 's: {
|
||||
let Some(top_route) = &routes.last().cloned() else {
|
||||
break 's None;
|
||||
};
|
||||
|
||||
let Some(scroll_id) = get_scroll_id(
|
||||
top_route,
|
||||
app.columns(ctx.accounts)
|
||||
.column(col)
|
||||
.router()
|
||||
.routes()
|
||||
.len(),
|
||||
&app.timeline_cache,
|
||||
col,
|
||||
) else {
|
||||
break 's None;
|
||||
};
|
||||
|
||||
let vertical_drag_id = if route_uses_frame(top_route) {
|
||||
get_drag_id_through_frame(ui, scroll_id)
|
||||
} else {
|
||||
get_drag_id(ui, scroll_id)
|
||||
};
|
||||
|
||||
let horizontal_drag_id = nav.drag_id(ui);
|
||||
|
||||
let drag = &mut get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache)
|
||||
.column_mut(col)
|
||||
.drag;
|
||||
|
||||
drag.update(horizontal_drag_id, vertical_drag_id, ui.ctx());
|
||||
|
||||
Some((horizontal_drag_id, vertical_drag_id))
|
||||
};
|
||||
|
||||
let nav_response = nav
|
||||
.navigating(
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.navigating,
|
||||
)
|
||||
.returning(
|
||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||
.column_mut(col)
|
||||
.router_mut()
|
||||
.returning,
|
||||
)
|
||||
.show_mut(ui, |ui, render_type, nav| match render_type {
|
||||
NavUiType::Title => NavTitle::new(
|
||||
ctx.ndb,
|
||||
ctx.img_cache,
|
||||
get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache),
|
||||
nav.routes(),
|
||||
col,
|
||||
ctx.i18n,
|
||||
)
|
||||
.show_move_button(!narrow)
|
||||
.show_delete_button(!narrow)
|
||||
.show(ui),
|
||||
|
||||
NavUiType::Body => {
|
||||
if let Some(top) = nav.routes().last() {
|
||||
render_nav_body(ui, app, ctx, top, nav.routes().len(), col, inner_rect)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if let Some((horizontal_drag_id, vertical_drag_id)) = drag_ids {
|
||||
let drag = &mut get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache)
|
||||
.column_mut(col)
|
||||
.drag;
|
||||
drag.check_for_drag_start(ui.ctx(), horizontal_drag_id, vertical_drag_id);
|
||||
}
|
||||
|
||||
RenderNavResponse::new(col, NotedeckNavResponse::Nav(Box::new(nav_response)))
|
||||
}
|
||||
|
||||
fn get_scroll_id(
|
||||
top: &Route,
|
||||
depth: usize,
|
||||
timeline_cache: &TimelineCache,
|
||||
col: usize,
|
||||
) -> Option<egui::Id> {
|
||||
match top {
|
||||
Route::Timeline(timeline_kind) => match timeline_kind {
|
||||
TimelineKind::List(_)
|
||||
| TimelineKind::Search(_)
|
||||
| TimelineKind::Algo(_)
|
||||
| TimelineKind::Notifications(_)
|
||||
| TimelineKind::Universe
|
||||
| TimelineKind::Hashtag(_)
|
||||
| TimelineKind::Generic(_) => {
|
||||
TimelineView::scroll_id(timeline_cache, timeline_kind, col)
|
||||
}
|
||||
TimelineKind::Profile(pubkey) => {
|
||||
if depth > 1 {
|
||||
Some(ProfileView::scroll_id(col, pubkey))
|
||||
} else {
|
||||
TimelineView::scroll_id(timeline_cache, timeline_kind, col)
|
||||
}
|
||||
}
|
||||
},
|
||||
Route::Thread(thread_selection) => Some(ThreadView::scroll_id(
|
||||
thread_selection.selected_or_root(),
|
||||
col,
|
||||
)),
|
||||
Route::Accounts(accounts_route) => match accounts_route {
|
||||
crate::accounts::AccountsRoute::Accounts => Some(AccountsView::scroll_id()),
|
||||
crate::accounts::AccountsRoute::AddAccount => None,
|
||||
},
|
||||
Route::Reply(note_id) => Some(PostReplyView::scroll_id(col, note_id.bytes())),
|
||||
Route::Quote(note_id) => Some(QuoteRepostView::scroll_id(col, note_id.bytes())),
|
||||
Route::Relays => Some(RelayView::scroll_id()),
|
||||
Route::ComposeNote => Some(PostView::scroll_id()),
|
||||
Route::AddColumn(add_column_route) => Some(AddColumnView::scroll_id(add_column_route)),
|
||||
Route::EditProfile(_) => Some(EditProfileView::scroll_id()),
|
||||
Route::Support => None,
|
||||
Route::NewDeck => Some(ConfigureDeckView::scroll_id()),
|
||||
Route::Search => Some(SearchView::scroll_id()),
|
||||
Route::EditDeck(_) => None,
|
||||
Route::Wallet(_) => None,
|
||||
Route::CustomizeZapAmount(_) => None,
|
||||
Route::Settings => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Does the corresponding View for the route use a egui::Frame to wrap the ScrollArea?
|
||||
/// TODO(kernelkind): this is quite hacky...
|
||||
fn route_uses_frame(route: &Route) -> bool {
|
||||
match route {
|
||||
Route::Accounts(accounts_route) => match accounts_route {
|
||||
crate::accounts::AccountsRoute::Accounts => true,
|
||||
crate::accounts::AccountsRoute::AddAccount => false,
|
||||
},
|
||||
Route::Relays => true,
|
||||
Route::Timeline(_) => false,
|
||||
Route::Thread(_) => false,
|
||||
Route::Reply(_) => false,
|
||||
Route::Quote(_) => false,
|
||||
Route::Settings => false,
|
||||
Route::ComposeNote => false,
|
||||
Route::AddColumn(_) => false,
|
||||
Route::EditProfile(_) => false,
|
||||
Route::Support => false,
|
||||
Route::NewDeck => false,
|
||||
Route::Search => false,
|
||||
Route::EditDeck(_) => false,
|
||||
Route::Wallet(_) => false,
|
||||
Route::CustomizeZapAmount(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ fn send_kind_3_event(ndb: &Ndb, pool: &mut RelayPool, accounts: &Accounts, actio
|
||||
let ContactState::Received {
|
||||
contacts: _,
|
||||
note_key,
|
||||
timestamp: _,
|
||||
} = accounts.get_selected_account().data.contacts.get_state()
|
||||
else {
|
||||
return;
|
||||
|
||||
@@ -19,6 +19,7 @@ pub enum Route {
|
||||
Reply(NoteId),
|
||||
Quote(NoteId),
|
||||
Relays,
|
||||
Settings,
|
||||
ComposeNote,
|
||||
AddColumn(AddColumnRoute),
|
||||
EditProfile(Pubkey),
|
||||
@@ -47,6 +48,10 @@ impl Route {
|
||||
Route::Relays
|
||||
}
|
||||
|
||||
pub fn settings() -> Self {
|
||||
Route::Settings
|
||||
}
|
||||
|
||||
pub fn thread(thread_selection: ThreadSelection) -> Self {
|
||||
Route::Thread(thread_selection)
|
||||
}
|
||||
@@ -110,6 +115,9 @@ impl Route {
|
||||
Route::Relays => {
|
||||
writer.write_token("relay");
|
||||
}
|
||||
Route::Settings => {
|
||||
writer.write_token("settings");
|
||||
}
|
||||
Route::ComposeNote => {
|
||||
writer.write_token("compose");
|
||||
}
|
||||
@@ -169,6 +177,12 @@ impl Route {
|
||||
Ok(Route::Relays)
|
||||
})
|
||||
},
|
||||
|p| {
|
||||
p.parse_all(|p| {
|
||||
p.parse_token("settings")?;
|
||||
Ok(Route::Settings)
|
||||
})
|
||||
},
|
||||
|p| {
|
||||
p.parse_all(|p| {
|
||||
p.parse_token("quote")?;
|
||||
@@ -250,6 +264,9 @@ impl Route {
|
||||
Route::Relays => {
|
||||
ColumnTitle::formatted(tr!(i18n, "Relays", "Column title for relay management"))
|
||||
}
|
||||
Route::Settings => {
|
||||
ColumnTitle::formatted(tr!(i18n, "Settings", "Column title for app settings"))
|
||||
}
|
||||
Route::Accounts(amr) => match amr {
|
||||
AccountsRoute::Accounts => ColumnTitle::formatted(tr!(
|
||||
i18n,
|
||||
@@ -555,6 +572,7 @@ impl fmt::Display for Route {
|
||||
write!(f, "{}", tr!("Quote", "Display name for quote composition"))
|
||||
}
|
||||
Route::Relays => write!(f, "{}", tr!("Relays", "Display name for relay management")),
|
||||
Route::Settings => write!(f, "{}", tr!("Settings", "Display name for settings management")),
|
||||
Route::Accounts(amr) => match amr {
|
||||
AccountsRoute::Accounts => write!(
|
||||
f,
|
||||
|
||||
@@ -607,6 +607,7 @@ pub fn fetch_contact_list(
|
||||
ContactState::Received {
|
||||
contacts: _,
|
||||
note_key: _,
|
||||
timestamp: _,
|
||||
} => FilterState::GotRemote(filter::GotRemoteType::Contact),
|
||||
};
|
||||
|
||||
@@ -726,6 +727,7 @@ pub fn is_timeline_ready(
|
||||
let ContactState::Received {
|
||||
contacts: _,
|
||||
note_key,
|
||||
timestamp: _,
|
||||
} = accounts.get_selected_account().data.contacts.get_state()
|
||||
else {
|
||||
return false;
|
||||
|
||||
@@ -87,8 +87,8 @@ pub fn render_thread_route(
|
||||
note_options,
|
||||
note_context,
|
||||
jobs,
|
||||
col,
|
||||
)
|
||||
.id_source(col)
|
||||
.ui(ui)
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
@@ -405,32 +405,13 @@ fn direct_replies_filter_non_root(
|
||||
let tmp_selected = *selected_note_id;
|
||||
nostrdb::Filter::new()
|
||||
.kinds([1])
|
||||
.custom(move |n: nostrdb::Note<'_>| {
|
||||
for tag in n.tags() {
|
||||
if tag.count() < 4 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some("e") = tag.get_str(0) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(tagged_id) = tag.get_id(1) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if *tagged_id != tmp_selected {
|
||||
// NOTE: if these aren't dereferenced a segfault occurs...
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(data) = tag.get_str(3) {
|
||||
if data == "reply" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
.custom(move |note: nostrdb::Note<'_>| {
|
||||
let reply = nostrdb::NoteReply::new(note.tags());
|
||||
if reply.is_reply_to_root() {
|
||||
return false;
|
||||
}
|
||||
false
|
||||
|
||||
reply.reply().is_some_and(|r| r.id == &tmp_selected)
|
||||
})
|
||||
.event(root_id)
|
||||
.build()
|
||||
@@ -448,42 +429,13 @@ fn direct_replies_filter_non_root(
|
||||
/// let tmp = *root_id;
|
||||
/// .custom(move |_| { tmp }) // ✅
|
||||
fn direct_replies_filter_root(root_id: &[u8; 32]) -> nostrdb::Filter {
|
||||
let tmp_root = *root_id;
|
||||
let moved_root_id = *root_id;
|
||||
nostrdb::Filter::new()
|
||||
.kinds([1])
|
||||
.custom(move |n: nostrdb::Note<'_>| {
|
||||
let mut contains_root = false;
|
||||
for tag in n.tags() {
|
||||
if tag.count() < 4 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some("e") = tag.get_str(0) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(s) = tag.get_str(3) {
|
||||
if s == "reply" {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let Some(tagged_id) = tag.get_id(1) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if *tagged_id != tmp_root {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(s) = tag.get_str(3) {
|
||||
if s == "root" {
|
||||
contains_root = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contains_root
|
||||
.custom(move |note: nostrdb::Note<'_>| {
|
||||
nostrdb::NoteReply::new(note.tags())
|
||||
.reply_to_root()
|
||||
.is_some_and(|r| r.id == &moved_root_id)
|
||||
})
|
||||
.event(root_id)
|
||||
.build()
|
||||
|
||||
@@ -52,6 +52,7 @@ impl<'a> AccountsView<'a> {
|
||||
|
||||
ui.add_space(8.0);
|
||||
scroll_area()
|
||||
.id_salt(AccountsView::scroll_id())
|
||||
.show(ui, |ui| {
|
||||
Self::show_accounts(ui, self.accounts, self.ndb, self.img_cache, self.i18n)
|
||||
})
|
||||
@@ -59,6 +60,10 @@ impl<'a> AccountsView<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn scroll_id() -> egui::Id {
|
||||
egui::Id::new("accounts")
|
||||
}
|
||||
|
||||
fn show_accounts(
|
||||
ui: &mut Ui,
|
||||
accounts: &Accounts,
|
||||
|
||||
@@ -64,14 +64,14 @@ enum AddColumnOption {
|
||||
Individual(PubkeySource),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, Default)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, Default, Hash)]
|
||||
pub enum AddAlgoRoute {
|
||||
#[default]
|
||||
Base,
|
||||
LastPerPubkey,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)]
|
||||
pub enum AddColumnRoute {
|
||||
Base,
|
||||
UndecidedNotification,
|
||||
@@ -187,8 +187,13 @@ impl<'a> AddColumnView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_id(route: &AddColumnRoute) -> egui::Id {
|
||||
egui::Id::new(("add_column", route))
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
|
||||
ScrollArea::vertical()
|
||||
.id_salt(AddColumnView::scroll_id(&AddColumnRoute::Base))
|
||||
.show(ui, |ui| {
|
||||
let mut selected_option: Option<AddColumnResponse> = None;
|
||||
for column_option_data in self.get_base_options(ui) {
|
||||
|
||||
@@ -481,6 +481,7 @@ impl<'a> NavTitle<'a> {
|
||||
Route::AddColumn(_add_col_route) => None,
|
||||
Route::Support => None,
|
||||
Route::Relays => None,
|
||||
Route::Settings => None,
|
||||
Route::NewDeck => None,
|
||||
Route::EditDeck(_) => None,
|
||||
Route::EditProfile(pubkey) => Some(self.show_profile(ui, pubkey, pfp_size)),
|
||||
|
||||
@@ -33,6 +33,10 @@ impl<'a> ConfigureDeckView<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn scroll_id() -> egui::Id {
|
||||
egui::Id::new("configure-deck")
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut Ui) -> Option<ConfigureDeckResponse> {
|
||||
let title_font = egui::FontId::new(
|
||||
notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Heading4),
|
||||
@@ -261,6 +265,7 @@ fn glyph_options_ui(
|
||||
) -> Option<char> {
|
||||
let mut selected_glyph = None;
|
||||
egui::ScrollArea::vertical()
|
||||
.id_salt(ConfigureDeckView::scroll_id())
|
||||
.max_height(max_height)
|
||||
.show(ui, |ui| {
|
||||
let max_width = ui.available_width();
|
||||
|
||||
@@ -12,6 +12,7 @@ pub mod profile;
|
||||
pub mod relay;
|
||||
pub mod search;
|
||||
pub mod search_results;
|
||||
pub mod settings;
|
||||
pub mod side_panel;
|
||||
pub mod support;
|
||||
pub mod thread;
|
||||
@@ -24,6 +25,7 @@ pub use note::{PostReplyView, PostView};
|
||||
pub use preview::{Preview, PreviewApp, PreviewConfig};
|
||||
pub use profile::ProfileView;
|
||||
pub use relay::RelayView;
|
||||
pub use settings::SettingsView;
|
||||
pub use side_panel::{DesktopSidePanel, SidePanelAction};
|
||||
pub use thread::ThreadView;
|
||||
pub use timeline::TimelineView;
|
||||
|
||||
@@ -35,7 +35,6 @@ pub struct PostView<'a, 'd> {
|
||||
draft: &'a mut Draft,
|
||||
post_type: PostType,
|
||||
poster: FilledKeypair<'a>,
|
||||
id_source: Option<egui::Id>,
|
||||
inner_rect: egui::Rect,
|
||||
note_options: NoteOptions,
|
||||
jobs: &'a mut JobsCache,
|
||||
@@ -112,12 +111,10 @@ impl<'a, 'd> PostView<'a, 'd> {
|
||||
note_options: NoteOptions,
|
||||
jobs: &'a mut JobsCache,
|
||||
) -> Self {
|
||||
let id_source: Option<egui::Id> = None;
|
||||
PostView {
|
||||
note_context,
|
||||
draft,
|
||||
poster,
|
||||
id_source,
|
||||
post_type,
|
||||
inner_rect,
|
||||
note_options,
|
||||
@@ -125,9 +122,12 @@ impl<'a, 'd> PostView<'a, 'd> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id_source(mut self, id_source: impl std::hash::Hash) -> Self {
|
||||
self.id_source = Some(egui::Id::new(id_source));
|
||||
self
|
||||
fn id() -> egui::Id {
|
||||
egui::Id::new("post")
|
||||
}
|
||||
|
||||
pub fn scroll_id() -> egui::Id {
|
||||
PostView::id().with("scroll")
|
||||
}
|
||||
|
||||
fn editbox(&mut self, txn: &nostrdb::Transaction, ui: &mut egui::Ui) -> egui::Response {
|
||||
@@ -213,7 +213,8 @@ impl<'a, 'd> PostView<'a, 'd> {
|
||||
|
||||
let focused = out.response.has_focus();
|
||||
|
||||
ui.ctx().data_mut(|d| d.insert_temp(self.id(), focused));
|
||||
ui.ctx()
|
||||
.data_mut(|d| d.insert_temp(PostView::id(), focused));
|
||||
|
||||
out.response
|
||||
}
|
||||
@@ -305,11 +306,7 @@ impl<'a, 'd> PostView<'a, 'd> {
|
||||
|
||||
fn focused(&self, ui: &egui::Ui) -> bool {
|
||||
ui.ctx()
|
||||
.data(|d| d.get_temp::<bool>(self.id()).unwrap_or(false))
|
||||
}
|
||||
|
||||
fn id(&self) -> egui::Id {
|
||||
self.id_source.unwrap_or_else(|| egui::Id::new("post"))
|
||||
.data(|d| d.get_temp::<bool>(PostView::id()).unwrap_or(false))
|
||||
}
|
||||
|
||||
pub fn outer_margin() -> i8 {
|
||||
@@ -321,6 +318,13 @@ impl<'a, 'd> PostView<'a, 'd> {
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, txn: &Transaction, ui: &mut egui::Ui) -> PostResponse {
|
||||
ScrollArea::vertical()
|
||||
.id_salt(PostView::scroll_id())
|
||||
.show(ui, |ui| self.ui_no_scroll(txn, ui))
|
||||
.inner
|
||||
}
|
||||
|
||||
pub fn ui_no_scroll(&mut self, txn: &Transaction, ui: &mut egui::Ui) -> PostResponse {
|
||||
let focused = self.focused(ui);
|
||||
let stroke = if focused {
|
||||
ui.visuals().selection.stroke
|
||||
@@ -467,7 +471,7 @@ impl<'a, 'd> PostView<'a, 'd> {
|
||||
self.note_context.img_cache,
|
||||
cache_type,
|
||||
url,
|
||||
notedeck_ui::images::ImageType::Content,
|
||||
notedeck_ui::images::ImageType::Content(Some((width, height))),
|
||||
);
|
||||
|
||||
render_post_view_media(
|
||||
@@ -802,13 +806,13 @@ mod preview {
|
||||
let mut note_context = NoteContext {
|
||||
ndb: app.ndb,
|
||||
accounts: app.accounts,
|
||||
global_wallet: app.global_wallet,
|
||||
img_cache: app.img_cache,
|
||||
note_cache: app.note_cache,
|
||||
zaps: app.zaps,
|
||||
pool: app.pool,
|
||||
job_pool: app.job_pool,
|
||||
unknown_ids: app.unknown_ids,
|
||||
current_account_has_wallet: false,
|
||||
clipboard: app.clipboard,
|
||||
i18n: app.i18n,
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::{
|
||||
ui::{self},
|
||||
};
|
||||
|
||||
use egui::ScrollArea;
|
||||
use enostr::{FilledKeypair, NoteId};
|
||||
use notedeck::NoteContext;
|
||||
use notedeck_ui::{jobs::JobsCache, NoteOptions};
|
||||
@@ -13,7 +14,7 @@ pub struct QuoteRepostView<'a, 'd> {
|
||||
poster: FilledKeypair<'a>,
|
||||
draft: &'a mut Draft,
|
||||
quoting_note: &'a nostrdb::Note<'a>,
|
||||
id_source: Option<egui::Id>,
|
||||
scroll_id: egui::Id,
|
||||
inner_rect: egui::Rect,
|
||||
note_options: NoteOptions,
|
||||
jobs: &'a mut JobsCache,
|
||||
@@ -29,22 +30,36 @@ impl<'a, 'd> QuoteRepostView<'a, 'd> {
|
||||
inner_rect: egui::Rect,
|
||||
note_options: NoteOptions,
|
||||
jobs: &'a mut JobsCache,
|
||||
col: usize,
|
||||
) -> Self {
|
||||
let id_source: Option<egui::Id> = None;
|
||||
QuoteRepostView {
|
||||
note_context,
|
||||
poster,
|
||||
draft,
|
||||
quoting_note,
|
||||
id_source,
|
||||
scroll_id: QuoteRepostView::scroll_id(col, quoting_note.id()),
|
||||
inner_rect,
|
||||
note_options,
|
||||
jobs,
|
||||
}
|
||||
}
|
||||
|
||||
fn id(col: usize, note_id: &[u8; 32]) -> egui::Id {
|
||||
egui::Id::new(("quote_repost", col, note_id))
|
||||
}
|
||||
|
||||
pub fn scroll_id(col: usize, note_id: &[u8; 32]) -> egui::Id {
|
||||
QuoteRepostView::id(col, note_id).with("scroll")
|
||||
}
|
||||
|
||||
pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
||||
let id = self.id();
|
||||
ScrollArea::vertical()
|
||||
.id_salt(self.scroll_id)
|
||||
.show(ui, |ui| self.show_internal(ui))
|
||||
.inner
|
||||
}
|
||||
|
||||
fn show_internal(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
||||
let quoting_note_id = self.quoting_note.id();
|
||||
|
||||
let post_resp = ui::PostView::new(
|
||||
@@ -56,18 +71,7 @@ impl<'a, 'd> QuoteRepostView<'a, 'd> {
|
||||
self.note_options,
|
||||
self.jobs,
|
||||
)
|
||||
.id_source(id)
|
||||
.ui(self.quoting_note.txn().unwrap(), ui);
|
||||
.ui_no_scroll(self.quoting_note.txn().unwrap(), ui);
|
||||
post_resp
|
||||
}
|
||||
|
||||
pub fn id_source(mut self, id: egui::Id) -> Self {
|
||||
self.id_source = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn id(&self) -> egui::Id {
|
||||
self.id_source
|
||||
.unwrap_or_else(|| egui::Id::new("quote-repost-view"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::ui::{
|
||||
note::{PostAction, PostResponse, PostType},
|
||||
};
|
||||
|
||||
use egui::{Rect, Response, Ui};
|
||||
use egui::{Rect, Response, ScrollArea, Ui};
|
||||
use enostr::{FilledKeypair, NoteId};
|
||||
use notedeck::NoteContext;
|
||||
use notedeck_ui::jobs::JobsCache;
|
||||
@@ -15,7 +15,7 @@ pub struct PostReplyView<'a, 'd> {
|
||||
poster: FilledKeypair<'a>,
|
||||
draft: &'a mut Draft,
|
||||
note: &'a nostrdb::Note<'a>,
|
||||
id_source: Option<egui::Id>,
|
||||
scroll_id: egui::Id,
|
||||
inner_rect: egui::Rect,
|
||||
note_options: NoteOptions,
|
||||
jobs: &'a mut JobsCache,
|
||||
@@ -31,31 +31,37 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
|
||||
inner_rect: egui::Rect,
|
||||
note_options: NoteOptions,
|
||||
jobs: &'a mut JobsCache,
|
||||
col: usize,
|
||||
) -> Self {
|
||||
let id_source: Option<egui::Id> = None;
|
||||
PostReplyView {
|
||||
note_context,
|
||||
poster,
|
||||
draft,
|
||||
note,
|
||||
id_source,
|
||||
scroll_id: PostReplyView::scroll_id(col, note.id()),
|
||||
inner_rect,
|
||||
note_options,
|
||||
jobs,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id_source(mut self, id: egui::Id) -> Self {
|
||||
self.id_source = Some(id);
|
||||
self
|
||||
fn id(col: usize, note_id: &[u8; 32]) -> egui::Id {
|
||||
egui::Id::new(("reply_view", col, note_id))
|
||||
}
|
||||
|
||||
pub fn id(&self) -> egui::Id {
|
||||
self.id_source
|
||||
.unwrap_or_else(|| egui::Id::new("post-reply-view"))
|
||||
pub fn scroll_id(col: usize, note_id: &[u8; 32]) -> egui::Id {
|
||||
PostReplyView::id(col, note_id).with("scroll")
|
||||
}
|
||||
|
||||
pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
||||
ScrollArea::vertical()
|
||||
.id_salt(self.scroll_id)
|
||||
.show(ui, |ui| self.show_internal(ui))
|
||||
.inner
|
||||
}
|
||||
|
||||
// no scroll
|
||||
fn show_internal(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
||||
ui.vertical(|ui| {
|
||||
let avail_rect = ui.available_rect_before_wrap();
|
||||
|
||||
@@ -81,7 +87,6 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
|
||||
})
|
||||
.inner;
|
||||
|
||||
let id = self.id();
|
||||
let replying_to = self.note.id();
|
||||
let rect_before_post = ui.min_rect();
|
||||
|
||||
@@ -95,8 +100,7 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
|
||||
self.note_options,
|
||||
self.jobs,
|
||||
)
|
||||
.id_source(id)
|
||||
.ui(self.note.txn().unwrap(), ui)
|
||||
.ui_no_scroll(self.note.txn().unwrap(), ui)
|
||||
};
|
||||
|
||||
post_response.action = post_response
|
||||
|
||||
@@ -24,9 +24,14 @@ impl<'a> EditProfileView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_id() -> egui::Id {
|
||||
egui::Id::new("edit_profile")
|
||||
}
|
||||
|
||||
// return true to save
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> bool {
|
||||
ScrollArea::vertical()
|
||||
.id_salt(EditProfileView::scroll_id())
|
||||
.show(ui, |ui| {
|
||||
banner(ui, self.state.banner(), 188.0);
|
||||
|
||||
|
||||
@@ -59,8 +59,12 @@ impl<'a, 'd> ProfileView<'a, 'd> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_id(col_id: usize, profile_pubkey: &Pubkey) -> egui::Id {
|
||||
egui::Id::new(("profile_scroll", col_id, profile_pubkey))
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<ProfileViewAction> {
|
||||
let scroll_id = egui::Id::new(("profile_scroll", self.col_id, self.pubkey));
|
||||
let scroll_id = ProfileView::scroll_id(self.col_id, self.pubkey);
|
||||
let offset_id = scroll_id.with("scroll_offset");
|
||||
|
||||
let mut scroll_area = ScrollArea::vertical().id_salt(scroll_id);
|
||||
|
||||
@@ -36,6 +36,7 @@ impl RelayView<'_> {
|
||||
ui.add_space(8.0);
|
||||
|
||||
egui::ScrollArea::vertical()
|
||||
.id_salt(RelayView::scroll_id())
|
||||
.scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden)
|
||||
.auto_shrink([false; 2])
|
||||
.show(ui, |ui| {
|
||||
@@ -51,6 +52,10 @@ impl RelayView<'_> {
|
||||
|
||||
action
|
||||
}
|
||||
|
||||
pub fn scroll_id() -> egui::Id {
|
||||
egui::Id::new("relay_scroll")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RelayView<'a> {
|
||||
|
||||
@@ -151,6 +151,7 @@ impl<'a, 'd> SearchView<'a, 'd> {
|
||||
|
||||
fn show_search_results(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
||||
egui::ScrollArea::vertical()
|
||||
.id_salt(SearchView::scroll_id())
|
||||
.show(ui, |ui| {
|
||||
let reversed = false;
|
||||
TimelineTabView::new(
|
||||
@@ -165,6 +166,10 @@ impl<'a, 'd> SearchView<'a, 'd> {
|
||||
})
|
||||
.inner
|
||||
}
|
||||
|
||||
pub fn scroll_id() -> egui::Id {
|
||||
egui::Id::new("search_results")
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_search(
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
use egui::{vec2, Button, Color32, ComboBox, Frame, Margin, RichText, ThemePreference};
|
||||
use notedeck::{tr, Images, LanguageIdentifier, Localization, NotedeckTextStyle, ThemeHandler};
|
||||
use notedeck_ui::NoteOptions;
|
||||
use strum::Display;
|
||||
|
||||
use crate::{nav::RouterAction, Damus, Route};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Display)]
|
||||
pub enum ShowNoteClientOptions {
|
||||
Hide,
|
||||
Top,
|
||||
Bottom,
|
||||
}
|
||||
|
||||
pub enum SettingsAction {
|
||||
SetZoom(f32),
|
||||
SetTheme(ThemePreference),
|
||||
SetShowNoteClient(ShowNoteClientOptions),
|
||||
SetLocale(LanguageIdentifier),
|
||||
OpenRelays,
|
||||
OpenCacheFolder,
|
||||
ClearCacheFolder,
|
||||
}
|
||||
|
||||
impl SettingsAction {
|
||||
pub fn process_settings_action<'a>(
|
||||
self,
|
||||
app: &mut Damus,
|
||||
theme_handler: &'a mut ThemeHandler,
|
||||
i18n: &'a mut Localization,
|
||||
img_cache: &mut Images,
|
||||
ctx: &egui::Context,
|
||||
) -> Option<RouterAction> {
|
||||
let mut route_action: Option<RouterAction> = None;
|
||||
|
||||
match self {
|
||||
SettingsAction::OpenRelays => {
|
||||
route_action = Some(RouterAction::route_to(Route::Relays));
|
||||
}
|
||||
SettingsAction::SetZoom(zoom_level) => {
|
||||
ctx.set_zoom_factor(zoom_level);
|
||||
}
|
||||
SettingsAction::SetShowNoteClient(newvalue) => match newvalue {
|
||||
ShowNoteClientOptions::Hide => {
|
||||
app.note_options.set(NoteOptions::ShowNoteClientTop, false);
|
||||
app.note_options
|
||||
.set(NoteOptions::ShowNoteClientBottom, false);
|
||||
}
|
||||
ShowNoteClientOptions::Bottom => {
|
||||
app.note_options.set(NoteOptions::ShowNoteClientTop, false);
|
||||
app.note_options
|
||||
.set(NoteOptions::ShowNoteClientBottom, true);
|
||||
}
|
||||
ShowNoteClientOptions::Top => {
|
||||
app.note_options.set(NoteOptions::ShowNoteClientTop, true);
|
||||
app.note_options
|
||||
.set(NoteOptions::ShowNoteClientBottom, false);
|
||||
}
|
||||
},
|
||||
SettingsAction::SetTheme(theme) => {
|
||||
ctx.options_mut(|o| {
|
||||
o.theme_preference = theme;
|
||||
});
|
||||
theme_handler.save(theme);
|
||||
}
|
||||
SettingsAction::SetLocale(language) => {
|
||||
_ = i18n.set_locale(language);
|
||||
}
|
||||
SettingsAction::OpenCacheFolder => {
|
||||
use opener;
|
||||
let _ = opener::open(img_cache.base_path.clone());
|
||||
}
|
||||
SettingsAction::ClearCacheFolder => {
|
||||
let _ = img_cache.clear_folder_contents();
|
||||
}
|
||||
}
|
||||
route_action
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SettingsView<'a> {
|
||||
theme: &'a mut String,
|
||||
selected_language: &'a mut String,
|
||||
show_note_client: &'a mut ShowNoteClientOptions,
|
||||
i18n: &'a mut Localization,
|
||||
img_cache: &'a mut Images,
|
||||
}
|
||||
|
||||
impl<'a> SettingsView<'a> {
|
||||
pub fn new(
|
||||
img_cache: &'a mut Images,
|
||||
selected_language: &'a mut String,
|
||||
theme: &'a mut String,
|
||||
show_note_client: &'a mut ShowNoteClientOptions,
|
||||
i18n: &'a mut Localization,
|
||||
) -> Self {
|
||||
Self {
|
||||
show_note_client,
|
||||
theme,
|
||||
img_cache,
|
||||
selected_language,
|
||||
i18n,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the localized name for a language identifier
|
||||
fn get_selected_language_name(&mut self) -> String {
|
||||
if let Ok(lang_id) = self.selected_language.parse::<LanguageIdentifier>() {
|
||||
self.i18n
|
||||
.get_locale_native_name(&lang_id)
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| lang_id.to_string())
|
||||
} else {
|
||||
self.selected_language.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the localized label for ShowNoteClientOptions
|
||||
fn get_show_note_client_label(&mut self, option: ShowNoteClientOptions) -> String {
|
||||
match option {
|
||||
ShowNoteClientOptions::Hide => tr!(
|
||||
self.i18n,
|
||||
"Hide",
|
||||
"Option in settings section to hide the source client label in note display"
|
||||
),
|
||||
ShowNoteClientOptions::Top => tr!(
|
||||
self.i18n,
|
||||
"Top",
|
||||
"Option in settings section to show the source client label at the top of the note"
|
||||
),
|
||||
ShowNoteClientOptions::Bottom => tr!(
|
||||
self.i18n,
|
||||
"Bottom",
|
||||
"Option in settings section to show the source client label at the bottom of the note"
|
||||
),
|
||||
}.to_string()
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> {
|
||||
let id = ui.id();
|
||||
let mut action = None;
|
||||
|
||||
Frame::default()
|
||||
.inner_margin(Margin::symmetric(10, 10))
|
||||
.show(ui, |ui| {
|
||||
Frame::group(ui.style())
|
||||
.fill(ui.style().visuals.widgets.open.bg_fill)
|
||||
.inner_margin(10.0)
|
||||
.show(ui, |ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.label(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Appearance",
|
||||
"Label for appearance settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Body.text_style()),
|
||||
);
|
||||
ui.separator();
|
||||
ui.spacing_mut().item_spacing = vec2(10.0, 10.0);
|
||||
|
||||
let current_zoom = ui.ctx().zoom_factor();
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Zoom Level:",
|
||||
"Label for zoom level, Appearance settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
);
|
||||
|
||||
if ui
|
||||
.button(
|
||||
RichText::new("-")
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
let new_zoom = (current_zoom - 0.1).max(0.1);
|
||||
action = Some(SettingsAction::SetZoom(new_zoom));
|
||||
};
|
||||
|
||||
ui.label(
|
||||
RichText::new(format!("{:.0}%", current_zoom * 100.0))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
);
|
||||
|
||||
if ui
|
||||
.button(
|
||||
RichText::new("+")
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
let new_zoom = (current_zoom + 0.1).min(10.0);
|
||||
action = Some(SettingsAction::SetZoom(new_zoom));
|
||||
};
|
||||
|
||||
if ui
|
||||
.button(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Reset",
|
||||
"Label for reset zoom level, Appearance settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
action = Some(SettingsAction::SetZoom(1.0));
|
||||
}
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Language:",
|
||||
"Label for language, Appearance settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
);
|
||||
ComboBox::from_label("")
|
||||
.selected_text(self.get_selected_language_name())
|
||||
.show_ui(ui, |ui| {
|
||||
for lang in self.i18n.get_available_locales() {
|
||||
let name = self.i18n
|
||||
.get_locale_native_name(lang)
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| lang.to_string());
|
||||
if ui
|
||||
.selectable_value(
|
||||
self.selected_language,
|
||||
lang.to_string(),
|
||||
&name,
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
action = Some(SettingsAction::SetLocale(lang.to_owned()))
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Theme:",
|
||||
"Label for theme, Appearance settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
);
|
||||
if ui
|
||||
.selectable_value(
|
||||
self.theme,
|
||||
"Light".into(),
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Light",
|
||||
"Label for Theme Light, Appearance settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
action = Some(SettingsAction::SetTheme(ThemePreference::Light));
|
||||
}
|
||||
if ui
|
||||
.selectable_value(
|
||||
self.theme,
|
||||
"Dark".into(),
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Dark",
|
||||
"Label for Theme Dark, Appearance settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
action = Some(SettingsAction::SetTheme(ThemePreference::Dark));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(5.0);
|
||||
|
||||
Frame::group(ui.style())
|
||||
.fill(ui.style().visuals.widgets.open.bg_fill)
|
||||
.inner_margin(10.0)
|
||||
.show(ui, |ui| {
|
||||
ui.label(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Storage",
|
||||
"Label for storage settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Body.text_style()),
|
||||
);
|
||||
ui.separator();
|
||||
|
||||
ui.vertical(|ui| {
|
||||
ui.spacing_mut().item_spacing = vec2(10.0, 10.0);
|
||||
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
let static_imgs_size = self
|
||||
.img_cache
|
||||
.static_imgs
|
||||
.cache_size
|
||||
.lock()
|
||||
.unwrap();
|
||||
|
||||
let gifs_size = self.img_cache.gifs.cache_size.lock().unwrap();
|
||||
|
||||
ui.label(
|
||||
RichText::new(format!("{} {}",
|
||||
tr!(
|
||||
self.i18n,
|
||||
"Image cache size:",
|
||||
"Label for Image cache size, Storage settings section"
|
||||
),
|
||||
format_size(
|
||||
[static_imgs_size, gifs_size]
|
||||
.iter()
|
||||
.fold(0_u64, |acc, cur| acc
|
||||
+ cur.unwrap_or_default())
|
||||
)
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
);
|
||||
|
||||
ui.end_row();
|
||||
|
||||
if !notedeck::ui::is_compiled_as_mobile() &&
|
||||
ui.button(RichText::new(tr!(self.i18n, "View folder:", "Label for view folder button, Storage settings section"))
|
||||
.text_style(NotedeckTextStyle::Small.text_style())).clicked() {
|
||||
action = Some(SettingsAction::OpenCacheFolder);
|
||||
}
|
||||
|
||||
let clearcache_resp = ui.button(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Clear cache",
|
||||
"Label for clear cache button, Storage settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style())
|
||||
.color(Color32::LIGHT_RED),
|
||||
);
|
||||
|
||||
let id_clearcache = id.with("clear_cache");
|
||||
if clearcache_resp.clicked() {
|
||||
ui.data_mut(|d| d.insert_temp(id_clearcache, true));
|
||||
}
|
||||
|
||||
if ui.data_mut(|d| *d.get_temp_mut_or_default(id_clearcache)) {
|
||||
let mut confirm_pressed = false;
|
||||
clearcache_resp.show_tooltip_ui(|ui| {
|
||||
let confirm_resp = ui.button(tr!(
|
||||
self.i18n,
|
||||
"Confirm",
|
||||
"Label for confirm clear cache, Storage settings section"
|
||||
));
|
||||
if confirm_resp.clicked() {
|
||||
confirm_pressed = true;
|
||||
}
|
||||
|
||||
if confirm_resp.clicked() || ui.button(tr!(
|
||||
self.i18n,
|
||||
"Cancel",
|
||||
"Label for cancel clear cache, Storage settings section"
|
||||
)).clicked() {
|
||||
ui.data_mut(|d| d.insert_temp(id_clearcache, false));
|
||||
}
|
||||
});
|
||||
|
||||
if confirm_pressed {
|
||||
action = Some(SettingsAction::ClearCacheFolder);
|
||||
} else if !confirm_pressed
|
||||
&& clearcache_resp.clicked_elsewhere()
|
||||
{
|
||||
ui.data_mut(|d| d.insert_temp(id_clearcache, false));
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(5.0);
|
||||
|
||||
Frame::group(ui.style())
|
||||
.fill(ui.style().visuals.widgets.open.bg_fill)
|
||||
.inner_margin(10.0)
|
||||
.show(ui, |ui| {
|
||||
ui.label(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Others",
|
||||
"Label for others settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Body.text_style()),
|
||||
);
|
||||
ui.separator();
|
||||
ui.vertical(|ui| {
|
||||
ui.spacing_mut().item_spacing = vec2(10.0, 10.0);
|
||||
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.label(
|
||||
RichText::new(
|
||||
tr!(
|
||||
self.i18n,
|
||||
"Show source client",
|
||||
"Label for Show source client, others settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
);
|
||||
|
||||
for option in [
|
||||
ShowNoteClientOptions::Hide,
|
||||
ShowNoteClientOptions::Top,
|
||||
ShowNoteClientOptions::Bottom,
|
||||
] {
|
||||
let label = self.get_show_note_client_label(option);
|
||||
|
||||
if ui
|
||||
.selectable_value(
|
||||
self.show_note_client,
|
||||
option,
|
||||
RichText::new(label)
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
)
|
||||
.changed()
|
||||
{
|
||||
action = Some(SettingsAction::SetShowNoteClient(option));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(10.0);
|
||||
|
||||
if ui
|
||||
.add_sized(
|
||||
[ui.available_width(), 30.0],
|
||||
Button::new(
|
||||
RichText::new(tr!(
|
||||
self.i18n,
|
||||
"Configure relays",
|
||||
"Label for configure relays, settings section"
|
||||
))
|
||||
.text_style(NotedeckTextStyle::Small.text_style()),
|
||||
),
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
action = Some(SettingsAction::OpenRelays);
|
||||
}
|
||||
});
|
||||
|
||||
action
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format_size(size_bytes: u64) -> String {
|
||||
const KB: f64 = 1024.0;
|
||||
const MB: f64 = KB * 1024.0;
|
||||
const GB: f64 = MB * 1024.0;
|
||||
|
||||
let size = size_bytes as f64;
|
||||
|
||||
if size < KB {
|
||||
format!("{size:.0} Bytes")
|
||||
} else if size < MB {
|
||||
format!("{:.1} KB", size / KB)
|
||||
} else if size < GB {
|
||||
format!("{:.1} MB", size / MB)
|
||||
} else {
|
||||
format!("{:.2} GB", size / GB)
|
||||
}
|
||||
}
|
||||
@@ -187,7 +187,7 @@ impl<'a> DesktopSidePanel<'a> {
|
||||
action: SidePanelAction,
|
||||
i18n: &mut Localization,
|
||||
) -> Option<SwitchingAction> {
|
||||
let router = get_active_columns_mut(i18n, accounts, decks_cache).get_first_router();
|
||||
let router = get_active_columns_mut(i18n, accounts, decks_cache).get_selected_router();
|
||||
let mut switching_response = None;
|
||||
match action {
|
||||
/*
|
||||
@@ -280,7 +280,7 @@ impl<'a> DesktopSidePanel<'a> {
|
||||
{
|
||||
edit_deck
|
||||
.columns_mut()
|
||||
.get_first_router()
|
||||
.get_selected_router()
|
||||
.route_to(Route::EditDeck(index));
|
||||
} else {
|
||||
error!("Cannot push EditDeck route to index {}", index);
|
||||
|
||||
@@ -14,7 +14,6 @@ pub struct ThreadView<'a, 'd> {
|
||||
selected_note_id: &'a [u8; 32],
|
||||
note_options: NoteOptions,
|
||||
col: usize,
|
||||
id_source: egui::Id,
|
||||
note_context: &'a mut NoteContext<'d>,
|
||||
jobs: &'a mut JobsCache,
|
||||
}
|
||||
@@ -27,37 +26,33 @@ impl<'a, 'd> ThreadView<'a, 'd> {
|
||||
note_options: NoteOptions,
|
||||
note_context: &'a mut NoteContext<'d>,
|
||||
jobs: &'a mut JobsCache,
|
||||
col: usize,
|
||||
) -> Self {
|
||||
let id_source = egui::Id::new("threadscroll_threadview");
|
||||
ThreadView {
|
||||
threads,
|
||||
selected_note_id,
|
||||
note_options,
|
||||
id_source,
|
||||
note_context,
|
||||
jobs,
|
||||
col: 0,
|
||||
col,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id_source(mut self, col: usize) -> Self {
|
||||
self.col = col;
|
||||
self.id_source = egui::Id::new(("threadscroll", col));
|
||||
self
|
||||
pub fn scroll_id(selected_note_id: &[u8; 32], col: usize) -> egui::Id {
|
||||
egui::Id::new(("threadscroll", selected_note_id, col))
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
||||
let txn = Transaction::new(self.note_context.ndb).expect("txn");
|
||||
|
||||
let scroll_id = ThreadView::scroll_id(self.selected_note_id, self.col);
|
||||
let mut scroll_area = egui::ScrollArea::vertical()
|
||||
.id_salt(self.id_source)
|
||||
.id_salt(scroll_id)
|
||||
.animated(false)
|
||||
.auto_shrink([false, false])
|
||||
.scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysVisible);
|
||||
|
||||
let offset_id = self
|
||||
.id_source
|
||||
.with(("scroll_offset", self.selected_note_id));
|
||||
let offset_id = scroll_id.with(("scroll_offset", self.selected_note_id));
|
||||
|
||||
if let Some(offset) = ui.data(|i| i.get_temp::<f32>(offset_id)) {
|
||||
scroll_area = scroll_area.vertical_scroll_offset(offset);
|
||||
|
||||
@@ -74,6 +74,15 @@ impl<'a, 'd> TimelineView<'a, 'd> {
|
||||
self.reverse = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn scroll_id(
|
||||
timeline_cache: &TimelineCache,
|
||||
timeline_id: &TimelineKind,
|
||||
col: usize,
|
||||
) -> Option<egui::Id> {
|
||||
let timeline = timeline_cache.get(timeline_id)?;
|
||||
Some(egui::Id::new(("tlscroll", timeline.view_id(col))))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -95,7 +104,9 @@ fn timeline_ui(
|
||||
|
||||
*/
|
||||
|
||||
let scroll_id = {
|
||||
let scroll_id = TimelineView::scroll_id(timeline_cache, timeline_id, col)?;
|
||||
|
||||
{
|
||||
let timeline = if let Some(timeline) = timeline_cache.get_mut(timeline_id) {
|
||||
timeline
|
||||
} else {
|
||||
@@ -114,8 +125,6 @@ fn timeline_ui(
|
||||
|
||||
// need this for some reason??
|
||||
ui.add_space(3.0);
|
||||
|
||||
egui::Id::new(("tlscroll", timeline.view_id(col)))
|
||||
};
|
||||
|
||||
let show_top_button_id = ui.id().with((scroll_id, "at_top"));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use egui::{vec2, CornerRadius, Layout};
|
||||
use egui_winit::clipboard::Clipboard;
|
||||
use notedeck::{
|
||||
get_current_wallet, tr, Accounts, DefaultZapMsats, GlobalWallet, Localization,
|
||||
get_current_wallet_mut, tr, Accounts, DefaultZapMsats, GlobalWallet, Localization,
|
||||
NotedeckTextStyle, PendingDefaultZapState, Wallet, WalletError, WalletUIState, ZapWallet,
|
||||
};
|
||||
|
||||
@@ -103,7 +104,7 @@ impl WalletAction {
|
||||
}
|
||||
WalletAction::SetDefaultZapSats(new_default) => 's: {
|
||||
let sats = {
|
||||
let Some(wallet) = get_current_wallet(accounts, global_wallet) else {
|
||||
let Some(wallet) = get_current_wallet_mut(accounts, global_wallet) else {
|
||||
break 's;
|
||||
};
|
||||
|
||||
@@ -138,7 +139,7 @@ impl WalletAction {
|
||||
global_wallet.save_wallet();
|
||||
}
|
||||
WalletAction::EditDefaultZaps => 's: {
|
||||
let Some(wallet) = get_current_wallet(accounts, global_wallet) else {
|
||||
let Some(wallet) = get_current_wallet_mut(accounts, global_wallet) else {
|
||||
break 's;
|
||||
};
|
||||
|
||||
@@ -154,11 +155,20 @@ impl WalletAction {
|
||||
pub struct WalletView<'a> {
|
||||
state: WalletState<'a>,
|
||||
i18n: &'a mut Localization,
|
||||
clipboard: &'a mut Clipboard,
|
||||
}
|
||||
|
||||
impl<'a> WalletView<'a> {
|
||||
pub fn new(state: WalletState<'a>, i18n: &'a mut Localization) -> Self {
|
||||
Self { state, i18n }
|
||||
pub fn new(
|
||||
state: WalletState<'a>,
|
||||
i18n: &'a mut Localization,
|
||||
clipboard: &'a mut Clipboard,
|
||||
) -> Self {
|
||||
Self {
|
||||
state,
|
||||
i18n,
|
||||
clipboard,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<WalletAction> {
|
||||
@@ -184,7 +194,7 @@ impl<'a> WalletView<'a> {
|
||||
WalletState::NoWallet {
|
||||
state,
|
||||
show_local_only,
|
||||
} => show_no_wallet(ui, self.i18n, state, *show_local_only),
|
||||
} => show_no_wallet(ui, self.i18n, state, *show_local_only, self.clipboard),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,8 +216,11 @@ fn show_no_wallet(
|
||||
i18n: &mut Localization,
|
||||
state: &mut WalletUIState,
|
||||
show_local_only: bool,
|
||||
clipboard: &mut Clipboard,
|
||||
) -> Option<WalletAction> {
|
||||
ui.horizontal_wrapped(|ui| 's: {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
use notedeck_ui::context_menu::{input_context, PasteBehavior};
|
||||
|
||||
let text_edit = egui::TextEdit::singleline(&mut state.buf)
|
||||
.hint_text(
|
||||
egui::RichText::new(tr!(
|
||||
@@ -223,10 +236,16 @@ fn show_no_wallet(
|
||||
.margin(egui::Margin::same(12))
|
||||
.password(true);
|
||||
|
||||
ui.add(text_edit);
|
||||
// add paste context menu
|
||||
input_context(
|
||||
&ui.add(text_edit),
|
||||
clipboard,
|
||||
&mut state.buf,
|
||||
PasteBehavior::Clear,
|
||||
);
|
||||
|
||||
let Some(error_msg) = &state.error_msg else {
|
||||
break 's;
|
||||
return;
|
||||
};
|
||||
|
||||
let error_str = match error_msg {
|
||||
|
||||
@@ -219,8 +219,8 @@ impl<'a> DaveUi<'a> {
|
||||
job_pool: ctx.job_pool,
|
||||
unknown_ids: ctx.unknown_ids,
|
||||
clipboard: ctx.clipboard,
|
||||
current_account_has_wallet: false,
|
||||
i18n: ctx.i18n,
|
||||
global_wallet: ctx.global_wallet,
|
||||
};
|
||||
|
||||
let txn = Transaction::new(note_context.ndb).unwrap();
|
||||
|
||||
@@ -20,8 +20,13 @@ pub fn hover_expand(
|
||||
(rect, size, response)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hover_small_size() -> f32 {
|
||||
14.0
|
||||
}
|
||||
|
||||
pub fn hover_expand_small(ui: &mut egui::Ui, id: egui::Id) -> (egui::Rect, f32, egui::Response) {
|
||||
let size = 10.0;
|
||||
let size = hover_small_size();
|
||||
let expand_size = 5.0;
|
||||
let anim_speed = 0.05;
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@ pub fn add_account_image() -> Image<'static> {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn accounts_image() -> Image<'static> {
|
||||
Image::new(include_image!("../../../assets/icons/accounts.png"))
|
||||
}
|
||||
|
||||
pub fn add_column_dark_image() -> Image<'static> {
|
||||
Image::new(include_image!(
|
||||
"../../../assets/icons/add_column_dark_4x.png"
|
||||
|
||||
@@ -106,19 +106,58 @@ pub fn round_image(image: &mut ColorImage) {
|
||||
}
|
||||
}
|
||||
|
||||
/// If the image's longest dimension is greater than max_edge, downscale
|
||||
fn resize_image_if_too_big(
|
||||
image: image::DynamicImage,
|
||||
max_edge: u32,
|
||||
filter: FilterType,
|
||||
) -> image::DynamicImage {
|
||||
// if we have no size hint, resize to something reasonable
|
||||
let w = image.width();
|
||||
let h = image.height();
|
||||
let long = w.max(h);
|
||||
|
||||
if long > max_edge {
|
||||
let scale = max_edge as f32 / long as f32;
|
||||
let new_w = (w as f32 * scale).round() as u32;
|
||||
let new_h = (h as f32 * scale).round() as u32;
|
||||
|
||||
image.resize(new_w, new_h, filter)
|
||||
} else {
|
||||
image
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Process an image, resizing so we don't blow up video memory or even crash
|
||||
///
|
||||
/// For profile pictures, make them round and small to fit the size hint
|
||||
/// For everything else, either:
|
||||
///
|
||||
/// - resize to the size hint
|
||||
/// - keep the size if the longest dimension is less than MAX_IMG_LENGTH
|
||||
/// - resize if any larger, using [`resize_image_if_too_big`]
|
||||
///
|
||||
#[profiling::function]
|
||||
fn process_pfp_bitmap(imgtyp: ImageType, mut image: image::DynamicImage) -> ColorImage {
|
||||
fn process_image(imgtyp: ImageType, mut image: image::DynamicImage) -> ColorImage {
|
||||
const MAX_IMG_LENGTH: u32 = 512;
|
||||
const FILTER_TYPE: FilterType = FilterType::CatmullRom;
|
||||
|
||||
match imgtyp {
|
||||
ImageType::Content => {
|
||||
let image_buffer = image.clone().into_rgba8();
|
||||
let color_image = ColorImage::from_rgba_unmultiplied(
|
||||
ImageType::Content(size_hint) => {
|
||||
let image = match size_hint {
|
||||
None => resize_image_if_too_big(image, MAX_IMG_LENGTH, FILTER_TYPE),
|
||||
Some((w, h)) => image.resize(w, h, FILTER_TYPE),
|
||||
};
|
||||
|
||||
let image_buffer = image.into_rgba8();
|
||||
ColorImage::from_rgba_unmultiplied(
|
||||
[
|
||||
image_buffer.width() as usize,
|
||||
image_buffer.height() as usize,
|
||||
],
|
||||
image_buffer.as_flat_samples().as_slice(),
|
||||
);
|
||||
color_image
|
||||
)
|
||||
}
|
||||
ImageType::Profile(size) => {
|
||||
// Crop square
|
||||
@@ -154,7 +193,8 @@ fn parse_img_response(
|
||||
let content_type = response.content_type().unwrap_or_default();
|
||||
let size_hint = match imgtyp {
|
||||
ImageType::Profile(size) => SizeHint::Size(size, size),
|
||||
ImageType::Content => SizeHint::default(),
|
||||
ImageType::Content(Some((w, h))) => SizeHint::Size(w, h),
|
||||
ImageType::Content(None) => SizeHint::default(),
|
||||
};
|
||||
|
||||
if content_type.starts_with("image/svg") {
|
||||
@@ -167,7 +207,7 @@ fn parse_img_response(
|
||||
} else if content_type.starts_with("image/") {
|
||||
profiling::scope!("load_from_memory");
|
||||
let dyn_image = image::load_from_memory(&response.bytes)?;
|
||||
Ok(process_pfp_bitmap(imgtyp, dyn_image))
|
||||
Ok(process_image(imgtyp, dyn_image))
|
||||
} else {
|
||||
Err(format!("Expected image, found content-type {content_type:?}").into())
|
||||
}
|
||||
@@ -351,8 +391,8 @@ pub fn fetch_binary_from_disk(path: PathBuf) -> Result<Vec<u8>, notedeck::Error>
|
||||
pub enum ImageType {
|
||||
/// Profile Image (size)
|
||||
Profile(u32),
|
||||
/// Content Image
|
||||
Content,
|
||||
/// Content Image with optional size hint
|
||||
Content(Option<(u32, u32)>),
|
||||
}
|
||||
|
||||
pub fn fetch_img(
|
||||
@@ -411,7 +451,7 @@ fn fetch_img_from_net(
|
||||
&cache_path,
|
||||
gif_bytes,
|
||||
true,
|
||||
move |img| process_pfp_bitmap(imgtyp, img),
|
||||
move |img| process_image(imgtyp, img),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ impl<'a, 'd> NoteContents<'a, 'd> {
|
||||
|
||||
impl egui::Widget for &mut NoteContents<'_, '_> {
|
||||
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
||||
if self.options.contains(NoteOptions::ShowNoteClientTop) {
|
||||
render_client(ui, self.note_context.note_cache, self.note);
|
||||
}
|
||||
let result = render_note_contents(
|
||||
ui,
|
||||
self.note_context,
|
||||
@@ -54,7 +57,7 @@ impl egui::Widget for &mut NoteContents<'_, '_> {
|
||||
self.options,
|
||||
self.jobs,
|
||||
);
|
||||
if self.options.contains(NoteOptions::ShowNoteClient) {
|
||||
if self.options.contains(NoteOptions::ShowNoteClientBottom) {
|
||||
render_client(ui, self.note_context.note_cache, self.note);
|
||||
}
|
||||
self.action = result.action;
|
||||
|
||||
@@ -90,7 +90,7 @@ pub(crate) fn image_carousel(
|
||||
url,
|
||||
*media_type,
|
||||
cache,
|
||||
ImageType::Content,
|
||||
ImageType::Content(Some((width as u32, height as u32))),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -201,7 +201,7 @@ fn show_full_screen_media(
|
||||
img_cache,
|
||||
media_type,
|
||||
image_url,
|
||||
ImageType::Content,
|
||||
ImageType::Content(None),
|
||||
);
|
||||
|
||||
let notedeck::TextureState::Loaded(textured_image) = cur_state.texture_state else {
|
||||
@@ -235,13 +235,32 @@ fn get_selected_index(ui: &egui::Ui, selection_id: egui::Id) -> usize {
|
||||
/// Checks to see if we have any left/right key presses and updates the carousel index
|
||||
fn update_selected_image_index(ui: &mut egui::Ui, carousel_id: egui::Id, num_urls: i32) -> usize {
|
||||
if num_urls > 1 {
|
||||
if ui.input(|i| i.key_pressed(egui::Key::ArrowRight) || i.key_pressed(egui::Key::L)) {
|
||||
let (next_image, prev_image) = ui.data(|data| {
|
||||
(
|
||||
data.get_temp(carousel_id.with("next_image"))
|
||||
.unwrap_or_default(),
|
||||
data.get_temp(carousel_id.with("prev_image"))
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
});
|
||||
|
||||
if next_image
|
||||
|| ui.input(|i| i.key_pressed(egui::Key::ArrowRight) || i.key_pressed(egui::Key::L))
|
||||
{
|
||||
let ind = select_next_media(ui, carousel_id, num_urls, 1);
|
||||
tracing::debug!("carousel selecting right {}/{}", ind + 1, num_urls);
|
||||
if next_image {
|
||||
ui.data_mut(|data| data.remove_temp::<bool>(carousel_id.with("next_image")));
|
||||
}
|
||||
ind
|
||||
} else if ui.input(|i| i.key_pressed(egui::Key::ArrowLeft) || i.key_pressed(egui::Key::H)) {
|
||||
} else if prev_image
|
||||
|| ui.input(|i| i.key_pressed(egui::Key::ArrowLeft) || i.key_pressed(egui::Key::H))
|
||||
{
|
||||
let ind = select_next_media(ui, carousel_id, num_urls, -1);
|
||||
tracing::debug!("carousel selecting left {}/{}", ind + 1, num_urls);
|
||||
if prev_image {
|
||||
ui.data_mut(|data| data.remove_temp::<bool>(carousel_id.with("prev_image")));
|
||||
}
|
||||
ind
|
||||
} else {
|
||||
get_selected_index(ui, selection_id(carousel_id))
|
||||
@@ -266,7 +285,13 @@ pub fn get_content_media_render_state<'a>(
|
||||
) -> MediaRenderState<'a> {
|
||||
let render_type = if media_trusted {
|
||||
cache.handle_and_get_or_insert_loadable(url, || {
|
||||
crate::images::fetch_img(cache_dir, ui.ctx(), url, ImageType::Content, cache_type)
|
||||
crate::images::fetch_img(
|
||||
cache_dir,
|
||||
ui.ctx(),
|
||||
url,
|
||||
ImageType::Content(None),
|
||||
cache_type,
|
||||
)
|
||||
})
|
||||
} else if let Some(render_type) = cache.get_and_handle(url) {
|
||||
render_type
|
||||
@@ -548,9 +573,20 @@ fn render_full_screen_media(
|
||||
Sense::click_and_drag(),
|
||||
);
|
||||
|
||||
let swipe_accum_id = carousel_id.with("swipe_accum");
|
||||
let mut swipe_delta = ui.ctx().memory(|mem| {
|
||||
mem.data
|
||||
.get_temp::<egui::Vec2>(swipe_accum_id)
|
||||
.unwrap_or(egui::Vec2::ZERO)
|
||||
});
|
||||
|
||||
// Handle pan via drag
|
||||
if response.dragged() {
|
||||
let delta = response.drag_delta();
|
||||
swipe_delta += delta;
|
||||
ui.ctx().memory_mut(|mem| {
|
||||
mem.data.insert_temp(swipe_accum_id, swipe_delta);
|
||||
});
|
||||
pan_offset -= delta;
|
||||
pan_offset.x = pan_offset.x.clamp(-max_pan_x, max_pan_x);
|
||||
pan_offset.y = pan_offset.y.clamp(-max_pan_y, max_pan_y);
|
||||
@@ -568,6 +604,27 @@ fn render_full_screen_media(
|
||||
});
|
||||
}
|
||||
|
||||
let swipe_threshold = 50.0;
|
||||
if response.drag_stopped() {
|
||||
if swipe_delta.x.abs() > swipe_threshold && swipe_delta.y.abs() < swipe_threshold {
|
||||
if swipe_delta.x < 0.0 {
|
||||
ui.ctx().data_mut(|data| {
|
||||
keep_popup_open = true;
|
||||
data.insert_temp(carousel_id.with("next_image"), true);
|
||||
});
|
||||
} else if swipe_delta.x > 0.0 {
|
||||
ui.ctx().data_mut(|data| {
|
||||
keep_popup_open = true;
|
||||
data.insert_temp(carousel_id.with("prev_image"), true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ui.ctx().memory_mut(|mem| {
|
||||
mem.data.remove::<egui::Vec2>(swipe_accum_id);
|
||||
});
|
||||
}
|
||||
|
||||
// bottom bar
|
||||
if num_urls > 1 {
|
||||
let bottom_rect = egui::Rect::from_min_max(
|
||||
|
||||
@@ -13,9 +13,12 @@ use crate::{
|
||||
|
||||
pub use contents::{render_note_contents, render_note_preview, NoteContents};
|
||||
pub use context::NoteContextButton;
|
||||
use notedeck::get_current_wallet;
|
||||
use notedeck::note::MediaAction;
|
||||
use notedeck::note::ZapTargetAmount;
|
||||
use notedeck::ui::is_narrow;
|
||||
use notedeck::Accounts;
|
||||
use notedeck::GlobalWallet;
|
||||
use notedeck::Images;
|
||||
use notedeck::Localization;
|
||||
pub use options::NoteOptions;
|
||||
@@ -426,7 +429,7 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
||||
break 's;
|
||||
}
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
note_action = reply_desc(
|
||||
ui,
|
||||
txn,
|
||||
@@ -451,18 +454,13 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
||||
note_action = contents.action.or(note_action);
|
||||
|
||||
if self.options().contains(NoteOptions::ActionBar) {
|
||||
let zapper = {
|
||||
let cur_acc = self.note_context.accounts.get_selected_account();
|
||||
let has_wallet = cur_acc.wallet.is_some();
|
||||
|
||||
has_wallet.then_some(Zapper {
|
||||
zaps: self.note_context.zaps,
|
||||
cur_acc: cur_acc.keypair(),
|
||||
})
|
||||
};
|
||||
note_action = render_note_actionbar(
|
||||
ui,
|
||||
zapper,
|
||||
get_zapper(
|
||||
self.note_context.accounts,
|
||||
self.note_context.global_wallet,
|
||||
self.note_context.zaps,
|
||||
),
|
||||
self.note.id(),
|
||||
self.note.pubkey(),
|
||||
note_key,
|
||||
@@ -500,7 +498,8 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
||||
profile,
|
||||
self.show_unread_indicator,
|
||||
);
|
||||
ui.horizontal(|ui| 's: {
|
||||
|
||||
ui.horizontal_wrapped(|ui| 's: {
|
||||
ui.spacing_mut().item_spacing.x = if is_narrow(ui.ctx()) { 1.0 } else { 2.0 };
|
||||
|
||||
let note_reply = self
|
||||
@@ -531,20 +530,14 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
||||
|
||||
note_action = contents.action.or(note_action);
|
||||
|
||||
let zapper = {
|
||||
let cur_acc = self.note_context.accounts.get_selected_account();
|
||||
let has_wallet = cur_acc.wallet.is_some();
|
||||
|
||||
has_wallet.then_some(Zapper {
|
||||
zaps: self.note_context.zaps,
|
||||
cur_acc: cur_acc.keypair(),
|
||||
})
|
||||
};
|
||||
|
||||
if self.options().contains(NoteOptions::ActionBar) {
|
||||
note_action = render_note_actionbar(
|
||||
ui,
|
||||
zapper,
|
||||
get_zapper(
|
||||
self.note_context.accounts,
|
||||
self.note_context.global_wallet,
|
||||
self.note_context.zaps,
|
||||
),
|
||||
self.note.id(),
|
||||
self.note.pubkey(),
|
||||
note_key,
|
||||
@@ -611,6 +604,20 @@ impl<'a, 'd> NoteView<'a, 'd> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_zapper<'a>(
|
||||
accounts: &'a Accounts,
|
||||
global_wallet: &'a GlobalWallet,
|
||||
zaps: &'a Zaps,
|
||||
) -> Option<Zapper<'a>> {
|
||||
let has_wallet = get_current_wallet(accounts, global_wallet).is_some();
|
||||
let cur_acc = accounts.get_selected_account();
|
||||
|
||||
has_wallet.then_some(Zapper {
|
||||
zaps,
|
||||
cur_acc: cur_acc.keypair(),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_reposted_note<'a>(ndb: &Ndb, txn: &'a Transaction, note: &Note) -> Option<Note<'a>> {
|
||||
if note.kind() != 6 {
|
||||
return None;
|
||||
@@ -769,30 +776,32 @@ struct Zapper<'a> {
|
||||
#[profiling::function]
|
||||
fn render_note_actionbar(
|
||||
ui: &mut egui::Ui,
|
||||
zapper: Option<Zapper>,
|
||||
zapper: Option<Zapper<'_>>,
|
||||
note_id: &[u8; 32],
|
||||
note_pubkey: &[u8; 32],
|
||||
note_key: NoteKey,
|
||||
i18n: &mut Localization,
|
||||
) -> egui::InnerResponse<Option<NoteAction>> {
|
||||
ui.horizontal(|ui| 's: {
|
||||
ui.horizontal(|ui| {
|
||||
ui.set_min_height(26.0);
|
||||
ui.spacing_mut().item_spacing.x = 24.0;
|
||||
|
||||
let reply_resp =
|
||||
reply_button(ui, i18n, note_key).on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
|
||||
let quote_resp =
|
||||
quote_repost_button(ui, i18n, note_key).on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
|
||||
let to_noteid = |id: &[u8; 32]| NoteId::new(*id);
|
||||
if reply_resp.clicked() {
|
||||
break 's Some(NoteAction::Reply(to_noteid(note_id)));
|
||||
return Some(NoteAction::Reply(to_noteid(note_id)));
|
||||
}
|
||||
|
||||
if quote_resp.clicked() {
|
||||
break 's Some(NoteAction::Quote(to_noteid(note_id)));
|
||||
return Some(NoteAction::Quote(to_noteid(note_id)));
|
||||
}
|
||||
|
||||
let Some(Zapper { zaps, cur_acc }) = zapper else {
|
||||
break 's None;
|
||||
};
|
||||
let Zapper { zaps, cur_acc } = zapper?;
|
||||
|
||||
let zap_target = ZapTarget::Note(NoteZapTarget {
|
||||
note_id,
|
||||
@@ -807,7 +816,7 @@ fn render_note_actionbar(
|
||||
};
|
||||
|
||||
if zap_state.is_err() {
|
||||
break 's Some(NoteAction::Zap(ZapAction::ClearError(target)));
|
||||
return Some(NoteAction::Zap(ZapAction::ClearError(target)));
|
||||
}
|
||||
|
||||
let zap_resp = {
|
||||
@@ -825,11 +834,11 @@ fn render_note_actionbar(
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
|
||||
if zap_resp.secondary_clicked() {
|
||||
break 's Some(NoteAction::Zap(ZapAction::CustomizeAmount(target)));
|
||||
return Some(NoteAction::Zap(ZapAction::CustomizeAmount(target)));
|
||||
}
|
||||
|
||||
if !zap_resp.clicked() {
|
||||
break 's None;
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(NoteAction::Zap(ZapAction::Send(ZapTargetAmount {
|
||||
@@ -895,7 +904,7 @@ fn quote_repost_button(
|
||||
i18n: &mut Localization,
|
||||
note_key: NoteKey,
|
||||
) -> egui::Response {
|
||||
let size = 14.0;
|
||||
let size = crate::anim::hover_small_size() + 4.0;
|
||||
let expand_size = 5.0;
|
||||
let anim_speed = 0.05;
|
||||
let id = ui.id().with(("repost_anim", note_key));
|
||||
|
||||
@@ -23,7 +23,8 @@ bitflags! {
|
||||
/// will end with a ... and a "Show more" button.
|
||||
const Truncate = 1 << 11;
|
||||
/// Show note's client in the note header
|
||||
const ShowNoteClient = 1 << 12;
|
||||
const ShowNoteClientTop = 1 << 12;
|
||||
const ShowNoteClientBottom = 1 << 13;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,16 +7,16 @@ use notedeck::{tr, NoteAction, NoteContext};
|
||||
|
||||
// Rich text segment types for internationalized rendering
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TextSegment {
|
||||
pub enum TextSegment<'a> {
|
||||
Plain(String),
|
||||
UserMention([u8; 32]), // pubkey
|
||||
ThreadUserMention([u8; 32]), // pubkey
|
||||
NoteLink([u8; 32]),
|
||||
ThreadLink([u8; 32]),
|
||||
UserMention(Option<&'a [u8; 32]>), // pubkey
|
||||
ThreadUserMention(Option<&'a [u8; 32]>), // pubkey
|
||||
NoteLink(Option<&'a [u8; 32]>),
|
||||
ThreadLink(Option<&'a [u8; 32]>),
|
||||
}
|
||||
|
||||
// Helper function to parse i18n template strings with placeholders
|
||||
fn parse_i18n_template(template: &str) -> Vec<TextSegment> {
|
||||
fn parse_i18n_template(template: &str) -> Vec<TextSegment<'_>> {
|
||||
let mut segments = Vec::new();
|
||||
let mut current_text = String::new();
|
||||
let mut chars = template.chars().peekable();
|
||||
@@ -41,10 +41,10 @@ fn parse_i18n_template(template: &str) -> Vec<TextSegment> {
|
||||
// Handle different placeholder types
|
||||
match placeholder.as_str() {
|
||||
// Placeholder values will be filled later.
|
||||
"user" => segments.push(TextSegment::UserMention([0; 32])),
|
||||
"thread_user" => segments.push(TextSegment::ThreadUserMention([0; 32])),
|
||||
"note" => segments.push(TextSegment::NoteLink([0; 32])),
|
||||
"thread" => segments.push(TextSegment::ThreadLink([0; 32])),
|
||||
"user" => segments.push(TextSegment::UserMention(None)),
|
||||
"thread_user" => segments.push(TextSegment::ThreadUserMention(None)),
|
||||
"note" => segments.push(TextSegment::NoteLink(None)),
|
||||
"thread" => segments.push(TextSegment::ThreadLink(None)),
|
||||
_ => {
|
||||
// Unknown placeholder, treat as plain text
|
||||
current_text.push_str(&format!("{{{placeholder}}}"));
|
||||
@@ -64,39 +64,45 @@ fn parse_i18n_template(template: &str) -> Vec<TextSegment> {
|
||||
}
|
||||
|
||||
// Helper function to fill in the actual data for placeholders
|
||||
fn fill_template_data(
|
||||
mut segments: Vec<TextSegment>,
|
||||
reply_pubkey: &[u8; 32],
|
||||
reply_note_id: &[u8; 32],
|
||||
root_pubkey: Option<&[u8; 32]>,
|
||||
root_note_id: Option<&[u8; 32]>,
|
||||
) -> Vec<TextSegment> {
|
||||
for segment in &mut segments {
|
||||
fn fill_template_data<'a>(
|
||||
segments: &mut [TextSegment<'a>],
|
||||
reply_pubkey: &'a [u8; 32],
|
||||
reply_note_id: &'a [u8; 32],
|
||||
root_pubkey: Option<&'a [u8; 32]>,
|
||||
root_note_id: Option<&'a [u8; 32]>,
|
||||
) {
|
||||
for segment in segments {
|
||||
match segment {
|
||||
TextSegment::UserMention(pubkey) if *pubkey == [0; 32] => {
|
||||
*pubkey = *reply_pubkey;
|
||||
TextSegment::UserMention(pubkey) => {
|
||||
if pubkey.is_none() {
|
||||
*pubkey = Some(reply_pubkey);
|
||||
}
|
||||
}
|
||||
TextSegment::ThreadUserMention(pubkey) if *pubkey == [0; 32] => {
|
||||
*pubkey = *root_pubkey.unwrap_or(reply_pubkey);
|
||||
TextSegment::ThreadUserMention(pubkey) => {
|
||||
if pubkey.is_none() {
|
||||
*pubkey = Some(root_pubkey.unwrap_or(reply_pubkey));
|
||||
}
|
||||
}
|
||||
TextSegment::NoteLink(note_id) if *note_id == [0; 32] => {
|
||||
*note_id = *reply_note_id;
|
||||
TextSegment::NoteLink(note_id) => {
|
||||
if note_id.is_none() {
|
||||
*note_id = Some(reply_note_id);
|
||||
}
|
||||
}
|
||||
TextSegment::ThreadLink(note_id) if *note_id == [0; 32] => {
|
||||
*note_id = *root_note_id.unwrap_or(reply_note_id);
|
||||
TextSegment::ThreadLink(note_id) => {
|
||||
if note_id.is_none() {
|
||||
*note_id = Some(root_note_id.unwrap_or(reply_note_id));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
TextSegment::Plain(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
segments
|
||||
}
|
||||
|
||||
// Main rendering function for text segments
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn render_text_segments(
|
||||
ui: &mut egui::Ui,
|
||||
segments: &[TextSegment],
|
||||
segments: &[TextSegment<'_>],
|
||||
txn: &Transaction,
|
||||
note_context: &mut NoteContext,
|
||||
note_options: NoteOptions,
|
||||
@@ -117,17 +123,25 @@ fn render_text_segments(
|
||||
);
|
||||
}
|
||||
TextSegment::UserMention(pubkey) | TextSegment::ThreadUserMention(pubkey) => {
|
||||
let action = Mention::new(note_context.ndb, note_context.img_cache, txn, pubkey)
|
||||
.size(size)
|
||||
.selectable(selectable)
|
||||
.show(ui);
|
||||
let action = Mention::new(
|
||||
note_context.ndb,
|
||||
note_context.img_cache,
|
||||
txn,
|
||||
pubkey.expect("expected pubkey"),
|
||||
)
|
||||
.size(size)
|
||||
.selectable(selectable)
|
||||
.show(ui);
|
||||
|
||||
if action.is_some() {
|
||||
note_action = action;
|
||||
}
|
||||
}
|
||||
TextSegment::NoteLink(note_id) => {
|
||||
if let Ok(note) = note_context.ndb.get_note_by_id(txn, note_id) {
|
||||
if let Ok(note) = note_context
|
||||
.ndb
|
||||
.get_note_by_id(txn, note_id.expect("expected text segment note_id"))
|
||||
{
|
||||
let r = ui.add(
|
||||
Label::new(
|
||||
RichText::new(tr!(
|
||||
@@ -158,7 +172,10 @@ fn render_text_segments(
|
||||
}
|
||||
}
|
||||
TextSegment::ThreadLink(note_id) => {
|
||||
if let Ok(note) = note_context.ndb.get_note_by_id(txn, note_id) {
|
||||
if let Ok(note) = note_context
|
||||
.ndb
|
||||
.get_note_by_id(txn, note_id.expect("expected text segment threadlink"))
|
||||
{
|
||||
let r = ui.add(
|
||||
Label::new(
|
||||
RichText::new(tr!(
|
||||
@@ -231,7 +248,7 @@ pub fn reply_desc(
|
||||
);
|
||||
};
|
||||
|
||||
let segments = if note_reply.is_reply_to_root() {
|
||||
if note_reply.is_reply_to_root() {
|
||||
// Template: "replying to {user}'s {thread}"
|
||||
let template = tr!(
|
||||
note_context.i18n,
|
||||
@@ -240,13 +257,23 @@ pub fn reply_desc(
|
||||
user = "{user}",
|
||||
thread = "{thread}"
|
||||
);
|
||||
let segments = parse_i18n_template(&template);
|
||||
let mut segments = parse_i18n_template(&template);
|
||||
fill_template_data(
|
||||
segments,
|
||||
&mut segments,
|
||||
reply_note.pubkey(),
|
||||
reply.id,
|
||||
None,
|
||||
Some(reply.id),
|
||||
);
|
||||
render_text_segments(
|
||||
ui,
|
||||
&segments,
|
||||
txn,
|
||||
note_context,
|
||||
note_options,
|
||||
jobs,
|
||||
size,
|
||||
selectable,
|
||||
)
|
||||
} else if let Some(root) = note_reply.root() {
|
||||
if let Ok(root_note) = note_context.ndb.get_note_by_id(txn, root.id) {
|
||||
@@ -259,8 +286,18 @@ pub fn reply_desc(
|
||||
user = "{user}",
|
||||
note = "{note}"
|
||||
);
|
||||
let segments = parse_i18n_template(&template);
|
||||
fill_template_data(segments, reply_note.pubkey(), reply.id, None, None)
|
||||
let mut segments = parse_i18n_template(&template);
|
||||
fill_template_data(&mut segments, reply_note.pubkey(), reply.id, None, None);
|
||||
render_text_segments(
|
||||
ui,
|
||||
&segments,
|
||||
txn,
|
||||
note_context,
|
||||
note_options,
|
||||
jobs,
|
||||
size,
|
||||
selectable,
|
||||
)
|
||||
} else {
|
||||
// Template: "replying to {reply_user}'s {note} in {thread_user}'s {thread}"
|
||||
// This would need more sophisticated placeholder handling
|
||||
@@ -273,13 +310,23 @@ pub fn reply_desc(
|
||||
thread_user = "{thread_user}",
|
||||
thread = "{thread}"
|
||||
);
|
||||
let segments = parse_i18n_template(&template);
|
||||
let mut segments = parse_i18n_template(&template);
|
||||
fill_template_data(
|
||||
segments,
|
||||
&mut segments,
|
||||
reply_note.pubkey(),
|
||||
reply.id,
|
||||
Some(root_note.pubkey()),
|
||||
Some(root.id),
|
||||
);
|
||||
render_text_segments(
|
||||
ui,
|
||||
&segments,
|
||||
txn,
|
||||
note_context,
|
||||
note_options,
|
||||
jobs,
|
||||
size,
|
||||
selectable,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -290,8 +337,18 @@ pub fn reply_desc(
|
||||
"Template for replying to user in unknown thread",
|
||||
user = "{user}"
|
||||
);
|
||||
let segments = parse_i18n_template(&template);
|
||||
fill_template_data(segments, reply_note.pubkey(), reply.id, None, None)
|
||||
let mut segments = parse_i18n_template(&template);
|
||||
fill_template_data(&mut segments, reply_note.pubkey(), reply.id, None, None);
|
||||
render_text_segments(
|
||||
ui,
|
||||
&segments,
|
||||
txn,
|
||||
note_context,
|
||||
note_options,
|
||||
jobs,
|
||||
size,
|
||||
selectable,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Fallback
|
||||
@@ -301,18 +358,17 @@ pub fn reply_desc(
|
||||
"Fallback template for replying to user",
|
||||
user = "{user}"
|
||||
);
|
||||
let segments = parse_i18n_template(&template);
|
||||
fill_template_data(segments, reply_note.pubkey(), reply.id, None, None)
|
||||
};
|
||||
|
||||
render_text_segments(
|
||||
ui,
|
||||
&segments,
|
||||
txn,
|
||||
note_context,
|
||||
note_options,
|
||||
jobs,
|
||||
size,
|
||||
selectable,
|
||||
)
|
||||
let mut segments = parse_i18n_template(&template);
|
||||
fill_template_data(&mut segments, reply_note.pubkey(), reply.id, None, None);
|
||||
render_text_segments(
|
||||
ui,
|
||||
&segments,
|
||||
txn,
|
||||
note_context,
|
||||
note_options,
|
||||
jobs,
|
||||
size,
|
||||
selectable,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ pub fn display_name_widget<'a>(
|
||||
|
||||
let nip05_resp = name.nip05.map(|nip05| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 2.0;
|
||||
|
||||
ui.add(app_images::verified_image());
|
||||
|
||||
ui.label(RichText::new(nip05).size(16.0).color(crate::colors::TEAL))
|
||||
|
||||
Reference in New Issue
Block a user