@@ -265,23 +265,14 @@ func (s service) ListTimeline(ctx context.Context, _ string, id uint64, opt *cha
					},
				})
			}
			continue
		}
		label, body, ok := parseMessage(message.Message)
		labels, body, ok := parseMessage(message.Message)
		if !ok {
			continue
		}
		var state change.ReviewState
		switch label {
		default:
			state = change.Commented
		case "Code-Review+2":
			state = change.Approved
		case "Code-Review-2":
			state = change.ChangesRequested
		}
		var cs []change.InlineComment
		for file, comments := range *comments {
			for _, c := range comments {
				if c.Updated.Equal(message.Date.Time) {
					cs = append(cs, change.InlineComment{
@@ -294,20 +285,20 @@ func (s service) ListTimeline(ctx context.Context, _ string, id uint64, opt *cha
		}
		timeline = append(timeline, change.Review{
			ID:        fmt.Sprint(idx), // TODO: message.ID is not uint64; e.g., "bfba753d015916303152305cee7152ea7a112fe0".
			User:      s.gerritUser(message.Author),
			CreatedAt: message.Date.Time,
			State:     state,
			State:     reviewState(labels),
			Body:      body,
			Editable:  false,
			Comments:  cs,
		})
	}
	return timeline, nil
}
func parseMessage(m string) (label string, body string, ok bool) {
func parseMessage(m string) (labels string, body string, ok bool) {
	// "Patch Set ".
	if !strings.HasPrefix(m, "Patch Set ") {
		return "", "", false
	}
	m = m[len("Patch Set "):]
@@ -325,33 +316,45 @@ func parseMessage(m string) (label string, body string, ok bool) {
	}
	m = m[1:]
	switch i = strings.IndexByte(m, '\n'); i {
	case -1:
		label = m
		labels = m
	default:
		label = m[:i]
		labels = m[:i]
		body = m[i+1:]
	}
	if label != "" {
	if labels != "" {
		// " ".
		if len(label) < 1 || label[0] != ' ' {
		if len(labels) < 1 || labels[0] != ' ' {
			return "", "", false
		}
		label = label[1:]
		labels = labels[1:]
	}
	if body != "" {
		// "\n".
		if len(body) < 1 || body[0] != '\n' {
			return "", "", false
		}
		body = body[1:]
	}
	return label, body, true
	return labels, body, true
}
func reviewState(labels string) change.ReviewState {
	for _, label := range strings.Split(labels, " ") {
		switch label {
		case "Code-Review+2":
			return change.Approved
		case "Code-Review-2":
			return change.ChangesRequested
		}
	}
	return change.Commented
}
func (service) EditComment(_ context.Context, repo string, id uint64, cr change.CommentRequest) (change.Comment, error) {
	return change.Comment{}, fmt.Errorf("EditComment: not implemented")
}