should be complete with initial read posts code
This commit is contained in:
+82
-8
@@ -17,12 +17,15 @@ import (
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.erbosoft.com/amy/amsterdam/database"
|
||||
"git.erbosoft.com/amy/amsterdam/htmlcheck"
|
||||
"git.erbosoft.com/amy/amsterdam/ui"
|
||||
"github.com/CloudyKit/jet/v6"
|
||||
"github.com/labstack/gommon/log"
|
||||
)
|
||||
|
||||
/* Conferences displayes the list of conferences in a community.
|
||||
@@ -325,18 +328,25 @@ func AttachmentUpload(ctxt ui.AmContext) (string, any, error) {
|
||||
return ui.ErrorPage(ctxt, errors.New("invalid button clicked on form"))
|
||||
}
|
||||
|
||||
/* breakRange breaks up a post range into two elements.
|
||||
* Parameters:
|
||||
* topic - The topic within which the range is defined.
|
||||
* into - The 2-element array into which the range will be filled.
|
||||
* param - The range parameter to be broken up.
|
||||
* sep - The separator character to use
|
||||
*/
|
||||
func breakRange(topic *database.Topic, into []int32, param string, sep string) error {
|
||||
rstr := strings.Split(param, sep)
|
||||
if len(rstr) == 0 {
|
||||
return fmt.Errorf("posts not found: %s in topic %d", param, topic.Number)
|
||||
}
|
||||
v, err := strconv.ParseInt(rstr[0], 10, 32)
|
||||
v, err := strconv.ParseInt(strings.TrimSpace(rstr[0]), 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("posts not found: %s in topic %d", param, topic.Number)
|
||||
}
|
||||
into[0] = int32(v)
|
||||
if len(rstr) > 1 {
|
||||
v, err = strconv.ParseInt(rstr[1], 10, 32)
|
||||
v, err = strconv.ParseInt(strings.TrimSpace(rstr[1]), 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("posts not found: %s in topic %d", param, topic.Number)
|
||||
}
|
||||
@@ -357,6 +367,63 @@ func breakRange(topic *database.Topic, into []int32, param string, sep string) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func templateExtractUserName(args jet.Arguments) reflect.Value {
|
||||
rc := "<<ERROR>>"
|
||||
post := args.Get(0).Convert(reflect.TypeFor[*database.PostHeader]()).Interface().(*database.PostHeader)
|
||||
user, err := database.AmGetUser(post.CreatorUid)
|
||||
if err == nil {
|
||||
rc = user.Username
|
||||
} else {
|
||||
log.Errorf("templateExtractUserName failed to get user #%d: %v", post.CreatorUid, err)
|
||||
}
|
||||
return reflect.ValueOf(rc)
|
||||
}
|
||||
|
||||
func templatePostText(args jet.Arguments) reflect.Value {
|
||||
post := args.Get(0).Convert(reflect.TypeFor[*database.PostHeader]()).Interface().(*database.PostHeader)
|
||||
rc, err := post.Text()
|
||||
if err != nil {
|
||||
log.Errorf("templatePostText could not get post text from post #%d: %v", post.PostId, err)
|
||||
rc = ""
|
||||
}
|
||||
return reflect.ValueOf(rc)
|
||||
}
|
||||
|
||||
func templateOverrideLine(args jet.Arguments) reflect.Value {
|
||||
post := args.Get(0).Convert(reflect.TypeFor[*database.PostHeader]()).Interface().(*database.PostHeader)
|
||||
ctxt := args.Get(1).Convert(reflect.TypeFor[ui.AmContext]()).Interface().(ui.AmContext)
|
||||
rc := ""
|
||||
if post.IsScribbled() {
|
||||
scr_date := ""
|
||||
scr_user, err := database.AmGetUser(*post.ScribbleUid)
|
||||
if err == nil {
|
||||
var p *database.UserPrefs
|
||||
p, err = ctxt.CurrentUser().Prefs()
|
||||
if err == nil {
|
||||
scr_date = p.Localizer().Strftime("%b %e, %Y %r", *post.ScribbleDate)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
rc = fmt.Sprintf("(Scribbled by %s on %s)", scr_user.Username, scr_date)
|
||||
} else {
|
||||
rc = fmt.Sprintf("<<<%v>>>", err)
|
||||
}
|
||||
} else if post.Hidden {
|
||||
rc = fmt.Sprintf("(Hidden Message: %d Lines)", *post.LineCount)
|
||||
}
|
||||
return reflect.ValueOf(rc)
|
||||
}
|
||||
|
||||
func templateOverrideLink(args jet.Arguments) reflect.Value {
|
||||
post := args.Get(0).Convert(reflect.TypeFor[*database.PostHeader]()).Interface().(*database.PostHeader)
|
||||
root := args.Get(1).Convert(reflect.TypeFor[string]()).String()
|
||||
rc := ""
|
||||
if post.Hidden {
|
||||
rc = fmt.Sprintf("%s?r=%d&ac=1", root, post.Num)
|
||||
}
|
||||
return reflect.ValueOf(rc)
|
||||
}
|
||||
|
||||
func ReadPosts(ctxt ui.AmContext) (string, any, error) {
|
||||
// If we need to reset a topic's last read count (as with "Next & Keep New"), spin the task off.
|
||||
if ctxt.HasParameter("rst") {
|
||||
@@ -420,7 +487,7 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
|
||||
} else if count < ctxt.Globals().PostsPerPage {
|
||||
pin = postRange[0] - 1
|
||||
postRange[0] = max(0, postRange[0]-ctxt.Globals().OldPostsAtTop)
|
||||
if pin < postRange[0] {
|
||||
if pin < postRange[0] || pin >= postRange[1] {
|
||||
pin = -1
|
||||
}
|
||||
}
|
||||
@@ -434,28 +501,35 @@ func ReadPosts(ctxt ui.AmContext) (string, any, error) {
|
||||
}
|
||||
|
||||
// Determine other required data.
|
||||
loc := prefs.Localizer()
|
||||
summaryLine := fmt.Sprintf("%d Total; %d New; Last: %s", topic.TopMessage+1, topic.TopMessage-lastRead, loc.Strftime("%b %e, %Y %r", topic.LastUpdate))
|
||||
plc := database.AmCreatePostLinkContext(comm.Alias, ctxt.GetScratch("currentAlias").(string), topic.Number)
|
||||
summaryLine := fmt.Sprintf("%d Total; %d New; Last: %s", topic.TopMessage+1, topic.TopMessage-lastRead, prefs.Localizer().Strftime("%b %e, %Y %r", topic.LastUpdate))
|
||||
plc := database.AmCreatePostLinkContext("", ctxt.GetScratch("currentAlias").(string), topic.Number)
|
||||
topicConferenceRef := plc.AsString()
|
||||
plc.Community = comm.Alias
|
||||
topicPostRef := plc.AsString()
|
||||
plc.FirstPost = postRange[0]
|
||||
plc.LastPost = postRange[1]
|
||||
postsPostRef := plc.AsString()
|
||||
|
||||
// Render the output.
|
||||
ctxt.VarMap().Set("stem", fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.GetScratch("currentAlias").(string)))
|
||||
ctxt.VarMap().Set("topicName", topic.Name)
|
||||
ctxt.VarMap().Set("summaryLine", summaryLine)
|
||||
ctxt.VarMap().Set("lastRead", lastRead)
|
||||
ctxt.VarMap().Set("pageSize", ctxt.Globals().PostsPerPage)
|
||||
ctxt.VarMap().Set("post_confRef", topicConferenceRef)
|
||||
ctxt.VarMap().SetFunc("post_getOverrideLine", templateOverrideLine)
|
||||
ctxt.VarMap().SetFunc("post.getOverrideLink", templateOverrideLink)
|
||||
ctxt.VarMap().SetFunc("post_getText", templatePostText)
|
||||
ctxt.VarMap().SetFunc("post_getUserName", templateExtractUserName)
|
||||
ctxt.VarMap().Set("post_stem", fmt.Sprintf("/comm/%s/conf/%s/r/%d", comm.Alias, ctxt.GetScratch("currentAlias").(string), topic.Number))
|
||||
ctxt.VarMap().Set("post_max", topic.TopMessage)
|
||||
ctxt.VarMap().Set("post_topicPermalink", fmt.Sprintf("/go/%s", topicPostRef))
|
||||
ctxt.VarMap().Set("posts", posts)
|
||||
ctxt.VarMap().Set("postsPermalink", fmt.Sprintf("/go/%s", postsPostRef))
|
||||
ctxt.VarMap().Set("pin", pin)
|
||||
ctxt.VarMap().Set("rangeEnd", postRange[1])
|
||||
ctxt.VarMap().Set("rangeStart", postRange[0])
|
||||
ctxt.VarMap().Set("topicListLink", fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, ctxt.GetScratch("currentAlias").(string)))
|
||||
ctxt.VarMap().Set("topicNum", topic.Number)
|
||||
ctxt.VarMap().Set("topicPermalink", fmt.Sprintf("/go/%s", topicPostRef))
|
||||
ctxt.VarMap().Set("amsterdam_pageTitle", fmt.Sprintf("%s: %s", topic.Name, summaryLine))
|
||||
if resetLastRead {
|
||||
user := ctxt.CurrentUser()
|
||||
|
||||
@@ -29,12 +29,49 @@ type PostHeader struct {
|
||||
Pseud *string `db:"pseud"` // post's "pseud" (name/header)
|
||||
}
|
||||
|
||||
type PostData struct {
|
||||
PostId int64 `db:"postid"` // ID of the post
|
||||
Data *string `db:"data"` // actual post data
|
||||
}
|
||||
|
||||
var ErrNoPostData = errors.New("no post data")
|
||||
|
||||
// IsScribbled returns true if the post has been scribbled, false if not.
|
||||
func (p *PostHeader) IsScribbled() bool {
|
||||
return p.ScribbleUid != nil && p.ScribbleDate != nil
|
||||
}
|
||||
|
||||
/* SetAttachment sets the attachment data for a post.
|
||||
* Parameters:
|
||||
* fileName - Name of the original attachment file.
|
||||
* mimeType - MIME type of the attachment data.
|
||||
* length - Length of the attachment data in bytes.
|
||||
* data - The attachment data itself.
|
||||
* Returns:
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (p *PostHeader) SetAttachment(fileName string, mimeType string, length int32, data []byte) error {
|
||||
_, err := amdb.Exec("INSERT INTO postattach (postid, datalen, filename, mimetype, data) VALUES (?, ?, ?, ?, ?)",
|
||||
p.PostId, length, fileName, mimeType, data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Text returns the text associated with a post.
|
||||
func (p *PostHeader) Text() (string, error) {
|
||||
var dbdata []PostData
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM postdata WHERE postid = ?", p.PostId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(dbdata) > 1 {
|
||||
return "", fmt.Errorf("too many data records (%d) for post #%d", len(dbdata), p.PostId)
|
||||
}
|
||||
if len(dbdata) == 0 || dbdata[0].Data == nil {
|
||||
return "", ErrNoPostData
|
||||
}
|
||||
return *dbdata[0].Data, nil
|
||||
}
|
||||
|
||||
func AmGetPost(postId int64) (*PostHeader, error) {
|
||||
var dbdata []PostHeader
|
||||
err := amdb.Select(&dbdata, "SELECT * FROM posts WHERE postid = ?", postId)
|
||||
|
||||
@@ -121,6 +121,18 @@ func extractCommunityLogo(a jet.Arguments) reflect.Value {
|
||||
return reflect.ValueOf(rc)
|
||||
}
|
||||
|
||||
// displayDateTime formats a date and time value.
|
||||
func displayDateTime(a jet.Arguments) reflect.Value {
|
||||
timeval := a.Get(0).Convert(reflect.TypeFor[time.Time]()).Interface().(time.Time)
|
||||
ctxt := a.Get(1).Convert(reflect.TypeFor[AmContext]()).Interface().(AmContext)
|
||||
prefs, err := ctxt.CurrentUser().Prefs()
|
||||
if err == nil {
|
||||
loc := prefs.Localizer()
|
||||
return reflect.ValueOf(loc.Strftime("%b %e, %Y %r", timeval))
|
||||
}
|
||||
return reflect.ValueOf(fmt.Sprintf("<<%v>>", err))
|
||||
}
|
||||
|
||||
// displayActivity displays an activity string formatted to the user's preferences.
|
||||
func displayActivity(a jet.Arguments) reflect.Value {
|
||||
timeval := a.Get(0).Convert(reflect.TypeFor[*time.Time]()).Interface().(*time.Time)
|
||||
@@ -273,6 +285,7 @@ func SetupTemplates() {
|
||||
views.AddGlobalFunc("MakeYearRange", makeYearRange)
|
||||
views.AddGlobalFunc("ExtractCommunityLogo", extractCommunityLogo)
|
||||
views.AddGlobalFunc("DisplayActivity", displayActivity)
|
||||
views.AddGlobalFunc("DisplayDateTime", displayDateTime)
|
||||
views.AddGlobalFunc("DisplayMemberCount", displayMemberCount)
|
||||
views.AddGlobalFunc("DisplayFullName", displayFullName)
|
||||
views.AddGlobalFunc("DisplayExpandCat", displayExpandCat)
|
||||
|
||||
+24
-16
@@ -18,7 +18,7 @@
|
||||
<!-- Topic Controls -->
|
||||
<div class="flex justify-between items-center mb-4 gap-2 flex-wrap">
|
||||
<div class="flex gap-2 flex-wrap">
|
||||
<a href="{{ stem }}"
|
||||
<a href="{{ topicListLink }}"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors">Topic List</a>
|
||||
<a href="/TODO"
|
||||
class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors">Hide Topic</a>
|
||||
@@ -41,23 +41,23 @@
|
||||
|
||||
<!-- Navigation Bar -->
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<form method="GET" action="{{ stem }}/r/{{ topicNum }}" class="flex items-center gap-2">
|
||||
<form method="GET" action="{{ post_stem }}" class="flex items-center gap-2">
|
||||
<input type="text" name="rgo" value="" size="6" maxlength="13" placeholder="Go to..."
|
||||
class="px-3 py-2 border border-gray-300 rounded font-mono text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||||
<button type="submit" name="go" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded text-sm font-medium transition-colors">Go</button>
|
||||
</form>
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
<div class="flex items-center gap-2 text-sm" name="top">
|
||||
<span>[</span>
|
||||
<a href="{{ stem }}/r/{{ topicNum }}?r=0,-1" class="text-blue-700 hover:text-blue-900">View All</a>
|
||||
<a href="{{ post_stem }}?r=0,-1" class="text-blue-700 hover:text-blue-900">View All</a>
|
||||
{{ if rangeStart > 0 }}
|
||||
<span>|</span>
|
||||
<a href="{{ stem }}/r/{{ topicNum }}?r={{ rangeStart - pageSize - 1 }},{{ rangeStart - 1 }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll Up {{ pageSize }}</a>
|
||||
<a href="{{ post_stem }}?r={{ rangeStart - pageSize - 1 }},{{ rangeStart - 1 }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll Up {{ pageSize }}</a>
|
||||
{{ end }}
|
||||
{{ if rangeEnd < post_max }}
|
||||
<span>|</span>
|
||||
<a href="{{ stem }}/r/{{ topicNum }}?r={{ rangeEnd + 1 }},{{ rangeEnd + pageSize + 1 }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll Down {{ pageSize }}</a>
|
||||
<a href="{{ post_stem }}?r={{ rangeEnd + 1 }},{{ rangeEnd + pageSize + 1 }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll Down {{ pageSize }}</a>
|
||||
<span>|</span>
|
||||
<a href="{{ stem }}/r/{{ topicNum }}?r={{ post_max - pageSize - 1 }},{{ post_max }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll To End</a>
|
||||
<a href="{{ post_stem }}?r={{ post_max - pageSize - 1 }},{{ post_max }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll To End</a>
|
||||
{{ end }}
|
||||
<span>|</span>
|
||||
<a href="#bottom" class="text-blue-700 hover:text-blue-900">Bottom</a>
|
||||
@@ -67,32 +67,40 @@
|
||||
|
||||
<!-- Permalink Info -->
|
||||
<div class="text-center text-xs text-gray-600 mb-6">
|
||||
<a href="/go/{{ topicPermalink }}" class="text-blue-700 hover:text-blue-900">[Permalink to this topic]</a>
|
||||
<a href="{{ post_topicPermalink }}" class="text-blue-700 hover:text-blue-900">[Permalink to this topic]</a>
|
||||
<span class="mx-2">·</span>
|
||||
<a href="/go/{{ postsPermalink }}" class="text-blue-700 hover:text-blue-900">[Permalink to these posts]</a>
|
||||
<a href="{{ postsPermalink }}" class="text-blue-700 hover:text-blue-900">[Permalink to these posts]</a>
|
||||
</div>
|
||||
|
||||
<!-- Messages -->
|
||||
<div class="space-y-6 mb-8">
|
||||
{{ range i, p := posts }}
|
||||
{{ post_userName := "" }}
|
||||
{{ post_text := "" }}
|
||||
{{ post_overrideLine := "" }}
|
||||
{{ post_overrideLink := "" }}
|
||||
{{ range i, post_cur := posts }}
|
||||
{{ post_userName = post_getUserName(post_cur) }}
|
||||
{{ post_text = post_getText(post_cur) }}
|
||||
{{ post_overrideLine = post_getOverrideLine(post_cur, .) }}
|
||||
{{ post_overrideLink = post_getOverrideLink(post_cur, post_topicPermalink) }}
|
||||
{{ .SubRender("singlepost.jet") | raw }}
|
||||
{{ if pin == p.Num }}<hr/>{{ end }}
|
||||
{{ if pin == post_cur.Num }}<hr/>{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<div class="flex justify-end items-center mb-6 text-sm">
|
||||
<div class="flex justify-end items-center mb-6 text-sm" name="bottom">
|
||||
<span>[</span>
|
||||
<a href="{{ stem }}/r/{{ topicNum }}?r=0,-1" class="text-blue-700 hover:text-blue-900 mx-2">View All</a>
|
||||
<a href="{{ post_stem }}?r=0,-1" class="text-blue-700 hover:text-blue-900 mx-2">View All</a>
|
||||
{{ if rangeStart > 0 }}
|
||||
<span>|</span>
|
||||
<a href="{{ stem }}/r/{{ topicNum }}?r={{ rangeStart - pageSize - 1 }},{{ rangeStart - 1 }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll Up {{ pageSize }}</a>
|
||||
<a href="{{ post_stem }}?r={{ rangeStart - pageSize - 1 }},{{ rangeStart - 1 }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll Up {{ pageSize }}</a>
|
||||
{{ end }}
|
||||
{{ if rangeEnd < post_max }}
|
||||
<span>|</span>
|
||||
<a href="{{ stem }}/r/{{ topicNum }}?r={{ rangeEnd + 1 }},{{ rangeEnd + pageSize + 1 }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll Down {{ pageSize }}</a>
|
||||
<a href="{{ post_stem }}?r={{ rangeEnd + 1 }},{{ rangeEnd + pageSize + 1 }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll Down {{ pageSize }}</a>
|
||||
<span>|</span>
|
||||
<a href="{{ stem }}/r/{{ topicNum }}?r={{ post_max - pageSize - 1 }},{{ post_max }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll To End</a>
|
||||
<a href="{{ post_stem }}?r={{ post_max - pageSize - 1 }},{{ post_max }}" class="text-blue-700 hover:text-blue-900 mx-2">Scroll To End</a>
|
||||
{{ end }}
|
||||
<span>|</span>
|
||||
<a href="#top" class="text-blue-700 hover:text-blue-900 mx-2">Top</a>
|
||||
|
||||
+17
-11
@@ -9,21 +9,27 @@
|
||||
<div class="border-2 border-gray-300 rounded-lg p-4 bg-white">
|
||||
<div class="flex justify-between items-start mb-3">
|
||||
<div class="text-sm text-gray-600">
|
||||
<a href="http://necrovenice:8080/venice/conf/posts.js.vs?cc=2&conf=2&top=4&shac=1&p1=0" class="text-blue-700 hover:text-blue-900 font-mono">0</a> of
|
||||
<a href="http://necrovenice:8080/venice/conf/posts.js.vs?cc=2&conf=2&top=4&shac=1&p1=3" class="text-blue-700 hover:text-blue-900 font-mono">3</a>
|
||||
<span class="ml-2 text-xs"><General.4.0></span>
|
||||
<a href="http://necrovenice:8080/venice/go/Piazza!General.4.0" class="ml-2 text-xs text-blue-700 hover:text-blue-900">[Permalink]</a>
|
||||
<a href="{{ post_stem }}?r={{ post_cur.Num }}&ac=1" class="text-blue-700 hover:text-blue-900 font-mono">{{ post_cur.Num }}</a> of
|
||||
<a href="{{ post_stem }}?r={{ post_max }}&ac=1" class="text-blue-700 hover:text-blue-900 font-mono">{{ post_max }}</a>
|
||||
🔗 <a href="{{ post_topicPermalink }}.{{ post_cur.Num }}" class="ml-2 text-xs text-blue-700 hover:text-blue-900"><{{ post_confRef }}.{{ post_cur.Num }}></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<strong class="text-lg">The first one</strong>
|
||||
<strong class="text-lg">{{ post_cur.Pseud }}</strong>
|
||||
<span class="text-gray-600 text-sm ml-2">(<em>
|
||||
<a href="http://necrovenice:8080/venice/user/Administrator" target="_blank" class="text-blue-700 hover:text-blue-900">Administrator</a>,
|
||||
Nov 20, 2025 10:47:17 PM</em>)
|
||||
<a href="/user/{{ post_userName }}" target="_blank" class="text-blue-700 hover:text-blue-900">{{ post_userName }}</a>,
|
||||
{{ DisplayDateTime(post_cur.Posted, .) }}</em>)
|
||||
</span>
|
||||
</div>
|
||||
<pre class="font-mono text-sm whitespace-pre-wrap bg-gray-50 p-4 rounded border border-gray-200">This is a test.
|
||||
This is <em>only</em> a test.
|
||||
If this had been an actual emergency, we would all be
|
||||
dead by now.</pre>
|
||||
{{ if post_overrideLine != "" }}
|
||||
<div class="mb-2">
|
||||
{{ if post_overrideLink != "" }}
|
||||
<a href="{{ post_overrideLink }}" target="_blank" class="text-blue-700 hover:text-blue-900"><span class="italic font-bold">{{ post_overrideLine }}</span></a>
|
||||
{{ else }}
|
||||
<span class="italic text-bold">{{ post_overrideLine }}</span>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ else }}
|
||||
<pre class="amsPost font-mono text-sm whitespace-pre-wrap bg-gray-50 p-4 rounded border border-gray-200">{{ post_text | postRewrite | raw }}</pre>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -44,15 +44,15 @@ func AmNewPool(parent context.Context, workers, queueSize int) *WorkerPool {
|
||||
tasks: make(chan Task, queueSize),
|
||||
}
|
||||
for i := range workers {
|
||||
p.wg.Add(1)
|
||||
go p.worker(i)
|
||||
p.wg.Go(func() {
|
||||
p.worker(i)
|
||||
})
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
// worker is the worker goroutine for a pool.
|
||||
func (p *WorkerPool) worker(id int) {
|
||||
defer p.wg.Done()
|
||||
for {
|
||||
select {
|
||||
case <-p.ctx.Done():
|
||||
|
||||
Reference in New Issue
Block a user