diff --git a/.gitignore b/.gitignore index dceb66d..15e8983 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,7 @@ yarn-error.log* next-env.d.ts # video -*.mp4 \ No newline at end of file +*.mp4 + +# template +/template \ No newline at end of file diff --git a/components/i18n/config/chat.ts b/components/i18n/config/chat.ts index ffd7445..f0eae99 100644 --- a/components/i18n/config/chat.ts +++ b/components/i18n/config/chat.ts @@ -2,122 +2,152 @@ const chat = { title: { 'zh-CN': '聊天编辑', 'zh-TW': '聊天編輯', + 'en-US': 'Chatting Edit', }, student: { 'zh-CN': '学生', 'zh-TW': '學生', + 'en-US': 'Students', }, allStudents: { 'zh-CN': '所有学生', 'zh-TW': '所有學生', + 'en-US': 'All Studnets', }, selectStudents: { 'zh-CN': '请选择学生。', 'zh-TW': '請選擇學生。', + 'en-US': 'Please select a student.', }, '+': { 'zh-CN': '添加', 'zh-TW': '添加', + 'en-US': 'ADD ', }, '-': { 'zh-CN': '去除', 'zh-TW': '去除', + 'en-US': 'DELETE ', }, idPromptTitle: { 'zh-CN': '输入ID', 'zh-TW': '輸入ID', + 'en-US': 'Input the ID', }, idPromptInfo: { 'zh-CN': '请输入需要在列表$0的学生的ID', 'zh-TW': '請輸入需要在列表$0的學生的ID', + 'en-US': 'Please input the ID of student that need to $0', }, error: { 'zh-CN': '错误', 'zh-TW': '錯誤', + 'en-US': 'Error', }, sameStudent: { 'zh-CN': '已有此学生', 'zh-TW': '已有此學生', + 'en-US': 'Repeat student', }, withoutStudent: { 'zh-CN': '列表中无此学生', 'zh-TW': '列表中無此學生', + 'en-US': 'The list don\'t have this student', }, sendMsg: { 'zh-CN': '发送', 'zh-TW': '發送', + 'en-US': 'Send', }, sendMsgStudent: { 'zh-CN': '发送学生消息', 'zh-TW': '發送學生消息', + 'en-US': 'Send Message of student', }, sendMsgSensei: { 'zh-CN': '发送老师消息', 'zh-TW': '發送老師消息', + 'en-US': 'Send Message of sensei', }, sendMsgInfo: { 'zh-CN': '请输入需要发送$0$1的$2', 'zh-TW': '請輸入需要發送$0$1的$2', + 'en-US': 'Please input the $2 message $0 $1', }, sendMsgStudentInfo: { 'zh-CN': '的', 'zh-TW': '的', + 'en-US': 'from', }, sendMsgSenseiInfo: { 'zh-CN': '给', 'zh-TW': '給', + 'en-US': 'to', }, text: { 'zh-CN': '消息', 'zh-TW': '消息', + 'en-US': 'text', }, img: { 'zh-CN': '图片链接', 'zh-TW': '圖片鏈接', + 'en-US': 'link of image', }, undefinedStudent: { 'zh-CN': '$0的学生ID不存在', 'zh-TW': '$0的學生ID不存在', + 'en-US': 'The $0 of student\'s ID is undefined', }, up: { 'zh-CN': '上传', 'zh-TW': '上傳', + 'en-US': 'Upload ', }, down: { 'zh-CN': '下载', 'zh-TW': '下載', + 'en-US': 'Download ', }, jsonFile: { 'zh-CN': 'JSON文件', 'zh-TW': 'JSON文件', + 'en-US': 'JSON File', }, copy: { 'zh-CN': '复制', 'zh-TW': '複製', + 'en-US': 'Copy', }, delete: { 'zh-CN': '删除', 'zh-TW': '刪除', + 'en-US': 'Delete', }, edit: { 'zh-CN': '编辑', 'zh-TW': '編輯', + 'en-US': 'Edit', }, idConfirmTitle: { 'zh-CN': '确定删除', 'zh-TW': '確定刪除', + 'en-US': 'Confirm to delete', }, idConfirmInfo: { 'zh-CN': '确定删除与$0的聊天吗', 'zh-TW': '確定刪除於$0的聊天嗎', + 'en-US': 'Are you sure to delete the chatting with $0?', }, confirm: { 'zh-CN': '确定', 'zh-TW': '確定', + 'en-US': 'Confirm', }, cancel: { 'zh-CN': '取消', 'zh-TW': '取消', + 'en-US': 'Cancel', }, } export default chat; \ No newline at end of file diff --git a/components/i18n/config/info.ts b/components/i18n/config/info.ts index 99236e0..6a5c700 100644 --- a/components/i18n/config/info.ts +++ b/components/i18n/config/info.ts @@ -2,18 +2,22 @@ const info = { title: { 'zh-CN': '学生信息', 'zh-TW': '學生信息', + 'en-US': 'Students Info' }, student: { 'zh-CN': '学生', 'zh-TW': '學生', + 'en-US': 'Students', }, allStudents: { 'zh-CN': '所有学生', 'zh-TW': '所有學生', + 'en-US': 'All Studnets', }, selectStudents: { 'zh-CN': '请选择学生。', 'zh-TW': '請選擇學生。', + 'en-US': 'Please select a student.', }, } export default info; \ No newline at end of file diff --git a/components/i18n/config/main.ts b/components/i18n/config/main.ts index 3e975da..6f18722 100644 --- a/components/i18n/config/main.ts +++ b/components/i18n/config/main.ts @@ -2,38 +2,127 @@ const main = { setting: { 'zh-CN': '设置', 'zh-TW': '設定', + 'en-US': 'Settings', + }, + confirm: { + 'zh-CN': '确定', + 'zh-TW': '確定', + 'en-US': 'Confirm', + }, + reload: { + 'zh-CN': '重新加载', + 'zh-TW': '重新載入', + 'en-US': 'Reload', + }, + cancel: { + 'zh-CN': '取消', + 'zh-TW': '取消', + 'en-US': 'Cancel', + }, + requiredReload: { + 'zh-CN': '$0\n*重新加载后生效', + 'zh-TW': '$0\n*重新載入後生效', + 'en-US': '$0\n*Get to work after reload', }, setLocale: { 'zh-CN': '选择语言', 'zh-TW': '選取語言', + 'en-US': 'Select language', + }, + setLocaleTitle: { + 'zh-CN': '设置全局语言', + 'zh-TW': '設定全局語言', + 'en-US': 'Set global language', }, locales: { 'zh-CN': '中文(简体)', 'zh-TW': '中文(繁體)', + 'en-US': 'English (US)', }, setAnimation: { 'zh-CN': '启动动画模式', 'zh-TW': '啟動動畫模式', + 'en-US': 'Mod of starting animation', + }, + setAnimationTitle: { + 'zh-CN': '加载页面后的动画模式', + 'zh-TW': '載入頁面後的動畫模式', + 'en-US': 'Starting animation after loading the page', }, animationTnone: { 'zh-CN': '从不', 'zh-TW': '從不', + 'en-US': 'never', }, animationTfirst: { 'zh-CN': '首次', 'zh-TW': '首次', + 'en-US': 'first', }, animationTevery: { 'zh-CN': '每次', 'zh-TW': '每次', + 'en-US': 'every', }, - done: { - 'zh-CN': '确定', - 'zh-TW': '確定', + setFontWeight: { + 'zh-CN': '字重', + 'zh-TW': '字重', + 'en-US': 'Font weight', + }, + fontTthin: { + 'zh-CN': '特细', + 'zh-TW': '特細', + 'en-US': 'Thin', + }, + fontTextralight: { + 'zh-CN': '非常细', + 'zh-TW': '非常細', + 'en-US': 'Extra Light', + }, + fontTlight: { + 'zh-CN': '细', + 'zh-TW': '細', + 'en-US': 'Light', + }, + fontTnormal: { + 'zh-CN': '标准', + 'zh-TW': '標準', + 'en-US': 'Normal', + }, + fontTregular: { + 'zh-CN': '常规', + 'zh-TW': '常規', + 'en-US': 'Regular', + }, + fontTmedium: { + 'zh-CN': '中等', + 'zh-TW': '中等', + 'en-US': 'Medium', + }, + fontTdemibold: { + 'zh-CN': '稍粗', + 'zh-TW': '稍粗', + 'en-US': 'Demi Bold', + }, + fontTsemibold: { + 'zh-CN': '半粗', + 'zh-TW': '半粗', + 'en-US': 'Semi Bold', + }, + fontTbold: { + 'zh-CN': '粗', + 'zh-TW': '粗', + 'en-US': 'Bold', + }, + fontTheavy: { + 'zh-CN': '特粗', + 'zh-TW': '特粗', + 'en-US': 'Heavy', }, setFileName: { 'zh-CN': '文件名称', 'zh-TW': '文件名稱', + 'en-US': 'File Name', }, } export default main; \ No newline at end of file diff --git a/components/i18n/index.ts b/components/i18n/index.ts index 8ad5386..7e62be5 100644 --- a/components/i18n/index.ts +++ b/components/i18n/index.ts @@ -1,9 +1,9 @@ import { useEffect, useState } from "react"; import { getSettingFun } from "../setting"; -export type Locales = 'zh-CN' | 'zh-TW'; +export type Locales = 'zh-CN' | 'zh-TW' | 'en-US'; -export type i18nContents = Record>; +export type i18nContents = Record>; export function fillBlank(i18n: string, ...fills: (string | undefined)[]): string { let text = i18n; @@ -13,13 +13,20 @@ export function fillBlank(i18n: string, ...fills: (string | undefined)[]): strin export function useLocale(i18n: T) { const [lo, setLo] = useState(''); + const { getSetting } = getSettingFun(); useEffect(() => setLo(getSetting().locale || window.navigator.language), []); + function locale(key: K, loc?: string) { - return (i18n as Record>)[key][loc || lo]; + const i18nAs = i18n as Record>; + const localeText = (i18nAs)[key][loc || lo]; + return localeText || (i18nAs)[key]['zh-CN']; } function localeType(key: Type, loc?: string) { - return (i18n as Record>)[key][loc || lo]; + const i18nAs = i18n as Record>; + const localeText = (i18nAs)[key][loc || lo]; + return localeText || (i18nAs)[key]['zh-CN']; } + return { lo, locale, localeType }; } \ No newline at end of file diff --git a/components/main.tsx b/components/main.tsx index a138e97..afb5dbd 100644 --- a/components/main.tsx +++ b/components/main.tsx @@ -9,9 +9,10 @@ import styles from '@/styles/MainNode.module.scss'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import Window, { AllWindow, AllWindows, getWindowFun } from './window'; -import { Locales, useLocale } from './i18n'; +import { Locales, fillBlank, useLocale } from './i18n'; import main from './i18n/config/main'; import { Settings, SettingArg } from '@/components/setting'; +import setFontWeight, { fontWeightNames } from './setFontWeight'; function MomoTalkIcon() { return ( @@ -75,8 +76,14 @@ export default function MainNode({ children, onBodyClick }: { }) { const { lo, locale, localeType } = useLocale(main); - const { setSetting, windowOnload } = getSettingFun(); - useEffect(windowOnload, []); + const { getSetting, setSetting, windowOnload } = getSettingFun({ + locale: 'zh-CN', + animation: 'first', + }); + useEffect(() => { + windowOnload(); + setFontWeight(getSetting().fontWeight); + }, []); const { allWindow, addNewWindow, openWindow, closeWindow } = getWindowFun(useState({ all: [], @@ -86,7 +93,6 @@ export default function MainNode({ children, onBodyClick }: { const Setting = new Window('Setting'); useEffect(() => { - const animations = ['none', 'first', 'every']; addNewWindow(Setting, (zIndex, id, display, { setting, setSetting }, all) => ( (), + getValue: v => locale('locales', v), }, animation: { type: 'option', label: locale('setAnimation'), - values: animations, + title: fillBlank(locale('requiredReload'), locale('setAnimationTitle')), + values: ['none', 'first', 'every'], defaultValue: setting.animation, - getValue: v => (), + getValue: v => localeType('animationT' + v), + }, + fontWeight: { + type: 'option', + label: locale('setFontWeight'), + values: fontWeightNames, + defaultValue: setting.fontWeight, + getValue: v => localeType('fontT' + v), }, fileName: { page: '/chat', type: 'input', label: locale('setFileName'), defaultValue: setting.fileName, - } + }, }} - done={locale('done')} + confirm={locale('confirm')} onSubmit={data => { + setFontWeight(data.fontWeight as Settings['fontWeight']); setSetting(data as Settings); close(); }} + otherButtons={<> + + + } /> )} zIndex={zIndex} @@ -142,7 +162,7 @@ export default function MainNode({ children, onBodyClick }: { openWindow(allWindow.all, Setting, { - setting: JSON.parse(window.localStorage.set), + setting: getSetting(), setSetting, })} /> diff --git a/components/setFontWeight.ts b/components/setFontWeight.ts new file mode 100644 index 0000000..dfd7d4c --- /dev/null +++ b/components/setFontWeight.ts @@ -0,0 +1,32 @@ +import { Settings } from "./setting"; + +export const fontWeightNames = [ + 'thin', + 'extralight', + 'light', + 'normal', + 'regular', + 'medium', + 'demibold', + 'semibold', + 'bold', + 'heavy' +]; + +export default function setFontWeight(fontWeight: Settings['fontWeight']) { + const MiSansFontWeightList: Record['fontWeight'], number> = { + thin: 100, + extralight: 200, + light: 300, + normal: 400, + regular: 400, + medium: 500, + demibold: 600, + semibold: 600, + bold: 700, + heavy: 900, + }; + const sheet = new CSSStyleSheet(); + sheet.replaceSync(`* {font-weight: ${MiSansFontWeightList[fontWeight || 'normal']}}`); + document.adoptedStyleSheets = [sheet]; +} \ No newline at end of file diff --git a/components/setting.tsx b/components/setting.tsx index 76e7cb5..49db408 100644 --- a/components/setting.tsx +++ b/components/setting.tsx @@ -1,23 +1,23 @@ import styles from '@/styles/MainNode.module.scss'; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import Repeat from './repeat'; import { useForm } from 'react-hook-form'; import { SetStateFun } from './extraReact'; -import { getClassState } from './extraReact'; import { useRouter } from 'next/router'; interface SettingOption { type: string; label: string; page?: string; + title?: string; } interface OptionSO extends SettingOption { type: 'option'; values?: T[]; defaultValue?: T; - getValue: (value: T, index: number, array: T[]) => React.ReactNode; + getValue: (value: T, index: number, array: T[]) => string; } interface InputSO extends SettingOption { @@ -29,11 +29,12 @@ type OptionTypes = OptionSO | InputSO; interface SettingFormProps { option: Record; - done: string; + confirm: string; onSubmit: (data: Record) => any; + otherButtons?: React.ReactElement; } -export function SettingForm({ option, done, onSubmit }: SettingFormProps) { +export function SettingForm({ option, confirm, onSubmit, otherButtons }: SettingFormProps) { const { register, handleSubmit } = useForm(); const { pathname } = useRouter(); @@ -54,14 +55,14 @@ export function SettingForm({ option, done, onSubmit }: Settin const o = optionArray[i]; if (o.page !== undefined && o.page !== pathname) return; return ( -