Metadata-Version: 2.4
Name: memobot
Version: 1.3.18
Summary: Google Drive-synchronized floating Post-it memo pad for Windows, macOS, and Linux
Home-page: https://github.com/yourusername/memo-bot
Author: Your Name
Author-email: Your Name <your.email@example.com>
Project-URL: Homepage, https://github.com/yourusername/memo-bot
Project-URL: Bug-Tracker, https://github.com/yourusername/memo-bot/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Office/Business :: News/Diary
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: pywebview>=5.0
Requires-Dist: google-api-python-client>=2.0
Requires-Dist: google-auth-oauthlib>=1.0
Requires-Dist: google-auth-httplib2>=0.1.0
Requires-Dist: pystray>=0.19.0
Requires-Dist: pillow>=10.0.0
Dynamic: author
Dynamic: home-page
Dynamic: requires-python

# Memo-Bot v1.3.18 📌

구글 드라이브 기반의 완벽히 동기화되는 크로스 플랫폼 포스트잇 메모장입니다.
안드로이드(Flutter)와 데스크톱(Windows, macOS, Linux - Python/PyWebView) 환경을 지원하며, 사용자의 구글 드라이브 **숨겨진 앱 폴더 (Application Data Folder)**를 이용해 보안이 매우 뛰어나고 깔끔한 동기화를 수행합니다.

---

## 🎨 기술 스택 및 특징

* **Desktop Client**: Python + PyWebView (HTML/JS/CSS). OS 내장 웹뷰를 사용하므로 배포 파일 및 메모리 소모가 최소화됩니다.
* **Mobile Client (Android)**: Flutter (Material 3 다크 모드). 모던하고 유려한 포스트잇 리스트 및 편집 인터페이스 제공.
* **Sync Engine**: Google Drive AppData API. 사용자의 파일 목록에 노출되지 않는 고유 앱 저장소를 사용하고, 파일의 `appProperties` 메타데이터를 캐싱하여 트래픽 소모가 매우 적고 반응이 빠른 동기화를 지원합니다.

---

## 📂 데이터 저장 경로 및 파일 포맷

메모를 작성하고 저장하면 각 메모는 로컬 컴퓨터에 개별 **JSON 파일** 형태로 저장됩니다.

