Skip to content

Commit

Permalink
Merge pull request #95 from jackschedel/working
Browse files Browse the repository at this point in the history
2.0.7
  • Loading branch information
jackschedel authored Jan 6, 2024
2 parents 73658eb + ca21a2d commit 7bf01c4
Show file tree
Hide file tree
Showing 65 changed files with 1,675 additions and 335 deletions.
39 changes: 39 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module.exports = {
settings: {
react: { version: 'detect' },
},
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
],
overrides: [
{
env: {
node: true,
},
files: ['.eslintrc.{js,cjs}'],
parserOptions: {
sourceType: 'script',
},
},
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'react'],
rules: {
// '@typescript-eslint/no-this-alias': 'warn',
// '@typescript-eslint/no-unused-vars': 'warn',
// 'no-useless-escape': 'warn',
'react/display-name': 'off',
},
};
38 changes: 38 additions & 0 deletions .github/workflows/eslint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: ESLint

on:
push:
branches: ['main']
pull_request:
# The branches below must be a subset of the branches above
branches: ['main']

jobs:
eslint:
name: Run eslint scanning
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Install ESLint
run: |
npm install [email protected]
npm install @microsoft/[email protected]
- name: Run ESLint
run: npx eslint .
--config .eslintrc.cjs
--format @microsoft/eslint-formatter-sarif
--output-file eslint-results.sarif
continue-on-error: true

- name: Upload analysis results to GitHub
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: eslint-results.sarif
wait-for-processing: true
3 changes: 3 additions & 0 deletions .github/workflows/prettier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ on:

jobs:
prettier:
permissions:
contents: write
actions: write
runs-on: ubuntu-latest

steps:
Expand Down
23 changes: 13 additions & 10 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ on:
branches: [main]
workflow_dispatch:

env:
VERSION: 2.0.6

permissions:
contents: write
id-token: write
Expand All @@ -26,6 +23,12 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Get version from package.json
id: packageJson
uses: RadovanPelka/github-action-json@main
with:
path: 'package.json'

- name: Use Node.js 18
uses: actions/setup-node@v3
with:
Expand Down Expand Up @@ -97,8 +100,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./release-Linux/koala-client-${{VERSION}}-linux-x86_64.AppImage
asset_name: KoalaClient-${{VERSION}}-linux-x86_64.AppImage
asset_path: ./release-Linux/koala-client-${{steps.packageJson.outputs.version}}-linux-x86_64.AppImage
asset_name: KoalaClient-${{steps.packageJson.outputs.version}}-linux-x86_64.AppImage
asset_content_type: application

- name: Upload Release Asset - MacOS
Expand All @@ -107,8 +110,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./release-macOS/koala-client-${{VERSION}}-mac-x64.dmg
asset_name: KoalaClient-${{VERSION}}-mac-x64.dmg
asset_path: ./release-macOS/koala-client-${{steps.packageJson.outputs.version}}-mac-x64.dmg
asset_name: KoalaClient-${{steps.packageJson.outputs.version}}-mac-x64.dmg
asset_content_type: application

- name: Upload Release Asset - Windows
Expand All @@ -117,8 +120,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./release-Windows/koala-client-${{VERSION}}-win-x64.exe
asset_name: KoalaClient-${{VERSION}}-win-x64.exe
asset_path: ./release-Windows/koala-client-${{steps.packageJson.outputs.version}}-win-x64.exe
asset_name: KoalaClient-${{steps.packageJson.outputs.version}}-win-x64.exe
asset_content_type: application

- name: Zip Unpacked Release - Windows
Expand All @@ -134,7 +137,7 @@ jobs:
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./release-Windows/win-unpacked.zip
asset_name: KoalaClient-${{VERSION}}-win-x64-portable.zip
asset_name: KoalaClient-${{steps.packageJson.outputs.version}}-win-x64-portable.zip
asset_content_type: zip

