mirror of
https://github.com/nostr-protocol/nips.git
synced 2025-12-09 16:48:50 +00:00
Compare commits
1 Commits
nh-editabl
...
editable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b6956ddad |
61
37.md
61
37.md
@@ -6,33 +6,54 @@ Editable Short Notes
|
||||
|
||||
`draft` `optional`
|
||||
|
||||
This NIP describes a flow for clients that want to support editable short notes without breaking the experience of clients that don't and keeping `kind:1` a safe place.
|
||||
This NIP describes a flow for editing `kind:1` notes that is mostly backwards-compatible (as long as clients support [NIP-09](./09.md) properly).
|
||||
|
||||
The idea is that editable notes are published as `kind:31000` notes that follow all the same rules of `kind:1`, except for the fact that they can be replaceable anytime.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kind": 31000,
|
||||
"created_at": 1730820000,
|
||||
"content": "I like dogs",
|
||||
"tags": [
|
||||
["d", "c2huy3f"],
|
||||
// other kind1 tags
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Clients that want to support edits would automatically only publish `kind:31000` notes, then immediately publish `kind:1` notes that quote the `kind:31000` note.
|
||||
The flow for editing a `kind:1` note consists of creating a new `kind:1` note to be published in its place, then issuing a `kind:5` delete request for the first, in both cases attaching special tags that denote the nature of the operation to clients that want to support a more rich edit flow.
|
||||
|
||||
## Example flow
|
||||
|
||||
Support `<bob>` publishes
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"id": "aaaaa",
|
||||
"kind": 1,
|
||||
"created_at": 1730820000,
|
||||
"content": "naddr1...",
|
||||
"pubkey": "<bob>",
|
||||
"content": "ehllo"
|
||||
}
|
||||
```
|
||||
|
||||
And now, for whatever, reason, he wants to edit the note to say "hello", so his client will publish the following two events:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"id": "bbbbbb",
|
||||
"kind": 1,
|
||||
"pubkey": "<bob>",
|
||||
"content": "hello",
|
||||
"tags": [
|
||||
["q", "31000:...:c2huy3f"]
|
||||
["s", "aaaaaa"] // this indicates the note that is being replaced
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
"kind": 5,
|
||||
"pubkey": "<bob>",
|
||||
"tags": [
|
||||
["e", "aaaaaa"], // this indicates the note that will be deleted in all non-upgraded clients
|
||||
["edit", "bbbbbb"], // this indicates the notes that replaced the one just deleted
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Clients that support this NIP would then fetch the `kind:31000` and display it normally in place of the `kind:1`. Other clients would display the editable event embedded inside the `kind:1`.
|
||||
## Backwards-compatibility
|
||||
|
||||
For all non-upgraded clients, this operation will look like a normal delete-and-replace. Replies, likes and everything else sent to node `aaaaaa` will be lost, but the feed will be intact and fine, with no need for any custom handling or complex replaceability.
|
||||
|
||||
## Progressive enhancement
|
||||
|
||||
Progressive enhancement may be applied, for example: when a user clicks to open note `bbbbbb` the client might try to query for `{"ids": ["aaaaaa"]}` upon seeing the `s` tag. And vice-versa, upon opening any other note a client might query for `{"#s": ["..."]}` to check if any edit is available. Both operations can enhance the focused note screen, but they don't have to be performed while loading a feed, and they remain strictly optional regardless.
|
||||
|
||||
## Full-blown upgrade
|
||||
|
||||
More complex clients that want to treat edits as pure edits and note as standalone notes may choose to hide any `kind:1` note that contains an `s` tag as a standalone entity, instead choosing to attach it to its "parent" that was edited. That must be combined with a refusal to _actually_ delete notes whenever the `kind:5` deletion request includes an `edit` tag. Such deletion request would then be only used as hints that an edit was performed, so it can be fetched and the note contents replaced in-place.
|
||||
|
||||
29
55.md
29
55.md
@@ -72,35 +72,6 @@ Set the Signer package name:
|
||||
intent.`package` = "com.example.signer"
|
||||
```
|
||||
|
||||
If you are sending multiple intents without awaiting you can add some intent flags to sign all events without opening multiple times the signer
|
||||
|
||||
```kotlin
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
```
|
||||
|
||||
If you are developing a signer application them you need to add this to your AndroidManifest.xml so clients can use the intent flags above
|
||||
|
||||
```kotlin
|
||||
android:launchMode="singleTop"
|
||||
```
|
||||
|
||||
Signer MUST answer multiple permissions with an array of results
|
||||
|
||||
```kotlin
|
||||
|
||||
val results = listOf(
|
||||
Result(
|
||||
package = signerPackageName,
|
||||
result = eventSignture,
|
||||
id = intentId
|
||||
)
|
||||
)
|
||||
|
||||
val json = results.toJson()
|
||||
|
||||
intent.putExtra("results", json)
|
||||
```
|
||||
|
||||
Send the Intent:
|
||||
|
||||
```kotlin
|
||||
|
||||
Reference in New Issue
Block a user