### 1. 로컬 저장 경로
* **Windows**: `C:\Users\<사용자명>\.memobot\notes\`
* **macOS / Linux**: `~/.memobot/notes/`

### 2. 파일 형식 및 이름
* 각 메모당 `note_<고유ID>.json` 형식으로 저장됩니다. (예: `note_a1b2c3d4.json`)

### 3. JSON 데이터 구조 예시
메모의 내용, 색상, 좌표 및 크기, 태그 정보뿐만 아니라 첨부된 이미지 데이터까지 단일 JSON 파일 내에 보관합니다.
```json
{
  "id": "a1b2c3d4-...",
  "content": "메모 내용입니다. #태그",
  "color": "yellow",
  "tags": ["태그"],
  "x": 120,
  "y": 250,
  "width": 250,
  "height": 250,
  "is_folded": false,
  "on_top": true,
  "updated_at": "2026-06-04T12:57:08Z",
  "image": "data:image/png;base64,iVBORw0KGgoAAA..." // 첨부된 이미지 데이터 (Base64 인코딩)
}
```

> [!NOTE]
> 구글 드라이브 동기화가 실행되면 구글 드라이브의 숨겨진 앱 전용 저장소(AppData Folder) 폴더에도 로컬과 동일한 파일명 및 JSON 데이터 포맷으로 저장 및 동기화됩니다.

---

## 🔑 구글 드라이브 API 설정 (OAuth 2.0)

양쪽 플랫폼에서 동기화 기능을 활성화하기 위해 Google Cloud Console에서 OAuth 2.0 자격 증명을 설정해야 합니다.

1. **Google Cloud Console 접속**:
   * [Google Cloud Console](https://console.cloud.google.com/)에 구글 계정으로 로그인합니다.
   * 새 프로젝트를 생성합니다 (예: `Memo-Bot`).

2. **Google Drive API 활성화**:
   * **API 및 서비스 > 라이브러리**로 이동합니다.
   * `Google Drive API`를 검색하고 **사용(Enable)** 버튼을 클릭합니다.

3. **OAuth 동의 화면 설정**:
   * **API 및 서비스 > OAuth 동의 화면**으로 이동합니다.
   * User Type을 **외부(External)**로 선택하고 생성을 누릅니다.
   * 필수 정보(앱 이름, 이메일 등)를 입력합니다.
   * **범위(Scopes)** 설정 단계에서 `.../auth/drive.appdata` 범위를 추가합니다 (구글 드라이브의 앱 전용 숨겨진 폴더 읽기/쓰기 권한).
   * **테스트 사용자 (Test Users)** 등록 단계에서 동기화 테스트에 사용할 본인의 구글 이메일을 반드시 추가합니다.

> [!IMPORTANT]
> OAuth 동의 화면의 퍼블리싱 상태가 **테스트(Testing)** 모드인 경우, 테스트 사용자로 이메일 계정이 등록되어 있어야만 구글 로그인이 정상 처리되고 차단 에러(403 access_denied)가 발생하지 않습니다.

4. **사용자 인증 정보(Credentials) 생성**:
   * **API 및 서비스 > 사용자 인증 정보**로 이동합니다.
   * **사용자 인증 정보 만들기 > OAuth 클라이언트 ID**를 클릭합니다.
   * 애플리케이션 유형을 **데스크톱 앱(Desktop App)**으로 선택하고 이름을 입력 후 생성합니다.
   * 생성된 클라이언트 ID의 JSON 파일을 다운로드합니다.

---

## 💻 데스크톱 앱 실행 및 배포 (Python)

### 1. 자격 증명 파일 배치
다운로드받은 클라이언트 비밀번호 JSON 파일을 `client_secrets.json`으로 이름을 변경하여 다음 경로에 저장합니다.
* **Windows**: `C:\Users\<사용자명>\.memobot\client_secrets.json`
* **macOS/Linux**: `~/.memobot/client_secrets.json`

### 2. 개발자 모드 로컬 실행
```bash
cd desktop
# 가상환경 생성 및 활성화
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# 의존성 패키지 설치
pip install -e .

