release v0.2.0 - refactoring done

This commit is contained in:
samtiz 2025-07-07 09:04:40 +09:00
parent 1f2eda1ee1
commit 6bbca03719
6 changed files with 1 additions and 370 deletions

View File

@ -1,87 +0,0 @@
# IPC Channel Reference
This document lists all the IPC channels used for communication between the main process and renderer processes in the Glass application. It serves as a central reference for developers.
---
## 1. Two-Way Channels (`ipcMain.handle` / `ipcRenderer.invoke`)
These channels are used for request-response communication where the renderer process expects a value to be returned from the main process.
### Window & System Management
- `get-header-position`: Gets the current [x, y] coordinates of the header window.
- `move-header-to`: Moves the header window to a specific [x, y] coordinate.
- `resize-header-window`: Resizes the header window to a specific width and height.
- `move-window-step`: Moves the header window by a predefined step in a given direction.
- `is-window-visible`: Checks if a specific feature window (e.g., 'ask') is currently visible.
- `force-close-window`: Forces a specific feature window to hide.
- `toggle-all-windows-visibility`: Toggles the visibility of all application windows.
- `toggle-feature`: Shows or hides a specific feature window (e.g., 'ask', 'listen').
- `quit-application`: Quits the entire application.
### Authentication & User
- `get-current-user`: Retrieves the full state of the current user (Firebase or local).
- `start-firebase-auth`: Opens the Firebase login flow in the system browser.
- `firebase-logout`: Initiates the user logout process.
- `save-api-key`: Saves a user-provided API key.
- `remove-api-key`: Removes the currently stored API key.
- `get-stored-api-key`: Retrieves the currently active API key.
- `get-ai-provider`: Gets the currently configured AI provider (e.g., 'openai').
### Permissions & Settings
- `get-content-protection-status`: Checks if window content protection is enabled.
- `check-system-permissions`: Checks for microphone and screen recording permissions.
- `request-microphone-permission`: Prompts the user for microphone access.
- `open-system-preferences`: Opens the macOS System Preferences for a specific privacy setting.
- `mark-permissions-completed`: Marks the initial permission setup as completed.
- `check-permissions-completed`: Checks if the initial permission setup was completed.
- `update-google-search-setting`: Updates the setting for Google Search integration.
### Data & Content
- `get-user-presets`: Fetches all custom prompt presets for the current user.
- `get-preset-templates`: Fetches the default prompt preset templates.
- `save-ask-message`: Saves a user question and AI response pair to the database.
- `get-web-url`: Gets the dynamically assigned URLs for the backend and web frontend.
### Features (Listen, Ask, etc.)
- `initialize-openai`: Initializes the STT and other AI services for a new session.
- `is-session-active`: Checks if a listen/summary session is currently active.
- `send-audio-content`: Sends a chunk of audio data from renderer to main for processing.
- `start-macos-audio`, `stop-macos-audio`: Controls the background process for system audio capture on macOS.
- `close-session`: Stops the current listen session.
- `message-sending`: Notifies the main process that an 'ask' message is being sent.
- `send-question-to-ask`: Sends a question from one feature window (e.g., listen) to the 'ask' window.
- `capture-screenshot`: Requests the main process to take a screenshot.
- `get-current-screenshot`: Retrieves the most recent screenshot.
- `adjust-window-height`: Requests the main process to resize a window to a specific height.
---
## 2. One-Way Channels (`ipcMain.on` / `ipcRenderer.send` / `webContents.send`)
These channels are used for events or commands that do not require a direct response.
### Main to Renderer (Events & Updates)
- `user-state-changed`: Notifies all windows that the user's authentication state has changed.
- `auth-failed`: Informs the UI that a Firebase authentication attempt failed.
- `session-state-changed`: Broadcasts whether a listen session is active or inactive.
- `api-key-validated`, `api-key-updated`, `api-key-removed`: Events related to the lifecycle of the API key.
- `stt-update`: Sends real-time speech-to-text transcription updates to the UI.
- `update-structured-data`: Sends processed data (summaries, topics) to the UI.
- `ask-response-chunk`, `ask-response-stream-end`: Sends streaming AI responses for the 'ask' feature.
- `window-show-animation`: Triggers a show/fade-in animation.
- `window-hide-animation`, `settings-window-hide-animation`: Triggers a hide/fade-out animation.
- `window-blur`: Notifies a window that it has lost focus.
- `window-did-show`: Confirms to a window that it is now visible.
- `click-through-toggled`: Informs the UI about the status of click-through mode.
- `start-listening-session`: Commands to control the main application view.
- `receive-question-from-assistant`: Delivers a question to the `AskView`.
- `ask-global-send`, `toggle-text-input`, `clear-ask-response`, `hide-text-input`: Commands for controlling the state of the `AskView`.
### Renderer to Main (Commands & Events)
- `header-state-changed`: Informs the `windowManager` that the header's state (e.g., `apikey` vs `app`) has changed.
- `update-keybinds`: Sends updated keybinding preferences to the main process.
- `view-changed`: Notifies the main process that the visible view in `PickleGlassApp` has changed.
- `header-animation-complete`: Lets the main process know that a show/hide animation has finished.
- `cancel-hide-window`, `show-window`, `hide-window`: Commands to manage feature window visibility from the renderer.
- `session-did-close`: Notifies the main process that the user has manually closed the listen session.

