ronantakizawa/codereview-bench huggingface dataset:
Repository: usememos/memos
File: server/rss.go (Go)

Code before:
		return c.String(http.StatusOK, rss)
	})
}

const MaxRSSItemCount = 100
const MaxRSSItemTitleLength = 100

func generateRSSFromMemoList(memoList []*api.Memo, baseURL string, profile *api.CustomizedProfile) (string, error) {
	feed := &feeds.Feed{
		Title:       profile.Name,
		Link:        &feeds.Link{Href: baseURL},
		Description: profile.Description,
		Created:     time.Now(),
	}

	var itemCountLimit = min(len(memoList), MaxRSSItemCount)

	feed.Items = make([]*feeds.Item, itemCountLimit)

	for i := 0; i < itemCountLimit; i++ {
		memo := memoList[i]

		feed.Items[i] = &feeds.Item{
			Title:       getRSSItemTitle(memo.Content),
			Link:        &feeds.Link{Href: baseURL + "/m/" + strconv.Itoa(memo.ID)},
			Description: getRssItemDescription(memo.Content),
			Created:     time.Unix(memo.CreatedTs, 0),
		}
	}

	rss, err := feed.ToRss()
	if err != nil {
		return "", err
	}
	return rss, nil
}

func getSystemCustomizedProfile(ctx context.Context, s *Server) (api.CustomizedProfile, error) {
	systemStatus := api.SystemStatus{
		CustomizedProfile: api.CustomizedProfile{
			Name:        "memos",
			LogoURL:     "",
			Description: "",
			Locale:      "en",
			Appearance:  "system",
			ExternalURL: "",
		},
	}

	systemSettingList, err := s.Store.FindSystemSettingList(ctx, &api.SystemSettingFind{})
	if err != nil {

Review comment (suggestion):
```suggestion
			Description: getRSSItemDescription(memo.Content),
```

Code after:
		return c.String(http.StatusOK, rss)
	})
}

const MaxRSSItemCount = 100
const MaxRSSItemTitleLength = 100

func generateRSSFromMemoList(memoList []*api.Memo, baseURL string, profile *api.CustomizedProfile) (string, error) {
	feed := &feeds.Feed{
		Title:       profile.Name,
		Link:        &feeds.Link{Href: baseURL},
		Description: profile.Description,
		Created:     time.Now(),
	}

	var itemCountLimit = min(len(memoList), MaxRSSItemCount)

	feed.Items = make([]*feeds.Item, itemCountLimit)

	for i := 0; i < itemCountLimit; i++ {
		memo := memoList[i]

		feed.Items[i] = &feeds.Item{
			Title:       getRSSItemTitle(memo.Content),
			Link:        &feeds.Link{Href: baseURL + "/m/" + strconv.Itoa(memo.ID)},
			Description: getRSSItemDescription(memo.Content),
			Created:     time.Unix(memo.CreatedTs, 0),
		}
	}

	rss, err := feed.ToRss()
	if err != nil {
		return "", err
	}
	return rss, nil
}

