This commit is contained in:
angworktop 2025-11-18 18:08:25 +09:00
commit 13cd08de8d
34 changed files with 805 additions and 0 deletions

26
.gitignore vendored Normal file
View File

@ -0,0 +1,26 @@
# Dependencies
node_modules/
package-lock.json
# Rust
src-tauri/target/
src-tauri/Cargo.lock
# Tauri
src-tauri/gen/
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
# Build outputs
dist/
build/

114
PROJECT_STRUCTURE.md Normal file
View File

@ -0,0 +1,114 @@
# 프로젝트 구조 가이드
## 현재 구조 (표준 Tauri 구조)
```
ndd-drive/
├── src/ # 프론트엔드 소스 코드
│ └── index.html # 메인 HTML 파일
├── src-tauri/ # Rust 백엔드 (Tauri)
│ ├── src/ # Rust 소스 파일
│ │ ├── main.rs # 진입점
│ │ └── lib.rs # 라이브러리 진입점
│ ├── Cargo.toml # Rust 의존성 관리
│ ├── tauri.conf.json # Tauri 설정
│ ├── build.rs # 빌드 스크립트
│ ├── icons/ # 앱 아이콘
│ ├── capabilities/ # Tauri 권한 설정
│ ├── gen/ # 자동 생성 파일 (gitignore)
│ └── target/ # 빌드 결과물 (gitignore)
├── package.json # Node.js 의존성 및 스크립트
├── node_modules/ # Node.js 패키지 (gitignore)
└── package-lock.json # 패키지 잠금 파일
```
## 개선된 구조 제안
### 옵션 1: 현재 구조 유지 + 모듈화 (추천)
```
ndd-drive/
├── src/ # 프론트엔드
│ ├── index.html
│ ├── css/
│ │ ├── main.css
│ │ └── components/
│ ├── js/
│ │ ├── main.js
│ │ ├── components/
│ │ └── utils/
│ ├── assets/
│ │ ├── images/
│ │ └── fonts/
│ └── components/ # 재사용 가능한 컴포넌트
├── src-tauri/ # Rust 백엔드
│ ├── src/
│ │ ├── main.rs
│ │ ├── lib.rs
│ │ ├── commands/ # Tauri 커맨드 (프론트엔드에서 호출)
│ │ │ └── mod.rs
│ │ ├── utils/ # 유틸리티 함수
│ │ │ └── mod.rs
│ │ └── models/ # 데이터 모델
│ │ └── mod.rs
│ ├── Cargo.toml
│ ├── tauri.conf.json
│ ├── build.rs
│ ├── icons/
│ └── capabilities/
├── package.json
└── README.md
```
### 옵션 2: 프론트엔드 프레임워크 사용 시 (React/Vue 등)
```
ndd-drive/
├── src/ # 프론트엔드 (프레임워크)
│ ├── index.html
│ ├── main.jsx / main.tsx
│ ├── App.jsx / App.tsx
│ ├── components/
│ ├── pages/
│ ├── hooks/ # React hooks 또는 Vue composables
│ ├── utils/
│ ├── styles/
│ └── assets/
├── src-tauri/ # Rust 백엔드 (동일)
│ └── ...
├── public/ # 정적 파일
├── package.json
└── vite.config.js / webpack.config.js
```
## 각 디렉토리 설명
### `/src` - 프론트엔드
- **index.html**: 앱의 진입점 HTML
- **css/**: 스타일시트 파일
- **js/**: JavaScript 파일
- **assets/**: 이미지, 폰트 등 정적 리소스
- **components/**: 재사용 가능한 UI 컴포넌트
### `/src-tauri` - Rust 백엔드
- **src/main.rs**: Rust 프로그램 진입점
- **src/lib.rs**: 라이브러리 진입점 (Tauri 앱 설정)
- **src/commands/**: Tauri 커맨드 (프론트엔드에서 호출 가능한 Rust 함수)
- **src/utils/**: 공통 유틸리티 함수
- **src/models/**: 데이터 구조 및 모델
- **tauri.conf.json**: Tauri 앱 설정 (윈도우 크기, 권한 등)
- **capabilities/**: 보안 권한 설정
## 권장 사항
1. **프론트엔드 모듈화**: CSS와 JS를 분리하여 관리
2. **Rust 코드 모듈화**: 기능별로 파일 분리 (commands, utils 등)
3. **.gitignore**: target/, node_modules/, gen/ 등 빌드 결과물 제외
4. **문서화**: README.md에 프로젝트 설명 및 실행 방법 작성

41
README_WEB.md Normal file
View File

@ -0,0 +1,41 @@
# 웹에서 실행하기
## 방법 1: npm 스크립트 사용 (추천)
```bash
npm run web:dev
```
또는
```bash
npm run web:serve
```
브라우저에서 `http://localhost:8080`으로 접속
## 방법 2: Python 간단 서버
```bash
# Python 3
cd src
python -m http.server 8080
```
## 방법 3: Node.js http-server
```bash
npx http-server src -p 8080 -o
```
## 방법 4: VS Code Live Server
VS Code의 "Live Server" 확장 프로그램 사용
## 주의사항
- 웹에서는 Tauri API가 작동하지 않습니다
- 트레이 기능은 데스크탑 앱에서만 동작합니다
- 웹에서는 UI만 확인 가능합니다
- 버튼 클릭 시 상태 텍스트는 변경되지만, 실제 트레이는 업데이트되지 않습니다

97
TRAY_IMPLEMENTATION.md Normal file
View File

@ -0,0 +1,97 @@
# 시스템 트레이 구현 가이드
## 개요
Proton Drive처럼 시스템 트레이 아이콘을 표시하고, 로그인 상태에 따라 아이콘 색상과 툴팁을 변경하는 기능을 구현하는 방법입니다.
## 구조 설명
### 1. 파일 구조
```
src-tauri/src/
├── lib.rs # 메인 앱 설정 (트레이 초기화)
├── tray.rs # 트레이 관련 로직 (별도 모듈)
└── commands/
└── tray_commands.rs # 프론트엔드에서 호출할 트레이 커맨드
```
### 2. 모듈 분리 이유
**`tray.rs` (별도 파일로 분리)**
- ✅ **유지보수성**: 트레이 관련 코드가 한 곳에 모여있어 수정이 쉬움
- ✅ **확장성**: 새로운 트레이 기능 추가 시 해당 파일만 수정
- ✅ **가독성**: 메인 코드(`lib.rs`)가 간결해짐
- ✅ **테스트 용이**: 트레이 로직을 독립적으로 테스트 가능
### 3. 구현 방법
#### Tauri 2.x에서 시스템 트레이 사용
Tauri 2.x에서는 시스템 트레이 기능이 변경되었을 수 있습니다. 다음 중 하나의 방법을 사용해야 합니다:
**방법 1: Tauri 플러그인 사용 (권장)**
```toml
# Cargo.toml에 추가
[dependencies]
tauri-plugin-system-tray = "2.0"
```
**방법 2: 직접 구현**
- `tray-icon` 크레이트 사용
- 또는 Tauri 2.x의 새로운 API 사용
### 4. 현재 구현된 구조
#### `src-tauri/src/tray.rs`
- `TrayStatus` 열거형: 로그인 상태 정의
- `create_system_tray()`: 트레이 생성
- `handle_tray_event()`: 트레이 이벤트 처리
- `update_tray_status()`: 상태에 따른 아이콘/툴팁 업데이트
#### `src-tauri/src/commands/tray_commands.rs`
- `update_tray_icon()`: 프론트엔드에서 호출 가능한 커맨드
### 5. 사용 예시
**프론트엔드에서 호출:**
```javascript
import { invoke } from '@tauri-apps/api/core';
// 로그인 상태로 변경
await invoke('update_tray_icon', { status: 'logged_in' });
// 동기화 중 상태로 변경
await invoke('update_tray_icon', { status: 'syncing' });
```
### 6. 아이콘 색상 변경 방법
Proton Drive처럼 아이콘 색상을 변경하려면:
**옵션 1: 상태별 아이콘 파일 준비**
```
src-tauri/icons/
├── icon_logged_out.png (회색)
├── icon_logged_in.png (녹색)
├── icon_syncing.png (파란색)
└── icon_error.png (빨간색)
```
**옵션 2: 런타임 아이콘 생성**
- `image` 크레이트를 사용하여 런타임에 아이콘 색상 변경
- Cargo.toml에 추가: `image = "0.24"`
### 7. 다음 단계
1. **Tauri 2.x API 확인**: 정확한 시스템 트레이 API 확인 필요
2. **플러그인 설치**: `tauri-plugin-system-tray` 플러그인 사용 여부 확인
3. **아이콘 준비**: 상태별 아이콘 파일 생성
4. **테스트**: 각 상태에서 트레이 동작 확인
## 참고사항
- Tauri 2.x의 시스템 트레이 API는 1.x와 다를 수 있습니다
- 실제 구현 전에 Tauri 2.x 공식 문서를 확인하세요
- OS별로 트레이 동작이 다를 수 있습니다 (Windows, macOS, Linux)

15
package.json Normal file
View File

@ -0,0 +1,15 @@
{
"scripts": {
"tauri": "tauri",
"tauri:dev": "tauri dev",
"tauri:build": "tauri build",
"web:dev": "npx http-server src -p 8080 -o",
"web:serve": "npx serve src -l 8080"
},
"dependencies": {
"@tauri-apps/api": "^2.0.0"
},
"devDependencies": {
"@tauri-apps/cli": "^2.9.4"
}
}

4
src-tauri/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Generated by Cargo
# will have compiled files and executables
/target/
/gen/schemas

25
src-tauri/Cargo.toml Normal file
View File

@ -0,0 +1,25 @@
[package]
name = "app"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
edition = "2021"
rust-version = "1.77.2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2.5.1", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
log = "0.4"
tauri = { version = "2.9.2", features = ["tray-icon"] }
tauri-plugin-log = "2"

3
src-tauri/build.rs Normal file
View File

@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

View File

@ -0,0 +1,11 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "enables the default permissions",
"windows": [
"main"
],
"permissions": [
"core:default"
]
}

BIN
src-tauri/icons/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
src-tauri/icons/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
src-tauri/icons/icon.icns Normal file

Binary file not shown.

BIN
src-tauri/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
src-tauri/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -0,0 +1,22 @@
// Tauri 커맨드 모듈
// 프론트엔드에서 호출할 수 있는 Rust 함수들을 여기에 정의
mod tray_commands;
pub use tray_commands::update_tray_icon;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct GreetResponse {
pub message: String,
}
/// 예시: 프론트엔드에서 호출할 수 있는 커맨드
#[tauri::command]
pub fn greet(name: &str) -> GreetResponse {
GreetResponse {
message: format!("Hello, {}! You've been greeted from Rust!", name),
}
}

View File

@ -0,0 +1,31 @@
// 트레이 관련 Tauri 커맨드
// 프론트엔드에서 트레이 상태를 업데이트할 수 있는 커맨드
use crate::tray::{TrayStatus, update_tray_status};
use tauri::{AppHandle, Manager};
use std::sync::{Arc, Mutex};
/// 프론트엔드에서 호출: 트레이 상태 업데이트
#[tauri::command]
pub fn update_tray_icon(app: AppHandle, status: String) -> Result<(), String> {
let tray_status = match status.as_str() {
"logged_out" => TrayStatus::LoggedOut,
"logged_in" => TrayStatus::LoggedIn,
"syncing" => TrayStatus::Syncing,
"error" => TrayStatus::Error,
_ => return Err(format!("Unknown status: {}", status)),
};
// 앱 상태에서 트레이 가져오기
if let Some(tray_state) = app.try_state::<Arc<Mutex<Option<tauri::tray::TrayIcon>>>>() {
if let Ok(tray_mutex) = tray_state.lock() {
if let Some(ref tray) = *tray_mutex {
update_tray_status(&app, tray, tray_status)
.map_err(|e| format!("Failed to update tray: {}", e))?;
}
}
}
Ok(())
}

54
src-tauri/src/lib.rs Normal file
View File

@ -0,0 +1,54 @@
// 모듈 선언
mod commands;
mod tray;
use commands::{greet, update_tray_icon};
use tray::{create_system_tray, update_tray_status, TrayStatus};
use tauri::Manager;
use std::sync::{Arc, Mutex};
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet, update_tray_icon])
.setup(|app| {
// 시스템 트레이 생성
let app_handle = app.handle().clone();
let tray = create_system_tray(&app_handle)?;
// 트레이를 앱 상태에 저장 (나중에 업데이트하기 위해)
app.manage(Arc::new(Mutex::new(Some(tray))));
// 초기 트레이 상태 설정 (로그아웃 상태)
if let Some(tray_state) = app.try_state::<Arc<Mutex<Option<tauri::tray::TrayIcon>>>>() {
if let Ok(tray_mutex) = tray_state.lock() {
if let Some(ref tray) = *tray_mutex {
update_tray_status(&app_handle, tray, TrayStatus::LoggedOut)?;
}
}
}
// X 버튼 클릭 시 종료하지 않고 숨기기
if let Some(window) = app.get_webview_window("main") {
let window_clone = window.clone();
window.on_window_event(move |event| {
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
// 종료 대신 숨기기
api.prevent_close();
let _ = window_clone.hide();
}
});
}
if cfg!(debug_assertions) {
app.handle().plugin(
tauri_plugin_log::Builder::default()
.level(log::LevelFilter::Info)
.build(),
)?;
}
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

6
src-tauri/src/main.rs Normal file
View File

@ -0,0 +1,6 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
app_lib::run();
}

100
src-tauri/src/tray.rs Normal file
View File

@ -0,0 +1,100 @@
// 시스템 트레이 모듈
// Proton Drive처럼 로그인 상태에 따라 아이콘과 툴팁을 변경하는 기능
use tauri::{AppHandle, Manager};
use tauri::tray::{TrayIconBuilder, MouseButton, MouseButtonState};
use tauri::menu::{Menu, MenuItem};
use tauri::tray::TrayIconEvent;
/// 트레이 상태 열거형
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum TrayStatus {
LoggedOut, // 로그아웃 상태
LoggedIn, // 로그인 상태
Syncing, // 동기화 중
Error, // 오류 상태
}
/// 시스템 트레이 생성 및 설정
pub fn create_system_tray(app: &AppHandle) -> Result<tauri::tray::TrayIcon, Box<dyn std::error::Error>> {
// 트레이 메뉴 생성
let show_item = MenuItem::with_id(app, "show", "Show Window", true, None::<&str>)?;
let quit_item = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
let menu = Menu::new(app)?;
menu.append(&show_item)?;
// separator는 Tauri 2.x에서 다른 방식으로 구현해야 할 수 있음
menu.append(&quit_item)?;
// 트레이 아이콘 생성 (기본 아이콘 사용)
// 아이콘은 tauri.conf.json에서 설정된 기본 아이콘 사용
// 런타임에 아이콘을 변경하려면 별도로 로드해야 함
let tray = TrayIconBuilder::new()
.tooltip("NaDoDev Drive")
.menu(&menu)
.on_menu_event(|app, event| {
match event.id.as_ref() {
"show" => {
if let Some(window) = app.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
"quit" => {
app.exit(0);
}
_ => {}
}
})
.on_tray_icon_event(|tray, event| {
if let TrayIconEvent::Click {
button: MouseButton::Left,
button_state: MouseButtonState::Up,
..
} = event
{
if let Some(window) = tray.app_handle().get_webview_window("main") {
if window.is_visible().unwrap_or(false) {
let _ = window.hide();
} else {
let _ = window.show();
let _ = window.set_focus();
}
}
}
})
.build(app)?;
Ok(tray)
}
// 트레이 이벤트는 create_system_tray 내부에서 처리됨
/// 트레이 아이콘 및 툴팁 업데이트
///
/// 참고: Proton Drive처럼 상태별로 다른 아이콘을 사용하려면
/// icons/ 디렉토리에 상태별 아이콘 파일을 준비해야 합니다:
/// - icon_logged_out.png (로그아웃)
/// - icon_logged_in.png (로그인 - 녹색)
/// - icon_syncing.png (동기화 중 - 파란색)
/// - icon_error.png (오류 - 빨간색)
pub fn update_tray_status(_app: &AppHandle, tray: &tauri::tray::TrayIcon, status: TrayStatus) -> Result<(), Box<dyn std::error::Error>> {
// 툴팁 텍스트 업데이트
let tooltip = match status {
TrayStatus::LoggedOut => "NaDoDev Drive - Not logged in",
TrayStatus::LoggedIn => "NaDoDev Drive - Logged in",
TrayStatus::Syncing => "NaDoDev Drive - Syncing...",
TrayStatus::Error => "NaDoDev Drive - Error",
};
tray.set_tooltip(Some(tooltip))?;
// TODO: 아이콘 색상 변경을 위해서는:
// 1. 상태별 아이콘 파일을 준비하고 런타임에 로드하거나
// 2. image 크레이트를 사용하여 런타임에 아이콘을 동적으로 생성
// 현재는 툴팁만 업데이트합니다.
Ok(())
}

36
src-tauri/tauri.conf.json Normal file
View File

@ -0,0 +1,36 @@
{
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
"productName": "NaDoDev Drive",
"version": "0.1.0",
"identifier": "com.tauri.dev",
"build": {
"frontendDist": "../src",
"beforeDevCommand": "",
"beforeBuildCommand": "npm run build"
},
"app": {
"windows": [
{
"title": "NaDoDev Drive",
"width": 800,
"height": 600,
"resizable": true,
"fullscreen": false
}
],
"security": {
"csp": null
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
]
}
}

99
src/css/main.css Normal file
View File

@ -0,0 +1,99 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.container {
text-align: center;
padding: 2rem;
}
h1 {
font-size: 3rem;
margin-bottom: 1rem;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
p {
font-size: 1.2rem;
opacity: 0.9;
}
.logo {
font-size: 5rem;
margin-bottom: 1rem;
}
.tray-controls {
margin-top: 3rem;
padding: 2rem;
background: rgba(255, 255, 255, 0.1);
border-radius: 1rem;
backdrop-filter: blur(10px);
max-width: 500px;
margin-left: auto;
margin-right: auto;
}
.tray-controls h2 {
font-size: 1.5rem;
margin-bottom: 1rem;
}
.status-text {
font-size: 1rem;
margin-bottom: 1.5rem;
opacity: 0.9;
}
#current-status {
font-weight: bold;
color: #ffd700;
}
.button-group {
display: flex;
flex-direction: column;
gap: 0.75rem;
margin-bottom: 1rem;
}
.tray-btn {
padding: 0.75rem 1.5rem;
font-size: 1rem;
border: none;
border-radius: 0.5rem;
background: rgba(255, 255, 255, 0.2);
color: white;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
}
.tray-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.tray-btn:active {
transform: translateY(0);
}
.hint {
font-size: 0.9rem;
opacity: 0.8;
margin-top: 1rem;
}

32
src/index.html Normal file
View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NaDoDev Drive</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="container">
<div class="logo">🚀</div>
<h1>NaDoDev Drive</h1>
<p>Tauri 데스크탑 애플리케이션</p>
<div class="tray-controls">
<h2>시스템 트레이 테스트</h2>
<p class="status-text">현재 상태: <span id="current-status">로그아웃</span></p>
<div class="button-group">
<button id="btn-logged-out" class="tray-btn">로그아웃 상태</button>
<button id="btn-logged-in" class="tray-btn">로그인 상태</button>
<button id="btn-syncing" class="tray-btn">동기화 중</button>
<button id="btn-error" class="tray-btn">오류 상태</button>
</div>
<p class="hint">💡 시스템 트레이 아이콘을 확인하세요!</p>
</div>
</div>
<script type="module" src="js/main.js"></script>
</body>
</html>

89
src/js/main.js Normal file
View File

@ -0,0 +1,89 @@
// 메인 JavaScript 파일
console.log('NaDoDev Drive 앱이 시작되었습니다.');
// Tauri API 체크 및 import
let invoke = null;
let isTauri = false;
// Tauri 환경 초기화 함수
async function initTauri() {
try {
// Tauri 환경 체크
if (window.__TAURI__) {
isTauri = true;
const tauriApi = await import('@tauri-apps/api/core');
invoke = tauriApi.invoke;
console.log('Tauri 환경에서 실행 중');
return true;
} else {
console.log('웹 브라우저에서 실행 중 (Tauri API 사용 불가)');
return false;
}
} catch (error) {
console.log('웹 브라우저에서 실행 중 (Tauri API 사용 불가)', error);
return false;
}
}
// 트레이 상태 업데이트 함수
async function updateTrayStatus(status, displayName) {
// UI 업데이트 (항상 실행)
const statusElement = document.getElementById('current-status');
if (statusElement) {
statusElement.textContent = displayName;
}
if (isTauri && invoke) {
// Tauri 환경: 실제 트레이 업데이트
try {
await invoke('update_tray_icon', { status });
console.log(`트레이 상태가 "${displayName}"로 변경되었습니다.`);
} catch (error) {
console.error('트레이 상태 업데이트 실패:', error);
alert(`오류 발생: ${error}`);
}
} else {
// 웹 환경: UI만 업데이트 (트레이 기능 없음)
console.log(`웹 모드: 상태 표시만 "${displayName}"로 변경됨 (트레이 기능 없음)`);
}
}
document.addEventListener('DOMContentLoaded', async () => {
console.log('DOM이 로드되었습니다.');
// Tauri 초기화
await initTauri();
// 버튼 이벤트 리스너 설정
const btnLoggedOut = document.getElementById('btn-logged-out');
const btnLoggedIn = document.getElementById('btn-logged-in');
const btnSyncing = document.getElementById('btn-syncing');
const btnError = document.getElementById('btn-error');
if (btnLoggedOut) {
btnLoggedOut.addEventListener('click', () => {
updateTrayStatus('logged_out', '로그아웃');
});
}
if (btnLoggedIn) {
btnLoggedIn.addEventListener('click', () => {
updateTrayStatus('logged_in', '로그인');
});
}
if (btnSyncing) {
btnSyncing.addEventListener('click', () => {
updateTrayStatus('syncing', '동기화 중');
});
}
if (btnError) {
btnError.addEventListener('click', () => {
updateTrayStatus('error', '오류');
});
}
console.log('트레이 테스트 UI가 준비되었습니다.');
});