View File

@ -1,119 +0,0 @@
# DB & Architecture Refactoring Plan
## 1. Goal
DB 접근 로직을 **Electron 메인 프로세스로 중앙화**하고, **Feature 중심의 계층형 아키텍처**를 도입하여 코드의 안정성과 유지보수성을 극대화한다.
---
## 2. Architecture: AS-IS → TO-BE
```mermaid
graph TD
subgraph "AS-IS: 다중 접근 (충돌 위험)"
A_Main[Main Process] --> A_DB[(DB)]
A_Backend[Web Backend] --> A_DB
A_Browser[Browser] -- HTTP --> A_Backend
style A_Backend fill:#f99
end
subgraph "TO-BE: 단일 접근 (안정)"
B_Main[Main Process] --> B_DB[(DB)]
B_Backend[Web Backend] -- IPC --> B_Main
B_Browser[Browser] -- HTTP --> B_Backend
style B_Main fill:#9f9
end
```
---
## 3. Target Folder Structure
- `features` : 기능별로 View, Service, Repository를 그룹화하여 응집도 상승
- `common`: 여러 기능이 공유하는 Repository 및 저수준 Service 배치
```
src/
├── features/
│ └── listen/
│ ├── listenView.js # View (UI)
│ ├── listenService.js # ViewModel (Logic)
│ └── repositories/ # Model (Feature-Data)
│ ├── index.js # <- 저장소 전략 선택
│ ├── sqlite.repository.js
│ └── firebase.repository.js
└── common/
├── services/
│ └── sqliteClient.js # <- DB 연결/관리
└── repositories/ # <- 공통 데이터
├── user/
└── session/
```
---
## 4. Key Changes
- **DB 접근 단일화**
- 모든 DB Read/Write는 **Electron 메인 프로세스**에서만 수행.
- 웹 백엔드(`backend_node`)는 IPC 통신을 통해 메인 프로세스에 데이터를 요청.
- 웹 백엔드의 DB 직접 연결 (`better-sqlite3`, `db.js`) 코드 전부 제거.
- **Repository 패턴 도입**
- 모든 SQL 쿼리는 `*.repository.js` 파일로 분리 및 이동.
- **공통 Repository:** `common/repositories/` (e.g., `user`, `session`)
- **기능별 Repository:** `features/*/repositories/` (e.g., `transcript`, `summary`)
- **Service 역할 명확화**
- `*Service.js`는 비즈니스 로직만 담당. Repository를 호출하여 데이터를 요청/저장하지만, **직접 SQL을 다루지 않음.**
- **`renderer.js` 제거**
- `renderer.js`의 기능들을 각 책임에 맞는 View, Service로 이전 후 최종적으로 파일 삭제.
---
## 5. Future-Proofing: 저장소 전략 패턴
로그인 여부에 따라 `SQLite``Firebase` 저장소를 동적으로 스위칭할 수 있는 기반을 마련한다. Service 코드는 수정할 필요 없이, Repository 구현체만 추가하면 된다.
```javascript
// e.g., common/repositories/session/index.js
const sqliteRepo = require('./sqlite.repository.js');
const firebaseRepo = require('./firebase.repository.js');
// 현재 상태에 따라 적절한 저장소를 동적으로 반환
exports.getRepository = () => {
return isUserLoggedIn() ? firebaseRepo : sqliteRepo;
};
```
---
## 6. Design Pattern & Feature Structure Guide
각 Feature는 아래의 3-Layer 구조를 따르며, 이는 MVVM 패턴의 정신을 차용한 것입니다.
| 파일 / 폴더 | 계층 (Layer) | 역할 (Role) & 책임 (Responsibilities) |
| ---------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `*View.js` | **View** | - **UI 렌더링:** Service로부터 받은 데이터를 화면에 표시.<br>- **사용자 입력:** 클릭, 입력 등의 이벤트를 감지하여 Service에 명령 전달. |
| `*Service.js` | **ViewModel** | - **상태 관리:** Feature에 필요한 모든 상태(State)를 소유하고 관리.<br>- **비즈니스 로직:** View의 요청을 받아 로직 수행.<br>- **데이터 조율:** Repository를 통해 데이터를 요청/저장하고, Main 프로세스와 IPC 통신. |
| `repositories/` | **Model / Data** | - **데이터 추상화:** DB(SQLite/Firebase)의 복잡한 쿼리를 숨기고, Service에 간단한 함수(`getById`, `save` 등)를 제공. |
### 확장성 가이드: 파일이 너무 커진다면?
"단일 책임 원칙"에 따라, 한 파일이 너무 많은 일을 하게 되면 주저 없이 분리합니다.
- **Service Layer 분할:**
- **언제?** `listenService.js`가 STT 연결, 오디오 처리, 텍스트 분석 등 너무 많은 역할을 맡게 될 때.
- **어떻게?** 책임을 기준으로 더 작은 서비스로 분리합니다.
- `listenService.js`**`sttService.js`**, **`audioService.js`**, **`analysisService.js`**
- 이때, 최상위 `listenService.js`는 여러 하위 서비스를 조율하는 **"Orchestrator(조정자)"**의 역할을 맡게 됩니다.
- **View Layer 분할:**
- **언제?** `AssistantView.js` 하나의 파일이 너무 많은 UI 요소를 포함하고 복잡해질 때.
- **어떻게?** 재사용 가능한 UI 조각으로 분리합니다.
- `AssistantView.js`**`TranscriptLog.js`**, **`SummaryDisplay.js`**, **`ActionButtons.js`**
이 가이드를 따르면, 기능이 추가되거나 복잡해지더라도 코드베이스 전체가 일관되고 예측 가능한 구조를 유지할 수 있습니다.