- name: Zip Hash Info
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "koala-client",
"private": true,
"version": "2.0.6",
"version": "2.0.7",
"type": "module",
"homepage": "./",
"main": "electron/index.cjs",
Expand All @@ -14,6 +14,8 @@
"electron": "concurrently -k \"BROWSER=none yarn dev\" \"wait-on tcp:5173 && electron .\"",
"pack": "yarn build && electron-builder --dir",
"make": "yarn build && electron-builder",
"lint": "eslint ./src",
"errors": "eslint ./src --quiet",
"format": "prettier --write ./"
},
"build": {
Expand Down Expand Up @@ -81,11 +83,15 @@
"@types/react-dom": "^18.0.10",
"@types/react-scroll-to-bottom": "^4.2.0",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.17.0",
"@vitejs/plugin-react-swc": "^3.0.0",
"autoprefixer": "^10.4.13",
"concurrently": "^8.0.1",
"electron": "^28.1.1",
"electron-builder": "^23.6.0",
"eslint": "^8.56.0",
"eslint-plugin-react": "^7.33.2",
"postcss": "^8.4.21",
"tailwindcss": "^3.2.7",
"typescript": "^4.9.3",
Expand Down
159 changes: 147 additions & 12 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,156 @@
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import useStore from '@store/store';
import i18n from './i18n';

import Chat from '@components/Chat';
import Menu from '@components/Menu';

import useAddChat from '@hooks/useAddChat';
import useGoBack from '@hooks/useGoBack';
import useGoForward from '@hooks/useGoForward';
import useCopyCodeBlock from '@hooks/useCopyCodeBlock';
import useInitialiseNewChat from '@hooks/useInitialiseNewChat';
import useSubmit from '@hooks/useSubmit';
import { ChatInterface } from '@type/chat';
import { Theme } from '@type/theme';
import ApiPopup from '@components/ApiPopup';
import Toast from '@components/Toast';
import isElectron from '@utils/electron';
import GlobalContext from '@hooks/GlobalContext';

function App() {
const initialiseNewChat = useInitialiseNewChat();
const setChats = useStore((state) => state.setChats);
const setTheme = useStore((state) => state.setTheme);
const setApiKey = useStore((state) => state.setApiKey);
const currentChatIndex = useStore((state) => state.currentChatIndex);
const setCurrentChatIndex = useStore((state) => state.setCurrentChatIndex);
const setHideSideMenu = useStore((state) => state.setHideSideMenu);
const hideSideMenu = useStore((state) => state.hideSideMenu);
const addChat = useAddChat();
const goBack = useGoBack();
const goForward = useGoForward();
const copyCodeBlock = useCopyCodeBlock();
const { handleSubmit } = useSubmit();

const [sharedTextareaRef, setSharedTextareaRef] =
useState<React.RefObject<HTMLTextAreaElement> | null>(null);

const setRef = (newRef: React.RefObject<HTMLTextAreaElement> | null) => {
setSharedTextareaRef(newRef);
};

const handleGenerate = () => {
if (useStore.getState().generating) return;
const updatedChats: ChatInterface[] = JSON.parse(
JSON.stringify(useStore.getState().chats)
);
const content = sharedTextareaRef?.current?.value;
const updatedMessages = updatedChats[currentChatIndex].messages;
if (!content) {
return;
}

updatedMessages.push({ role: 'user', content: content });
if (sharedTextareaRef && sharedTextareaRef.current) {
sharedTextareaRef.current.value = '';
}

setChats(updatedChats);
handleSubmit();
};

const pasteSubmit = async () => {
try {
if (useStore.getState().generating) return;
const updatedChats: ChatInterface[] = JSON.parse(
JSON.stringify(useStore.getState().chats)
);
const updatedMessages = updatedChats[currentChatIndex].messages;

const text = await navigator.clipboard.readText();
if (!text) {
return;
}

updatedMessages.push({ role: 'user', content: text });
if (sharedTextareaRef && sharedTextareaRef.current) {
sharedTextareaRef.current.value = '';
}

setChats(updatedChats);
handleSubmit();
} catch (err) {
console.error('Failed to read clipboard contents:', err);
}
};

const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
// put any general app-wide keybinds here
// Put any general app-wide keybinds here:

// ctrl+e - Toggle side menu
if (e.ctrlKey && e.key === 'e') {
e.preventDefault();
setHideSideMenu(!hideSideMenu);
}

// ctrl+n - New chat
if (e.ctrlKey && e.key === 'n') {
e.preventDefault();
addChat();
sharedTextareaRef?.current?.focus();
}

// ctrl+o - Copy code block
if (e.ctrlKey && e.key === 'o') {
e.preventDefault();
copyCodeBlock();
}

// ctrl+g - Focus textarea
if (e.ctrlKey && e.key === 'g') {
e.preventDefault();
sharedTextareaRef?.current?.focus();
}

// ctrl+s - Save bottom message + generate
if (e.ctrlKey && e.key === 's') {
e.preventDefault();
handleGenerate();
}

// ctrl+p - New chat from clipboard (insta-generate)
if (e.ctrlKey && e.key === 'p') {
e.preventDefault();
console.log('test');
addChat();
pasteSubmit();
}

// ctrl+left - Previous chat
if (e.ctrlKey && e.key === 'ArrowLeft') {
e.preventDefault();
goBack();
}

// ctrl+left - Next chat
if (e.ctrlKey && e.key === 'ArrowRight') {
e.preventDefault();
goForward();
}
};

const handleMouseUp = (e: React.MouseEvent<HTMLDivElement>) => {
// Mouse button 3 (back)
if (e.button === 3) {
e.preventDefault();
goBack();
}

// Mouse button 4 (forward)
if (e.button === 4) {
e.preventDefault();
goForward();
}
};

Expand Down Expand Up @@ -96,17 +214,34 @@ function App() {
}
}, []);

useEffect(() => {
const handleGlobalMouseUp = (e: MouseEvent) => {
if (e.button === 3 || e.button === 4) {
handleMouseUp(e as unknown as React.MouseEvent<HTMLDivElement>);
}
};

document.addEventListener('mouseup', handleGlobalMouseUp);

return () => {
document.removeEventListener('mouseup', handleGlobalMouseUp);
};
}, []);

return (
<div
tabIndex={0}
className='overflow-hidden w-full h-full relative'
onKeyDown={handleKeyDown}
>
<Menu />
<Chat />
<ApiPopup />
<Toast />
</div>
<GlobalContext.Provider value={{ ref: sharedTextareaRef, setRef }}>
<div
tabIndex={0}
className='overflow-hidden w-full h-full relative'
onKeyDown={handleKeyDown}
onMouseUp={handleMouseUp}
>
<Menu />
<Chat />
<ApiPopup />
<Toast />
</div>
</GlobalContext.Provider>
);
}

Expand Down
Loading

0 comments on commit 7bf01c4

Please sign in to comment.