반응형
참고
- 깃허브 RESTful API 한글 깨짐 현상 해결하기
깃허브 RESTful API 한글 깨짐 현상 해결하기를 참고해서 아래 코드를 실행해보자.
import React, { useState } from "react";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import { TextField } from "@mui/material";
import { Textarea } from "@mui/joy";
import { Octokit } from "@octokit/rest";
let myKey = "...";
const App = () => {
const [repo, setRepo] = useState("auto-test");
const [path, setPath] = useState("README.md");
const [contents, setContents] = useState("");
const getSHA = async (octokit) => {
const result = await octokit.request(
`GET /repos/bloodstrawberry/${repo}/contents/${path}`,
{
owner: "bloodstrawberry",
repo: `${repo}`,
path: `${path}`,
}
);
return result.data.sha;
};
const fileWrite = async () => {
const octokit = new Octokit({
auth: myKey,
});
const currentSHA = await getSHA(octokit);
const result = await octokit.request(
`PUT /repos/bloodstrawberry/${repo}/contents/${path}`,
{
owner: "bloodstrawberry",
repo: `${repo}`,
path: `${path}`,
message: "commit message!",
sha: currentSHA,
committer: {
name: "bloodstrawberry",
email: "bloodstrawberry@github.com",
},
// content: `${btoa(`${contents}`)}`,
content: `${btoa(unescape(encodeURIComponent(`${contents}`)))}`,
headers: {
"X-GitHub-Api-Version": "2022-11-28",
},
}
);
console.log(result.status);
};
const fileRead = async () => {
const octokit = new Octokit({
auth: myKey,
});
const result = await octokit.request(
`GET /repos/bloodstrawberry/${repo}/contents/${path}`,
{
owner: "bloodstrawberry",
repo: `${repo}`,
path: `${path}`,
}
);
// setContents(atob(result.data.content));
setContents(decodeURIComponent(escape(window.atob(result.data.content))));
};
return (
<div>
<h1>깃허브 파일 편집기</h1>
<Stack sx={{ m: 5 }} spacing={2} direction="row">
<Button variant="outlined" color="primary" onClick={fileRead}>
불러오기
</Button>
<Button variant="outlined" color="secondary" onClick={fileWrite}>
저장하기
</Button>
</Stack>
<Stack sx={{ m: 5 }} spacing={2} direction="row">
<TextField
id="outlined-required"
label="repository"
value={repo}
onChange={(e) => setRepo(e.target.value)}
/>
<TextField
id="outlined-required"
label="filePath"
value={path}
onChange={(e) => setPath(e.target.value)}
/>
</Stack>
<Stack sx={{ m: 5 }}>
<Textarea
name="Primary"
placeholder="Type in here…"
variant="outlined"
color="primary"
value={contents}
onChange={(e) => setContents(e.target.value)}
/>
</Stack>
</div>
);
};
export default App;
깃허브에는 내용이 즉시 바뀌지만, 다시 불러오기를 할 경우 이전 정보가 갱신되는 것을 알 수 있다.
이 현상은 깃허브 내부 정책에 의해 발생하기 때문에 클라이언트가 수정할 수 없다.
여기서는 IndexedDB를 이용해서 최신 정보를 저장해보자.
만들어둔 IndexedDB 라이브러리를 import 한다.
import * as idblib from "./indexeddblibrary.js";
fileWrite에서는 PUT가 성공한 경우, 최신 정보를 DB에 저장한다.
const fileWrite = async () => {
let date = new Date();
...
if (result.status === 200) {
let tempData = {
id: "temp",
contents,
date,
};
idblib.addDataToIndexedDB(tempData);
}
};
fileRead의 경우 불러온 정보의 갱신 날짜(headers의 last-modified)와 비교하여,
수정된 날짜가 DB의 날짜보다 작은 경우, DB의 정보를 보여주도록 한다.
초 단위까지 비교하면 항상 tempTime이 큰 경우가 발생할 수 있으므로, 100ms * 60s = 6000 만큼 나눠서 비교한다.
const fileRead = async () => {
...
let content = decodeURIComponent(escape(window.atob(result.data.content)));
let modifiedDate = new Date(result.headers["last-modified"]);
let mdTime = parseInt(modifiedDate.getTime() / 6000);
let tempData = await idblib.getDataFromIndexedDB("temp");
if (tempData === undefined) {
setContents(content);
return;
}
let tempTime = parseInt(tempData.date.getTime() / 6000);
console.log({ mdTime, tempTime });
if (mdTime < tempTime) {
console.log(tempData);
content = tempData.contents;
}
// setContents(atob(result.data.content));
setContents(content);
};
이제 최신 정보를 불러오지 못한다면 IndexedDB가 내용을 대체한다.
전체 코드는 다음과 같다.
import React, { useState } from "react";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import { TextField } from "@mui/material";
import { Textarea } from "@mui/joy";
import { Octokit } from "@octokit/rest";
import * as idblib from "./indexeddblibrary.js";
let myKey = "...";
const App = () => {
const [repo, setRepo] = useState("auto-test");
const [path, setPath] = useState("README.md");
const [contents, setContents] = useState("");
const getSHA = async (octokit) => {
const result = await octokit.request(
`GET /repos/bloodstrawberry/${repo}/contents/${path}`,
{
owner: "bloodstrawberry",
repo: `${repo}`,
path: `${path}`,
}
);
return result.data.sha;
};
const fileWrite = async () => {
const octokit = new Octokit({
auth: myKey,
});
const currentSHA = await getSHA(octokit);
let date = new Date();
const result = await octokit.request(
`PUT /repos/bloodstrawberry/${repo}/contents/${path}`,
{
owner: "bloodstrawberry",
repo: `${repo}`,
path: `${path}`,
message: "commit message!",
sha: currentSHA,
committer: {
name: "bloodstrawberry",
email: "bloodstrawberry@github.com",
},
// content: `${btoa(`${contents}`)}`,
content: `${btoa(unescape(encodeURIComponent(`${contents}`)))}`,
headers: {
"X-GitHub-Api-Version": "2022-11-28",
},
}
);
console.log(result);
if (result.status === 200) {
let tempData = {
id: "temp",
contents,
date,
};
idblib.addDataToIndexedDB(tempData);
}
};
const fileRead = async () => {
const octokit = new Octokit({
auth: myKey,
});
const result = await octokit.request(
`GET /repos/bloodstrawberry/${repo}/contents/${path}`,
{
owner: "bloodstrawberry",
repo: `${repo}`,
path: `${path}`,
}
);
let content = decodeURIComponent(escape(window.atob(result.data.content)));
let modifiedDate = new Date(result.headers["last-modified"]);
let mdTime = parseInt(modifiedDate.getTime() / 6000);
let tempData = await idblib.getDataFromIndexedDB("temp");
if (tempData === undefined) {
setContents(content);
return;
}
let tempTime = parseInt(tempData.date.getTime() / 6000);
console.log({ mdTime, tempTime });
if (mdTime < tempTime) {
console.log(tempData);
content = tempData.contents;
}
// setContents(atob(result.data.content));
setContents(content);
};
return (
<div>
<h1>깃허브 파일 편집기</h1>
<Stack sx={{ m: 5 }} spacing={2} direction="row">
<Button variant="outlined" color="primary" onClick={fileRead}>
불러오기
</Button>
<Button variant="outlined" color="secondary" onClick={fileWrite}>
저장하기
</Button>
</Stack>
<Stack sx={{ m: 5 }} spacing={2} direction="row">
<TextField
id="outlined-required"
label="repository"
value={repo}
onChange={(e) => setRepo(e.target.value)}
/>
<TextField
id="outlined-required"
label="filePath"
value={path}
onChange={(e) => setPath(e.target.value)}
/>
</Stack>
<Stack sx={{ m: 5 }}>
<Textarea
name="Primary"
placeholder="Type in here…"
variant="outlined"
color="primary"
value={contents}
onChange={(e) => setContents(e.target.value)}
/>
</Stack>
</div>
);
};
export default App;
반응형
'개발 > React' 카테고리의 다른 글
리액트 - Toast UI 에디터 글자색 변경 플러그인 추가하기 (Add Color Syntax Plugin Toast UI Editor) (0) | 2023.07.30 |
---|---|
리액트 - Toast UI로 에디터 만들기 (React Editor with Toast Editor 3.0) (0) | 2023.07.30 |
리액트 - Indexed DB로 로컬에 데이터 저장하기 (How to use Indexed DB in React) (0) | 2023.07.22 |
리액트 - 깃허브 마크다운 스타일 적용하기 (Github Markdown Style) (0) | 2023.07.12 |
React Material - Mui Table 세로 줄 변경하기 (Enable Column Ordering) (0) | 2023.07.12 |
댓글