View File

@ -1,80 +0,0 @@
# 리팩터링 진행 상황 보고서
> 이 문서는 `REFACTORING_PLAN.md`를 기준으로 현재까지의 진행 상황과 남은 과제를 추적합니다.
### Phase 1: 아키텍처 기반 구축 (완료)
이 단계의 목표는 **DB 접근을 메인 프로세스로 중앙화**하고, **계층형 아키텍처의 뼈대를 구축**하는 것이었습니다. 이 목표는 성공적으로 달성되었습니다.
- **[✓] DB 접근 단일화:**
- `dataService.js`와 웹 백엔드의 DB 직접 접근 코드를 모두 제거했습니다.
- 이제 모든 DB 접근은 메인 프로세스의 `Repository` 계층을 통해서만 안전하게 이루어집니다.
- **[✓] Repository 패턴 도입:**
- `userRepository`, `systemSettingsRepository`, `presetRepository` 등 공통 데이터 관리를 위한 저장소 계층을 성공적으로 구현하고 적용했습니다.
- **[✓] Service 역할 명확화:**
- `authService`를 도입하여 모든 인증 로직을 중앙에서 관리하도록 했습니다.
- `liveSummaryService` 등 기존 서비스들이 더 이상 직접 DB에 접근하지 않고 Repository에 의존하도록 수정했습니다.
### Phase 1.5: 인증 시스템 현대화 및 안정화 (완료)
1단계에서 구축한 뼈대 위에, 앱의 핵심인 인증 시스템을 더욱 견고하고 사용자 친화적으로 만드는 작업을 완료했습니다.
- **[✓] 완전한 인증 생명주기 관리:**
- `authService`가 Firebase 로그인 시 가상 API 키를 **자동으로 발급/저장**하고, 로그아웃 시 **자동으로 삭제**하는 전체 흐름을 구현했습니다.
- **[✓] 상태 관리 중앙화 및 전파:**
- `authService`가 **유일한 진실의 원천(Single Source of Truth)**이 되어, `isLoggedIn``hasApiKey` 상태를 명확히 구분하여 관리합니다.
- `user-state-changed`라는 단일 이벤트를 통해 모든 UI 컴포넌트가 일관된 상태 정보를 받도록 데이터 흐름을 정리했습니다.
- **[✓] 레거시 코드 제거:**
- `windowManager`와 여러 렌더러 파일에 흩어져 있던 레거시 인증 로직, API 키 캐싱, 불필요한 IPC 핸들러들을 모두 제거하여 코드베이스를 깔끔하게 정리했습니다.
- **[✓] 사용자 경험 최적화:**
- 로그인 세션을 영속화하여 **자동 로그인**을 구현했으며, 느린 네트워크 요청을 **비동기 백그라운드 처리**하여 UI 반응성을 극대화했습니다.
---
### Phase 2: 기능별 모듈화 및 레거시 코드 완전 제거 (진행 예정)
핵심 아키텍처가 안정화된 지금, 남아있는 기술 부채를 청산하고 앱 전체에 일관된 구조를 적용하는 마지막 단계를 진행합니다.
#### 1. `renderer.js` 책임 분산 및 제거 (최우선 과제)
- **최종 목표:** 거대 파일 `renderer.js` (1100+줄)를 완전히 제거하여, 각 기능의 UI 로직이 독립적인 모듈에서 관리되도록 합니다.
- **현황:** 현재 `renderer.js``ask` 기능의 AI 메시지 전송, `listen` 기능의 오디오/스크린 캡처 및 전처리, 상태 관리 등 여러 책임이 복잡하게 얽혀있습니다.
- **수행 작업:**
1. **`ask` 기능 책임 이전:**
- `renderer.js``sendMessage`, `PICKLE_GLASS_SYSTEM_PROMPT`, 관련 유틸 함수(`formatRealtimeConversationHistory`, `getCurrentScreenshot` 등)를 `features/ask/askService.js` (또는 유사 모듈)로 이전합니다.
- `liveSummaryService.js``save-ask-message` IPC 핸들러 로직을 `features/ask/repositories/askRepository.js`를 사용하는 `askService.js`로 이동시킵니다.
2. **`listen` 기능 책임 이전:**
- `renderer.js``startCapture`, `stopCapture`, `setupMicProcessing` 등 오디오/스크린 캡처 및 처리 관련 로직을 `features/listen/` 폴더 내의 적절한 파일 (예: `listenView.js` 또는 신규 `listenCaptureService.js`)로 이전합니다.
3. **`renderer.js` 최종 제거:**
- 위 1, 2번 작업이 완료되어 `renderer.js`에 더 이상 의존하는 코드가 없을 때, 이 파일을 프로젝트에서 **삭제**합니다.
#### 2. `listen` 기능 심화 리팩터링
- **목표:** 거대해진 `liveSummaryService.js`를 단일 책임 원칙에 따라 여러 개의 작은 서비스로 분리하여 유지보수성을 극대화합니다.
- **수행 작업:**
- `sttService.js`: STT 세션 연결 및 데이터 스트리밍을 전담합니다.
- `analysisService.js`: STT 텍스트를 받아 AI 모델에게 분석/요약을 요청하는 로직을 전담합니다.
- `listenService.js`: 상위 서비스로서, `sttService``analysisService`를 조율하고 전체 "Listen" 기능의 상태를 관리하는 **조정자(Orchestrator)** 역할을 수행합니다.
#### 3. `windowManager` 모듈화
- **목표:** 비대해진 `windowManager.js`의 책임들을 기능별로 분리하여, 각 모듈이 자신의 창 관련 로직만 책임지도록 구조를 개선합니다.
- **현황:** 현재 `windowManager.js`는 모든 창의 생성, 위치 계산, 단축키 등록, IPC 핸들링 등 너무 많은 역할을 수행하고 있습니다.
- **수행 작업:**
- **`windowLayoutManager.js`:** 여러 창의 위치를 동적으로 계산하고 배치하는 로직을 분리합니다.
- **`shortcutManager.js`:** 전역 단축키를 등록하고 관리하는 로직을 분리합니다.
- **`featureWindowManager.js` (가칭):** `ask`, `listen` 등 각 기능 창의 생성/소멸 및 관련 IPC 핸들러를 관리하는 로직을 분리합니다.
- `windowManager.js`: 최상위 관리자로서, `header` 창과 각 하위 관리자 모듈을 총괄하는 역할만 남깁니다.
---
### Phase 3: 최종 정리 및 고도화 (향후)
- **[ ] 전체 기능 회귀 테스트:** 모든 리팩터링 완료 후, 앱의 모든 기능이 의도대로 동작하는지 검증합니다.
- **[ ] 코드 클린업:** 디버깅용 `console.log`, 불필요한 주석 등을 최종적으로 정리합니다.
- **[ ] 문서 최신화:** `IPC_CHANNELS.md`를 포함한 모든 관련 문서를 최종 아키텍처에 맞게 업데이트합니다.

