Skip to content

添加Champion Rankings数据 #123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions app/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ if (ignoreSystemScale) {
// Prevent window from being garbage collected
let mainWindow: BrowserWindow | null;
let popupWindow: BrowserWindow | null;
let statisticsWindow: BrowserWindow | null;
let tray = null;
let lcuWatcher: LcuWatcher | null = null;

Expand Down Expand Up @@ -90,6 +91,7 @@ const createMainWindow = async () => {
// For multiple windows store them in an array
mainWindow = null;
popupWindow = null;
statisticsWindow = null;
});

await win.loadURL(
Expand Down Expand Up @@ -143,6 +145,52 @@ const createPopupWindow = async () => {
return popup;
};

const createStatisticsWindow = async () => {
const [mX, mY] = mainWindow!.getPosition();
const curDisplay = screen.getDisplayNearestPoint({
x: mX,
y: mY,
});

const statisticsConfig = appConfig.get(`statistics`);
const statistics = new BrowserWindow({
show: false,
frame: false,
resizable: true,
fullscreenable: false,

skipTaskbar: statisticsConfig.alwaysOnTop,
alwaysOnTop: statisticsConfig.alwaysOnTop,
width: statisticsConfig.width || 400,
height: statisticsConfig.height || 650,
x: curDisplay.bounds.width / 2 + 201,
y: curDisplay.workAreaSize.height / 2 - 325,
webPreferences,
});

statistics.on(
`move`,
_debounce(() => persistStatisticsBounds(statistics), 1000),
);

statistics.on(
`resize`,
_debounce(() => persistStatisticsBounds(statistics), 1000),
);

statistics.on('closed', () => {
statisticsWindow = null;
});

await statistics.loadURL(
isDev
? `http://127.0.0.1:3000/statistics.html`
: `file://${path.join(__dirname, 'statistics.html')}`,
);

return statistics;
};

// Prevent multiple instances of the app
if (!app.requestSingleInstanceLock()) {
app.quit();
Expand All @@ -161,6 +209,7 @@ app.on('second-instance', () => {
app.on(`quit`, () => {
mainWindow = null;
popupWindow = null;
statisticsWindow = null;
});

app.on('window-all-closed', () => {
Expand All @@ -187,6 +236,18 @@ function persistPopUpBounds(w: BrowserWindow) {
appConfig.set(`popup.height`, height);
}

function persistStatisticsBounds(w: BrowserWindow) {
if (!w) {
return;
}

const { x, y, width, height } = w.getBounds();
appConfig.set(`statistics.x`, x);
appConfig.set(`statistics.y`, y);
appConfig.set(`statistics.width`, width);
appConfig.set(`statistics.height`, height);
}

let lastChampion = 0;

async function onShowPopup(data: IPopupEventData) {
Expand Down Expand Up @@ -217,11 +278,43 @@ async function onShowPopup(data: IPopupEventData) {
}, 300);
}

async function onShowStatistics(data: IPopupEventData) {
if (!data.championId || lastChampion === data.championId) {
return;
}

lastChampion = data.championId;
if (!statisticsWindow) {
statisticsWindow = await createStatisticsWindow();
}

// popupWindow.setAlwaysOnTop(true);
statisticsWindow.show();
// popupWindow.setAlwaysOnTop(false);
// app.focus();
statisticsWindow.focus();

const task = setInterval(() => {
if (!statisticsWindow!.isVisible()) {
return;
}

statisticsWindow!.webContents.send(`for-statistics`, {
championId: data.championId,
});
clearInterval(task);
}, 300);
}

function registerMainListeners() {
ipcMain.on(`toggle-main-window`, () => {
toggleMainWindow();
});

ipcMain.on(`toggle-statistics-window`, () => {
toggleStatisticsWindow();
});

ipcMain.on(`restart-app`, () => {
app.relaunch();
app.exit();
Expand All @@ -237,6 +330,16 @@ function registerMainListeners() {
appConfig.set(`popup.alwaysOnTop`, next);
});

ipcMain.on(`statistics:toggle-always-on-top`, () => {
if (!statisticsWindow) return;

const next = !statisticsWindow.isAlwaysOnTop();
statisticsWindow.setAlwaysOnTop(next);
statisticsWindow.setSkipTaskbar(next);

appConfig.set(`statistics.alwaysOnTop`, next);
});

ipcMain.on(`popup:reset-position`, () => {
const [mx, my] = mainWindow!.getPosition();
const { bounds } = screen.getDisplayNearestPoint({ x: mx, y: my });
Expand Down Expand Up @@ -287,6 +390,10 @@ function registerMainListeners() {
app.quit();
});

ipcMain.on(`quit-statistics`, () => {
statisticsWindow?.close();
});

ipcMain.on(`applyRunePage`, async (_ev, data: IRuneItem & { jobId: string }) => {
try {
await lcuWatcher?.applyRunePage(data);
Expand All @@ -303,6 +410,10 @@ function registerMainListeners() {
ipcMain.on(`showPopup`, (_ev, data: IPopupEventData) => {
onShowPopup(data);
});

ipcMain.on(`showStatistics`, (_ev, data: IPopupEventData) => {
onShowStatistics(data);
});
}

function toggleMainWindow() {
Expand All @@ -320,6 +431,21 @@ function toggleMainWindow() {
}
}

function toggleStatisticsWindow() {
if (!statisticsWindow) {
return;
}

const visible = statisticsWindow.isVisible();
if (!visible) {
statisticsWindow.show();
statisticsWindow.setSkipTaskbar(false);
} else {
statisticsWindow.hide();
statisticsWindow.setSkipTaskbar(true);
}
}

function makeTray() {
const iconPath = path.join(
isDev ? `${__dirname}/../` : process.resourcesPath,
Expand Down
7 changes: 7 additions & 0 deletions app/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ export const appConfig = new Store({
y: null,
alwaysOnTop: true,
},
statistics: {
width: 400,
height: 650,
x: null,
y: null,
alwaysOnTop: false,
},
sourceList: DefaultSourceList,
lolDirHasCJKChar: false,
},
Expand Down
4 changes: 3 additions & 1 deletion config/paths.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';


const path = require('path');
const fs = require('fs');
Expand Down Expand Up @@ -82,8 +82,10 @@ module.exports = {
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
popupHtml: resolveApp('public/popup.html'),
statisticsHtml: resolveApp('public/statistics.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
popupIndexJs: resolveModule(resolveApp, 'src/popup.index'),
statisticsIndexJs: resolveModule(resolveApp, 'src/statistics.index'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'),
Expand Down
35 changes: 35 additions & 0 deletions config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ module.exports = function (webpackEnv) {
isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'),
paths.popupIndexJs,
].filter(Boolean),

statistics: [
isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'),
paths.statisticsIndexJs,
].filter(Boolean),
},

target: 'web',
Expand Down Expand Up @@ -524,6 +529,36 @@ module.exports = function (webpackEnv) {
: undefined,
),
),

new HtmlWebpackPlugin(
Object.assign(
{
chunks: [`statistics`],
filename: `./statistics.html`,
},
{
inject: true,
template: paths.statisticsHtml,
},
isEnvProduction
? {
enableGA: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined,
),
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
// https://github.com/facebook/create-react-app/issues/5358
Expand Down
10 changes: 10 additions & 0 deletions interfaces/commonTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ export interface IChampionInfo {
id: string;
}

export interface IChampionRank {
version: string;
rank: string;
id: string;
position: string;
winRate: string;
pickRate: string;
tier: string | undefined;
}

export interface IFileResult {
champion: string;
position: string;
Expand Down
55 changes: 55 additions & 0 deletions public/statistics.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>ChampR</title>
</head>
<body>
<div id="statistics"></div>

<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.

To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<% if (htmlWebpackPlugin.options.enableGA) { %>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-166772221-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());

gtag('config', 'UA-166772221-1');
</script>
<% } %>

</body>
</html>
16 changes: 15 additions & 1 deletion src/components/toolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { useHistory } from 'react-router-dom';
import { useTranslation } from 'react-i18next';

import { StatefulTooltip } from 'baseui/tooltip';
import { Settings, Minimize2, X } from 'react-feather';
import { Database, Settings, Minimize2, X } from 'react-feather';
import { ChampionKeys } from 'src/share/constants/champions';

const Toolbar = () => {
const [t] = useTranslation();
Expand All @@ -20,6 +21,19 @@ const Toolbar = () => {

return (
<div className={s.toolbar}>
<StatefulTooltip accessibilityType={'tooltip'} content={t(`statistics`)}>
<span
className={s.icon}
onClick={() => {
const championId = ChampionKeys[Math.floor(Math.random() * ChampionKeys.length)];
window.bridge.sendMessage(`showStatistics`, {
championId,
});
}}>
<Database size={16} />
</span>
</StatefulTooltip>

<StatefulTooltip accessibilityType={'tooltip'} content={t(`minimize`)}>
<span className={s.icon} onClick={onHide}>
<Minimize2 size={16} />
Expand Down
1 change: 1 addition & 0 deletions src/modules/i18n/en-us.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default {
minimize: `Minimize`,
close: `Close`,
settings: `Settings`,
statistics: `Statistics`,
'display language': `Display language`,
'select language': `Select language`,
'removed outdated items': `Removed outdated items`,
Expand Down
1 change: 1 addition & 0 deletions src/modules/i18n/fr-fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default {
minimize: `Réduire`,
close: `Fermer`,
settings: `Paramètres`,
statistics: `Statistiques`,
'display language': `Langue d'affichage`,
'select language': `Sélectionner une langue`,
'removed outdated items': `Anciens objets supprimés`,
Expand Down
Loading