User:Legoktm/flow backend

Overall (IMO) one of the largest issues with Flow is its lack of integration with MediaWiki, and requiring custom code and random hooks to implement what is already core functionality. It is currently marking its pages as using the Flow board content model, but not actually storing content in the page text.

This RfC aims to:

  • Overhaul the backend system to properly use ContentHandler where text is stored as revisions
  • Remove the abundance of hooks where overrides were needed for Flow
  • ...


Flow is currently storing


I sort of have some thoughts about what I think a cool on wiki
discussion system would look like (With the standard disclaimer that I
have not tried any of this, it may not work in practice).

A large part of my beef with flow is actually frontend, I think a flow
page should look as much like a normal wiki talk page as possible. And
if we're going to look to other forum software for inspiration for the
"look", I think we should look to things that are rather condensed
like reddit, as opposed to things like /., phpBB or word press
comments, where the comments have a lot of whitespace separating them
from each other.

But anyways, backend thoughts:

I think it'd be best to have each section (ie thread - I mean a post +
all the replies to a post) have its own page, and then have the main
talk page (ie flow board) be the collection of all the current
threads. This would match current practice on wiki for a lot of more
complex talk pages (e.g. Deletion requests where each item up for
discussion gets its own page, which is transcluded on the master
page). And would also allow for more complex features, such as cross
posting a thread to multiple talk pages.

The structure I had in mind was that the actual talk page (What flow
calls a "board" I believe and what lives at Talk:Foo) is a minimal
json structure, mostly to keep track of some advanced options that are
hidden very far away from the user. What threads appear on the page is
controlled by the thread and actually knowing how to render the talk
page comes from a db query and not the content of that page.

I imagine it looking something like:
  header: "Optional wikitext to put in the header",
  footer: "Optional wikitext to put in the footer",
  style: "plain" | "date"
  archiveSettings: {
    maxShowOnPage: 50, /* Don't show more than this current threads on
a page at once */
    minShowOnPage: 0, /* Min to show. e.g. Keep showing an old thread
even if it has had no activity in a long time to keep at least this
many on the page */
    rmArchivedAfter: 259200, /* 3 days. Once a thread has been
archived, remove from talk page after this many days */
    showOldArchive: false, /* Whether to show archived threads to
meet minShowOnPage threshold */
    rmNoActivity: 2592000, /* 30 days. When to remove a thread due to
no activity */
    allowForceArchiving: true,
    bottomPost: true /* new on top or bottom */

Header and footer options allow users to put some wikitext on the top
or bottom of the page if they want. The style option would allow
changing the talk page style (So far I envision something like plain
for normal talk page, and date for something like Commons:VP that has
date headers for when the conversation was started).

In this model, individual threads could be archived, which cause them
to be removed from the page quicker (And presumably displayed
differently). They can also be force archived to immediately remove
from the page.

For threads. I personally think its best that they appear in the same
namespace as the main talk page as a subpage. That way they stay on
recentchanges and are easier to follow. So if the main talk page is
named talk:Foo, then a thread on that page might be named
talk:Foo/threads/I_think_bar_is_a_better_variable_name (I am not a fan
of how flow uses UUIDs to name threads. I don't think a UUID should
ever be exposed to a user)

The json structure of a thread might look like:
  status: "open" | "archived" | "force-archived",
  lastModified: <timestamp>,
  includeOn: ["Talk:Foo", "User_talk:Somebody", ...]

  header: "optional random wikitext. Meant for things like

templates. Perhaps summaries of thread after archiving, although maybe
that should be a separate field",
  title: "Title of thread",
  children: [ // The initial comment is also considered a "child"
      text: "wikitext of comment",
      user: "Bawolff",
      lastEdited: false, // date last edited if its modified
      deleted: ... // not sure how rev-delete will work with this, but
rev-delete info here.
      childType: "list" | "thread" | "vote" | "s-vote" | "o-vote" | "n-vote",
      break: "auto" | "none" | "unindent" | "hr" | "section-1" | "section-2" ...
      children: [
        /* if there are children, then they go here in a recursive fashion */
    }, /* If there are more comments on the same level, they go here */

And there is also a table in db with columns status, last_modified,
included_page, so that on links update, the status, last_modified, and
page_id of includeOn (one row for each page included on) is inserted
in db. When it comes time to render a talk page, MW selects from that
table in order to see which threads to render. This should be fairly
efficient since it can use status and last_modified to only select the
threads it should display, and then does rendering which should be
roughly the same as the current practice of transcluding a bunch of
discussions on to a master talk page.

For child-type property (I'm kind of envisioning something here that
would do exactly the same thing as what people currently use talk
pages for), the default would be thread, but would also allow someone
to specify that replies should be rendered as an un-ordered list, or a
vote (a vote being same as list, but software automatically prompts
user for   Support/  Oppose.) s-vote would be for a vote where
this is the support section so everything is   Support

The break property could allow users to force an unindent (I
imagine that generally software would unindent things in the
rendering after some level of indentation, but would internally record
indentation to infinite depth). The break property could have some
other unident methods, such as section for "arbitrary section break"
type things.