# 앱 실행
memobot
```

### 3. PyPI 배포용 빌드 및 업로드
패키지 청소, 빌드, 업로드를 일괄적으로 자동 처리해주는 배치 스크립트가 제공됩니다:
```bash
# Windows 환경에서 빌드 및 배포 배치파일 실행
./publish_pypi.bat
```
* 실행 시 기존 빌드 임시 파일들을 모두 초기화하고, `build` 및 `twine` 모듈을 자동으로 최신 설치/업그레이드한 후 빌드를 수행합니다.
* 빌드 완료 후 **[1] TestPyPI 업로드**, **[2] 공식 PyPI 업로드**, **[3] 업로드 없이 빌드만 수행** 중 하나를 선택해 진행할 수 있습니다.
* 배포 완료 시 사용자는 `pip install memobot` 명령어만으로 크로스 플랫폼(Windows, macOS, Linux) 환경에 설치하고 `memobot` 명령어로 즉시 앱을 실행할 수 있습니다.

### 4. PyPI 패키지 관리 방법 (설치, 업데이트, 삭제)

일반 사용자는 파이썬이 설치된 환경에서 아래의 pip 명령어를 사용해 패키지를 편리하게 관리할 수 있습니다.

* **설치 (Install)**:
  ```bash
  pip install memobot
  ```
* **실행 (Run)**:
  설치 후 터미널이나 명령 프롬프트에서 아래 명령을 실행하면 데스크톱 앱이 실행됩니다 (윈도우 환경에서는 검은색 콘솔창 없이 백그라운드용 앱으로 실행됩니다).
  ```bash
  memobot
  ```
* **최신 버전 업데이트 (Update)**:
  ```bash
  pip install --upgrade memobot
  ```
* **삭제 (Uninstall)**:
  ```bash
  pip uninstall memobot
  ```

---

## 📱 모바일 앱 실행 (Flutter Android)

### 1. Flutter 의존성 구성
```bash
cd mobile
flutter pub get
```

### 2. 안드로이드 플랫폼 설정
구글 로그인 연동을 위해 안드로이드 앱의 패키지명과 디버그 서명 키(SHA-1)를 Google Cloud Console의 동일 프로젝트에 등록해야 합니다.

1. **OAuth 클라이언트 ID 추가 생성**:
   * Google Cloud Console > 사용자 인증 정보 > OAuth 클라이언트 ID 생성.
   * 유형을 **Android**로 선택합니다.
   * 패키지 이름 입력 (예: `com.example.memobot`).
   * 개발용 SHA-1 지문 인증서를 입력합니다 (JDK의 `keytool`을 통해 조회 가능).
2. **서비스 파일 다운로드**:
   * 필요에 따라 Firebase와 결합하여 사용할 경우 `google-services.json`을 `mobile/android/app/` 아래에 배치할 수 있으나, 본 구현에서는 `google_sign_in` 패키지가 클라이언트 ID를 통해 직접 동작하므로 최소한의 설정만으로 작동 가능합니다.

### 3. 앱 실행
```bash
flutter run
```

---

## 🔄 동기화 및 충돌 방지 세부 설계

* **Tombstoning (소프트 삭제)**: 사용자가 앱 내에서 메모를 삭제하면 파일이 즉시 영구 삭제되지 않고 내부 필드가 `is_deleted: true`로 갱신됩니다. 이는 다른 디바이스가 동기화 시점에 해당 메모를 로컬에서도 똑같이 지워주도록 유도하며, 완벽한 삭제 전파를 제공합니다.
* **Last-Write-Wins (최종 쓰기 우선)**: 오프라인 수정을 포함하여 서로 다른 기기에서 같은 포스트잇을 수정한 경우, JSON 내부의 `updated_at` 타임스탬프를 기준으로 더 늦게 편집된 최종 데이터를 기준으로 덮어씁니다.

---

## 🚀 업데이트 내역 (Changelog)

### v1.3.18 (2026-06-07)
* **타 기기 실행 오류 및 호환성 대폭 개선**:
  - **WebView2 런타임 누락 예외 처리**: Windows 10/11 환경에서 Microsoft Edge WebView2 Runtime이 미설치/손상되어 앱이 즉시 종료되던 문제를 보완하여, 구동 실패 시 알림창을 띄우고 설치 페이지로 바로 연결해주는 네이티브 다운로드 가이드를 추가했습니다.
  - **64비트 Windows 크래시(Access Violation) 방지**: 64비트 OS에서 `SetWindowLongW` API 호출 시 핸들 포인터(HWND)가 절단되어 프로그램이 비정상 종료되던 버그를 자동 아키텍처 판별을 통해 `SetWindowLongPtrW` 호출로 교체하여 해결했습니다.
  - **PyInstaller hiddenimports 누락 보완**: `webview.platforms.winforms`, `pystray`, `PIL`, `ctypes`, `winreg` 등 런타임 렌더링 드라이버 및 필수 모듈들을 실행 바이너리에 확실히 동봉하여 환경 제약 없는 구동을 확보했습니다.
  - **하드코딩된 개발자 계정 경로 제거**: 가이드 내 특정 개인화 경로를 플레이스홀더 및 동적 계정명 감지(API 브릿지 `get_secrets_path()`) 형태로 변경하여 가독성을 높였습니다.

### v1.3.17 (2026-06-07)
* **작은 메모 크기에서의 확인창(오버레이) 잘림 현상 해결**:
  - 메모 창의 높이가 대폭 작아진 상태에서 잠금 해제 비밀번호 입력 오버레이나 삭제 확인 팝업 등이 뜰 때, 하단의 확인/취소 버튼이 창 하단부 밖으로 밀려나 보이지 않던 잘림 버그를 수정했습니다.
  - 창의 높이가 240px 이하가 되면 팝업 상자의 여백(padding/gap), 글꼴 크기, 아이콘 크기 등을 대폭 슬림하게 조정하는 반응형 미디어 쿼리를 추가하고, 스크롤 가능하도록 레이아웃을 보완했습니다.

### v1.3.16 (2026-06-07)
* **비밀번호 수정 시 기존 비밀번호 검증 단계 추가**:
  - 설정 메뉴에서 잠금 비밀번호를 새로 수정하거나 해제하려고 할 때, 타인이 함부로 접근해 변경하지 못하도록 **기존 비밀번호 입력 확인** 대화상자를 필수적으로 거치도록 설계했습니다.
  - 이 기능은 데스크톱 설정 창(JS `prompt` 다이얼로그) 및 모바일(Flutter Android overlay) 양쪽 모두에 공통 적용되었으며, 검증에 통과해야만 새 비밀번호로의 저장이 승인됩니다.

### v1.3.15 (2026-06-07)
* **메모 비밀번호 잠금 기능 추가 (크로스 플랫폼 연동)**:
  - 데스크톱 및 모바일(Android) 양쪽 앱 모두에 개별 메모 비밀번호 잠금 기능을 도입했습니다.
  - 설정 메뉴에서 사용할 잠금 비밀번호를 개별 기기에 지정할 수 있으며(비밀번호는 동기화되지 않고 각 기기별 로컬 보안 설정에만 독립 저장), 에디터 툴바에 새로 배치된 자물쇠 토글 버튼을 통해 특정 메모를 잠그거나 해제할 수 있습니다.
  - 보안을 위해 잠긴 메모는 대시보드 리스트에서 마스킹(`🔒 잠긴 메모입니다.`) 처리되고, 실제 본문 콘텐츠와 미디어 데이터(이미지/오디오)는 검증 완료 전까지 백엔드와 클라이언트 단 모두에서 완전히 차단되어 유출을 방지합니다.
  - 메모의 잠금 여부 상태(`is_locked`)는 구글 드라이브 동기화를 통해 양방향으로 자동 연동 및 공유됩니다.

### v1.3.14 (2026-06-07)
* **설정 창 독립 팝업 분리**:
  - 기존 메모 매니저(Dashboard) 내부 레이어 모달로 띄우던 설정 창을 독립된 별도 외부 팝업 창(크기 `450x620` 고정, 타이틀바를 가진 윈도우)으로 분리하여 오픈하도록 개선했습니다.
  - 이를 통해 매니저 창의 크기 제한으로 인해 설정 메뉴 하단 및 우측 항목들이 화면에서 잘리는 현상을 완벽히 해결했습니다.
  - 기존 설정 API 및 이벤트 구조를 그대로 이식 및 활용하여 설정 변경사항이 로컬 메모, 매니저, 개별 메모 윈도우에 실시간으로 즉시 동기화됩니다.

### v1.3.13 (2026-06-07)
* **자석 정렬 드래그 개선 및 불필요한 로그/경고 제거**:
  * 접힌 메모가 자석(Magnetic) 정렬 상태로 달라붙어 있을 때 마우스 드래그를 통해 매끄럽게 떼어낼 수 없던 현상을 해결하기 위해, 누적 마우스 움직임을 추적하는 **논리적 좌표계(Logical Coordinates)** 시스템을 도입했습니다. 이제 자석 고정점으로부터 마우스를 15px 이상 이동하면 부드럽고 자연스럽게 스냅이 풀리며 이동할 수 있습니다.
  * 구글 드라이브 동기화 API 초기화 시 터미널에 불필요하게 출력되던 `file_cache is only supported with oauth2client<4.0.0` 경고 메시지를 `cache_discovery=False` 설정을 통해 억제하고 초기화 동작을 최적화했습니다.

### v1.3.12 (2026-06-07)
* **위키링크 포맷 수정 및 작업 표시줄 개별 메모 노출 방지**:
  * 위키링크 복사 시 기존 ID 및 제목 조합 방식(`[[noteId|Title]]`)에서 대중적이고 명확한 `[[NoteTitle]]` 형태로 복사되도록 수정한 후, 메모 본문 파싱 및 클릭 네비게이션 시에도 대괄호 기호(`[[`, `]]`)를 자동 제거해 올바르게 매칭되도록 보완했습니다.
  * Windows 환경에서 개별 포스트잇 메모 창들이 작업 표시줄(Taskbar)에 우후죽순 생성되는 현상을 차단하고, 오직 메인 "메모 관리자(Memo-Bot Manager)" 대시보드 창만 작업 표시줄에 노출되도록 스타일링(`WS_EX_TOOLWINDOW` 및 `ShowInTaskbar = False`)을 수정하였습니다.

### v1.3.11 (2026-06-07)
* **해시태그/위키링크 검색 및 위키링크 복사 기능 추가**: 대시보드 메인 화면에서 `#태그` 검색어 또는 `[[위키링크]]` 검색어 패턴을 인식하는 지능형 필터링 기능을 추가했습니다. 또한 개별 메모 헤더에 "위키링크 복사" 단추를 새로 배치하여 클릭 시 `[[noteId|Title]]` 포맷의 마크다운 링크가 원터치로 클립보드에 복사되고, 성공 시 체크 아이콘으로 1초간 시각적 피드백(플래시 애니메이션)을 주도록 사용성을 강화했습니다.