View File

@ -1,33 +0,0 @@
const path = require('path');
const databaseInitializer = require('../../src/common/services/databaseInitializer');
const Database = require('better-sqlite3');
const dbPath = databaseInitializer.getDatabasePath();
const db = new Database(dbPath);
db.pragma('journal_mode = WAL');
// The schema is now managed by the main Electron process on startup.
// This file can assume the schema is correct and up-to-date.
const defaultPresets = [
['school', 'School', 'You are a school and lecture assistant. Your goal is to help the user, a student, understand academic material and answer questions.\n\nWhenever a question appears on the user\'s screen or is asked aloud, you provide a direct, step-by-step answer, showing all necessary reasoning or calculations.\n\nIf the user is watching a lecture or working through new material, you offer concise explanations of key concepts and clarify definitions as they come up.', 1],
['meetings', 'Meetings', 'You are a meeting assistant. Your goal is to help the user capture key information during meetings and follow up effectively.\n\nYou help capture meeting notes, track action items, identify key decisions, and summarize important points discussed during meetings.', 1],
['sales', 'Sales', 'You are a real-time AI sales assistant, and your goal is to help the user close deals during sales interactions.\n\nYou provide real-time sales support, suggest responses to objections, help identify customer needs, and recommend strategies to advance deals.', 1],
['recruiting', 'Recruiting', 'You are a recruiting assistant. Your goal is to help the user interview candidates and evaluate talent effectively.\n\nYou help evaluate candidates, suggest interview questions, analyze responses, and provide insights about candidate fit for positions.', 1],
['customer-support', 'Customer Support', 'You are a customer support assistant. Your goal is to help resolve customer issues efficiently and thoroughly.\n\nYou help diagnose customer problems, suggest solutions, provide step-by-step troubleshooting guidance, and ensure customer satisfaction.', 1],
];
const stmt = db.prepare(`
INSERT OR IGNORE INTO prompt_presets (id, uid, title, prompt, is_default, created_at)
VALUES (@id, 'default_user', @title, @prompt, @is_default, strftime('%s','now'));
`);
db.transaction(() => defaultPresets.forEach(([id, title, prompt, is_default]) => stmt.run({ id, title, prompt, is_default })))();
const defaultUserStmt = db.prepare(`
INSERT OR IGNORE INTO users (uid, display_name, email, created_at)
VALUES ('default_user', 'Default User', 'contact@pickle.com', strftime('%s','now'));
`);
defaultUserStmt.run();
module.exports = db;

View File

@ -1,7 +1,7 @@
{ {
"name": "pickle-glass", "name": "pickle-glass",
"productName": "Glass", "productName": "Glass",
"version": "0.1.2", "version": "0.2.0",
"description": "Cl*ely for Free", "description": "Cl*ely for Free",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {

View File

@ -1,50 +0,0 @@
# Code Formatting Test
Test various code blocks to ensure proper formatting:
## Python Example (from screenshot)
```python
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
def backtrack(start, path):
res.append(path[:])
for i in range(start, len(nums)):
path.append(nums[i])
backtrack(i + 1, path)
path.pop()
backtrack(0, [])
return res
```
## JavaScript Example
```javascript
function calculateSum(numbers) {
let sum = 0;
for (let i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
return sum;
}
```
## Indented Code with Complex Structure
```python
def complex_function():
if True:
for i in range(10):
if i % 2 == 0:
print(f"Even: {i}")
else:
print(f"Odd: {i}")
if i > 5:
print(" Greater than 5")
nested = {
"key": "value",
"nested": {
"deep": "structure"
}
}
```