Regenerated with Backlogger and fixes

This commit is contained in:
diamondburned 2020-09-27 20:37:27 -07:00
parent f515470458
commit 2d93bf62ea
8 changed files with 742 additions and 597 deletions

977
cchat.go

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,17 @@
package main
import (
"sort"
"github.com/dave/jennifer/jen"
"github.com/diamondburned/cchat/repository"
)
func generateEnums(enums []repository.Enumeration) jen.Code {
sort.Slice(enums, func(i, j int) bool {
return enums[i].Name < enums[j].Name
})
var stmt = new(jen.Statement)
for _, enum := range enums {

View File

@ -1,11 +1,17 @@
package main
import (
"sort"
"github.com/dave/jennifer/jen"
"github.com/diamondburned/cchat/repository"
)
func generateInterfaces(ifaces []repository.Interface) jen.Code {
sort.Slice(ifaces, func(i, j int) bool {
return ifaces[i].Name < ifaces[j].Name
})
var stmt = new(jen.Statement)
for _, iface := range ifaces {
@ -23,7 +29,25 @@ func generateInterfaces(ifaces []repository.Interface) jen.Code {
group.Line()
}
// Put Asserter methods last.
sort.SliceStable(iface.Methods, func(i, j int) bool {
_, assert := iface.Methods[i].(repository.AsserterMethod)
return !assert
})
// Boolean to only write the Asserter comment once.
var writtenComment bool
for _, method := range iface.Methods {
if !writtenComment {
if _, ok := method.(repository.AsserterMethod); ok {
group.Line()
group.Comment("// Asserters.")
group.Line()
writtenComment = true
}
}
var stmt = new(jen.Statement)
if comment := method.UnderlyingComment(); !comment.IsEmpty() {
stmt.Comment(comment.GoString(1))

View File

@ -1,11 +1,17 @@
package main
import (
"sort"
"github.com/dave/jennifer/jen"
"github.com/diamondburned/cchat/repository"
)
func generateStructs(structs []repository.Struct) jen.Code {
sort.Slice(structs, func(i, j int) bool {
return structs[i].Name < structs[j].Name
})
var stmt = new(jen.Statement)
for _, s := range structs {
@ -18,6 +24,10 @@ func generateStructs(structs []repository.Struct) jen.Code {
}
func generateErrorStructs(errStructs []repository.ErrorStruct) jen.Code {
sort.Slice(errStructs, func(i, j int) bool {
return errStructs[i].Name < errStructs[j].Name
})
var stmt = new(jen.Statement)
for _, errStruct := range errStructs {

View File

@ -1,11 +1,17 @@
package main
import (
"sort"
"github.com/dave/jennifer/jen"
"github.com/diamondburned/cchat/repository"
)
func generateTypeAlises(aliases []repository.TypeAlias) jen.Code {
sort.Slice(aliases, func(i, j int) bool {
return aliases[i].Name < aliases[j].Name
})
var stmt = new(jen.Statement)
for _, alias := range aliases {

Binary file not shown.

View File

@ -389,8 +389,8 @@ var Main = Packages{
Below is an example of checking for an extended interface.
if backlogger := server.AsBacklogger(); backlogger != nil {
println("Server implements Backlogger.")
if iconer := server.AsIconer(); iconer != nil {
println("Server implements Iconer.")
}
Frontend
@ -922,6 +922,7 @@ var Main = Packages{
AsserterMethod{ChildType: "Editor"},
AsserterMethod{ChildType: "Actioner"},
AsserterMethod{ChildType: "Nicknamer"},
AsserterMethod{ChildType: "Backlogger"},
AsserterMethod{ChildType: "MemberLister"},
AsserterMethod{ChildType: "UnreadIndicator"},
AsserterMethod{ChildType: "TypingIndicator"},
@ -1062,6 +1063,51 @@ var Main = Packages{
HasStopFn: true,
},
},
}, {
Comment: Comment{`
Backlogger adds message history capabilities into a message
container. The backend should send old messages using the
MessageCreate method of the MessageContainer, and the frontend
should automatically sort messages based on the timestamp.
As there is no stop callback, if the backend needs to fetch
messages asynchronously, it is expected to use the context to
know when to cancel.
The frontend should usually call this method when the user
scrolls to the top. It is expected to guarantee not to call
MessagesBefore more than once on the same ID. This can usually
be done by deactivating the UI.
Note that the optional usage of contexts also apply here. The
frontend should deactivate the UI when the backend is working.
However, the frontend can accomodate this by not deactivating
until another event is triggered, then freeze the UI until the
method is cancelled. This works even when the backend does not
use the context.
`},
Name: "Backlogger",
Methods: []Method{
IOMethod{ // technically a ContainerMethod.
method: method{
Comment: Comment{`
MessagesBefore fetches messages before the given
message ID into the MessagesContainer.
This method is technically a ContainerMethod, but
is listed as an IOMethod because of the additional
message ID parameter.
`},
Name: "MessagesBefore",
},
Parameters: []NamedType{
{"ctx", "context.Context"},
{"before", "ID"},
{"msgc", "MessagesContainer"},
},
ReturnError: true,
},
},
}, {
Comment: Comment{`
MemberLister adds a member list into a message server.

View File

@ -37,15 +37,62 @@ type Rich struct {
Segments []Segment
}
// Segment is the minimum requirement for a format segment. Frontends will use
// this to determine when the format starts and ends. They will also assert this
// interface to any other formatting interface, including Linker, Colorer and
// Attributor.
// Attributor is a rich text markup format that a segment could implement. This
// is to be applied directly onto the text.
type Attributor interface {
Mentioner
Attribute() Attribute
}
// Avatarer implies the segment should be replaced with a rounded-corners image.
// This works similarly to Imager.
type Avatarer interface {
Segment
// AvatarText returns the underlying text of the image. Frontends could use this
// for hovering or displaying the text instead of the image.
AvatarText() string
// AvatarSize returns the requested dimension for the image. This function could
// return (0, 0), which the frontend should use the avatar's dimensions.
AvatarSize() (size int)
// Avatar returns the URL for the image.
Avatar() (url string)
}
// Codeblocker is a codeblock that supports optional syntax highlighting using
// the language given. Note that as this is a block, it will appear separately
// from the rest of the paragraph.
//
// Note that a segment may implement multiple interfaces. For example, a
// Mentioner may also implement Colorer.
type Segment interface {
Bounds() (start int, end int)
// This interface is equivalent to Markdown's codeblock syntax.
type Codeblocker interface {
Segment
CodeblockLanguage() (language string)
}
// Colorer is a text color format that a segment could implement. This is to be
// applied directly onto the text.
type Colorer interface {
Mentioner
// Color returns a 24-bit RGB or 32-bit RGBA color.
Color() uint32
}
// Imager implies the segment should be replaced with a (possibly inlined)
// image. Only the starting bound matters, as images cannot substitute texts.
type Imager interface {
Segment
// ImageText returns the underlying text of the image. Frontends could use this
// for hovering or displaying the text instead of the image.
ImageText() string
// ImageSize returns the requested dimension for the image. This function could
// return (0, 0), which the frontend should use the image's dimensions.
ImageSize() (w int, h int)
// Image returns the URL for the image.
Image() (url string)
}
// Linker is a hyperlink format that a segment could implement. This implies
@ -57,36 +104,6 @@ type Linker interface {
Link() (url string)
}
// Imager implies the segment should be replaced with a (possibly inlined)
// image. Only the starting bound matters, as images cannot substitute texts.
type Imager interface {
Segment
// Image returns the URL for the image.
Image() (url string)
// ImageSize returns the requested dimension for the image. This function could
// return (0, 0), which the frontend should use the image's dimensions.
ImageSize() (w int, h int)
// ImageText returns the underlying text of the image. Frontends could use this
// for hovering or displaying the text instead of the image.
ImageText() string
}
// Avatarer implies the segment should be replaced with a rounded-corners image.
// This works similarly to Imager.
type Avatarer interface {
Segment
// Avatar returns the URL for the image.
Avatar() (url string)
// AvatarSize returns the requested dimension for the image. This function could
// return (0, 0), which the frontend should use the avatar's dimensions.
AvatarSize() (size int)
// AvatarText returns the underlying text of the image. Frontends could use this
// for hovering or displaying the text instead of the image.
AvatarText() string
}
// Mentioner implies that the segment can be clickable, and when clicked it
// should open up a dialog containing information from MentionInfo().
//
@ -101,16 +118,6 @@ type Mentioner interface {
MentionInfo() Rich
}
// MentionerImage extends Mentioner to give the mentioned object an image. This
// interface allows the frontend to be more flexible in layouting. A Mentioner
// can only implement EITHER MentionedImage or MentionedAvatar.
type MentionerImage interface {
Mentioner
// Image returns the mentioned object's image URL.
Image() (url string)
}
// MentionerAvatar extends Mentioner to give the mentioned object an avatar.
// This interface allows the frontend to be more flexible in layouting. A
// Mentioner can only implement EITHER MentionedImage or MentionedAvatar.
@ -121,32 +128,14 @@ type MentionerAvatar interface {
Avatar() (url string)
}
// Colorer is a text color format that a segment could implement. This is to be
// applied directly onto the text.
type Colorer interface {
// MentionerImage extends Mentioner to give the mentioned object an image. This
// interface allows the frontend to be more flexible in layouting. A Mentioner
// can only implement EITHER MentionedImage or MentionedAvatar.
type MentionerImage interface {
Mentioner
// Color returns a 24-bit RGB or 32-bit RGBA color.
Color() uint32
}
// Attributor is a rich text markup format that a segment could implement. This
// is to be applied directly onto the text.
type Attributor interface {
Mentioner
Attribute() Attribute
}
// Codeblocker is a codeblock that supports optional syntax highlighting using
// the language given. Note that as this is a block, it will appear separately
// from the rest of the paragraph.
//
// This interface is equivalent to Markdown's codeblock syntax.
type Codeblocker interface {
Segment
CodeblockLanguage() (language string)
// Image returns the mentioned object's image URL.
Image() (url string)
}
// Quoteblocker represents a quoteblock that behaves similarly to the blockquote
@ -160,3 +149,14 @@ type Quoteblocker interface {
// information to format the quote properly.
QuotePrefix() (prefix string)
}
// Segment is the minimum requirement for a format segment. Frontends will use
// this to determine when the format starts and ends. They will also assert this
// interface to any other formatting interface, including Linker, Colorer and
// Attributor.
//
// Note that a segment may implement multiple interfaces. For example, a
// Mentioner may also implement Colorer.
type Segment interface {
Bounds() (start int, end int)
}