### v1.3.10 (2026-06-06)
* **백그라운드 실행(noconsole) 기본화**: PyInstaller 빌드 시와 PyPI 패키지 배포 시 윈도우 환경에서 터미널 창 없이 백그라운드용 GUI 앱으로 즉시 실행되도록 설정을 최적화했습니다 (`--noconsole` 및 `gui_scripts` 적용).

### v1.3.9 (2026-06-06)
* **메모 관리자 초기 로드 및 레이스 컨디션 해결**: 매니저 창 첫 실행 시 `window.pywebview` 객체가 아직 브라우저에 생성되지 않았을 때 웹 모드로 성급하게 차단되어 로컬 메모 목록이 화면에 나타나지 않던 문제를 해결하기 위해, `pywebviewready` 이벤트 리스너 등록 및 대기 로직을 전면 최적화하여 안정적으로 로컬 메모를 초기 화면에 로드합니다.

### v1.3.8 (2026-06-06)
* **대시보드 초기화 시 로컬 메모 자동 로드 수정**: 앱 실행 시 `pywebviewready` 이벤트가 리스너 등록 전에 이미 호출되어 대시보드가 처음 켜졌을 때 로컬 메모 목록이 자동으로 나타나지 않던 문제를 수정했습니다. 이제 웹뷰 API 로드 여부를 즉시 검사하여 메모 로딩이 바로 실행됩니다.
* **임포트 오류 수정 (NameError: time)**: 닫기 지연 처리(`defer_hide`) 함수 내에서 `time.sleep` 호출 시 `time` 모듈이 글로벌 임포트되어 있지 않아 발생하던 NameError 버그 및 이로 인해 닫기 동작이 아예 불가능해지던 오동작을 수정했습니다.

