feat: add color theme selector

This commit is contained in:
steven 2023-09-05 23:59:24 +08:00
parent b50e809125
commit 5e6190b181
2 changed files with 73 additions and 1 deletions

View File

@ -51,6 +51,16 @@ func (s *UserSettingService) UpdateUserSetting(ctx context.Context, request *api
}); err != nil { }); err != nil {
return nil, status.Errorf(codes.Internal, "failed to update user setting: %v", err) return nil, status.Errorf(codes.Internal, "failed to update user setting: %v", err)
} }
} else if path == "color_theme" {
if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{
UserId: userID,
Key: storepb.UserSettingKey_USER_SETTING_COLOR_THEME,
Value: &storepb.UserSetting_ColorTheme{
ColorTheme: convertUserSettingColorThemeToStore(request.UserSetting.ColorTheme),
},
}); err != nil {
return nil, status.Errorf(codes.Internal, "failed to update user setting: %v", err)
}
} else { } else {
return nil, status.Errorf(codes.InvalidArgument, "invalid path: %s", path) return nil, status.Errorf(codes.InvalidArgument, "invalid path: %s", path)
} }
@ -80,6 +90,8 @@ func getUserSetting(ctx context.Context, s *store.Store, userID int32) (*apiv2pb
for _, setting := range userSettings { for _, setting := range userSettings {
if setting.Key == storepb.UserSettingKey_USER_SETTING_LOCALE { if setting.Key == storepb.UserSettingKey_USER_SETTING_LOCALE {
userSetting.Locale = convertUserSettingLocaleFromStore(setting.GetLocale()) userSetting.Locale = convertUserSettingLocaleFromStore(setting.GetLocale())
} else if setting.Key == storepb.UserSettingKey_USER_SETTING_COLOR_THEME {
userSetting.ColorTheme = convertUserSettingColorThemeFromStore(setting.GetColorTheme())
} }
} }
return userSetting, nil return userSetting, nil
@ -106,3 +118,25 @@ func convertUserSettingLocaleFromStore(locale storepb.LocaleUserSetting) apiv2pb
return apiv2pb.UserSetting_LOCALE_UNSPECIFIED return apiv2pb.UserSetting_LOCALE_UNSPECIFIED
} }
} }
func convertUserSettingColorThemeToStore(colorTheme apiv2pb.UserSetting_ColorTheme) storepb.ColorThemeUserSetting {
switch colorTheme {
case apiv2pb.UserSetting_COLOR_THEME_LIGHT:
return storepb.ColorThemeUserSetting_COLOR_THEME_USER_SETTING_LIGHT
case apiv2pb.UserSetting_COLOR_THEME_DARK:
return storepb.ColorThemeUserSetting_COLOR_THEME_USER_SETTING_DARK
default:
return storepb.ColorThemeUserSetting_COLOR_THEME_USER_SETTING_UNSPECIFIED
}
}
func convertUserSettingColorThemeFromStore(colorTheme storepb.ColorThemeUserSetting) apiv2pb.UserSetting_ColorTheme {
switch colorTheme {
case storepb.ColorThemeUserSetting_COLOR_THEME_USER_SETTING_LIGHT:
return apiv2pb.UserSetting_COLOR_THEME_LIGHT
case storepb.ColorThemeUserSetting_COLOR_THEME_USER_SETTING_DARK:
return apiv2pb.UserSetting_COLOR_THEME_DARK
default:
return apiv2pb.UserSetting_COLOR_THEME_UNSPECIFIED
}
}

View File

@ -1,6 +1,6 @@
import { Option, Select } from "@mui/joy"; import { Option, Select } from "@mui/joy";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { UserSetting, UserSetting_Locale } from "@/types/proto/api/v2/user_setting_service_pb"; import { UserSetting, UserSetting_ColorTheme, UserSetting_Locale } from "@/types/proto/api/v2/user_setting_service_pb";
import useUserStore from "../../stores/v1/user"; import useUserStore from "../../stores/v1/user";
const PreferenceSection: React.FC = () => { const PreferenceSection: React.FC = () => {
@ -8,6 +8,7 @@ const PreferenceSection: React.FC = () => {
const userStore = useUserStore(); const userStore = useUserStore();
const userSetting = userStore.getCurrentUserSetting(); const userSetting = userStore.getCurrentUserSetting();
const language = userSetting.locale || UserSetting_Locale.EN; const language = userSetting.locale || UserSetting_Locale.EN;
const colorTheme = userSetting.colorTheme;
const languageOptions = [ const languageOptions = [
{ {
@ -20,6 +21,21 @@ const PreferenceSection: React.FC = () => {
}, },
]; ];
const colorThemeOptions = [
{
value: "COLOR_THEME_UNSPECIFIED",
label: "Auto",
},
{
value: "COLOR_THEME_LIGHT",
label: "Light",
},
{
value: "COLOR_THEME_DARK",
label: "Dark",
},
];
const handleSelectLanguage = async (locale: UserSetting_Locale) => { const handleSelectLanguage = async (locale: UserSetting_Locale) => {
if (!locale) { if (!locale) {
return; return;
@ -34,6 +50,16 @@ const PreferenceSection: React.FC = () => {
); );
}; };
const handleSelectColorTheme = async (colorTheme: UserSetting_ColorTheme) => {
await userStore.updateUserSetting(
{
...userSetting,
colorTheme: colorTheme,
} as UserSetting,
["color_theme"]
);
};
return ( return (
<> <>
<div className="w-full flex flex-col justify-start items-start gap-y-2"> <div className="w-full flex flex-col justify-start items-start gap-y-2">
@ -50,6 +76,18 @@ const PreferenceSection: React.FC = () => {
})} })}
</Select> </Select>
</div> </div>
<div className="w-full flex flex-row justify-between items-center">
<span>Color Theme</span>
<Select defaultValue={colorTheme} onChange={(_, value) => handleSelectColorTheme(value as UserSetting_ColorTheme)}>
{colorThemeOptions.map((option) => {
return (
<Option key={option.value} value={option.value}>
{option.label}
</Option>
);
})}
</Select>
</div>
</div> </div>
</> </>
); );