Skip to content

Commit

Permalink
Merge pull request #760 from taboowiths/feat/#752
Browse files Browse the repository at this point in the history
[view] Theme Selector 테마 전역 저장 및 코드 리팩토링
  • Loading branch information
taboowiths authored Oct 10, 2024
2 parents 615f458 + 7bd6aa5 commit 8f28b4e
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 79 deletions.
11 changes: 7 additions & 4 deletions packages/view/public/index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
<script>
window.isProduction = false;
window.primaryColor = '#ffbbff';
window.isProduction = false;
window.theme = "githru";
</script>
<title>Githru</title>
</head>
Expand Down
93 changes: 54 additions & 39 deletions packages/view/src/components/ThemeSelector/ThemeSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import "./ThemeSelector.scss";
import AutoAwesomeIcon from "@mui/icons-material/AutoAwesome";
import CloseIcon from "@mui/icons-material/Close";

const themes = [
import { setCustomTheme } from "services";

type ThemeInfo = {
title: string;
value: string;
colors: {
primary: string;
secondary: string;
tertiary: string;
};
};

type ThemeIconsProps = ThemeInfo & {
onClick: () => void;
};

const themeInfo: ThemeInfo[] = [
{
title: "Githru",
value: "githru",
Expand Down Expand Up @@ -52,83 +68,82 @@ const themes = [
},
];

type ThemeIconsProps = {
title: string;
value: string;
colors: {
primary: string;
secondary: string;
tertiary: string;
};
onClick: () => void;
};

const ThemeIcons = ({ title, value, colors, onClick }: ThemeIconsProps) => {
const [isSelected, setIsSelected] = useState<string>("");
const [selectedItem, setSelectedItem] = useState<string>("");

useEffect(() => {
const selectedTheme = document.documentElement.getAttribute("custom-type");
if (selectedTheme) setIsSelected(selectedTheme);
if (selectedTheme) setSelectedItem(selectedTheme);
}, []);

return (
<div
className={`theme-icon${isSelected === value ? "--selected" : ""}`}
className={`theme-icon${selectedItem === value ? "--selected" : ""}`}
onClick={onClick}
role="presentation"
>
<div className="theme-icon__container">
<div
className="theme-icon__color"
style={{ backgroundColor: colors.primary }}
/>
<div
className="theme-icon__color"
style={{ backgroundColor: colors.secondary }}
/>
<div
className="theme-icon__color"
style={{ backgroundColor: colors.tertiary }}
/>
{Object.values(colors).map((color, index) => (
<div
key={Number(index)}
className="theme-icon__color"
style={{ backgroundColor: color }}
/>
))}
</div>
<p className="theme-icon__title">{title}</p>
</div>
);
};

const ThemeSelector = () => {
const [open, setOpen] = useState<boolean>(false);
const [isOpen, setIsOpen] = useState<boolean>(false);
const themeSelectorRef = useRef<HTMLDivElement>(null);

const handleTheme = (value: string) => {
setCustomTheme(value);
document.documentElement.setAttribute("custom-type", value);
};

useEffect(() => {
document.documentElement.setAttribute("custom-type", "githru");
const handleClickOutside = (event: MouseEvent) => {
if (themeSelectorRef.current && !themeSelectorRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);

useEffect(() => {
document.documentElement.setAttribute("custom-type", window.theme);
}, []);

return (
<div className="theme-selector">
<AutoAwesomeIcon onClick={() => setOpen(true)} />
{open && (
<div
className="theme-selector"
ref={themeSelectorRef}
>
<AutoAwesomeIcon onClick={() => setIsOpen(true)} />
{isOpen && (
<div className="theme-selector__container">
<div className="theme-selector__header">
<p>Theme</p>
<CloseIcon
fontSize="small"
onClick={() => setOpen(false)}
onClick={() => setIsOpen(false)}
/>
</div>
<div className="theme-selector__list">
{themes.map((theme) => (
{themeInfo.map((theme) => (
<ThemeIcons
key={theme.value}
title={theme.title}
value={theme.value}
colors={theme.colors}
{...theme}
onClick={() => {
handleTheme(theme.value);
setOpen(false);
setIsOpen(false);
}}
/>
))}
Expand Down
8 changes: 4 additions & 4 deletions packages/view/src/ide/FakeIDEAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ export default class FakeIDEAdapter implements IDEPort {
this.sendMessageToMe(message);
}

public setPrimaryColor(color: string) {
public setCustomTheme(color: string) {
sessionStorage.setItem("PRIMARY_COLOR", color);
const message: IDEMessage = {
command: "updatePrimaryColor",
command: "updateCustomTheme",
};
this.sendMessageToMe(message);
}
Expand All @@ -76,10 +76,10 @@ export default class FakeIDEAdapter implements IDEPort {
command,
payload: JSON.stringify(fakeBranchList),
};
case "updatePrimaryColor":
case "updateCustomTheme":
return {
command,
payload: sessionStorage.getItem("PRIMARY_COLOR") as string,
payload: sessionStorage.getItem("CUSTOM_THEME") as string,
};
default:
return {
Expand Down
2 changes: 1 addition & 1 deletion packages/view/src/ide/IDEPort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ export default interface IDEPort {
sendRefreshDataMessage: (payload?: string) => void;
sendFetchAnalyzedDataMessage: (payload?: string) => void;
sendFetchBranchListMessage: () => void;
setPrimaryColor: (color: string) => void;
setCustomTheme: (theme: string) => void;
}
6 changes: 3 additions & 3 deletions packages/view/src/ide/VSCodeIDEAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ export default class VSCodeIDEAdapter implements IDEPort {
this.sendMessageToIDE(message);
}

public setPrimaryColor(color: string) {
public setCustomTheme(theme: string) {
const message: IDEMessage = {
command: "updatePrimaryColor",
payload: JSON.stringify({ primary: color }),
command: "updateCustomTheme",
payload: JSON.stringify({ theme }),
};
this.sendMessageToIDE(message);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/view/src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { container } from "tsyringe";

import type IDEPort from "ide/IDEPort";

export const setPrimaryColor = (color: string) => {
export const setCustomTheme = (color: string) => {
const ideAdapter = container.resolve<IDEPort>("IDEAdapter");
ideAdapter.setPrimaryColor(color);
ideAdapter.setCustomTheme(color);
};

export const sendFetchAnalyzedDataCommand = (selectedBranch?: string) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/view/src/types/IDEMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export type IDEMessageCommandNames =
| "fetchAnalyzedData"
| "fetchBranchList"
| "fetchCurrentBranch"
| "updatePrimaryColor";
| "updateCustomTheme";
2 changes: 1 addition & 1 deletion packages/view/src/types/custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ interface Window {
githruNodesData: unknown;
githruBranchesData: unknown;
isProduction: boolean;
primaryColor: string;
theme: string;
}

declare module "*.svg" {
Expand Down
6 changes: 3 additions & 3 deletions packages/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@
"configuration": {
"title": "Githru",
"properties": {
"githru.color.primary": {
"githru.theme": {
"type": "string",
"default": "#ff8272",
"description": "Insert your primary color."
"default": "githru",
"description": "Insert your theme name: githru, hacker-blue, aqua, cotton-candy, mono"
}
}
}
Expand Down
23 changes: 11 additions & 12 deletions packages/vscode/src/setting-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as vscode from "vscode";

const SETTING_PROPERTY_NAMES = {
GITHUB_TOKEN: "githru.github.token",
PRIMARY_COLOR: "githru.color.primary",
THEME: "githru.theme",
};

export const getGithubToken = async (secrets: vscode.SecretStorage) => {
Expand All @@ -14,22 +14,21 @@ export const setGithubToken = async (secrets: vscode.SecretStorage, newGithubTok
};

export const deleteGithubToken = async (secrets: vscode.SecretStorage) => {
return await secrets.delete(SETTING_PROPERTY_NAMES.GITHUB_TOKEN);
}
return await secrets.delete(SETTING_PROPERTY_NAMES.GITHUB_TOKEN);
};

export const setPrimaryColor = (color: string) => {
export const setTheme = async (newTheme: string) => {
const configuration = vscode.workspace.getConfiguration();
configuration.update(SETTING_PROPERTY_NAMES.PRIMARY_COLOR, color);
configuration.update(SETTING_PROPERTY_NAMES.THEME, newTheme);
};

export const getPrimaryColor = (): string => {
export const getTheme = async (): Promise<string> => {
const configuration = vscode.workspace.getConfiguration();
const primaryColor = configuration.get(SETTING_PROPERTY_NAMES.PRIMARY_COLOR) as string;
const theme = configuration.get(SETTING_PROPERTY_NAMES.THEME) as string;

if (!primaryColor) {
configuration.update(SETTING_PROPERTY_NAMES.PRIMARY_COLOR, "#ff8272");
return "#ff8272";
} else {
return primaryColor;
if (!theme) {
await setTheme("githru");
return "githru";
}
return theme;
};
24 changes: 15 additions & 9 deletions packages/vscode/src/webview-loader.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as path from "path";
import * as vscode from "vscode";

import { getPrimaryColor, setPrimaryColor } from "./setting-repository";
import { getTheme, setTheme } from "./setting-repository";
import type { ClusterNode } from "./types/Node";

const ANALYZE_DATA_KEY = "memento_analyzed_data";
Expand Down Expand Up @@ -77,10 +77,10 @@ export default class WebviewLoader implements vscode.Disposable {
});
}

if (command === "updatePrimaryColor") {
if (command === "updateCustomTheme") {
const colorCode = payload && JSON.parse(payload);
if (colorCode.primary) {
setPrimaryColor(colorCode.primary);
if (colorCode.theme) {
setTheme(colorCode.theme);
}
}
} catch (e) {
Expand All @@ -92,7 +92,7 @@ export default class WebviewLoader implements vscode.Disposable {
// this.dispose();
// throw new Error("Project not connected to Git.");
// }
this._panel.webview.html = this.getWebviewContent(this._panel.webview);
this.setWebviewContent();
}

dispose() {
Expand All @@ -111,13 +111,12 @@ export default class WebviewLoader implements vscode.Disposable {
});
}

private getWebviewContent(webview: vscode.Webview): string {
private async getWebviewContent(webview: vscode.Webview): Promise<string> {
const reactAppPathOnDisk = vscode.Uri.file(path.join(this.extensionPath, "dist", "webviewApp.js"));
const reactAppUri = webview.asWebviewUri(reactAppPathOnDisk);
// const reactAppUri = reactAppPathOnDisk.with({ scheme: "vscode-resource" });

const primaryColor = getPrimaryColor();

const theme = await getTheme();
const returnString = `
<!DOCTYPE html>
<html lang="en">
Expand All @@ -127,7 +126,7 @@ export default class WebviewLoader implements vscode.Disposable {
<title>githru-vscode-ext webview</title>
<script>
window.isProduction = true;
window.primaryColor = "${primaryColor}";
window.theme = "${theme}";
</script>
</head>
<body>
Expand All @@ -141,6 +140,13 @@ export default class WebviewLoader implements vscode.Disposable {
`;
return returnString;
}

private async setWebviewContent() {
if (this._panel) {
this._panel.webview.html = await this.getWebviewContent(this._panel.webview);
}
}

public setGlobalOwnerAndRepo(owner: string, repo: string) {
if (this._panel) {
this._panel.webview.postMessage({
Expand Down

0 comments on commit 8f28b4e

Please sign in to comment.