### v1.3.7 (2026-06-06)
* **구글 드라이브 탭 목록 레이아웃 개선 및 미리보기 수정**: 구글 클라우드 메모 관리 테이블에서 첫 번째 열(메모 미리보기)의 너비가 다른 열의 고정 너비로 인해 극도로 축소되어 `#...`이나 `메...`처럼 한 글자와 말줄임표로만 보이던 문제를 해결했습니다. 열 비율을 고정하는 대신 유연하게 설정하고 반응형 레이아웃을 도입하였으며, 마크다운 헤더 기호(예: `## `, `# `)를 제외하고 출력하도록 텍스트 전처리 기능을 추가했습니다.

### v1.3.6 (2026-06-06)
* **메모 관리자 창 닫기 무한 루프 버그 수정**: Windows 환경에서 메모 관리자 창을 닫아 트레이 아이콘으로 숨길 때, pywebview의 `hide()` 동작이 내부적으로 `closing` 이벤트를 재발하여 무한 닫기 루프(윈도우가 열리자마자 바로 사라지는 현상)가 발생하는 현상을 방지하기 위해 상태 락(is_hiding_manager)을 도입하여 예외 처리했습니다.

### v1.3.5 (2026-06-06)
* **구글 드라이브 메모 첫 줄 미리보기 지원**: 로컬에 다운로드되지 않은 클라우드 전용 메모도 대시보드의 클라우드 탭 목록에서 본문 첫 줄 내용을 미리 짧게 볼 수 있도록 개선했습니다. 이를 위해 동기화 시 메모의 첫 줄 텍스트를 드라이브 파일의 `appProperties` 메타데이터에 함께 실어 보내고, 목록 렌더링 시 이를 파싱해 출력하도록 연동했습니다.


