Open evanp opened 6 years ago
So, this is used in OStatus for big hierarchical conversations. So when you have Notes like this:
Here, Note6 is inReplyTo Note5, and Note10 is inReplyTo Note9. But it's not clear that they are part of a larger conversation, unless you walk up the tree.
A conversation
property links them all together. I think that most OStatus implementations use the ID of the root object (which is inReplyTo nothing else) as the conversation identifier, but I don't think they are required to.
So, related features we already have in AS2:
Identifies the context within which the object exists or an activity was performed.
The notion of "context" used is intentionally vague. The intended function is to serve
as a means of grouping objects and activities that share a common originating context
or purpose. An example could be all activities relating to a common project or event.
One thing we could do is define a Conversation
type, and use it like this:
{
"type": "Note",
"id": "https://an.example/note/6",
"inReplyTo": "https://an.example/note/5",
"context": {
"type": "Conversation",
"id": "https://an.example/conversation/1"
}
}
Another is to specify a root
or op
item:
{
"type": "Note",
"id": "https://an.example/note/6",
"inReplyTo": "https://an.example/note/5",
"root": {
"type": "Note",
"id": "https://an.example/note/1"
}
}
Or we could use a conversation
property:
{
"type": "Note",
"id": "https://an.example/note/6",
"inReplyTo": "https://an.example/note/5",
"conversation": {
"type": "Conversation",
"id": "https://an.example/conversation/1"
}
}
{
"type": "Note",
"id": "https://an.example/note/6",
"inReplyTo": "https://an.example/note/5",
"conversation": {
"type": "Note",
"id": "https://an.example/note/1"
}
}
It's also worth noting that many systems use a flat commenting/replying hierarchy, so everything would be inReplyTo Note1.
for the record, even though mastodon uses a flat commenting UX, posts still technically form a nested heiarchy. (and even in more flat system, it's more intuitive sometimes to have notes as in reply to the last note in the thread, not the root note)
On Wed, May 9, 2018, 1:44 PM Evan Prodromou notifications@github.com wrote:
It's also worth noting that many systems use a flat commenting/replying hierarchy, so everything would be inReplyTo Note1.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/w3c/activitystreams/issues/476#issuecomment-387819135, or mute the thread https://github.com/notifications/unsubscribe-auth/AAORV--5CXtuWUG2SVnOSgUURbzrmswNks5twyr9gaJpZM4T4icd .
inReplyTo
is not marked as a functional
property (there can be more than one), so is it expected that single objects could be part of many conversations?
I am a fan of the extra properties!
However, what is the compelling reason to having a separate Conversation
type, too? I could maybe see an argument for it being a (Ordered
?) Collection
of a list of IRIs to every object in the conversation, but I don't see the utility that extra abstraction layer brings and two major costs: putting an arbitrary logical grouping in the graph, and forcing everyone to adhere to it. Instead, it seems more straightforward for any new properties to point directly to the head object and let applications crawl as far down as they please with whatever caching/grouping they want to do.
@cjslep so say you have a conversation tree like in https://github.com/w3c/activitystreams/issues/476#issuecomment-387813503. In your UI you want to know if, say, note 6 and note 10 are associated with each other (which they are because they're both replies to replies to note 1). Normally you would be required to walk the entire tree to find that information, but with this extension you could determine that information in constant time.
Also remember that nobody's forced to use it - extensions are optional :P
@strugee Yes, I agree, that can be accomplished with just the new properties referencing the IRI of the root node and comparing them. I like that. I just don't see a compelling need for a whole new Conversation
type to embody this concept.
Also, in practice I am sure it is constant time with most people replying to 1 thread at a time. But theoretically, it is linear time with respect to the number of conversations the replies are in (since inReplyTo
is not marked as functional).
Don't think "Conversation" type is necessary. a Property whose range is Link would be sufficient for
{ "conversation": "https://conversation-url.com" }
I worked at a "conversation not comments" company for a long time. It's quite the overloaded term. I think inReplyToRoot
would be a bit more clear and specific to what we're talking about here ('inReplyTo' relation-following as opposed to something else, root of tree data structure)
So, 5 years later, we have a number of solutions to this issue. Mastodon uses the ostatus:conversation
property directly. Here's an example "toot" from Mastodon:
{
"@context" : [
"https://www.w3.org/ns/activitystreams",
{
"atomUri" : "ostatus:atomUri",
"conversation" : "ostatus:conversation",
"inReplyToAtomUri" : "ostatus:inReplyToAtomUri",
"ostatus" : "http://ostatus.org#",
"sensitive" : "as:sensitive",
"toot" : "http://joinmastodon.org/ns#",
"votersCount" : "toot:votersCount"
}
],
"atomUri" : "https://cosocial.ca/users/evan/statuses/110257163940796886",
"attachment" : [],
"attributedTo" : "https://cosocial.ca/users/evan",
"cc" : [
"https://cosocial.ca/users/evan/followers"
],
"content" : "<p>Why: temp rise under 1.5C</p><p>What: zero emissions by 2050; capture CO2</p><p>How to get to zero: vote and donate to climate+ pols, electric or no car, trains not planes, clean electricity or home solar, low or no meat, buy climate+</p><p>How to capture: plant 500 billion trees</p>",
"contentMap" : {
"en" : "<p>Why: temp rise under 1.5C</p><p>What: zero emissions by 2050; capture CO2</p><p>How to get to zero: vote and donate to climate+ pols, electric or no car, trains not planes, clean electricity or home solar, low or no meat, buy climate+</p><p>How to capture: plant 500 billion trees</p>"
},
"conversation" : "tag:cosocial.ca,2023-04-25:objectId=483056:objectType=Conversation",
"id" : "https://cosocial.ca/users/evan/statuses/110257163940796886",
"inReplyTo" : null,
"inReplyToAtomUri" : null,
"published" : "2023-04-25T02:46:47Z",
"replies" : {
"first" : {
"items" : [],
"next" : "https://cosocial.ca/users/evan/statuses/110257163940796886/replies?only_other_accounts=true&page=true",
"partOf" : "https://cosocial.ca/users/evan/statuses/110257163940796886/replies",
"type" : "CollectionPage"
},
"id" : "https://cosocial.ca/users/evan/statuses/110257163940796886/replies",
"type" : "Collection"
},
"sensitive" : false,
"summary" : null,
"tag" : [],
"to" : [
"https://www.w3.org/ns/activitystreams#Public"
],
"type" : "Note",
"url" : "https://cosocial.ca/@evan/110257163940796886"
}
I believe other implementations use the context
property for something similar. I think the best resolution here is to create a page at https://www.w3.org/wiki/Activity_Streams/Primer/Conversation and collect best practices.
Right now, I agree with @cjslep that the best way to do this is with a context
property that links to the original post:
"context": {
"type": "Note",
"id": "https://an.example/note/1"
}
Rather than linking to the original post, it would be better to have an explicit collection that can be managed by a mechanism similar to FEP-7888
We should be able to associate a big thread for conversation