func getSystemCustomizedProfile(ctx context.Context, s *Server) (api.CustomizedProfile, error) {
	systemStatus := api.SystemStatus{
		CustomizedProfile: api.CustomizedProfile{
			Name:        "memos",
			LogoURL:     "",
			Description: "",
			Locale:      "en",
			Appearance:  "system",
			ExternalURL: "",
		},
	}

	systemSettingList, err := s.Store.FindSystemSettingList(ctx, &api.SystemSettingFind{})
	if err != nil {
Repository: usememos/memos
File: api/system.go (Go)

Code before:
package api

import "github.com/usememos/memos/server/profile"

type SystemStatus struct {
	Host    *User           `json:"host"`
	Profile profile.Profile `json:"profile"`
	DBSize  int64           `json:"dbSize"`

	// System settings
	// Allow sign up.
	AllowSignUp bool `json:"allowSignUp"`
	// Disable public memos.
	DisablePublicMemos bool `json:"disablePublicMemos"`
	// Additional style.
	AdditionalStyle string `json:"additionalStyle"`
	// Additional script.
	AdditionalScript string `json:"additionalScript"`
	// Customized server profile, including server name and external url.
	CustomizedProfile CustomizedProfile `json:"customizedProfile"`
	StorageServiceID  int               `json:"storageServiceId"`
	// OpenAI Host
	OpenAIApiHost string `json:"openAIApiHost"`
}


Review comment (suggestion):
```suggestion
	// OpenAI API Host
	OpenAIAPIHost string `json:"openAIApiHost"`
```

Code after:
package api

import "github.com/usememos/memos/server/profile"

type SystemStatus struct {
	Host    *User           `json:"host"`
	Profile profile.Profile `json:"profile"`
	DBSize  int64           `json:"dbSize"`

	// System settings
	// Allow sign up.
	AllowSignUp bool `json:"allowSignUp"`
	// Disable public memos.
	DisablePublicMemos bool `json:"disablePublicMemos"`
	// Additional style.
	AdditionalStyle string `json:"additionalStyle"`
	// Additional script.
	AdditionalScript string `json:"additionalScript"`
	// Customized server profile, including server name and external url.
	CustomizedProfile CustomizedProfile `json:"customizedProfile"`
	StorageServiceID  int               `json:"storageServiceId"`
	// OpenAI API Host
	OpenAIAPIHost string `json:"openAIApiHost"`
}
Repository: usememos/memos
File: web/src/labs/marked/index.tsx (TypeScript)

Code before:
import { matcher } from "./matcher";
import { blockElementParserList, inlineElementParserList } from "./parser";

type Parser = typeof blockElementParserList[0];

const findMatchingParser = (parsers: Parser[], markdownStr: string): Parser | undefined => {
  let matchedParser = undefined;
  let matchedIndex = -1;

  for (const parser of parsers) {
    const matchResult = matcher(markdownStr, parser.regexp);
    if (!matchResult) {
      continue;
    }

    if (parser.name === "plain text" && matchedParser !== undefined) {
      continue;
    }

    const startIndex = matchResult.index as number;
    if (matchedParser === undefined || matchedIndex > startIndex) {
      matchedParser = parser;
      matchedIndex = startIndex;
    }
  }

  return matchedParser;
};


Review comment (suggestion):
We can declare its structure instead of using `typeof blockElementParserList[0]`

Code after:
import { matcher } from "./matcher";
import { blockElementParserList, inlineElementParserList } from "./parser";

type Parser = {
  name: string;
  regexp: RegExp;
  renderer: (rawStr: string) => JSX.Element | string;
};

const findMatchingParser = (parsers: Parser[], markdownStr: string): Parser | undefined => {
  let matchedParser = undefined;
  let matchedIndex = -1;

  for (const parser of parsers) {
    const matchResult = matcher(markdownStr, parser.regexp);
    if (!matchResult) {
      continue;
    }

    if (parser.name === "plain text" && matchedParser !== undefined) {
      continue;
    }

    const startIndex = matchResult.index as number;
    if (matchedParser === undefined || matchedIndex > startIndex) {
      matchedParser = parser;
      matchedIndex = startIndex;
    }
  }
Repository: usememos/memos
File: web/src/hooks/useEvent.ts (TypeScript)

Code before:
import React, { useEffect, useRef, EffectCallback, DependencyList } from "react";

const useIsoMorphicEffect = (effect: EffectCallback, deps?: DependencyList | undefined) => {
  useEffect(effect, deps);
};

function useLatestValue<T>(value: T) {
  const cache = useRef(value);

  useIsoMorphicEffect(() => {
    cache.current = value;
  }, [value]);

  return cache;
}

// TODO: Add React.useEvent ?? once the useEvent hook is available
const useEvent = function useEvent<F extends (...args: any[]) => any, P extends any[] = Parameters<F>, R = ReturnType<F>>(
  cb: (...args: P) => R
) {
  const cache = useLatestValue(cb);
  return React.useCallback((...args: P) => cache.current(...args), [cache]);
};

export default useEvent;


Review comment (suggestion):
```suggestion
function useEvent<F extends (...args: any[]) => any, P extends any[] = Parameters<F>, R = ReturnType<F>>(
```

Code after:
import React, { useEffect, useRef, EffectCallback, DependencyList } from "react";

const useIsoMorphicEffect = (effect: EffectCallback, deps?: DependencyList | undefined) => {
  useEffect(effect, deps);
};

function useLatestValue<T>(value: T) {
  const cache = useRef(value);

  useIsoMorphicEffect(() => {
    cache.current = value;
  }, [value]);

  return cache;
}

// TODO: Add React.useEvent ?? once the useEvent hook is available
function useEvent<F extends (...args: any[]) => any, P extends any[] = Parameters<F>, R = ReturnType<F>>(
  cb: (...args: P) => R
) {
  const cache = useLatestValue(cb);
  return React.useCallback((...args: P) => cache.current(...args), [cache]);
};

export default useEvent;
Repository: usememos/memos
File: plugin/telegram/chat.go (Go)

Code before:
package telegram

type Chat struct {
	// ID is a unique identifier for this chat
	ID int `json:"id"`
	// Title for supergroups, channels and group chats
	Title string `json:"title"`
	// Type of chat, can be either “private”, “group”, “supergroup” or “channel”
	Type string `json:"type"`
	// FirstName of the other party in a private chat
	FirstName string `json:"first_name"`
	// LastName of the other party in a private chat
	LastName string `json:"last_name"`
	// UserName for private chats, supergroups and channels if available
	UserName string `json:"username"`
}

// IsPrivate returns if the Chat is a private conversation.
func (c Chat) IsPrivate() bool {
	return c.Type == "private"
}

// IsGroup returns if the Chat is a group.
func (c Chat) IsGroup() bool {
	return c.Type == "group"
}

// IsSuperGroup returns if the Chat is a supergroup.
func (c Chat) IsSuperGroup() bool {
	return c.Type == "supergroup"
}

Review comment (suggestion):
Just add a enum type `ChatType` and some const for exists value, like the code in other packages.

Code after:
package telegram

type ChatType string

const (
	Private    = "private"
	Group      = "group"
	SuperGroup = "supergroup"
	Channel    = "channel"
)

type Chat struct {
	ID        int      `json:"id"`
	Title     string   `json:"title"`      // Title for supergroups, channels and group chats
	Type      ChatType `json:"type"`       // Type of chat, can be either “private”, “group”, “supergroup” or “channel”
	FirstName string   `json:"first_name"` // FirstName of the other party in a private chat
	LastName  string   `json:"last_name"`  // LastName of the other party in a private chat
	UserName  string   `json:"username"`   // UserName for private chats, supergroups and channels if available
}
Repository: usememos/memos
File: server/telegram.go (Go)

Code before:
		return bot.AnswerCallbackQuery(ctx, callbackQuery.ID, fmt.Sprintf("fail to EditMessage %s", err))
	}

	return bot.AnswerCallbackQuery(ctx, callbackQuery.ID, fmt.Sprintf("Success change Memo %d to %s", memoID, visibility))
}

func generateKeyboardForMemoID(id int) [][]telegram.InlineKeyboardButton {
	allVisibility := []store.Visibility{
		store.Public,
		store.Protected,
		store.Private,
	}

	buttons := make([]telegram.InlineKeyboardButton, 0, len(allVisibility))
	for _, v := range allVisibility {
		button := telegram.InlineKeyboardButton{
			Text:         v.String(),
			CallbackData: fmt.Sprintf("%s %d", v, id),
		}
		buttons = append(buttons, button)
	}

	return [][]telegram.InlineKeyboardButton{buttons}
}

func ConvertToMarkdown(text string, messageEntities []telegram.MessageEntity) string {
	insertions := make(map[int]string)

	for _, e := range messageEntities {
		var before, after string

		if e.IsBold() {
			before = "**"
			after = "**"
		} else if e.IsItalic() {
			before = "*"
			after = "*"
		} else if e.IsStrikethrough() {
			before = "~~"
			after = "~~"
		} else if e.IsCode() {
			before = "`"
			after = "`"
		} else if e.IsPre() {
			before = "```" + e.Language
			after = "```"
		} else if e.IsTextLink() {
			before = "["
			after = fmt.Sprintf(`](%s)`, e.URL)
		}


Review comment (suggestion):
If all Telegram message entity could convert or compatible with `Markdown`?

If this can be done, just add all entity type, else leave it unsupported is better than support with exceptions.

Code after:
	}

	buttons := make([]telegram.InlineKeyboardButton, 0, len(allVisibility))
	for _, v := range allVisibility {
		button := telegram.InlineKeyboardButton{
			Text:         v.String(),
			CallbackData: fmt.Sprintf("%s %d", v, id),
		}
		buttons = append(buttons, button)
	}

	return [][]telegram.InlineKeyboardButton{buttons}
}

func convertToMarkdown(text string, messageEntities []telegram.MessageEntity) string {
	insertions := make(map[int]string)

	for _, e := range messageEntities {
		var before, after string

		// this is supported by the current markdown
		switch e.Type {
		case telegram.Bold:
			before = "**"
			after = "**"
		case telegram.Italic:
			before = "*"
			after = "*"
		case telegram.Strikethrough:
			before = "~~"
			after = "~~"
		case telegram.Code:
			before = "`"
			after = "`"
		case telegram.Pre:
			before = "```" + e.Language
			after = "```"
		case telegram.TextLink:
			before = "["
			after = fmt.Sprintf(`](%s)`, e.URL)
		}

		if before != "" {
			insertions[e.Offset] += before
			insertions[e.Offset+e.Length] = after + insertions[e.Offset+e.Length]
		}
	}

	input := []rune(text)
	var output []rune
	utf16pos := 0
Repository: usememos/memos
File: web/src/components/MemosChat/ConversationTab.tsx (TypeScript)

Code before:
import { Conversation } from "@/store/zustand/conversation";
import Icon from "@/components/Icon";

interface ConversationTabProps {
  item: Conversation;
  selectedConversationId: string;
  setSelectedConversationId: (id: string) => void;
  closeConversation: (e: any) => void;
}
const ConversationTab = ({ item, selectedConversationId, setSelectedConversationId, closeConversation }: ConversationTabProps) => {
  return (
    <div
      className={`flex rounded-lg h-8 px-3 border dark:border-zinc-600 ${
        selectedConversationId === item.messageStorageId ? "bg-white dark:bg-zinc-700" : "bg-gray-200 dark:bg-zinc-800 opacity-60"
      }`}
      key={item.messageStorageId}
      onClick={() => {
        setSelectedConversationId(item.messageStorageId);
      }}
    >
      <div className="truncate m-auto">{item.name}</div>
      <Icon.X
        className="w-4 h-auto m-auto cursor-pointer"
        onClick={(e: any) => {
          closeConversation(e);
        }}
      />
    </div>
  );
};
export default ConversationTab;


Review comment (suggestion):
```suggestion

const ConversationTab = ({ item, selectedConversationId, setSelectedConversationId, closeConversation }: ConversationTabProps) => {
```

Code after:
import { Conversation } from "@/store/zustand/conversation";
import Icon from "@/components/Icon";

interface ConversationTabProps {
  item: Conversation;
  selectedConversationId: string;
  setSelectedConversationId: (id: string) => void;
  closeConversation: (e: any) => void;
}

const ConversationTab = ({ item, selectedConversationId, setSelectedConversationId, closeConversation }: ConversationTabProps) => {
  return (
    <div
      className={`flex rounded-lg h-8 px-3 border dark:border-zinc-600 ${
        selectedConversationId === item.messageStorageId ? "bg-white dark:bg-zinc-700" : "bg-gray-200 dark:bg-zinc-800 opacity-60"
      }`}
      key={item.messageStorageId}
      onClick={() => {
        setSelectedConversationId(item.messageStorageId);
      }}
    >
      <div className="truncate m-auto">{item.name}</div>
      <Icon.X
        className="w-4 h-auto m-auto cursor-pointer"
        onClick={(e: any) => {
          closeConversation(e);
        }}
      />
    </div>
  );
};

export default ConversationTab;
Repository: usememos/memos
File: web/src/components/MemosChat/ConversationTab.tsx (TypeScript)

Code before:
import { Conversation } from "@/store/zustand/conversation";
import Icon from "@/components/Icon";

interface ConversationTabProps {
  item: Conversation;
  selectedConversationId: string;
  setSelectedConversationId: (id: string) => void;
  closeConversation: (e: any) => void;
}
const ConversationTab = ({ item, selectedConversationId, setSelectedConversationId, closeConversation }: ConversationTabProps) => {
  return (
    <div
      className={`flex rounded-lg h-8 px-3 border dark:border-zinc-600 ${
        selectedConversationId === item.messageStorageId ? "bg-white dark:bg-zinc-700" : "bg-gray-200 dark:bg-zinc-800 opacity-60"
      }`}
      key={item.messageStorageId}
      onClick={() => {
        setSelectedConversationId(item.messageStorageId);
      }}
    >
      <div className="truncate m-auto">{item.name}</div>
      <Icon.X
        className="w-4 h-auto m-auto cursor-pointer"
        onClick={(e: any) => {
          closeConversation(e);
        }}
      />
    </div>
  );
};
export default ConversationTab;


Review comment (suggestion):
There should be a blank line.

```suggestion

export default ConversationTab;
```

Code after:
  closeConversation: (e: any) => void;
}

const ConversationTab = ({ item, selectedConversationId, setSelectedConversationId, closeConversation }: ConversationTabProps) => {
  return (
    <div
      className={`flex rounded-lg h-8 px-3 border dark:border-zinc-600 ${
        selectedConversationId === item.messageStorageId ? "bg-white dark:bg-zinc-700" : "bg-gray-200 dark:bg-zinc-800 opacity-60"
      }`}
      key={item.messageStorageId}
      onClick={() => {
        setSelectedConversationId(item.messageStorageId);
      }}
    >
      <div className="truncate m-auto">{item.name}</div>
      <Icon.X
        className="w-4 h-auto m-auto cursor-pointer"
        onClick={(e: any) => {
          closeConversation(e);
        }}
      />
    </div>
  );
};

export default ConversationTab;
Repository: usememos/memos
File: web/src/pages/Archived.tsx (TypeScript)

Code before:
import { useEffect, useState } from "react";
import { useTranslate } from "@/utils/i18n";
import toast from "react-hot-toast";
import { useFilterStore, useMemoStore } from "@/store/module";
import useLoading from "@/hooks/useLoading";
import ArchivedMemo from "@/components/ArchivedMemo";
import MobileHeader from "@/components/MobileHeader";
import Empty from "@/components/Empty";
import "@/less/archived.less";
import SearchBar from "@/components/SearchBar";
import MemoFilter from "@/components/MemoFilter";

const Archived = () => {
  const t = useTranslate();
  const memoStore = useMemoStore();
  const loadingState = useLoading();
  const [archivedMemos, setArchivedMemos] = useState<Memo[]>([]);
  const memos = memoStore.state.memos;
  const filterStore = useFilterStore();
  const filter = filterStore.state;
  const { text: textQuery } = filter;

  useEffect(() => {
    memoStore
      .fetchArchivedMemos()
      .then((result) => {
        const filteredMemos = textQuery ? result.filter((memo) => memo.content.toLowerCase().includes(textQuery.toLowerCase())) : result;
        setArchivedMemos(filteredMemos);
      })
      .catch((error) => {
        console.error(error);
        toast.error(error.response.data.message);
      })
      .finally(() => {
        loadingState.setFinish();
      });

Review comment (suggestion):
```suggestion
import Empty from "@/components/Empty";
import SearchBar from "@/components/SearchBar";
import MemoFilter from "@/components/MemoFilter";
import "@/less/archived.less";
```

Code after:
import { useEffect, useState } from "react";
import { useTranslate } from "@/utils/i18n";
import toast from "react-hot-toast";
import { useFilterStore, useMemoStore } from "@/store/module";
import useLoading from "@/hooks/useLoading";
import ArchivedMemo from "@/components/ArchivedMemo";
import MobileHeader from "@/components/MobileHeader";
import Empty from "@/components/Empty";
import SearchBar from "@/components/SearchBar";
import MemoFilter from "@/components/MemoFilter";
import "@/less/archived.less";

const Archived = () => {
  const t = useTranslate();
  const memoStore = useMemoStore();
  const loadingState = useLoading();
  const [archivedMemos, setArchivedMemos] = useState<Memo[]>([]);
  const memos = memoStore.state.memos;
  const filterStore = useFilterStore();
  const filter = filterStore.state;
  const { text: textQuery } = filter;

  useEffect(() => {
    memoStore
      .fetchArchivedMemos()
      .then((result) => {
        const filteredMemos = textQuery ? result.filter((memo) => memo.content.toLowerCase().includes(textQuery.toLowerCase())) : result;
        setArchivedMemos(filteredMemos);
      })
      .catch((error) => {
        console.error(error);
        toast.error(error.response.data.message);
      })
      .finally(() => {
        loadingState.setFinish();
      });
Repository: usememos/memos
File: proto/api/v2/memo_service.proto (Protocol Buffers)

Code before:
  string content = 6;

  Visibility visibility = 7;

  bool pinned = 8;
}

message CreateMemoRequest {
  string content = 1;

  Visibility visibility = 2;
}

message CreateMemoResponse {
  Memo memo = 1;
}

message ListMemosRequest {
  int32 page = 1;

  int32 page_size = 2;

  // Filter is used to filter memos returned in the list.
  string filter = 3;

  int32 creator_id = 4;
}

message ListMemosResponse {
  repeated Memo memos = 1;
}

message GetMemoRequest {
  int32 id = 1;
}

message GetMemoResponse {
  Memo memo = 1;
}

message CreateMemoCommentRequest {
  // id is the memo id to create comment for.
  int32 id = 1;

  CreateMemoRequest create = 2;
}

message CreateMemoCommentResponse {
  Memo memo = 1;
}


Review comment (suggestion):
```suggestion
  optional int32 creator_id = 4;
```

Code after:
  string content = 6;

  Visibility visibility = 7;

  bool pinned = 8;
}

message CreateMemoRequest {
  string content = 1;

  Visibility visibility = 2;
}

message CreateMemoResponse {
  Memo memo = 1;
}

message ListMemosRequest {
  int32 page = 1;

  int32 page_size = 2;

  // Filter is used to filter memos returned in the list.
  string filter = 3;

  optional int32 creator_id = 4;
}

message ListMemosResponse {
  repeated Memo memos = 1;
}

message GetMemoRequest {
  int32 id = 1;
}

message GetMemoResponse {
  Memo memo = 1;
}

message CreateMemoCommentRequest {
  // id is the memo id to create comment for.
  int32 id = 1;

  CreateMemoRequest create = 2;
}

message CreateMemoCommentResponse {
  Memo memo = 1;
}
Repository: usememos/memos
File: web/src/hooks/useDateTime.ts (TypeScript)

Code before:
import { useState } from "react";

const useDateTime = (initalState?: Date) => {
  const [dateTime, _setDateTime] = useState<Date | undefined>(initalState && new Date(initalState));

  return {
    setDateTime: (dateTimeString: string) => _setDateTime(new Date(dateTimeString)),
    displayDateTime: dateTime && dateTime.toLocaleString(),
    datePickerDateTime: dateTime && new Date(dateTime.getTime() - dateTime.getTimezoneOffset() * 60000).toISOString().split(".")[0],
  };
};

export default useDateTime;


Review comment (suggestion):
```suggestion
  const [dateTime, setDateTimeInternal] = useState<Date | undefined>(initalState && new Date(initalState));
```

Code after:
import { useState } from "react";

const useDateTime = (initalState?: Date) => {
  const [dateTime, setDateTimeInternal] = useState<Date | undefined>(initalState && new Date(initalState));

  return {
    setDateTime: (dateTimeString: string) => setDateTimeInternal(new Date(dateTimeString)),
    displayDateTime: dateTime && dateTime.toLocaleString(),
    datePickerDateTime: dateTime && new Date(dateTime.getTime() - dateTime.getTimezoneOffset() * 60000).toISOString().split(".")[0],
  };
};

export default useDateTime;