### v1.3.4 (2026-06-06)
* **단축키 범위(Scope) 최적화**: 새 메모 추가(`Ctrl+N`) 및 동기화(`Ctrl+S`) 단축키가 메모 관리자 대시보드가 열리고 포커스되었을 때만 작동하도록 범위를 가두고, 개별 메모 삭제(`Ctrl+D`), 항상 위 토글(`Ctrl+P`), 접기 토글(`Ctrl+L`)은 개별 메모 창이 활성화되어 있을 때만 반응하도록 개선하여 단축키 충돌을 방지했습니다.
* **글로벌 단축키 지원 (Windows)**: 관리자 창이 닫혀 있거나(트레이 아이콘 상태) 백그라운드에 있을 때도 언제든지 `Ctrl+O`를 누르면 메모 관리자가 최상단으로 복원 및 강제 포커싱되도록 Windows API(RegisterHotKey)를 연동한 글로벌 단축키 스레드를 적용했습니다. 설정에서 단축키를 비활성화하면 시스템 등록도 실시간 해제됩니다.


### v1.3.3 (2026-06-06)
* **버튼 미니멀화 및 도움말 가이드 추가**: 대시보드 제어 버튼을 슬림하고 미니멀하게 디자인을 조정하고, 해시태그, 메모링크(WikiLinks), AI(Gemini) 설정 및 사용법을 상세 안내하는 도움말 가이드 모달을 탑재했습니다.

### v1.3.2 (2026-06-06)
* **Gemini API 키 다중 입력 UI 개선**: 단일 입력창에 쉼표로 길게 나열해야 했던 기존 방식 대신, 설정 창에서 한 칸에 키 하나씩 깔끔하게 등록할 수 있도록 다중 키 동적 추가(`+`)/삭제(휴지통) 인터페이스를 구현했습니다. 기존 백엔드 자동 키 순환(rotation) 알고리즘과 100% 하위 호환됩니다.

### v1.3.1 (2026-06-05)
* **옵디시언 스타일 위키링크 `[[ ]]` 연동**: 메모 본문 내 대괄호 링크(`[[메모 제목]]`) 클릭 시 해당 메모 창을 즉시 포커스하고, 메모가 없는 경우 자동으로 첫 줄 제목을 가진 신규 메모를 생성해 연동해주는 WikiLinks 기능을 탑재했습니다.
* **구글 드라이브 삭제된 메모 완전 삭제**: 구글 드라이브와 동기화 시, 이미 소프트 삭제(Tombstone) 처리된 삭제 대기 메모가 동기화 목록에 남아 잔존하는 현상을 방지하도록 원격 및 로컬에서 영구 삭제 처리하는 루틴을 보강했습니다.
* **기본 웰컴 메모 비활성화**: 앱 처음 실행 시 로컬 저장소에 기본으로 생성되던 2개의 튜토리얼 성격의 가이드 메모가 생성되지 않도록 수정하여 더 깔끔한 시작 화면을 제공합니다.
* **날짜 포맷 변경**: 메모 생성 및 업데이트 시, 시간(시/분/초) 정보만 노출되던 화면에 년-월-일 정보가 함께 노출되도록 날짜 표시 포맷을 수정했습니다 (`YYYY-MM-DD HH:MM:SS`).
* **필터 초기화 자동화**: 해시태그나 메모 내용을 수정한 후 저장 시, 편집한 메모가 현재 검색 또는 태그 필터 때문에 보이지 않는 현상을 방지하기 위해 필터를 자동으로 '전체'로 초기화하여 방금 수정한 메모가 대시보드에 즉시 노출되도록 개선했습니다.
* **슬림 카드 뷰 & 휠 스크롤 지원**: 대시보드에서 접힌 상태의 메모 카드를 대폭 슬림화(38px)하고 접힌 상태에서도 메모 본문 첫 번째 줄이 상단에 노출되도록 최적화했습니다. 추가로, 스크롤바 노출 없이 마우스 휠 스크롤을 감지해 간편하게 오르내릴 수 있도록 편의성을 강화했습니다.
* **버전 뱃지 추가**: 매니저 창 헤더의 로고 우측에 메인 테마와 조화로운 Glassmorphism 스타일의 버전 뱃지(`v1.3.1`)를 부착했습니다.

