mirror of
https://github.com/nostr-protocol/nips.git
synced 2025-12-10 17:18:50 +00:00
Compare commits
8 Commits
editable
...
nh-editabl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d527dba15 | ||
|
|
c275ae74eb | ||
|
|
03a555beb5 | ||
|
|
93e6c3880b | ||
|
|
061d2ac47d | ||
|
|
5bcb2d834a | ||
|
|
4aa46562eb | ||
|
|
c0568fe8cc |
59
37.md
59
37.md
@@ -6,54 +6,33 @@ Editable Short Notes
|
|||||||
|
|
||||||
`draft` `optional`
|
`draft` `optional`
|
||||||
|
|
||||||
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).
|
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.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
## Example flow
|
|
||||||
|
|
||||||
Support `<bob>` publishes
|
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
"id": "aaaaa",
|
"kind": 31000,
|
||||||
"kind": 1,
|
"created_at": 1730820000,
|
||||||
"pubkey": "<bob>",
|
"content": "I like dogs",
|
||||||
"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": [
|
"tags": [
|
||||||
["s", "aaaaaa"] // this indicates the note that is being replaced
|
["d", "c2huy3f"],
|
||||||
]
|
// other kind1 tags
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
"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
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Backwards-compatibility
|
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.
|
||||||
|
|
||||||
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.
|
```jsonc
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"created_at": 1730820000,
|
||||||
|
"content": "naddr1...",
|
||||||
|
"tags": [
|
||||||
|
["q", "31000:...:c2huy3f"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Progressive enhancement
|
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`.
|
||||||
|
|
||||||
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,6 +72,35 @@ Set the Signer package name:
|
|||||||
intent.`package` = "com.example.signer"
|
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:
|
Send the Intent:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
|||||||
Reference in New Issue
Block a user